/* * usb module start/end */ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) { struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); struct usbhs_mod *mod = usbhs_mod_get_current(priv); struct device *dev = usbhs_priv_to_dev(priv); unsigned long flags; int ret = 0; /******************** spin lock ********************/ usbhs_lock(priv, flags); usbhsg_status_set(gpriv, status); if (!(usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD))) ret = -1; /* not ready */ usbhs_unlock(priv, flags); /******************** spin unlock ********************/ if (ret < 0) return 0; /* not ready is not error */ /* * enable interrupt and systems if ready */ dev_dbg(dev, "start gadget\n"); /* * pipe initialize and enable DCP */ usbhs_pipe_init(priv, usbhsg_queue_done, usbhsg_dma_map_ctrl); usbhs_fifo_init(priv); usbhsg_uep_init(gpriv); /* dcp init */ dcp->pipe = usbhs_dcp_malloc(priv); dcp->pipe->mod_private = dcp; /* * system config enble * - HI speed * - function * - usb module */ usbhs_sys_hispeed_ctrl(priv, 1); usbhs_sys_function_ctrl(priv, 1); usbhs_sys_usb_ctrl(priv, 1); /* * enable irq callback */ mod->irq_dev_state = usbhsg_irq_dev_state; mod->irq_ctrl_stage = usbhsg_irq_ctrl_stage; usbhs_irq_callback_update(priv, mod); return 0; }
/* * module start/stop */ static void usbhsh_pipe_init_for_host(struct usbhs_priv *priv) { struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); struct usbhs_pipe *pipe; struct renesas_usbhs_driver_pipe_config *pipe_configs = usbhs_get_dparam(priv, pipe_configs); int pipe_size = usbhs_get_dparam(priv, pipe_size); int old_type, dir_in, i; /* init all pipe */ old_type = USB_ENDPOINT_XFER_CONTROL; for (i = 0; i < pipe_size; i++) { /* * data "output" will be finished as soon as possible, * but there is no guaranty at data "input" case. * * "input" needs "standby" pipe. * So, "input" direction pipe > "output" direction pipe * is good idea. * * 1st USB_ENDPOINT_XFER_xxx will be output direction, * and the other will be input direction here. * * ex) * ... * USB_ENDPOINT_XFER_ISOC -> dir out * USB_ENDPOINT_XFER_ISOC -> dir in * USB_ENDPOINT_XFER_BULK -> dir out * USB_ENDPOINT_XFER_BULK -> dir in * USB_ENDPOINT_XFER_BULK -> dir in * ... */ dir_in = (pipe_configs[i].type == old_type); old_type = pipe_configs[i].type; if (USB_ENDPOINT_XFER_CONTROL == pipe_configs[i].type) { pipe = usbhs_dcp_malloc(priv); usbhsh_hpriv_to_dcp(hpriv) = pipe; } else { pipe = usbhs_pipe_malloc(priv, pipe_configs[i].type, dir_in); } pipe->mod_private = NULL; } }
/* * * usb_dcp_ops * */ static int usbhsg_dcp_enable(struct usbhsg_uep *uep) { struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); struct usbhs_pipe *pipe; /* ********* assume under spin lock ********* */ pipe = usbhs_dcp_malloc(priv); if (!pipe) return -EIO; uep->pipe = pipe; uep->pipe->mod_private = uep; INIT_LIST_HEAD(&uep->list); return 0; }