/*! * generic_cf_modexit() - module init * * This is called by the Linux kernel; when the module is being unloaded * if compiled as a module. This function is never called if the * driver is linked into the kernel. * * @param void * @return void */ static void generic_cf_modexit (void) { int i; otg_trace_invalidate_tag(GENERIC); for (i = 0; ; i++) { struct generic_config *config = generic_configs + i; BREAK_UNLESS(config->interface_names); //printk(KERN_INFO"%s: %s registered: %d\n", // __FUNCTION__, config->composite_driver.driver.name, config->registered); CONTINUE_UNLESS(config->registered); usbd_deregister_composite_function (&config->composite_driver); if (config->interface_list) LKFREE(config->interface_list); } if (generic_config.registered) usbd_deregister_composite_function (&generic_config.composite_driver); if (generic_config.interface_list) LKFREE(generic_config.interface_list); }
/*! arc_udc_init */ static struct arcotg_udc *arc_udc_init (struct otg_dev *otg_dev) { struct device *device = otg_dev_get_drvdata(otg_dev); struct platform_device *pdev = to_platform_device(device); struct fsl_usb2_platform_data *pdata = (struct fsl_usb2_platform_data*)pdev->dev.platform_data; struct otg_instance *otg = otg_dev->otg_instance; struct pcd_instance *pcd = otg_dev->pcd_instance; struct arcotg_udc *udc = NULL; int timeout; /* Setting up the udc structure */ THROW_UNLESS((udc = (struct arcotg_udc *) CKMALLOC(sizeof(struct arcotg_udc))), error); /* Allocate queue */ THROW_UNLESS((udc->ep_qh = (struct ep_queue_head *) KMALLOC_ALIGN( USB_MAX_PIPES * sizeof(struct ep_queue_head), GFP_KERNEL | GFP_DMA, 2 * 1024, (void **)&ep_qh_base)), error); THROW_UNLESS(ep_qh_base, error); THROW_UNLESS((udc->ep_dtd = (struct ep_td_struct *) CKMALLOC(USB_MAX_PIPES * sizeof(struct ep_td_struct))), error); /* Stop, reset and wait for the UDC to reset */ UOG_USBCMD &= ~USB_CMD_RUN_STOP; UOG_USBCMD |= USB_CMD_CTRL_RESET; timeout = 10000000; // XXX This needs to be fixed, should not need to resort to timeout while ((UOG_USBCMD & USB_CMD_CTRL_RESET) && --timeout) { continue; } if (timeout == 0) { printk(KERN_DEBUG "%s: TIMEOUT\n", __FUNCTION__); return NULL; } /* Setup UDC mode and disable lock out mode*/ UOG_USBMODE |= USB_MODE_CTRL_MODE_DEVICE | USB_MODE_SETUP_LOCK_OFF; UOG_EPLISTADDR = virt_to_phys(udc->ep_qh); UOG_EPLISTADDR &= USB_EP_LIST_ADDRESS_MASK; /* Setup transceiver type, N.B. this must be done in one assignment */ UOG_PORTSC1 = (UOG_PORTSC1 & ~PORTSCX_PHY_TYPE_SEL) | pdata->xcvr_type; #if !defined(CONFIG_OTG_HIGH_SPEED) UOG_PORTSC1 |= (0x01000000); #endif fsl_platform_set_vbus_power(pdata, 0); CATCH(error) { if (ep_qh_base) kfree(ep_qh_base); if (udc) { if (udc->ep_dtd) LKFREE(udc->ep_dtd); LKFREE(udc); } udc = NULL; } return udc; }
/*! arc_udc_init */ void arc_udc_release (void) { kfree(ep_qh_base); ep_qh_base = NULL; if (udc_controller) { if (udc_controller->ep_dtd) LKFREE(udc_controller->ep_dtd); LKFREE(udc_controller); udc_controller = NULL; } }
/*! otg_tasklet_init * Create otg task structure, create workqueue, initialize it. * @param name - otg_tasklet name * @param proc - otg_tasklet process * @param data - otg_taskle data, argument for proc * @param tag - otg_tasklet tag * @return initialized otg_tasklet instance pointer */ static inline struct otg_tasklet *otg_tasklet_init(char *name, otg_tasklet_proc_t proc, otg_tasklet_arg_t data, otg_tag_t tag) { struct otg_tasklet *tasklet; //TRACE_STRING(tag, "INIT: %s", name); //printk(KERN_INFO"%s: %s\n", __FUNCTION__, name); RETURN_NULL_UNLESS((tasklet = CKMALLOC(sizeof (struct otg_tasklet)))); tasklet->tag = tag; tasklet->name = name; tasklet->terminated = TRUE; tasklet->proc = proc; tasklet->data = data; #ifdef OTG_TASKLET_WORK INIT_WORK(&tasklet->work, otg_tasklet_run, tasklet); #else /* OTG_TASKLET_WORK */ tasklet_init(&tasklet->tasklet, otg_tasklet_run, (otg_tasklet_arg_t) tasklet); #endif /* OTG_TASKLET_WORK */ return tasklet; CATCH(error) { if (tasklet) LKFREE(tasklet); return NULL; } }
/*! otg_workitem_init * Create otg work structure, create workqueue, initialize it. * @param name - workitem name * @param proc - workitem handler * @param data - workitem data * @param tag - otg tag * @return otg_workitem instance pointer */ static inline struct otg_workitem *otg_workitem_init(char *name, otg_workitem_proc_t proc, otg_workitem_arg_t data, otg_tag_t tag) { struct otg_workitem *workitem; //TRACE_STRING(tag, "INIT: %s", name); //printk(KERN_INFO"%s: %s\n", __FUNCTION__, name); RETURN_NULL_UNLESS((workitem = CKMALLOC(sizeof (struct otg_workitem)))); workitem->data = data; workitem->tag = tag; workitem->name = name; workitem->proc = proc; //workitem->debug = TRUE; workitem->terminated = workitem->terminate = TRUE; INIT_WORK(&workitem->work, otg_workitem_run, workitem); return workitem; CATCH(error) { printk(KERN_INFO"%s: ERROR\n", __FUNCTION__); if (workitem) LKFREE(workitem); return NULL; } }
/*! otg_workitem_exit * Terminate and wait for otg work. * @param workitem - workitem pointer */ static void inline otg_workitem_exit(struct otg_workitem *workitem) { //TRACE_STRING(workitem->tag, "EXIT: %s", workitem->name); if (workitem->debug) printk(KERN_INFO"%s: %s terminating\n", __FUNCTION__, workitem->name); while (!workitem->terminated) { otg_sleep( 1 ); } if (workitem->debug) printk(KERN_INFO"%s: %s terminated\n", __FUNCTION__, workitem->name); LKFREE(workitem); }
/*! otg_tasklet_exit * Terminate and wait for otg task. * @param tasklet - otg_tasklet instance pointer */ static void inline otg_tasklet_exit(struct otg_tasklet *tasklet) { //TRACE_STRING(tag, "EXIT: %s", name); if (tasklet->debug) printk(KERN_INFO"%s: %s\n", __FUNCTION__, tasklet->name); #ifdef OTG_TASKLET_WORK while (!tasklet->terminated) { if (tasklet->debug) printk(KERN_INFO"%s: SLEEPING\n", __FUNCTION__); otg_sleep( 1 ); if (tasklet->debug) printk(KERN_INFO"%s: RUNNING\n", __FUNCTION__); } #else /* OTG_TASKLET_WORK */ tasklet_kill(&tasklet->tasklet); #endif /* OTG_TASKLET_WORK */ LKFREE(tasklet); }
/*! otg_task_exit * Terminate and wait for otg task. * @param task - otg_task instance pointer */ void otg_task_exit(struct otg_task *task) { TRACE_STRING(task->tag, "EXIT: %s", task->name); if (task->debug) printk(KERN_INFO"%s: %s\n", __FUNCTION__, task->name); #if defined(OTG_TASK_WORK) while (!task->terminated) { otg_sleep( 1 ); } #else /* defined(OTG_TASK_WORK) */ /* signal termination */ task->terminate = TRUE; otg_up_work(task); otg_down_admin(task); /* destroy workqueue */ flush_workqueue(task->work_queue); destroy_workqueue(task->work_queue); #endif /* defined(OTG_TASK_WORK) */ LKFREE(task); }
/*! otg_task_init *@brief Create otg task structure, create workqueue, initialize it. *@param name - name of task or workqueue *@param proc - handler *@param data - parameter pointer for handler *@param tag- *@return initialized otg_task instance pointer */ struct otg_task *otg_task_init2(char *name, otg_task_proc_t proc, otg_task_arg_t data, otg_tag_t tag) { struct otg_task *task; //TRACE_STRING(tag, "INIT: %s", name); RETURN_NULL_UNLESS((task = CKMALLOC(sizeof (struct otg_task)))); task->tag = tag; task->data = data; task->name = name; task->proc = proc; #if defined(OTG_TASK_WORK) task->terminated = task->terminate = TRUE; #else /* defined(OTG_TASK_WORK) */ task->terminated = task->terminate = FALSE; #if defined(LINUX26) THROW_UNLESS((task->work_queue = create_singlethread_workqueue(name)), error); #else /* LINUX26 */ THROW_UNLESS((task->work_queue = create_workqueue(name)), error); #endif /* LINUX26 */ init_MUTEX_LOCKED(&task->admin_sem); init_MUTEX_LOCKED(&task->work_sem); #endif /* defined(OTG_TASK_WORK) */ INIT_WORK(&task->work, otg_task_proc, task); return task; CATCH(error) { printk(KERN_INFO"%s: ERROR\n", __FUNCTION__); if (task) LKFREE(task); return NULL; } }