/* blocking notifier support */ int musb_notifier_call(struct notifier_block *nb, unsigned long event, void *unused) { struct musb *musb = container_of(nb, struct musb, nb); struct device *dev = musb->controller; struct musb_hdrc_platform_data *pdata = dev->platform_data; struct omap_musb_board_data *data = pdata->board_data; static int hostmode; u32 val; switch (event) { case USB_EVENT_ID: DBG(1, "ID GND\n"); /* configure musb into smartidle with wakeup enabled * smart standby mode. */ musb_writel(musb->mregs, OTG_FORCESTDBY, 0); val = musb_readl(musb->mregs, OTG_SYSCONFIG); if (cpu_is_omap44xx()) val |= SMARTIDLEWKUP | SMARTSTDBY | ENABLEWAKEUP; else val |= SMARTIDLE | SMARTSTDBY | ENABLEWAKEUP; musb_writel(musb->mregs, OTG_SYSCONFIG, val); if (data->interface_type == MUSB_INTERFACE_UTMI) { otg_init(musb->xceiv); hostmode = 1; musb_enable_vbus(musb); } val = __raw_readl(phymux_base + USBA0_OTG_CE_PAD1_USBA0_OTG_DP); val |= DP_WAKEUPENABLE; __raw_writel(val, phymux_base + USBA0_OTG_CE_PAD1_USBA0_OTG_DP); break; case USB_EVENT_VBUS: DBG(1, "VBUS Connect\n"); /* configure musb into smartidle with wakeup enabled * smart standby mode. */ musb_writel(musb->mregs, OTG_FORCESTDBY, 0); val = musb_readl(musb->mregs, OTG_SYSCONFIG); if (cpu_is_omap44xx()) val |= SMARTIDLEWKUP | SMARTSTDBY | ENABLEWAKEUP; else val |= SMARTIDLE | SMARTSTDBY | ENABLEWAKEUP; musb_writel(musb->mregs, OTG_SYSCONFIG, val); if (data->interface_type == MUSB_INTERFACE_UTMI) { otg_init(musb->xceiv); if (!hostmode) { /* Enable VBUS Valid, AValid. Clear SESSEND.*/ __raw_writel(IDDIG | AVALID | VBUSVALID, ctrl_base + USBOTGHS_CONTROL); } } break; case USB_EVENT_NONE: DBG(1, "VBUS Disconnect\n"); if (data->interface_type == MUSB_INTERFACE_UTMI) { /* enable this clock because in suspend interrupt * handler phy clocks are disabled. If phy clocks are * not enabled then DISCONNECT interrupt will not be * reached to mentor */ otg_set_clk(musb->xceiv, 1); __raw_writel(SESSEND | IDDIG, ctrl_base + USBOTGHS_CONTROL); if (musb->xceiv->set_vbus) otg_set_vbus(musb->xceiv, 0); otg_shutdown(musb->xceiv); } hostmode = 0; /* configure in force idle/ standby */ musb_writel(musb->mregs, OTG_FORCESTDBY, 1); val = musb_readl(musb->mregs, OTG_SYSCONFIG); val &= ~(SMARTIDLEWKUP | SMARTSTDBY | ENABLEWAKEUP); val |= FORCEIDLE | FORCESTDBY; musb_writel(musb->mregs, OTG_SYSCONFIG, val); val = __raw_readl(phymux_base + USBA0_OTG_CE_PAD1_USBA0_OTG_DP); val &= ~DP_WAKEUPENABLE; __raw_writel(val, phymux_base + USBA0_OTG_CE_PAD1_USBA0_OTG_DP); break; default: DBG(1, "ID float\n"); return NOTIFY_DONE; } return NOTIFY_OK; }
/* blocking notifier support */ int musb_notifier_call(struct notifier_block *nb, unsigned long event, void *unused) { struct musb *musb = container_of(nb, struct musb, nb); struct device *dev = musb->controller; struct musb_hdrc_platform_data *pdata = dev->platform_data; static int hostmode; switch (event) { case USB_EVENT_ID: DBG(1, "ID GND\n"); musb->is_active = 1; if (omap_readl(0x4A002300)&0x1) { omap_writel(0x0, 0x4A002300); mdelay(500); } hostmode = 1; musb_enable_vbus(musb); break; case USB_EVENT_VBUS: DBG(1, "VBUS Connect\n"); wake_lock(&usb_lock); musb->is_active = 1; if (omap_readl(0x4A002300)&0x1) { omap_writel(0x0, 0x4A002300); mdelay(400); } /* hold the L3 constraint as there was performance drop with * ondemand governor */ if (pdata->set_min_bus_tput) pdata->set_min_bus_tput(musb->controller, OCP_INITIATOR_AGENT, (200*1000*4)); if (!hostmode) { /* Enable VBUS Valid, BValid, AValid. Clear SESSEND.*/ omap_writel(0x00000015, 0x4A00233C); } break; case USB_EVENT_NONE: DBG(1, "VBUS Disconnect\n"); omap_writel(0x00000018, 0x4A00233C); if (musb->xceiv->set_vbus) otg_set_vbus(musb->xceiv, 0); /* put the phy in powerdown mode*/ omap_writel(0x1, 0x4A002300); hostmode = 0; wake_unlock(&usb_lock); /* Release L3 constraint */ if (pdata->set_min_bus_tput) pdata->set_min_bus_tput(musb->controller, OCP_INITIATOR_AGENT, -1); break; default: DBG(1, "ID float\n"); return NOTIFY_DONE; } return NOTIFY_OK; }