diff options
Diffstat (limited to 'drivers/staging/tidspbridge/rmgr/drv_interface.c')
-rw-r--r-- | drivers/staging/tidspbridge/rmgr/drv_interface.c | 650 |
1 files changed, 0 insertions, 650 deletions
diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c deleted file mode 100644 index e3918d2efa17..000000000000 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ /dev/null @@ -1,650 +0,0 @@ -/* - * drv_interface.c - * - * DSP-BIOS Bridge driver support functions for TI OMAP processors. - * - * DSP/BIOS Bridge driver interface. - * - * Copyright (C) 2005-2006 Texas Instruments, Inc. - * - * This package is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#include <linux/platform_data/dsp-omap.h> - -#include <linux/types.h> -#include <linux/platform_device.h> -#include <linux/pm.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/moduleparam.h> -#include <linux/cdev.h> - -/* ----------------------------------- DSP/BIOS Bridge */ -#include <dspbridge/dbdefs.h> - -/* ----------------------------------- OS Adaptation Layer */ -#include <dspbridge/clk.h> - -/* ----------------------------------- Platform Manager */ -#include <dspbridge/dspapi.h> -#include <dspbridge/dspdrv.h> - -/* ----------------------------------- Resource Manager */ -#include <dspbridge/pwr.h> - -#include <dspbridge/resourcecleanup.h> -#include <dspbridge/proc.h> -#include <dspbridge/dev.h> - -#ifdef CONFIG_TIDSPBRIDGE_DVFS -#include <mach-omap2/omap3-opp.h> -#endif - -/* ----------------------------------- Globals */ -#define DSPBRIDGE_VERSION "0.3" -s32 dsp_debug; - -struct platform_device *omap_dspbridge_dev; -struct device *bridge; - -/* This is a test variable used by Bridge to test different sleep states */ -s32 dsp_test_sleepstate; - -static struct cdev bridge_cdev; - -static struct class *bridge_class; - -static u32 driver_context; -static s32 driver_major; -static char *base_img; -static s32 shm_size = 0x500000; /* 5 MB */ -static int tc_wordswapon; /* Default value is always false */ -#ifdef CONFIG_TIDSPBRIDGE_RECOVERY -#define REC_TIMEOUT 5000 /*recovery timeout in msecs */ -static atomic_t bridge_cref; /* number of bridge open handles */ -static struct workqueue_struct *bridge_rec_queue; -static struct work_struct bridge_recovery_work; -static DECLARE_COMPLETION(bridge_comp); -static DECLARE_COMPLETION(bridge_open_comp); -static bool recover; -#endif - -#ifdef CONFIG_PM -struct omap34_xx_bridge_suspend_data { - int suspended; - wait_queue_head_t suspend_wq; -}; - -static struct omap34_xx_bridge_suspend_data bridge_suspend_data; - -static int omap34_xxbridge_suspend_lockout(struct omap34_xx_bridge_suspend_data - *s, struct file *f) -{ - if ((s)->suspended) { - if ((f)->f_flags & O_NONBLOCK) - return -EPERM; - wait_event_interruptible((s)->suspend_wq, (s)->suspended == 0); - } - return 0; -} -#endif - -module_param(dsp_debug, int, 0); -MODULE_PARM_DESC(dsp_debug, "Wait after loading DSP image. default = false"); - -module_param(dsp_test_sleepstate, int, 0); -MODULE_PARM_DESC(dsp_test_sleepstate, "DSP Sleep state = 0"); - -module_param(base_img, charp, 0); -MODULE_PARM_DESC(base_img, "DSP base image, default = NULL"); - -module_param(shm_size, int, 0); -MODULE_PARM_DESC(shm_size, "shm size, default = 4 MB, minimum = 64 KB"); - -module_param(tc_wordswapon, int, 0); -MODULE_PARM_DESC(tc_wordswapon, "TC Word Swap Option. default = 0"); - -MODULE_AUTHOR("Texas Instruments"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DSPBRIDGE_VERSION); - -/* - * This function is called when an application opens handle to the - * bridge driver. - */ -static int bridge_open(struct inode *ip, struct file *filp) -{ - int status = 0; - struct process_context *pr_ctxt = NULL; - - /* - * Allocate a new process context and insert it into global - * process context list. - */ - -#ifdef CONFIG_TIDSPBRIDGE_RECOVERY - if (recover) { - if (filp->f_flags & O_NONBLOCK || - wait_for_completion_interruptible(&bridge_open_comp)) - return -EBUSY; - } -#endif - pr_ctxt = kzalloc(sizeof(struct process_context), GFP_KERNEL); - if (!pr_ctxt) - return -ENOMEM; - - pr_ctxt->res_state = PROC_RES_ALLOCATED; - spin_lock_init(&pr_ctxt->dmm_map_lock); - INIT_LIST_HEAD(&pr_ctxt->dmm_map_list); - spin_lock_init(&pr_ctxt->dmm_rsv_lock); - INIT_LIST_HEAD(&pr_ctxt->dmm_rsv_list); - - pr_ctxt->node_id = kzalloc(sizeof(struct idr), GFP_KERNEL); - if (!pr_ctxt->node_id) { - status = -ENOMEM; - goto err1; - } - - idr_init(pr_ctxt->node_id); - - pr_ctxt->stream_id = kzalloc(sizeof(struct idr), GFP_KERNEL); - if (!pr_ctxt->stream_id) { - status = -ENOMEM; - goto err2; - } - - idr_init(pr_ctxt->stream_id); - - filp->private_data = pr_ctxt; - -#ifdef CONFIG_TIDSPBRIDGE_RECOVERY - atomic_inc(&bridge_cref); -#endif - return 0; - -err2: - kfree(pr_ctxt->node_id); -err1: - kfree(pr_ctxt); - return status; -} - -/* - * This function is called when an application closes handle to the bridge - * driver. - */ -static int bridge_release(struct inode *ip, struct file *filp) -{ - int status = 0; - struct process_context *pr_ctxt; - - if (!filp->private_data) { - status = -EIO; - goto err; - } - - pr_ctxt = filp->private_data; - flush_signals(current); - drv_remove_all_resources(pr_ctxt); - proc_detach(pr_ctxt); - kfree(pr_ctxt->node_id); - kfree(pr_ctxt->stream_id); - kfree(pr_ctxt); - - filp->private_data = NULL; - -err: -#ifdef CONFIG_TIDSPBRIDGE_RECOVERY - if (!atomic_dec_return(&bridge_cref)) - complete(&bridge_comp); -#endif - return status; -} - -/* This function provides IO interface to the bridge driver. */ -static long bridge_ioctl(struct file *filp, unsigned int code, - unsigned long args) -{ - int status; - u32 retval = 0; - union trapped_args buf_in; - -#ifdef CONFIG_TIDSPBRIDGE_RECOVERY - if (recover) { - status = -EIO; - goto err; - } -#endif -#ifdef CONFIG_PM - status = omap34_xxbridge_suspend_lockout(&bridge_suspend_data, filp); - if (status != 0) - return status; -#endif - - if (!filp->private_data) { - status = -EIO; - goto err; - } - - status = copy_from_user(&buf_in, (union trapped_args *)args, - sizeof(union trapped_args)); - - if (!status) { - status = api_call_dev_ioctl(code, &buf_in, &retval, - filp->private_data); - - if (!status) { - status = retval; - } else { - dev_dbg(bridge, "%s: IOCTL Failed, code: 0x%x " - "status 0x%x\n", __func__, code, status); - status = -1; - } - - } - -err: - return status; -} - -/* This function maps kernel space memory to user space memory. */ -static int bridge_mmap(struct file *filp, struct vm_area_struct *vma) -{ - unsigned long base_pgoff; - int status; - struct omap_dsp_platform_data *pdata = - omap_dspbridge_dev->dev.platform_data; - - /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */ - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - - dev_dbg(bridge, "%s: vm filp %p start %lx end %lx page_prot %ulx " - "flags %lx\n", __func__, filp, - vma->vm_start, vma->vm_end, vma->vm_page_prot, - vma->vm_flags); - - /* - * vm_iomap_memory() expects vma->vm_pgoff to be expressed as an offset - * from the start of the physical memory pool, but we're called with - * a pfn (physical page number) stored there instead. - * - * To avoid duplicating lots of tricky overflow checking logic, - * temporarily convert vma->vm_pgoff to the offset vm_iomap_memory() - * expects, but restore the original value once the mapping has been - * created. - */ - base_pgoff = pdata->phys_mempool_base >> PAGE_SHIFT; - - if (vma->vm_pgoff < base_pgoff) - return -EINVAL; - - vma->vm_pgoff -= base_pgoff; - - status = vm_iomap_memory(vma, - pdata->phys_mempool_base, - pdata->phys_mempool_size); - - /* Restore the original value of vma->vm_pgoff */ - vma->vm_pgoff += base_pgoff; - - return status; -} - -static const struct file_operations bridge_fops = { - .open = bridge_open, - .release = bridge_release, - .unlocked_ioctl = bridge_ioctl, - .mmap = bridge_mmap, - .llseek = noop_llseek, -}; - -#ifdef CONFIG_PM -static u32 time_out = 1000; -#ifdef CONFIG_TIDSPBRIDGE_DVFS -s32 dsp_max_opps = VDD1_OPP5; -#endif - -/* Maximum Opps that can be requested by IVA */ -/*vdd1 rate table */ -#ifdef CONFIG_TIDSPBRIDGE_DVFS -const struct omap_opp vdd1_rate_table_bridge[] = { - {0, 0, 0}, - /*OPP1 */ - {S125M, VDD1_OPP1, 0}, - /*OPP2 */ - {S250M, VDD1_OPP2, 0}, - /*OPP3 */ - {S500M, VDD1_OPP3, 0}, - /*OPP4 */ - {S550M, VDD1_OPP4, 0}, - /*OPP5 */ - {S600M, VDD1_OPP5, 0}, -}; -#endif -#endif - -struct omap_dsp_platform_data *omap_dspbridge_pdata; - -u32 vdd1_dsp_freq[6][4] = { - {0, 0, 0, 0}, - /*OPP1 */ - {0, 90000, 0, 86000}, - /*OPP2 */ - {0, 180000, 80000, 170000}, - /*OPP3 */ - {0, 360000, 160000, 340000}, - /*OPP4 */ - {0, 396000, 325000, 376000}, - /*OPP5 */ - {0, 430000, 355000, 430000}, -}; - -#ifdef CONFIG_TIDSPBRIDGE_RECOVERY -static void bridge_recover(struct work_struct *work) -{ - struct dev_object *dev; - struct cfg_devnode *dev_node; - - if (atomic_read(&bridge_cref)) { - reinit_completion(&bridge_comp); - while (!wait_for_completion_timeout(&bridge_comp, - msecs_to_jiffies(REC_TIMEOUT))) - pr_info("%s:%d handle(s) still opened\n", - __func__, atomic_read(&bridge_cref)); - } - dev = dev_get_first(); - dev_get_dev_node(dev, &dev_node); - if (!dev_node || proc_auto_start(dev_node, dev)) - pr_err("DSP could not be restarted\n"); - recover = false; - complete_all(&bridge_open_comp); -} - -void bridge_recover_schedule(void) -{ - reinit_completion(&bridge_open_comp); - recover = true; - queue_work(bridge_rec_queue, &bridge_recovery_work); -} -#endif -#ifdef CONFIG_TIDSPBRIDGE_DVFS -static int dspbridge_scale_notification(struct notifier_block *op, - unsigned long val, void *ptr) -{ - struct omap_dsp_platform_data *pdata = - omap_dspbridge_dev->dev.platform_data; - - if (CPUFREQ_POSTCHANGE == val && pdata->dsp_get_opp) - pwr_pm_post_scale(PRCM_VDD1, pdata->dsp_get_opp()); - - return 0; -} - -static struct notifier_block iva_clk_notifier = { - .notifier_call = dspbridge_scale_notification, - NULL, -}; -#endif - -/** - * omap3_bridge_startup() - perform low lever initializations - * @pdev: pointer to platform device - * - * Initializes recovery, PM and DVFS required data, before calling - * clk and memory init routines. - */ -static int omap3_bridge_startup(struct platform_device *pdev) -{ - struct omap_dsp_platform_data *pdata = pdev->dev.platform_data; - struct drv_data *drv_datap = NULL; - u32 phys_membase, phys_memsize; - int err; - -#ifdef CONFIG_TIDSPBRIDGE_RECOVERY - bridge_rec_queue = create_workqueue("bridge_rec_queue"); - INIT_WORK(&bridge_recovery_work, bridge_recover); - reinit_completion(&bridge_comp); -#endif - -#ifdef CONFIG_PM - /* Initialize the wait queue */ - bridge_suspend_data.suspended = 0; - init_waitqueue_head(&bridge_suspend_data.suspend_wq); - -#ifdef CONFIG_TIDSPBRIDGE_DVFS - for (i = 0; i < 6; i++) - pdata->mpu_speed[i] = vdd1_rate_table_bridge[i].rate; - - err = cpufreq_register_notifier(&iva_clk_notifier, - CPUFREQ_TRANSITION_NOTIFIER); - if (err) - pr_err("%s: clk_notifier_register failed for iva2_ck\n", - __func__); -#endif -#endif - - dsp_clk_init(); - - drv_datap = kzalloc(sizeof(struct drv_data), GFP_KERNEL); - if (!drv_datap) { - err = -ENOMEM; - goto err1; - } - - drv_datap->shm_size = shm_size; - drv_datap->tc_wordswapon = tc_wordswapon; - - if (base_img) { - drv_datap->base_img = kstrdup(base_img, GFP_KERNEL); - if (!drv_datap->base_img) { - err = -ENOMEM; - goto err2; - } - } - - dev_set_drvdata(bridge, drv_datap); - - if (shm_size < 0x10000) { /* 64 KB */ - err = -EINVAL; - pr_err("%s: shm size must be at least 64 KB\n", __func__); - goto err3; - } - dev_dbg(bridge, "%s: requested shm_size = 0x%x\n", __func__, shm_size); - - phys_membase = pdata->phys_mempool_base; - phys_memsize = pdata->phys_mempool_size; - if (phys_membase > 0 && phys_memsize > 0) - mem_ext_phys_pool_init(phys_membase, phys_memsize); - - if (tc_wordswapon) - dev_dbg(bridge, "%s: TC Word Swap is enabled\n", __func__); - - driver_context = dsp_init(&err); - if (err) { - pr_err("DSP Bridge driver initialization failed\n"); - goto err4; - } - - return 0; - -err4: - mem_ext_phys_pool_release(); -err3: - kfree(drv_datap->base_img); -err2: - kfree(drv_datap); -err1: -#ifdef CONFIG_TIDSPBRIDGE_DVFS - cpufreq_unregister_notifier(&iva_clk_notifier, - CPUFREQ_TRANSITION_NOTIFIER); -#endif - dsp_clk_exit(); - - return err; -} - -static int omap34_xx_bridge_probe(struct platform_device *pdev) -{ - int err; - dev_t dev = 0; -#ifdef CONFIG_TIDSPBRIDGE_DVFS - int i = 0; -#endif - - omap_dspbridge_dev = pdev; - - /* Global bridge device */ - bridge = &omap_dspbridge_dev->dev; - - /* Bridge low level initializations */ - err = omap3_bridge_startup(pdev); - if (err) - goto err1; - - /* use 2.6 device model */ - err = alloc_chrdev_region(&dev, 0, 1, "DspBridge"); - if (err) { - pr_err("%s: Can't get major %d\n", __func__, driver_major); - goto err1; - } - - cdev_init(&bridge_cdev, &bridge_fops); - bridge_cdev.owner = THIS_MODULE; - - err = cdev_add(&bridge_cdev, dev, 1); - if (err) { - pr_err("%s: Failed to add bridge device\n", __func__); - goto err2; - } - - /* udev support */ - bridge_class = class_create(THIS_MODULE, "ti_bridge"); - if (IS_ERR(bridge_class)) { - pr_err("%s: Error creating bridge class\n", __func__); - err = PTR_ERR(bridge_class); - goto err3; - } - - driver_major = MAJOR(dev); - device_create(bridge_class, NULL, MKDEV(driver_major, 0), - NULL, "DspBridge"); - pr_info("DSP Bridge driver loaded\n"); - - return 0; - -err3: - cdev_del(&bridge_cdev); -err2: - unregister_chrdev_region(dev, 1); -err1: - return err; -} - -static int omap34_xx_bridge_remove(struct platform_device *pdev) -{ - dev_t devno; - int status = 0; - struct drv_data *drv_datap = dev_get_drvdata(bridge); - - /* Retrieve the Object handle from the driver data */ - if (!drv_datap || !drv_datap->drv_object) { - status = -ENODATA; - pr_err("%s: Failed to retrieve the object handle\n", __func__); - goto func_cont; - } - -#ifdef CONFIG_TIDSPBRIDGE_DVFS - if (cpufreq_unregister_notifier(&iva_clk_notifier, - CPUFREQ_TRANSITION_NOTIFIER)) - pr_err("%s: cpufreq_unregister_notifier failed for iva2_ck\n", - __func__); -#endif /* #ifdef CONFIG_TIDSPBRIDGE_DVFS */ - - if (driver_context) { - /* Put the DSP in reset state */ - dsp_deinit(driver_context); - driver_context = 0; - } - - kfree(drv_datap); - dev_set_drvdata(bridge, NULL); - -func_cont: - mem_ext_phys_pool_release(); - - dsp_clk_exit(); - - devno = MKDEV(driver_major, 0); - cdev_del(&bridge_cdev); - unregister_chrdev_region(devno, 1); - if (bridge_class) { - /* remove the device from sysfs */ - device_destroy(bridge_class, MKDEV(driver_major, 0)); - class_destroy(bridge_class); - - } - return status; -} - -#ifdef CONFIG_PM -static int bridge_suspend(struct platform_device *pdev, pm_message_t state) -{ - u32 status; - u32 command = PWR_EMERGENCYDEEPSLEEP; - - status = pwr_sleep_dsp(command, time_out); - if (status) - return -1; - - bridge_suspend_data.suspended = 1; - return 0; -} - -static int bridge_resume(struct platform_device *pdev) -{ - u32 status; - - status = pwr_wake_dsp(time_out); - if (status) - return -1; - - bridge_suspend_data.suspended = 0; - wake_up(&bridge_suspend_data.suspend_wq); - return 0; -} -#endif - -static struct platform_driver bridge_driver = { - .driver = { - .name = "omap-dsp", - }, - .probe = omap34_xx_bridge_probe, - .remove = omap34_xx_bridge_remove, -#ifdef CONFIG_PM - .suspend = bridge_suspend, - .resume = bridge_resume, -#endif -}; - -/* To remove all process resources before removing the process from the - * process context list */ -int drv_remove_all_resources(void *process_ctxt) -{ - int status = 0; - struct process_context *ctxt = (struct process_context *)process_ctxt; - - drv_remove_all_strm_res_elements(ctxt); - drv_remove_all_node_res_elements(ctxt); - drv_remove_all_dmm_res_elements(ctxt); - ctxt->res_state = PROC_RES_FREED; - return status; -} - -module_platform_driver(bridge_driver); |