static int __devexit omap34_xx_bridge_remove(struct platform_device *pdev) { dev_t devno; bool ret; int status = 0; bhandle hdrv_obj = NULL; status = cfg_get_object((u32 *) &hdrv_obj, REG_DRV_OBJECT); if (DSP_FAILED(status)) goto func_cont; #ifdef CONFIG_BRIDGE_DVFS if (cpufreq_unregister_notifier(&iva_clk_notifier, CPUFREQ_TRANSITION_NOTIFIER)) pr_err("%s: clk_notifier_unregister failed for iva2_ck\n", __func__); #endif /* #ifdef CONFIG_BRIDGE_DVFS */ if (driver_context) { /* Put the DSP in reset state */ ret = dsp_deinit(driver_context); driver_context = 0; DBC_ASSERT(ret == true); } #ifdef CONFIG_BRIDGE_DVFS clk_put(clk_handle); clk_handle = NULL; #endif /* #ifdef CONFIG_BRIDGE_DVFS */ func_cont: mem_ext_phys_pool_release(); services_exit(); bridge_destroy_sysfs(); 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 0; }
/* * ======== dsp_deinit ======== * Frees the resources allocated for bridge. */ bool dsp_deinit(u32 deviceContext) { bool ret = true; u32 device_node; struct mgr_object *mgr_obj = NULL; while ((device_node = drv_get_first_dev_extension()) != 0) { (void)dev_remove_device((struct cfg_devnode *)device_node); (void)drv_release_resources((u32) device_node, (struct drv_object *)deviceContext); } (void)drv_destroy((struct drv_object *)deviceContext); /* Get the Manager Object from Registry * MGR Destroy will unload the DCD dll */ if (DSP_SUCCEEDED(cfg_get_object((u32 *) &mgr_obj, REG_MGR_OBJECT))) (void)mgr_destroy(mgr_obj); wcd_exit(); return ret; }
/* * ======== dev_create_device ======== * Purpose: * Called by the operating system to load the PM Mini Driver for a * PM board (device). */ int dev_create_device(OUT struct dev_object **phDevObject, IN CONST char *pstrWMDFileName, struct cfg_devnode *dev_node_obj) { struct cfg_hostres *host_res; struct ldr_module *module_obj = NULL; struct bridge_drv_interface *drv_fxns = NULL; struct dev_object *dev_obj = NULL; struct chnl_mgrattrs mgr_attrs; struct io_attrs io_mgr_attrs; u32 num_windows; struct drv_object *hdrv_obj = NULL; int status = 0; DBC_REQUIRE(refs > 0); DBC_REQUIRE(phDevObject != NULL); DBC_REQUIRE(pstrWMDFileName != NULL); status = drv_request_bridge_res_dsp((void *)&host_res); if (DSP_FAILED(status)) dev_dbg(bridge, "%s: Failed to reserve bridge resources\n", __func__); /* Get the WMD interface functions */ bridge_drv_entry(&drv_fxns, pstrWMDFileName); if (DSP_FAILED(cfg_get_object((u32 *) &hdrv_obj, REG_DRV_OBJECT))) { /* don't propogate CFG errors from this PROC function */ status = -EPERM; } /* Create the device object, and pass a handle to the WMD for * storage. */ if (DSP_SUCCEEDED(status)) { DBC_ASSERT(drv_fxns); dev_obj = kzalloc(sizeof(struct dev_object), GFP_KERNEL); if (dev_obj) { /* Fill out the rest of the Dev Object structure: */ dev_obj->dev_node_obj = dev_node_obj; dev_obj->module_obj = module_obj; dev_obj->cod_mgr = NULL; dev_obj->hchnl_mgr = NULL; dev_obj->hdeh_mgr = NULL; dev_obj->lock_owner = NULL; dev_obj->word_size = DSPWORDSIZE; dev_obj->hdrv_obj = hdrv_obj; dev_obj->dev_type = DSP_UNIT; /* Store this WMD's interface functions, based on its * version. */ store_interface_fxns(drv_fxns, &dev_obj->wmd_interface); /* Call fxn_dev_create() to get the WMD's device * context handle. */ status = (dev_obj->wmd_interface.pfn_dev_create) (&dev_obj->hwmd_context, dev_obj, host_res); /* Assert bridge_dev_create()'s ensure clause: */ DBC_ASSERT(DSP_FAILED(status) || (dev_obj->hwmd_context != NULL)); } else { status = -ENOMEM; } } /* Attempt to create the COD manager for this device: */ if (DSP_SUCCEEDED(status)) status = init_cod_mgr(dev_obj); /* Attempt to create the channel manager for this device: */ if (DSP_SUCCEEDED(status)) { mgr_attrs.max_channels = CHNL_MAXCHANNELS; io_mgr_attrs.birq = host_res->birq_registers; io_mgr_attrs.irq_shared = (host_res->birq_attrib & CFG_IRQSHARED); io_mgr_attrs.word_size = DSPWORDSIZE; mgr_attrs.word_size = DSPWORDSIZE; num_windows = host_res->num_mem_windows; if (num_windows) { /* Assume last memory window is for CHNL */ io_mgr_attrs.shm_base = host_res->dw_mem_base[1] + host_res->dw_offset_for_monitor; io_mgr_attrs.usm_length = host_res->dw_mem_length[1] - host_res->dw_offset_for_monitor; } else { io_mgr_attrs.shm_base = 0; io_mgr_attrs.usm_length = 0; pr_err("%s: No memory reserved for shared structures\n", __func__); } status = chnl_create(&dev_obj->hchnl_mgr, dev_obj, &mgr_attrs); if (status == -ENOSYS) { /* It's OK for a device not to have a channel * manager: */ status = 0; } /* Create CMM mgr even if Msg Mgr not impl. */ status = cmm_create(&dev_obj->hcmm_mgr, (struct dev_object *)dev_obj, NULL); /* Only create IO manager if we have a channel manager */ if (DSP_SUCCEEDED(status) && dev_obj->hchnl_mgr) { status = io_create(&dev_obj->hio_mgr, dev_obj, &io_mgr_attrs); } /* Only create DEH manager if we have an IO manager */ if (DSP_SUCCEEDED(status)) { /* Instantiate the DEH module */ status = (*dev_obj->wmd_interface.pfn_deh_create) (&dev_obj->hdeh_mgr, dev_obj); } /* Create DMM mgr . */ status = dmm_create(&dev_obj->dmm_mgr, (struct dev_object *)dev_obj, NULL); } /* Add the new DEV_Object to the global list: */ if (DSP_SUCCEEDED(status)) { lst_init_elem(&dev_obj->link); status = drv_insert_dev_object(hdrv_obj, dev_obj); } /* Create the Processor List */ if (DSP_SUCCEEDED(status)) { dev_obj->proc_list = kzalloc(sizeof(struct lst_list), GFP_KERNEL); if (!(dev_obj->proc_list)) status = -EPERM; else INIT_LIST_HEAD(&dev_obj->proc_list->head); } /* If all went well, return a handle to the dev object; * else, cleanup and return NULL in the OUT parameter. */ if (DSP_SUCCEEDED(status)) { *phDevObject = dev_obj; } else { kfree(dev_obj->proc_list); if (dev_obj && dev_obj->cod_mgr) cod_delete(dev_obj->cod_mgr); if (dev_obj && dev_obj->dmm_mgr) dmm_destroy(dev_obj->dmm_mgr); kfree(dev_obj); *phDevObject = NULL; } DBC_ENSURE((DSP_SUCCEEDED(status) && *phDevObject) || (DSP_FAILED(status) && !*phDevObject)); return status; }