static int usbhsg_irq_ready(struct usbhs_priv *priv, struct usbhs_irq_state *irq_state) { struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); struct usbhsg_uep *uep; struct usbhs_pipe *pipe; struct device *dev = usbhsg_gpriv_to_dev(gpriv); int i, ret; if (!irq_state->brdysts) { dev_err(dev, "debug %s !!\n", __func__); return -EIO; } dev_dbg(dev, "irq ready [0x%04x]\n", irq_state->brdysts); /* * search interrupted "pipe" * not "uep". */ usbhs_for_each_pipe_with_dcp(pipe, priv, i) { if (!(irq_state->brdysts & (1 << i))) continue; uep = usbhsg_pipe_to_uep(pipe); ret = usbhsg_queue_handle(uep); if (ret < 0) dev_err(dev, "receive error %d : %d\n", i, ret); } return 0; }
/* * pullup control */ static int usbhsg_can_pullup(struct usbhs_priv *priv) { struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); return gpriv->driver && usbhsg_status_has(gpriv, USBHSG_STATUS_SOFT_CONNECT); }
/* * VBUS provided by the PHY */ static int usbhsm_phy_get_vbus(struct platform_device *pdev) { struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); return gpriv->vbus_active; }
/* * 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; }
/* * USB_TYPE handler */ static int usbhsg_recip_run_handle(struct usbhs_priv *priv, struct usbhsg_recip_handle *handler, struct usb_ctrlrequest *ctrl) { struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); struct device *dev = usbhsg_gpriv_to_dev(gpriv); struct usbhsg_uep *uep; struct usbhs_pipe *pipe; int recip = ctrl->bRequestType & USB_RECIP_MASK; int nth = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK; int ret; int (*func)(struct usbhs_priv *priv, struct usbhsg_uep *uep, struct usb_ctrlrequest *ctrl); char *msg; uep = usbhsg_gpriv_to_nth_uep(gpriv, nth); pipe = usbhsg_uep_to_pipe(uep); if (!pipe) { dev_err(dev, "wrong recip request\n"); ret = -EINVAL; goto usbhsg_recip_run_handle_end; } switch (recip) { case USB_RECIP_DEVICE: msg = "DEVICE"; func = handler->device; break; case USB_RECIP_INTERFACE: msg = "INTERFACE"; func = handler->interface; break; case USB_RECIP_ENDPOINT: msg = "ENDPOINT"; func = handler->endpoint; break; default: dev_warn(dev, "unsupported RECIP(%d)\n", recip); func = NULL; ret = -EINVAL; } if (func) { unsigned long flags; dev_dbg(dev, "%s (pipe %d :%s)\n", handler->name, nth, msg); /******************** spin lock ********************/ usbhs_lock(priv, flags); ret = func(priv, uep, ctrl); usbhs_unlock(priv, flags); /******************** spin unlock ******************/ } usbhsg_recip_run_handle_end: usbhs_pkt_start(pipe); return ret; }
/* * 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); spinlock_t *lock; unsigned long flags; /******************** spin lock ********************/ lock = usbhsg_trylock(gpriv, &flags); /* * enable interrupt and systems if ready */ usbhsg_status_set(gpriv, status); if (!(usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD))) goto usbhsg_try_start_unlock; dev_dbg(dev, "start gadget\n"); /* * pipe initialize and enable DCP */ usbhs_pipe_init(priv); usbhsg_uep_init(gpriv); usbhsg_dcp_enable(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; mod->irq_empty = usbhsg_irq_empty; mod->irq_ready = usbhsg_irq_ready; mod->irq_bempsts = 0; mod->irq_brdysts = 0; usbhs_irq_callback_update(priv, mod); usbhsg_try_start_unlock: usbhsg_unlock(lock, &flags); /******************** spin unlock ********************/ return 0; }
static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) { struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); struct usbhs_mod *mod = usbhs_mod_get_current(priv); struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); struct device *dev = usbhs_priv_to_dev(priv); spinlock_t *lock; unsigned long flags; /******************** spin lock ********************/ lock = usbhsg_trylock(gpriv, &flags); /* * disable interrupt and systems if 1st try */ usbhsg_status_clr(gpriv, status); if (!usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && !usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD)) goto usbhsg_try_stop_unlock; /* disable all irq */ mod->irq_dev_state = NULL; mod->irq_ctrl_stage = NULL; mod->irq_empty = NULL; mod->irq_ready = NULL; mod->irq_bempsts = 0; mod->irq_brdysts = 0; usbhs_irq_callback_update(priv, mod); usbhsg_dcp_disable(dcp); gpriv->gadget.speed = USB_SPEED_UNKNOWN; /* disable sys */ usbhs_sys_hispeed_ctrl(priv, 0); usbhs_sys_function_ctrl(priv, 0); usbhs_sys_usb_ctrl(priv, 0); usbhsg_unlock(lock, &flags); /******************** spin unlock ********************/ if (gpriv->driver && gpriv->driver->disconnect) gpriv->driver->disconnect(&gpriv->gadget); dev_dbg(dev, "stop gadget\n"); return 0; usbhsg_try_stop_unlock: usbhsg_unlock(lock, &flags); return 0; }
static int usbhsg_stop(struct usbhs_priv *priv) { struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); /* cable disconnect */ if (gpriv->driver && gpriv->driver->disconnect) gpriv->driver->disconnect(&gpriv->gadget); return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED); }
/* * USB_TYPE_STANDARD / clear feature functions */ static int usbhsg_recip_handler_std_control_done(struct usbhs_priv *priv, struct usbhsg_uep *uep, struct usb_ctrlrequest *ctrl) { struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(dcp); usbhs_dcp_control_transfer_done(pipe); return 0; }
/* * irq functions * * it will be called from usbhs_interrupt */ static int usbhsg_irq_dev_state(struct usbhs_priv *priv, struct usbhs_irq_state *irq_state) { struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); struct device *dev = usbhsg_gpriv_to_dev(gpriv); gpriv->gadget.speed = usbhs_status_get_usb_speed(irq_state); dev_dbg(dev, "state = %x : speed : %d\n", usbhs_status_get_device_state(irq_state), gpriv->gadget.speed); return 0; }
static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) { struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); struct usbhs_mod *mod = usbhs_mod_get_current(priv); struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); struct device *dev = usbhs_priv_to_dev(priv); unsigned long flags; int ret = 0; /******************** spin lock ********************/ usbhs_lock(priv, flags); usbhsg_status_clr(gpriv, status); if (!usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && !usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD)) ret = -1; /* already done */ usbhs_unlock(priv, flags); /******************** spin unlock ********************/ if (ret < 0) return 0; /* already done is not error */ /* * disable interrupt and systems if 1st try */ usbhs_fifo_quit(priv); /* disable all irq */ mod->irq_dev_state = NULL; mod->irq_ctrl_stage = NULL; usbhs_irq_callback_update(priv, mod); gpriv->gadget.speed = USB_SPEED_UNKNOWN; /* disable sys */ usbhs_sys_hispeed_ctrl(priv, 0); usbhs_sys_function_ctrl(priv, 0); usbhs_sys_usb_ctrl(priv, 0); usbhsg_pipe_disable(dcp); if (gpriv->driver && gpriv->driver->disconnect) gpriv->driver->disconnect(&gpriv->gadget); dev_dbg(dev, "stop gadget\n"); return 0; }
static int usbhsg_irq_ctrl_stage(struct usbhs_priv *priv, struct usbhs_irq_state *irq_state) { struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(dcp); struct device *dev = usbhsg_gpriv_to_dev(gpriv); struct usb_ctrlrequest ctrl; struct usbhsg_recip_handle *recip_handler = NULL; int stage = usbhs_status_get_ctrl_stage(irq_state); int ret = 0; dev_dbg(dev, "stage = %d\n", stage); /* * see Manual * * "Operation" * - "Interrupt Function" * - "Control Transfer Stage Transition Interrupt" * - Fig. "Control Transfer Stage Transitions" */ switch (stage) { case READ_DATA_STAGE: dcp->handler = &usbhsg_handler_send_ctrl; break; case WRITE_DATA_STAGE: dcp->handler = &usbhsg_handler_recv_ctrl; break; case NODATA_STATUS_STAGE: dcp->handler = &usbhsg_handler_ctrl_stage_end; break; default: return ret; } /* * get usb request */ usbhs_usbreq_get_val(priv, &ctrl); switch (ctrl.bRequestType & USB_TYPE_MASK) { case USB_TYPE_STANDARD: switch (ctrl.bRequest) { case USB_REQ_CLEAR_FEATURE: recip_handler = &req_clear_feature; break; } } /* * setup stage / run recip */ if (recip_handler) ret = usbhsg_recip_run_handle(priv, recip_handler, &ctrl); else ret = gpriv->driver->setup(&gpriv->gadget, &ctrl); if (ret < 0) usbhs_fifo_stall(pipe); return ret; }