static int davinci_musb_exit(struct musb *musb) { if (is_host_enabled(musb)) del_timer_sync(&otg_workaround); if (cpu_is_davinci_dm355()) { u32 deepsleep = __raw_readl(DM355_DEEPSLEEP); deepsleep &= ~DRVVBUS_FORCE; deepsleep |= DRVVBUS_OVERRIDE; __raw_writel(deepsleep, DM355_DEEPSLEEP); } davinci_musb_source_power(musb, 0 , 1); if (is_host_enabled(musb) && musb->xceiv->otg->default_a) { int maxdelay = 30; u8 devctl, warn = 0; do { devctl = musb_readb(musb->mregs, MUSB_DEVCTL); if (!(devctl & MUSB_DEVCTL_VBUS)) break; if ((devctl & MUSB_DEVCTL_VBUS) != warn) { warn = devctl & MUSB_DEVCTL_VBUS; dev_dbg(musb->controller, "VBUS %d\n", warn >> MUSB_DEVCTL_VBUS_SHIFT); } msleep(1000); maxdelay--; } while (maxdelay > 0);
int musb_platform_exit(struct musb *musb) { if (is_host_enabled(musb)) del_timer_sync(&otg_workaround); davinci_source_power(musb, 0 /*off*/, 1); /* delay, to avoid problems with module reload */ if (is_host_enabled(musb) && musb->xceiv.default_a) { int maxdelay = 30; u8 devctl, warn = 0; /* if there's no peripheral connected, this can take a * long time to fall, especially on EVM with huge C133. */ do { devctl = musb_readb(musb->mregs, MUSB_DEVCTL); if (!(devctl & MUSB_DEVCTL_VBUS)) break; if ((devctl & MUSB_DEVCTL_VBUS) != warn) { warn = devctl & MUSB_DEVCTL_VBUS; DBG(1, "VBUS %d\n", warn >> MUSB_DEVCTL_VBUS_SHIFT); } msleep(1000); maxdelay--; } while (maxdelay > 0);
static int sunxi_musb_enable(struct musb *musb) { int ret; pr_debug("%s():\n", __func__); musb_ep_select(musb->mregs, 0); musb_writeb(musb->mregs, MUSB_FADDR, 0); if (enabled) return 0; /* select PIO mode */ musb_writeb(musb->mregs, USBC_REG_o_VEND0, 0); if (is_host_enabled(musb)) { ret = sunxi_usb_phy_vbus_detect(0); if (ret == 1) { printf("A charger is plugged into the OTG: "); return -ENODEV; } ret = sunxi_usb_phy_id_detect(0); if (ret == 1) { printf("No host cable detected: "); return -ENODEV; } sunxi_usb_phy_power_on(0); /* port power on */ } USBC_ForceVbusValidToHigh(musb->mregs); enabled = true; return 0; }
static int sunxi_musb_init(struct musb *musb) { int err; pr_debug("%s():\n", __func__); err = sunxi_usbc_request_resources(0); if (err) return err; musb->isr = sunxi_musb_interrupt; sunxi_usbc_enable(0); USBC_ConfigFIFO_Base(); USBC_EnableDpDmPullUp(musb->mregs); USBC_EnableIdPullUp(musb->mregs); if (is_host_enabled(musb)) { /* Host mode */ USBC_ForceIdToLow(musb->mregs); USBC_ForceVbusValidToHigh(musb->mregs); } else { /* Peripheral mode */ USBC_ForceIdToHigh(musb->mregs); USBC_ForceVbusValidDisable(musb->mregs); } return 0; }
int __init musb_platform_init(struct musb *musb) { struct otg_transceiver *x = otg_get_transceiver(); u32 l; #if defined(CONFIG_ARCH_OMAP2430) omap_cfg_reg(AE5_2430_USB0HS_STP); #endif /* Reset controller */ if (musb->set_clock) musb->set_clock(musb->clock, 1); else clk_enable(musb->clock); l = omap_readl(OTG_SYSCONFIG); l |= SOFTRST; omap_writel(l, OTG_SYSCONFIG); while (!(RESETDONE & omap_readl(OTG_SYSSTATUS))) cpu_relax(); musb->xceiv = *x; musb_platform_resume(musb); l = omap_readl(OTG_SYSCONFIG); l &= ~ENABLEWAKEUP; /* disable wakeup */ l &= ~NOSTDBY; /* remove possible nostdby */ l |= SMARTSTDBY; /* enable smart standby */ l &= ~AUTOIDLE; /* disable auto idle */ l &= ~NOIDLE; /* remove possible noidle */ l |= SMARTIDLE; /* enable smart idle */ /* * MUSB AUTOIDLE don't work in 3430. * Workaround by Richard Woodruff/TI */ if (!cpu_is_omap3430()) l |= AUTOIDLE; /* enable auto idle */ omap_writel(l, OTG_SYSCONFIG); l = omap_readl(OTG_INTERFSEL); l |= ULPI_12PIN; omap_writel(l, OTG_INTERFSEL); pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, " "sysstatus 0x%x, intrfsel 0x%x, simenable 0x%x\n", omap_readl(OTG_REVISION), omap_readl(OTG_SYSCONFIG), omap_readl(OTG_SYSSTATUS), omap_readl(OTG_INTERFSEL), omap_readl(OTG_SIMENABLE)); omap_vbus_power(musb, musb->board_mode == MUSB_HOST, 1); if (is_host_enabled(musb)) musb->board_set_vbus = omap_set_vbus; if (!musb->xceiv.set_power && is_peripheral_enabled(musb)) musb->xceiv.set_power = omap_set_power; musb->a_wait_bcon = MUSB_TIMEOUT_A_WAIT_BCON; setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); return 0; }
static int sunxi_musb_init(struct musb *musb) { struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; pr_debug("%s():\n", __func__); musb->isr = sunxi_musb_interrupt; setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0); #ifdef CONFIG_SUNXI_GEN_SUN6I setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); #endif sunxi_usb_phy_init(0); USBC_ConfigFIFO_Base(); USBC_EnableDpDmPullUp(musb->mregs); USBC_EnableIdPullUp(musb->mregs); if (is_host_enabled(musb)) { /* Host mode */ USBC_ForceIdToLow(musb->mregs); } else { /* Peripheral mode */ USBC_ForceIdToHigh(musb->mregs); } USBC_ForceVbusValidToHigh(musb->mregs); return 0; }
int __init musb_platform_init(struct musb *musb) { int err; #ifndef CONFIG_MT6575T_FPGA if (is_host_enabled(musb)) { #ifdef CONFIG_USB_MTK_HDRC_HCD musb->board_set_vbus = mtk_set_vbus; mt_set_gpio_mode(GPIO_OTG_DRVVBUS_PIN,GPIO_OTG_DRVVBUS_PIN_M_GPIO);//should set GPIO2 as gpio mode. mt_set_gpio_dir(GPIO_OTG_DRVVBUS_PIN,GPIO_DIR_OUT); mt_get_gpio_pull_enable(GPIO_OTG_DRVVBUS_PIN); mt_set_gpio_pull_select(GPIO_OTG_DRVVBUS_PIN,GPIO_PULL_UP); #endif } #endif musb->nIrq = MT_USB0_IRQ_ID; musb->dma_irq= (int)SHARE_IRQ; musb->fifo_cfg = fifo_cfg; musb->fifo_cfg_size = ARRAY_SIZE(fifo_cfg); musb->fifo_cfg_host = fifo_cfg_host; musb->fifo_cfg_host_size = ARRAY_SIZE(fifo_cfg_host); mtk_musb->power = FALSE; mtk_musb->is_host = FALSE; mtk_musb->fifo_size = 8*1024; musb_platform_enable(musb); musb->isr = mt_usb_interrupt; musb_writel(musb->mregs,MUSB_HSDMA_INTR,0xff | (0xff << DMA_INTR_UNMASK_SET_OFFSET)); DBG(2,"musb platform init %x\n",musb_readl(musb->mregs,MUSB_HSDMA_INTR)); musb_writel(musb->mregs,USB_L1INTM,TX_INT_STATUS | RX_INT_STATUS | USBCOM_INT_STATUS | DMA_INT_STATUS); err = device_create_file(musb->controller,&dev_attr_cmode); return 0; }
int __init musb_platform_init(struct musb *musb, void *board_data) { u32 l; struct omap_musb_board_data *data = board_data; /* We require some kind of external transceiver, hooked * up through ULPI. TWL4030-family PMICs include one, * which needs a driver, drivers aren't always needed. */ musb->xceiv = otg_get_transceiver(); if (!musb->xceiv) { pr_err("HS USB OTG: no transceiver configured\n"); return -ENODEV; } musb_platform_resume(musb); l = musb_readl(musb->mregs, OTG_SYSCONFIG); l &= ~ENABLEWAKEUP; /* disable wakeup */ l &= ~NOSTDBY; /* remove possible nostdby */ l |= SMARTSTDBY; /* enable smart standby */ l &= ~AUTOIDLE; /* disable auto idle */ l &= ~NOIDLE; /* remove possible noidle */ l |= SMARTIDLE; /* enable smart idle */ /* * MUSB AUTOIDLE don't work in 3430. * Workaround by Richard Woodruff/TI */ if (!cpu_is_omap3430()) l |= AUTOIDLE; /* enable auto idle */ musb_writel(musb->mregs, OTG_SYSCONFIG, l); l = musb_readl(musb->mregs, OTG_INTERFSEL); if (data->interface_type == MUSB_INTERFACE_UTMI) { /* OMAP4 uses Internal PHY GS70 which uses UTMI interface */ l &= ~ULPI_12PIN; /* Disable ULPI */ l |= UTMI_8BIT; /* Enable UTMI */ } else { l |= ULPI_12PIN; } musb_writel(musb->mregs, OTG_INTERFSEL, l); pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, " "sysstatus 0x%x, intrfsel 0x%x, simenable 0x%x\n", musb_readl(musb->mregs, OTG_REVISION), musb_readl(musb->mregs, OTG_SYSCONFIG), musb_readl(musb->mregs, OTG_SYSSTATUS), musb_readl(musb->mregs, OTG_INTERFSEL), musb_readl(musb->mregs, OTG_SIMENABLE)); if (is_host_enabled(musb)) musb->board_set_vbus = omap_set_vbus; setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); return 0; }
int __init musb_platform_init(struct musb *musb) { struct otg_transceiver *x = otg_get_transceiver(); u32 l; u8 val; #if defined(CONFIG_ARCH_OMAP2430) omap_cfg_reg(AE5_2430_USB0HS_STP); #endif if (!x) { pr_err("omap: musb: null transceiver found\n"); return -ENODEV; } musb->xceiv = *x; musb_platform_resume(musb); l = omap_readl(OTG_SYSCONFIG); l &= ~ENABLEWAKEUP; /* disable wakeup */ l &= ~NOSTDBY; /* remove possible nostdby */ l |= SMARTSTDBY; /* enable smart standby */ l &= ~AUTOIDLE; /* disable auto idle */ l &= ~NOIDLE; /* remove possible noidle */ l |= SMARTIDLE; /* enable smart idle */ l |= AUTOIDLE; /* enable auto idle */ omap_writel(l, OTG_SYSCONFIG); l = omap_readl(OTG_INTERFSEL); l |= ULPI_12PIN; omap_writel(l, OTG_INTERFSEL); #ifdef CONFIG_MACH_OMAP3EVM /* Program PHY to use external Vbus supply on new OMAP3EVM */ if (get_omap3evm_board_rev() >= OMAP3EVM_BOARD_GEN_2) { val = musb_readb(musb->mregs, MUSB_ULPI_BUSCONTROL); val |= ULPI_USE_EXTVBUS; musb_writeb(musb->mregs, MUSB_ULPI_BUSCONTROL, val); } #endif pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, " "sysstatus 0x%x, intrfsel 0x%x, simenable 0x%x\n", omap_readl(OTG_REVISION), omap_readl(OTG_SYSCONFIG), omap_readl(OTG_SYSSTATUS), omap_readl(OTG_INTERFSEL), omap_readl(OTG_SIMENABLE)); omap_vbus_power(musb, musb->board_mode == MUSB_HOST, 1); if (is_host_enabled(musb)) musb->board_set_vbus = omap_set_vbus; if (is_peripheral_enabled(musb)) musb->xceiv.set_power = omap_set_power; musb->a_wait_bcon = MUSB_TIMEOUT_A_WAIT_BCON; setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); return 0; }
int __init musb_platform_init(struct musb *musb) { u32 l; #if defined(CONFIG_ARCH_OMAP2430) omap_cfg_reg(AE5_2430_USB0HS_STP); #endif /* We require some kind of external transceiver, hooked * up through ULPI. TWL4030-family PMICs include one, * which needs a driver, drivers aren't always needed. */ musb->xceiv = otg_get_transceiver(); if (!musb->xceiv) { pr_err("HS USB OTG: no transceiver configured\n"); return -ENODEV; } musb_platform_resume(musb); l = musb_readl(musb->mregs, OTG_SYSCONFIG); l &= ~ENABLEWAKEUP; /* disable wakeup */ l &= ~NOSTDBY; /* remove possible nostdby */ l |= SMARTSTDBY; /* enable smart standby */ l &= ~AUTOIDLE; /* disable auto idle */ l &= ~NOIDLE; /* remove possible noidle */ l |= SMARTIDLE; /* enable smart idle */ /* * MUSB AUTOIDLE don't work in 3430. * Workaround by Richard Woodruff/TI */ if (!cpu_is_omap3430()) l |= AUTOIDLE; /* enable auto idle */ musb_writel(musb->mregs, OTG_SYSCONFIG, l); l = musb_readl(musb->mregs, OTG_INTERFSEL); l |= ULPI_12PIN; musb_writel(musb->mregs, OTG_INTERFSEL, l); pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, " "sysstatus 0x%x, intrfsel 0x%x, simenable 0x%x\n", musb_readl(musb->mregs, OTG_REVISION), musb_readl(musb->mregs, OTG_SYSCONFIG), musb_readl(musb->mregs, OTG_SYSSTATUS), musb_readl(musb->mregs, OTG_INTERFSEL), musb_readl(musb->mregs, OTG_SIMENABLE)); omap_vbus_power(musb, musb->board_mode == MUSB_HOST, 1); if (is_host_enabled(musb)) musb->board_set_vbus = omap_set_vbus; setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); return 0; }
int __init musb_platform_init(struct musb *musb) { struct otg_transceiver xceiv; void __iomem *tibase = musb->ctrl_base; u32 revision; musb->mregs += DAVINCI_BASE_OFFSET; #if 0 /* REVISIT there's something odd about clocking, this * didn't appear do the job ... */ musb->clock = clk_get(pDevice, "usb"); if (IS_ERR(musb->clock)) return PTR_ERR(musb->clock); status = clk_enable(musb->clock); if (status < 0) return -ENODEV; #endif memset(&xceiv, 0, sizeof(xceiv)); xceiv.label = "davinci"; xceiv.dev = musb->controller; otg_set_transceiver(&xceiv); musb->xceiv = &xceiv; /* returns zero if e.g. not clocked */ revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG); if (revision == 0) return -ENODEV; if (is_host_enabled(musb)) setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); musb->board_set_vbus = davinci_set_vbus; davinci_source_power(musb, 0, 1); /* reset the controller */ musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1); /* start the on-chip PHY and its PLL */ phy_on(); msleep(5); /* NOTE: irqs are in mixed mode, not bypass to pure-musb */ pr_debug("DaVinci OTG revision %08x phy %03x control %02x\n", revision, __raw_readl((void __force __iomem *) IO_ADDRESS(USBPHY_CTL_PADDR)), musb_readb(tibase, DAVINCI_USB_CTRL_REG)); musb->isr = davinci_interrupt; musb->suspendm = true; return 0; }
static int da8xx_musb_exit(struct musb *musb) { if (is_host_enabled(musb)) del_timer_sync(&otg_workaround); phy_off(); usb_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); return 0; }
static void sunxi_musb_enable(struct musb *musb) { pr_debug("%s():\n", __func__); /* select PIO mode */ musb_writeb(musb->mregs, USBC_REG_o_VEND0, 0); if (is_host_enabled(musb)) { /* port power on */ sunxi_usbc_vbus_enable(0); } }
static void sunxi_musb_disable(struct musb *musb) { pr_debug("%s():\n", __func__); if (!enabled) return; if (is_host_enabled(musb)) sunxi_usb_phy_power_off(0); /* port power off */ USBC_ForceVbusValidToLow(musb->mregs); mdelay(200); /* Wait for the current session to timeout */ enabled = false; }
static int davinci_musb_exit(struct musb *musb) { if (is_host_enabled(musb)) del_timer_sync(&otg_workaround); /* force VBUS off */ if (cpu_is_davinci_dm355()) { u32 deepsleep = __raw_readl(DM355_DEEPSLEEP); deepsleep &= ~DRVVBUS_FORCE; deepsleep |= DRVVBUS_OVERRIDE; __raw_writel(deepsleep, DM355_DEEPSLEEP); } davinci_musb_source_power(musb, 0 /*off*/, 1); /* delay, to avoid problems with module reload */ if (is_host_enabled(musb) && musb->xceiv->default_a) { int maxdelay = 30; u8 devctl, warn = 0; /* if there's no peripheral connected, this can take a * long time to fall, especially on EVM with huge C133. */ do { devctl = musb_readb(musb->mregs, MUSB_DEVCTL); if (!(devctl & MUSB_DEVCTL_VBUS)) break; if ((devctl & MUSB_DEVCTL_VBUS) != warn) { warn = devctl & MUSB_DEVCTL_VBUS; DBG(1, "VBUS %d\n", warn >> MUSB_DEVCTL_VBUS_SHIFT); } msleep(1000); maxdelay--; } while (maxdelay > 0);
int __init musb_platform_init(struct musb *musb) { u32 l; #if defined(CONFIG_ARCH_OMAP2430) omap_cfg_reg(AE5_2430_USB0HS_STP); #endif musb->xceiv = otg_get_transceiver(); if (!musb->xceiv) { pr_err("HS USB OTG: no transceiver configured\n"); return -ENODEV; } musb_platform_resume(musb); l = omap_readl(OTG_SYSCONFIG); l &= ~ENABLEWAKEUP; l &= ~NOSTDBY; l |= SMARTSTDBY; l &= ~AUTOIDLE; l &= ~NOIDLE; l |= SMARTIDLE; if (!cpu_is_omap3430()) l |= AUTOIDLE; omap_writel(l, OTG_SYSCONFIG); l = omap_readl(OTG_INTERFSEL); l |= ULPI_12PIN; omap_writel(l, OTG_INTERFSEL); pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, " "sysstatus 0x%x, intrfsel 0x%x, simenable 0x%x\n", omap_readl(OTG_REVISION), omap_readl(OTG_SYSCONFIG), omap_readl(OTG_SYSSTATUS), omap_readl(OTG_INTERFSEL), omap_readl(OTG_SIMENABLE)); omap_vbus_power(musb, musb->board_mode == MUSB_HOST, 1); if (is_host_enabled(musb)) musb->board_set_vbus = omap_set_vbus; setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); return 0; }
int __init musb_platform_init(struct musb *musb) { int err; #ifdef CONFIG_USB_MTK_HDRC_HCD if (is_host_enabled(musb)) { musb->board_set_vbus = mtk_set_vbus; //<2013/03/27-23263-stevenchen, Correct GPIO12 & GPIO38 configuration to low down standby current. #ifndef CONFIG_MT6589_FPGA #ifndef MTK_BQ24196_SUPPORT #ifndef MTK_BQ24157_SUPPORT mt_set_gpio_mode(GPIO_OTG_DRVVBUS_PIN,GPIO_OTG_DRVVBUS_PIN_M_GPIO);//should set GPIO2 as gpio mode. mt_set_gpio_dir(GPIO_OTG_DRVVBUS_PIN,GPIO_DIR_OUT); mt_get_gpio_pull_enable(GPIO_OTG_DRVVBUS_PIN); mt_set_gpio_pull_select(GPIO_OTG_DRVVBUS_PIN,GPIO_PULL_UP); #endif #endif #endif //>2013/03/27-23263-stevenchen } #endif musb->nIrq = MT6589_USB0_IRQ_ID; musb->dma_irq= (int)SHARE_IRQ; musb->fifo_cfg = fifo_cfg; musb->fifo_cfg_size = ARRAY_SIZE(fifo_cfg); musb->fifo_cfg_host = fifo_cfg_host; musb->fifo_cfg_host_size = ARRAY_SIZE(fifo_cfg_host); mtk_musb->power = FALSE; mtk_musb->is_host = FALSE; mtk_musb->fifo_size = 8*1024; #ifndef CONFIG_MT6589_FPGA hwPowerOn(MT65XX_POWER_LDO_VUSB, VOL_3300, "VUSB_LDO"); printk("%s, enable VBUS_LDO \n", __func__); #endif musb_platform_enable(musb); emi_mpu_notifier_register(MST_ID_MMPERI_1, musb_check_mpu_violation); musb->isr = mt_usb_interrupt; musb_writel(musb->mregs,MUSB_HSDMA_INTR,0xff | (0xff << DMA_INTR_UNMASK_SET_OFFSET)); DBG(2,"musb platform init %x\n",musb_readl(musb->mregs,MUSB_HSDMA_INTR)); musb_writel(musb->mregs,USB_L1INTM,TX_INT_STATUS | RX_INT_STATUS | USBCOM_INT_STATUS | DMA_INT_STATUS); err = device_create_file(musb->controller,&dev_attr_cmode); return 0; }
static void sunxi_musb_enable(struct musb *musb) { pr_debug("%s():\n", __func__); if (enabled) return; /* select PIO mode */ musb_writeb(musb->mregs, USBC_REG_o_VEND0, 0); if (is_host_enabled(musb)) sunxi_usb_phy_power_on(0); /* port power on */ USBC_ForceVbusValidToHigh(musb->mregs); enabled = true; }
static int am35x_musb_exit(struct musb *musb) { struct device *dev = musb->controller; struct musb_hdrc_platform_data *plat = dev->platform_data; struct omap_musb_board_data *data = plat->board_data; if (is_host_enabled(musb)) del_timer_sync(&otg_workaround); /* Shutdown the on-chip PHY and its PLL. */ if (data->set_phy_power) data->set_phy_power(0); otg_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(); return 0; }
static int am35x_musb_init(struct musb *musb) { struct device *dev = musb->controller; struct musb_hdrc_platform_data *plat = dev->platform_data; struct omap_musb_board_data *data = plat->board_data; void __iomem *reg_base = musb->ctrl_base; u32 rev; musb->mregs += USB_MENTOR_CORE_OFFSET; /* Returns zero if e.g. not clocked */ rev = musb_readl(reg_base, USB_REVISION_REG); if (!rev) return -ENODEV; usb_nop_xceiv_register(); musb->xceiv = otg_get_transceiver(); if (!musb->xceiv) return -ENODEV; if (is_host_enabled(musb)) setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); /* Reset the musb */ if (data->reset) data->reset(); /* Reset the controller */ musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK); /* Start the on-chip PHY and its PLL. */ if (data->set_phy_power) data->set_phy_power(1); msleep(5); musb->isr = am35x_musb_interrupt; /* clear level interrupt */ if (data->clear_irq) data->clear_irq(); return 0; }
int __init musb_platform_init(struct musb *musb) { struct otg_transceiver *xceiv; xceiv = kzalloc(sizeof(struct otg_transceiver), GFP_KERNEL); if (!xceiv) return -ENOMEM; xceiv->set_peripheral = sep0611_set_peripheral; otg_set_transceiver(xceiv); musb->xceiv = otg_get_transceiver(); if (!musb->xceiv) { return -ENODEV; } musb_platform_resume(musb); if (is_host_enabled(musb)) musb->xceiv->set_host = sep0611_set_host; musb->board_set_vbus = sep0611_set_vbus; if (is_peripheral_enabled(musb)) musb->xceiv->set_power = sep0611_set_power; musb->a_wait_bcon = MUSB_TIMEOUT_A_WAIT_BCON; setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); musb_writew(musb->mregs, RX_DPKTBUFDIS, 0xffff); /* disable RX double packet buffer */ musb_writew(musb->mregs, TX_DPKTBUFDIS, 0xffff); /* disable TX double packet buffer */ #ifdef SEP0611_ULPI_RST /*spdw_board has two usb ports,one is otg(port_index=0), the other is host(port_index=1),default is otg port*/ musb->port_index = 0; #endif #ifdef SEP0611_PHY_RST /*demo_board has two usb ports*/ musb->port_index = 0; #endif return 0; }
static int da8xx_musb_init(struct musb *musb) { void __iomem *reg_base = musb->ctrl_base; u32 rev; musb->mregs += DA8XX_MENTOR_CORE_OFFSET; /* Returns zero if e.g. not clocked */ rev = musb_readl(reg_base, DA8XX_USB_REVISION_REG); if (!rev) goto fail; usb_nop_xceiv_register(); musb->xceiv = usb_get_transceiver(); if (!musb->xceiv) goto fail; if (is_host_enabled(musb)) setup_timer(&otg_workaround, otg_timer, (unsigned long)musb); /* Reset the controller */ musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK); /* Start the on-chip PHY and its PLL. */ phy_on(); msleep(5); /* NOTE: IRQs are in mixed mode, not bypass to pure MUSB */ pr_debug("DA8xx OTG revision %08x, PHY %03x, control %02x\n", rev, __raw_readl(CFGCHIP2), musb_readb(reg_base, DA8XX_USB_CTRL_REG)); musb->isr = da8xx_musb_interrupt; return 0; fail: return -ENODEV; }
int __init musb_platform_init(struct musb *musb) { usb_nop_xceiv_register(); /* We require some kind of external transceiver, hooked * up through ULPI. TWL4030-family PMICs include one, * which needs a driver, drivers aren't always needed. */ musb->xceiv = otg_get_transceiver(); if (!musb->xceiv) { pr_err("HS USB OTG: no transceiver configured\n"); return -ENODEV; } m2s_usb_platform_resume(musb); m2s_usb_vbus_power(musb, musb->board_mode == MUSB_HOST, 1); if (is_host_enabled(musb)) musb->board_set_vbus = m2s_usb_vbus_set; return 0; }
int __init musb_platform_init(struct musb *musb) { void __iomem *tibase = musb->ctrl_base; u32 revision; musb->mregs += DAVINCI_BASE_OFFSET; clk_enable(musb->clock); /* returns zero if e.g. not clocked */ revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG); if (revision == 0) return -ENODEV; if (is_host_enabled(musb)) setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); musb->board_set_vbus = davinci_set_vbus; davinci_source_power(musb, 0, 1); /* reset the controller */ musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1); /* start the on-chip PHY and its PLL */ phy_on(); msleep(5); /* NOTE: irqs are in mixed mode, not bypass to pure-musb */ pr_debug("DaVinci OTG revision %08x phy %03x control %02x\n", revision, __raw_readl((void __force __iomem *) IO_ADDRESS(USBPHY_CTL_PADDR)), musb_readb(tibase, DAVINCI_USB_CTRL_REG)); musb->isr = davinci_interrupt; return 0; }
int __init musb_platform_init(struct musb *musb) { u32 l; struct device *dev = musb->controller; struct musb_hdrc_platform_data *plat = dev->platform_data; struct omap_musb_board_data *data = plat->board_data; int status; u32 val; /* We require some kind of external transceiver, hooked * up through ULPI. TWL4030-family PMICs include one, * which needs a driver, drivers aren't always needed. */ musb->xceiv = otg_get_transceiver(); if (!musb->xceiv) { pr_err("HS USB OTG: no transceiver configured\n"); return -ENODEV; } /* Fixme this can be enabled when load the gadget driver also*/ musb_platform_resume(musb); /*powerup the phy as romcode would have put the phy in some state * which is impacting the core retention if the gadget driver is not * loaded. */ l = musb_readl(musb->mregs, OTG_INTERFSEL); if (data->interface_type == MUSB_INTERFACE_UTMI) { /* OMAP4 uses Internal PHY GS70 which uses UTMI interface */ l &= ~ULPI_12PIN; /* Disable ULPI */ l |= UTMI_8BIT; /* Enable UTMI */ } else { l |= ULPI_12PIN; } musb_writel(musb->mregs, OTG_INTERFSEL, l); pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, " "sysstatus 0x%x, intrfsel 0x%x, simenable 0x%x\n", musb_readl(musb->mregs, OTG_REVISION), musb_readl(musb->mregs, OTG_SYSCONFIG), musb_readl(musb->mregs, OTG_SYSSTATUS), musb_readl(musb->mregs, OTG_INTERFSEL), musb_readl(musb->mregs, OTG_SIMENABLE)); if (is_host_enabled(musb)) musb->board_set_vbus = omap_set_vbus; setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); plat->is_usb_active = is_musb_active; wake_lock_init(&plat->musb_lock, WAKE_LOCK_SUSPEND, "musb_wake_lock"); if (cpu_is_omap44xx()) { phymux_base = ioremap(0x4A100000, SZ_1K); ctrl_base = ioremap(0x4A002000, SZ_1K); /* register for transciever notification*/ status = otg_register_notifier(musb->xceiv, &musb->nb); if (status) { DBG(1, "notification register failed\n"); wake_lock_destroy(&plat->musb_lock); } ctrl_base = ioremap(0x4A002000, SZ_1K); if (!ctrl_base) { dev_err(dev, "ioremap failed\n"); return -ENOMEM; } } /* configure in force idle/ standby */ musb_writel(musb->mregs, OTG_FORCESTDBY, 1); val = musb_readl(musb->mregs, OTG_SYSCONFIG); val &= ~(SMARTIDLEWKUP | NOSTDBY | ENABLEWAKEUP); val |= FORCEIDLE | FORCESTDBY; musb_writel(musb->mregs, OTG_SYSCONFIG, val); l = musb_readl(musb->mregs, OTG_FORCESTDBY); l &= ~ENABLEFORCE; /* disable MSTANDBY */ musb_writel(musb->mregs, OTG_FORCESTDBY, l); return 0; }
static void musb_port_suspend(struct musb *musb, bool do_suspend) { u8 power; void __iomem *mbase = musb->mregs; if (!is_host_enabled(musb)) return; /* NOTE: this doesn't necessarily put PHY into low power mode, * turning off its clock; that's a function of PHY integration and * MUSB_POWER_ENSUSPEND. PHY may need a clock (sigh) to detect * SE0 changing to connect (J) or wakeup (K) states. */ power = musb_readb(mbase, MUSB_POWER); if (do_suspend) { int retries = 10000; power &= ~MUSB_POWER_RESUME; power |= MUSB_POWER_SUSPENDM; musb_writeb(mbase, MUSB_POWER, power); /* Needed for OPT A tests */ power = musb_readb(mbase, MUSB_POWER); while (power & MUSB_POWER_SUSPENDM) { power = musb_readb(mbase, MUSB_POWER); if (retries-- < 1) break; } dev_dbg(musb->controller, "Root port suspended, power %02x\n", power); musb->port1_status |= USB_PORT_STAT_SUSPEND; switch (musb->xceiv->state) { case OTG_STATE_A_HOST: musb->xceiv->state = OTG_STATE_A_SUSPEND; musb->is_active = is_otg_enabled(musb) && musb->xceiv->host->b_hnp_enable; musb_platform_try_idle(musb, 0); break; case OTG_STATE_B_HOST: if (is_otg_enabled(musb)) { musb->xceiv->state = OTG_STATE_B_WAIT_ACON; musb->is_active = is_otg_enabled(musb) && musb->xceiv->host->b_hnp_enable; musb_platform_try_idle(musb, 0); } break; default: dev_dbg(musb->controller, "bogus rh suspend? %s\n", otg_state_string(musb->xceiv->state)); } } else if (power & MUSB_POWER_SUSPENDM) { power &= ~MUSB_POWER_SUSPENDM; power |= MUSB_POWER_RESUME; musb_writeb(mbase, MUSB_POWER, power); dev_dbg(musb->controller, "Root port resuming, power %02x\n", power); /* later, GetPortStatus will stop RESUME signaling */ musb->port1_status |= MUSB_PORT_STAT_RESUME; musb->rh_timer = jiffies + msecs_to_jiffies(20); } }
int musb_hub_control( struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { struct musb *musb = hcd_to_musb(hcd); u32 temp; int retval = 0; unsigned long flags; spin_lock_irqsave(&musb->lock, flags); if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) { spin_unlock_irqrestore(&musb->lock, flags); return -ESHUTDOWN; } /* hub features: always zero, setting is a NOP * port features: reported, sometimes updated when host is active * no indicators */ switch (typeReq) { case ClearHubFeature: case SetHubFeature: switch (wValue) { case C_HUB_OVER_CURRENT: case C_HUB_LOCAL_POWER: break; default: goto error; } break; case ClearPortFeature: if ((wIndex & 0xff) != 1) goto error; switch (wValue) { case USB_PORT_FEAT_ENABLE: break; case USB_PORT_FEAT_SUSPEND: musb_port_suspend(musb, false); break; case USB_PORT_FEAT_POWER: if (!(is_otg_enabled(musb) && hcd->self.is_b_host)) musb_platform_set_vbus(musb, 0); break; case USB_PORT_FEAT_C_CONNECTION: case USB_PORT_FEAT_C_ENABLE: case USB_PORT_FEAT_C_OVER_CURRENT: case USB_PORT_FEAT_C_RESET: case USB_PORT_FEAT_C_SUSPEND: break; default: goto error; } dev_dbg(musb->controller, "clear feature %d\n", wValue); musb->port1_status &= ~(1 << wValue); break; case GetHubDescriptor: { struct usb_hub_descriptor *desc = (void *)buf; desc->bDescLength = 9; desc->bDescriptorType = 0x29; desc->bNbrPorts = 1; desc->wHubCharacteristics = cpu_to_le16( 0x0001 /* per-port power switching */ | 0x0010 /* no overcurrent reporting */ ); desc->bPwrOn2PwrGood = 5; /* msec/2 */ desc->bHubContrCurrent = 0; /* workaround bogus struct definition */ desc->u.hs.DeviceRemovable[0] = 0x02; /* port 1 */ desc->u.hs.DeviceRemovable[1] = 0xff; } break; case GetHubStatus: temp = 0; *(__le32 *) buf = cpu_to_le32(temp); break; case GetPortStatus: if (wIndex != 1) goto error; /* finish RESET signaling? */ if ((musb->port1_status & USB_PORT_STAT_RESET) && time_after_eq(jiffies, musb->rh_timer)) musb_port_reset(musb, false); /* finish RESUME signaling? */ if ((musb->port1_status & MUSB_PORT_STAT_RESUME) && time_after_eq(jiffies, musb->rh_timer)) { u8 power; power = musb_readb(musb->mregs, MUSB_POWER); power &= ~MUSB_POWER_RESUME; dev_dbg(musb->controller, "root port resume stopped, power %02x\n", power); musb_writeb(musb->mregs, MUSB_POWER, power); /* ISSUE: DaVinci (RTL 1.300) disconnects after * resume of high speed peripherals (but not full * speed ones). */ musb->is_active = 1; musb->port1_status &= ~(USB_PORT_STAT_SUSPEND | MUSB_PORT_STAT_RESUME); musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16; usb_hcd_poll_rh_status(musb_to_hcd(musb)); /* NOTE: it might really be A_WAIT_BCON ... */ musb->xceiv->state = OTG_STATE_A_HOST; } put_unaligned(cpu_to_le32(musb->port1_status & ~MUSB_PORT_STAT_RESUME), (__le32 *) buf); /* port change status is more interesting */ dev_dbg(musb->controller, "port status %08x\n", musb->port1_status); break; case SetPortFeature: if ((wIndex & 0xff) != 1) goto error; switch (wValue) { case USB_PORT_FEAT_POWER: /* NOTE: this controller has a strange state machine * that involves "requesting sessions" according to * magic side effects from incompletely-described * rules about startup... * * This call is what really starts the host mode; be * very careful about side effects if you reorder any * initialization logic, e.g. for OTG, or change any * logic relating to VBUS power-up. */ if (!(is_otg_enabled(musb) && hcd->self.is_b_host)) musb_start(musb); break; case USB_PORT_FEAT_RESET: musb_port_reset(musb, true); break; case USB_PORT_FEAT_SUSPEND: musb_port_suspend(musb, true); break; case USB_PORT_FEAT_TEST: if (unlikely(is_host_enabled(musb))) goto error; wIndex >>= 8; switch (wIndex) { case 1: pr_debug("TEST_J\n"); temp = MUSB_TEST_J; break; case 2: pr_debug("TEST_K\n"); temp = MUSB_TEST_K; break; case 3: pr_debug("TEST_SE0_NAK\n"); temp = MUSB_TEST_SE0_NAK; break; case 4: pr_debug("TEST_PACKET\n"); temp = MUSB_TEST_PACKET; musb_load_testpacket(musb); break; case 5: pr_debug("TEST_FORCE_ENABLE\n"); temp = MUSB_TEST_FORCE_HOST | MUSB_TEST_FORCE_HS; musb_writeb(musb->mregs, MUSB_DEVCTL, MUSB_DEVCTL_SESSION); break; case 6: pr_debug("TEST_FIFO_ACCESS\n"); temp = MUSB_TEST_FIFO_ACCESS; break; default: goto error; } musb_writeb(musb->mregs, MUSB_TESTMODE, temp); if (wIndex == 4) { musb_writew(musb->endpoints[0].regs, MUSB_CSR0, MUSB_CSR0_TXPKTRDY); } break; default: goto error; } dev_dbg(musb->controller, "set feature %d\n", wValue); musb->port1_status |= 1 << wValue; break; default: error: /* "protocol stall" on error */ retval = -EPIPE; } spin_unlock_irqrestore(&musb->lock, flags); return retval; }
static void musb_port_reset(struct musb *musb, bool do_reset) { u8 power; void __iomem *mbase = musb->mregs; if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE) { dev_dbg(musb->controller, "HNP: Returning from HNP; no hub reset from b_idle\n"); musb->port1_status &= ~USB_PORT_STAT_RESET; return; } if (!is_host_enabled(musb)) return; /* NOTE: caller guarantees it will turn off the reset when * the appropriate amount of time has passed */ power = musb_readb(mbase, MUSB_POWER); if (do_reset) { /* * If RESUME is set, we must make sure it stays minimum 20 ms. * Then we must clear RESUME and wait a bit to let musb start * generating SOFs. If we don't do this, OPT HS A 6.8 tests * fail with "Error! Did not receive an SOF before suspend * detected". */ if (power & MUSB_POWER_RESUME) { while (time_before(jiffies, musb->rh_timer)) msleep(1); musb_writeb(mbase, MUSB_POWER, power & ~MUSB_POWER_RESUME); msleep(1); } musb->ignore_disconnect = true; power &= 0xf0; musb_writeb(mbase, MUSB_POWER, power | MUSB_POWER_RESET); musb->port1_status |= USB_PORT_STAT_RESET; musb->port1_status &= ~USB_PORT_STAT_ENABLE; musb->rh_timer = jiffies + msecs_to_jiffies(50); } else { dev_dbg(musb->controller, "root port reset stopped\n"); musb_writeb(mbase, MUSB_POWER, power & ~MUSB_POWER_RESET); musb->ignore_disconnect = false; power = musb_readb(mbase, MUSB_POWER); if (power & MUSB_POWER_HSMODE) { dev_dbg(musb->controller, "high-speed device connected\n"); musb->port1_status |= USB_PORT_STAT_HIGH_SPEED; } musb->port1_status &= ~USB_PORT_STAT_RESET; musb->port1_status |= USB_PORT_STAT_ENABLE | (USB_PORT_STAT_C_RESET << 16) | (USB_PORT_STAT_C_ENABLE << 16); usb_hcd_poll_rh_status(musb_to_hcd(musb)); musb->vbuserr_retry = VBUSERR_RETRY_COUNT; } }
static int davinci_musb_init(struct musb *musb) { void __iomem *tibase = musb->ctrl_base; u32 revision; usb_nop_xceiv_register(musb->id); musb->xceiv = otg_get_transceiver(musb->id); if (!musb->xceiv) return -ENODEV; musb->mregs += DAVINCI_BASE_OFFSET; /* returns zero if e.g. not clocked */ revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG); if (revision == 0) goto fail; if (is_host_enabled(musb)) setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); davinci_musb_source_power(musb, 0, 1); /* dm355 EVM swaps D+/D- for signal integrity, and * is clocked from the main 24 MHz crystal. */ if (machine_is_davinci_dm355_evm()) { u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); phy_ctrl &= ~(3 << 9); phy_ctrl |= USBPHY_DATAPOL; __raw_writel(phy_ctrl, USB_PHY_CTRL); } /* On dm355, the default-A state machine needs DRVVBUS control. * If we won't be a host, there's no need to turn it on. */ if (cpu_is_davinci_dm355()) { u32 deepsleep = __raw_readl(DM355_DEEPSLEEP); if (is_host_enabled(musb)) { deepsleep &= ~DRVVBUS_OVERRIDE; } else { deepsleep &= ~DRVVBUS_FORCE; deepsleep |= DRVVBUS_OVERRIDE; } __raw_writel(deepsleep, DM355_DEEPSLEEP); } /* reset the controller */ musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1); /* start the on-chip PHY and its PLL */ phy_on(); msleep(5); /* NOTE: irqs are in mixed mode, not bypass to pure-musb */ pr_debug("DaVinci OTG revision %08x phy %03x control %02x\n", revision, __raw_readl(USB_PHY_CTRL), musb_readb(tibase, DAVINCI_USB_CTRL_REG)); musb->isr = davinci_musb_interrupt; return 0; fail: otg_put_transceiver(musb->xceiv); usb_nop_xceiv_unregister(musb->id); return -ENODEV; }
static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) { unsigned long flags; irqreturn_t retval = IRQ_NONE; struct musb *musb = __hci; void __iomem *tibase = musb->ctrl_base; struct cppi *cppi; u32 tmp; spin_lock_irqsave(&musb->lock, flags); /* NOTE: DaVinci shadows the Mentor IRQs. Don't manage them through * the Mentor registers (except for setup), use the TI ones and EOI. * * Docs describe irq "vector" registers associated with the CPPI and * USB EOI registers. These hold a bitmask corresponding to the * current IRQ, not an irq handler address. Would using those bits * resolve some of the races observed in this dispatch code?? */ /* CPPI interrupts share the same IRQ line, but have their own * mask, state, "vector", and EOI registers. */ cppi = container_of(musb->dma_controller, struct cppi, controller); if (is_cppi_enabled(musb) && musb->dma_controller && !cppi->irq) retval = cppi_interrupt(irq, __hci); /* ack and handle non-CPPI interrupts */ tmp = musb_readl(tibase, DAVINCI_USB_INT_SRC_MASKED_REG); musb_writel(tibase, DAVINCI_USB_INT_SRC_CLR_REG, tmp); DBG(4, "IRQ %08x\n", tmp); musb->int_rx = (tmp & DAVINCI_USB_RXINT_MASK) >> DAVINCI_USB_RXINT_SHIFT; musb->int_tx = (tmp & DAVINCI_USB_TXINT_MASK) >> DAVINCI_USB_TXINT_SHIFT; musb->int_usb = (tmp & DAVINCI_USB_USBINT_MASK) >> DAVINCI_USB_USBINT_SHIFT; /* DRVVBUS irqs are the only proxy we have (a very poor one!) for * DaVinci's missing ID change IRQ. We need an ID change IRQ to * switch appropriately between halves of the OTG state machine. * Managing DEVCTL.SESSION per Mentor docs requires we know its * value, but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set. * Also, DRVVBUS pulses for SRP (but not at 5V) ... */ if (tmp & (DAVINCI_INTR_DRVVBUS << DAVINCI_USB_USBINT_SHIFT)) { int drvvbus = musb_readl(tibase, DAVINCI_USB_STAT_REG); void __iomem *mregs = musb->mregs; u8 devctl = musb_readb(mregs, MUSB_DEVCTL); int err = musb->int_usb & MUSB_INTR_VBUSERROR; err = is_host_enabled(musb) && (musb->int_usb & MUSB_INTR_VBUSERROR); if (err) { /* The Mentor core doesn't debounce VBUS as needed * to cope with device connect current spikes. This * means it's not uncommon for bus-powered devices * to get VBUS errors during enumeration. * * This is a workaround, but newer RTL from Mentor * seems to allow a better one: "re"starting sessions * without waiting (on EVM, a **long** time) for VBUS * to stop registering in devctl. */ musb->int_usb &= ~MUSB_INTR_VBUSERROR; musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); WARNING("VBUS error workaround (delay coming)\n"); } else if (is_host_enabled(musb) && drvvbus) { MUSB_HST_MODE(musb); musb->xceiv->default_a = 1; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; portstate(musb->port1_status |= USB_PORT_STAT_POWER); del_timer(&otg_workaround); } else { musb->is_active = 0; MUSB_DEV_MODE(musb); musb->xceiv->default_a = 0; musb->xceiv->state = OTG_STATE_B_IDLE; portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); } /* NOTE: this must complete poweron within 100 msec * (OTG_TIME_A_WAIT_VRISE) but we don't check for that. */ davinci_musb_source_power(musb, drvvbus, 0); DBG(2, "VBUS %s (%s)%s, devctl %02x\n", drvvbus ? "on" : "off", otg_state_string(musb), err ? " ERROR" : "", devctl); retval = IRQ_HANDLED; } if (musb->int_tx || musb->int_rx || musb->int_usb) retval |= musb_interrupt(musb); /* irq stays asserted until EOI is written */ musb_writel(tibase, DAVINCI_USB_EOI_REG, 0); /* poll for ID change */ if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE) mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); spin_unlock_irqrestore(&musb->lock, flags); return retval; }