static int usbhsh_stop(struct usbhs_priv *priv) { struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv); struct usbhs_mod *mod = usbhs_mod_get_current(priv); struct device *dev = usbhs_priv_to_dev(priv); /* * disable irq callback */ mod->irq_attch = NULL; mod->irq_dtch = NULL; mod->irq_sack = NULL; mod->irq_sign = NULL; usbhs_irq_callback_update(priv, mod); usb_remove_hcd(hcd); /* disable sys */ usbhs_sys_host_ctrl(priv, 0); dev_dbg(dev, "quit host\n"); return 0; }
/* * 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 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; }
int usbhs_mod_is_host(struct usbhs_priv *priv) { struct usbhs_mod *mod = usbhs_mod_get_current(priv); struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv); if (!mod) return -EINVAL; return info->mod[USBHS_HOST] == mod; }
/* * hotplug */ static void usbhsc_hotplug(struct usbhs_priv *priv) { struct platform_device *pdev = usbhs_priv_to_pdev(priv); struct usbhs_mod *mod = usbhs_mod_get_current(priv); int id; int enable; int ret; /* * get vbus status from platform */ enable = usbhs_platform_call(priv, get_vbus, pdev); /* * get id from platform */ id = usbhs_platform_call(priv, get_id, pdev); if (enable && !mod) { ret = usbhs_mod_change(priv, id); if (ret < 0) return; dev_dbg(&pdev->dev, "%s enable\n", __func__); /* power on */ if (usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) usbhsc_power_ctrl(priv, enable); /* bus init */ usbhsc_set_buswait(priv); usbhsc_bus_init(priv); /* module start */ usbhs_mod_call(priv, start, priv); } else if (!enable && mod) { dev_dbg(&pdev->dev, "%s disable\n", __func__); /* module stop */ usbhs_mod_call(priv, stop, priv); /* bus init */ usbhsc_bus_init(priv); /* power off */ if (usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) usbhsc_power_ctrl(priv, enable); usbhs_mod_change(priv, -1); /* reset phy for next connection */ usbhs_platform_call(priv, phy_reset, pdev); } }
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_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 usbhsc_suspend(struct device *dev) { struct usbhs_priv *priv = dev_get_drvdata(dev); struct usbhs_mod *mod = usbhs_mod_get_current(priv); if (mod) { usbhs_mod_call(priv, stop, priv); usbhs_mod_change(priv, -1); } if (mod || !usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) usbhsc_power_ctrl(priv, 0); return 0; }
static int usbhs_status_get_each_irq(struct usbhs_priv *priv, struct usbhs_irq_state *state) { struct usbhs_mod *mod = usbhs_mod_get_current(priv); u16 intenb0, intenb1; unsigned long flags; /******************** spin lock ********************/ usbhs_lock(priv, flags); state->intsts0 = usbhs_read(priv, INTSTS0); intenb0 = usbhs_read(priv, INTENB0); if (usbhs_mod_is_host(priv)) { state->intsts1 = usbhs_read(priv, INTSTS1); intenb1 = usbhs_read(priv, INTENB1); } else { state->intsts1 = intenb1 = 0; } /* mask */ if (mod) { state->brdysts = usbhs_read(priv, BRDYSTS); state->nrdysts = usbhs_read(priv, NRDYSTS); state->bempsts = usbhs_read(priv, BEMPSTS); state->bempsts &= mod->irq_bempsts; state->brdysts &= mod->irq_brdysts; } usbhs_unlock(priv, flags); /******************** spin unlock ******************/ /* * Check whether the irq enable registers and the irq status are set * when IRQF_SHARED is set. */ if (priv->irqflags & IRQF_SHARED) { if (!(intenb0 & state->intsts0) && !(intenb1 & state->intsts1) && !(state->bempsts) && !(state->brdysts)) return -EIO; } return 0; }
static void usbhs_status_get_each_irq(struct usbhs_priv *priv, struct usbhs_irq_state *state) { struct usbhs_mod *mod = usbhs_mod_get_current(priv); state->intsts0 = usbhs_read(priv, INTSTS0); state->intsts1 = usbhs_read(priv, INTSTS1); /* mask */ if (mod) { state->brdysts = usbhs_read(priv, BRDYSTS); state->nrdysts = usbhs_read(priv, NRDYSTS); state->bempsts = usbhs_read(priv, BEMPSTS); state->bempsts &= mod->irq_bempsts; state->brdysts &= mod->irq_brdysts; } }
static int usbhsh_start(struct usbhs_priv *priv) { struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv); struct usbhs_mod *mod = usbhs_mod_get_current(priv); struct device *dev = usbhs_priv_to_dev(priv); int ret; /* add hcd */ ret = usb_add_hcd(hcd, 0, 0); if (ret < 0) return 0; device_wakeup_enable(hcd->self.controller); /* * pipe initialize and enable DCP */ usbhs_fifo_init(priv); usbhs_pipe_init(priv, usbhsh_dma_map_ctrl); usbhsh_pipe_init_for_host(priv); /* * system config enble * - HI speed * - host * - usb module */ usbhs_sys_host_ctrl(priv, 1); /* * enable irq callback */ mod->irq_attch = usbhsh_irq_attch; mod->irq_dtch = usbhsh_irq_dtch; mod->irq_sack = usbhsh_irq_setup_ack; mod->irq_sign = usbhsh_irq_setup_err; usbhs_irq_callback_update(priv, mod); dev_dbg(dev, "start host\n"); return ret; }
/* * hotplug */ static void usbhsc_hotplug(struct usbhs_priv *priv) { struct platform_device *pdev = usbhs_priv_to_pdev(priv); struct usbhs_mod *mod = usbhs_mod_get_current(priv); int id; int enable; int cable; int ret; /* * get vbus status from platform */ enable = usbhs_platform_call(priv, get_vbus, pdev); /* * get id from platform */ id = usbhs_platform_call(priv, get_id, pdev); if (enable && !mod) { if (priv->edev) { cable = extcon_get_cable_state(priv->edev, "USB-HOST"); if ((cable > 0 && id != USBHS_HOST) || (!cable && id != USBHS_GADGET)) { dev_info(&pdev->dev, "USB cable plugged in doesn't match the selected role!\n"); return; } } ret = usbhs_mod_change(priv, id); if (ret < 0) return; dev_dbg(&pdev->dev, "%s enable\n", __func__); /* power on */ if (usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) usbhsc_power_ctrl(priv, enable); /* bus init */ usbhsc_set_buswait(priv); usbhsc_bus_init(priv); /* module start */ usbhs_mod_call(priv, start, priv); } else if (!enable && mod) { dev_dbg(&pdev->dev, "%s disable\n", __func__); /* module stop */ usbhs_mod_call(priv, stop, priv); /* bus init */ usbhsc_bus_init(priv); /* power off */ if (usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) usbhsc_power_ctrl(priv, enable); usbhs_mod_change(priv, -1); /* reset phy for next connection */ usbhs_platform_call(priv, phy_reset, pdev); } }