/*------------------------------------------------------------------------- * */ static int setup_tll(struct ehci_hcd_omap *omap) { unsigned long timeout = jiffies + msecs_to_jiffies(1000); int ret = 0; u8 tll_ch_mask = 0; /* perform TLL soft reset, and wait until reset is complete */ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, OMAP_USBTLL_SYSCONFIG_SOFTRESET); /* Wait for TLL reset to complete */ while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS) & OMAP_USBTLL_SYSSTATUS_RESETDONE)) { cpu_relax(); if (time_after(jiffies, timeout)) { dev_dbg(omap->dev, "operation timed out\n"); ret = -EINVAL; return ret; } } dev_dbg(omap->dev, "TLL RESET DONE\n"); /* (1<<3) = no idle mode only for initial debugging */ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | OMAP_USBTLL_SYSCONFIG_SIDLEMODE | OMAP_USBTLL_SYSCONFIG_CACTIVITY); if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) tll_ch_mask |= OMAP_TLL_CHANNEL_1_EN_MASK; if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) tll_ch_mask |= OMAP_TLL_CHANNEL_2_EN_MASK; if (!cpu_is_omap44xx()) { if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL) tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK; if (tll_ch_mask != 0) omap_usb_utmi_init(omap, tll_ch_mask,OMAP_TLL_CHANNEL_COUNT); } else { if (tll_ch_mask != 0) omap_usb_utmi_init(omap, tll_ch_mask, OMAP4_TLL_CHANNEL_COUNT); } return ret; }
/* omap_start_ehc * - Start the TI USBHOST controller */ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) { unsigned long timeout = jiffies + msecs_to_jiffies(1000); u8 tll_ch_mask = 0; unsigned reg = 0; int ret = 0; dev_dbg(omap->dev, "starting TI EHCI USB Controller\n"); /* Enable Clocks for USBHOST */ omap->usbhost_ick = clk_get(omap->dev, "usbhost_ick"); if (IS_ERR(omap->usbhost_ick)) { ret = PTR_ERR(omap->usbhost_ick); goto err_host_ick; } clk_enable(omap->usbhost_ick); omap->usbhost2_120m_fck = clk_get(omap->dev, "usbhost_120m_fck"); if (IS_ERR(omap->usbhost2_120m_fck)) { ret = PTR_ERR(omap->usbhost2_120m_fck); goto err_host_120m_fck; } clk_enable(omap->usbhost2_120m_fck); omap->usbhost1_48m_fck = clk_get(omap->dev, "usbhost_48m_fck"); if (IS_ERR(omap->usbhost1_48m_fck)) { ret = PTR_ERR(omap->usbhost1_48m_fck); goto err_host_48m_fck; } clk_enable(omap->usbhost1_48m_fck); if (omap->phy_reset) { /* Refer: ISSUE1 */ if (gpio_is_valid(omap->reset_gpio_port[0])) { gpio_request(omap->reset_gpio_port[0], "USB1 PHY reset"); gpio_direction_output(omap->reset_gpio_port[0], 0); } if (gpio_is_valid(omap->reset_gpio_port[1])) { gpio_request(omap->reset_gpio_port[1], "USB2 PHY reset"); gpio_direction_output(omap->reset_gpio_port[1], 0); } /* Hold the PHY in RESET for enough time till DIR is high */ udelay(10); } /* Configure TLL for 60Mhz clk for ULPI */ omap->usbtll_fck = clk_get(omap->dev, "usbtll_fck"); if (IS_ERR(omap->usbtll_fck)) { ret = PTR_ERR(omap->usbtll_fck); goto err_tll_fck; } clk_enable(omap->usbtll_fck); omap->usbtll_ick = clk_get(omap->dev, "usbtll_ick"); if (IS_ERR(omap->usbtll_ick)) { ret = PTR_ERR(omap->usbtll_ick); goto err_tll_ick; } clk_enable(omap->usbtll_ick); /* perform TLL soft reset, and wait until reset is complete */ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, OMAP_USBTLL_SYSCONFIG_SOFTRESET); /* Wait for TLL reset to complete */ while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS) & OMAP_USBTLL_SYSSTATUS_RESETDONE)) { cpu_relax(); if (time_after(jiffies, timeout)) { dev_dbg(omap->dev, "operation timed out\n"); ret = -EINVAL; goto err_sys_status; } } dev_dbg(omap->dev, "TLL RESET DONE\n"); /* (1<<3) = no idle mode only for initial debugging */ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | OMAP_USBTLL_SYSCONFIG_SIDLEMODE | OMAP_USBTLL_SYSCONFIG_CACTIVITY); /* Put UHH in NoIdle/NoStandby mode */ reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG); reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP | OMAP_UHH_SYSCONFIG_SIDLEMODE | OMAP_UHH_SYSCONFIG_CACTIVITY | OMAP_UHH_SYSCONFIG_MIDLEMODE); reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG); /* setup ULPI bypass and burst configurations */ reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN | OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN); reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN) reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN) reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS; if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN) reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; /* Bypass the TLL module for PHY mode operation */ if (omap_rev() <= OMAP3430_REV_ES2_1) { dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1 \n"); if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) || (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) || (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY)) reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; else reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; } else { dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n"); if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; else if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; else if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY) reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; else if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL) reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; } ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg); if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) || (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) || (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)) { if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) tll_ch_mask |= OMAP_TLL_CHANNEL_1_EN_MASK; if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) tll_ch_mask |= OMAP_TLL_CHANNEL_2_EN_MASK; if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL) tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK; /* Enable UTMI mode for required TLL channels */ omap_usb_utmi_init(omap, tll_ch_mask); } if (omap->phy_reset) { /* Refer ISSUE1: * Hold the PHY in RESET for enough time till * PHY is settled and ready */ udelay(10); if (gpio_is_valid(omap->reset_gpio_port[0])) gpio_set_value(omap->reset_gpio_port[0], 1); if (gpio_is_valid(omap->reset_gpio_port[1])) gpio_set_value(omap->reset_gpio_port[1], 1); } return 0; err_sys_status: clk_disable(omap->usbtll_ick); clk_put(omap->usbtll_ick); err_tll_ick: clk_disable(omap->usbtll_fck); clk_put(omap->usbtll_fck); err_tll_fck: clk_disable(omap->usbhost1_48m_fck); clk_put(omap->usbhost1_48m_fck); if (omap->phy_reset) { if (gpio_is_valid(omap->reset_gpio_port[0])) gpio_free(omap->reset_gpio_port[0]); if (gpio_is_valid(omap->reset_gpio_port[1])) gpio_free(omap->reset_gpio_port[1]); } err_host_48m_fck: clk_disable(omap->usbhost2_120m_fck); clk_put(omap->usbhost2_120m_fck); err_host_120m_fck: clk_disable(omap->usbhost_ick); clk_put(omap->usbhost_ick); err_host_ick: return ret; }
/* omap_start_ehc * - Start the TI USBHOST controller */ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) { unsigned long timeout = jiffies + msecs_to_jiffies(1000); unsigned reg = 0; int ret = 0; int reset_delay; int i; dev_dbg(&omap->dev->dev, "starting TI EHCI USB Controller\n"); /* Enable Clocks for USBHOST */ omap->usbhost_ick = clk_get(&omap->dev->dev, "usbhost_ick"); if (IS_ERR(omap->usbhost_ick)) { ret = PTR_ERR(omap->usbhost_ick); goto err_host_ick; } clk_enable(omap->usbhost_ick); omap->usbhost2_120m_fck = clk_get(&omap->dev->dev, "usbhost_120m_fck"); if (IS_ERR(omap->usbhost2_120m_fck)) { ret = PTR_ERR(omap->usbhost2_120m_fck); goto err_host_120m_fck; } clk_enable(omap->usbhost2_120m_fck); omap->usbhost1_48m_fck = clk_get(&omap->dev->dev, "usbhost_48m_fck"); if (IS_ERR(omap->usbhost1_48m_fck)) { ret = PTR_ERR(omap->usbhost1_48m_fck); goto err_host_48m_fck; } clk_enable(omap->usbhost1_48m_fck); reset_delay = 0; for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { reset_delay = reset_delay > omap->port_data[i].reset_delay ? reset_delay : omap->port_data[i].reset_delay; if (omap->port_data[i].startup) { ret = omap->port_data[i].startup(omap->dev, i); if (ret < 0) return ret; } if (omap->port_data[i].reset) omap->port_data[i].reset(omap->dev, i, 0); } if (reset_delay) udelay(reset_delay); /* Configure TLL for 60Mhz clk for ULPI */ omap->usbtll_fck = clk_get(&omap->dev->dev, "usbtll_fck"); if (IS_ERR(omap->usbtll_fck)) { ret = PTR_ERR(omap->usbtll_fck); goto err_tll_fck; } clk_enable(omap->usbtll_fck); omap->usbtll_ick = clk_get(&omap->dev->dev, "usbtll_ick"); if (IS_ERR(omap->usbtll_ick)) { ret = PTR_ERR(omap->usbtll_ick); goto err_tll_ick; } clk_enable(omap->usbtll_ick); /* perform TLL soft reset, and wait until reset is complete */ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, OMAP_USBTLL_SYSCONFIG_SOFTRESET); /* Wait for TLL reset to complete */ while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS) & OMAP_USBTLL_SYSSTATUS_RESETDONE)) { cpu_relax(); if (time_after(jiffies, timeout)) { dev_dbg(&omap->dev->dev, "operation timed out\n"); ret = -EINVAL; goto err_sys_status; } } dev_dbg(&omap->dev->dev, "TLL RESET DONE\n"); /* (1<<3) = no idle mode only for initial debugging */ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | OMAP_USBTLL_SYSCONFIG_SIDLEMODE | OMAP_USBTLL_SYSCONFIG_CACTIVITY); /* Put UHH in NoIdle/NoStandby mode */ ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, OMAP_UHH_SYSCONFIG_ENAWAKEUP | OMAP_UHH_SYSCONFIG_SIDLEMODE | OMAP_UHH_SYSCONFIG_MIDLEMODE | OMAP_UHH_SYSCONFIG_AUTOIDLE); reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG); /* setup ULPI bypass and burst configurations */ reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN | OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN); reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; if (omap->port_data[0].flags != EHCI_HCD_OMAP_FLAG_ENABLED) reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; if (omap->port_data[1].flags != EHCI_HCD_OMAP_FLAG_ENABLED) reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS; if (omap->port_data[2].flags != EHCI_HCD_OMAP_FLAG_ENABLED) reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; /* Bypass the TLL module for PHY mode operation */ if (omap_rev() <= OMAP3430_REV_ES2_1) { dev_dbg(&omap->dev->dev, "OMAP3 ES version <= ES2.1 \n"); if (omap_usb_port_ulpi_bypass(omap->port_data[0].mode)) reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; else reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; } else { dev_dbg(&omap->dev->dev, "OMAP3 ES version > ES2.1\n"); if (omap_usb_port_ulpi_bypass(omap->port_data[0].mode)) reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; else reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; if (omap_usb_port_ulpi_bypass(omap->port_data[1].mode)) reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; else reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; if (omap_usb_port_ulpi_bypass(omap->port_data[2].mode)) reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; else reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; } ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); dev_dbg(&omap->dev->dev, "UHH setup done, uhh_hostconfig=%x\n", reg); /* Enable UTMI mode for required TLL channels */ omap_usb_utmi_init(omap); reset_delay = 0; for (i = 0; i < OMAP3_HS_USB_PORTS; i++) { reset_delay = reset_delay > omap->port_data[i].reset_delay ? reset_delay : omap->port_data[i].reset_delay; } if (reset_delay) udelay(reset_delay); for (i = 0; i < OMAP3_HS_USB_PORTS; i++) { if (omap->port_data[i].reset) omap->port_data[i].reset(omap->dev, i, 1); } return 0; err_sys_status: clk_disable(omap->usbtll_ick); clk_put(omap->usbtll_ick); err_tll_ick: clk_disable(omap->usbtll_fck); clk_put(omap->usbtll_fck); err_tll_fck: clk_disable(omap->usbhost1_48m_fck); clk_put(omap->usbhost1_48m_fck); err_host_48m_fck: clk_disable(omap->usbhost2_120m_fck); clk_put(omap->usbhost2_120m_fck); err_host_120m_fck: clk_disable(omap->usbhost_ick); clk_put(omap->usbhost_ick); err_host_ick: return ret; }
static int omap_init_uhh_registers(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) { unsigned long timeout = jiffies + msecs_to_jiffies(1000); u8 tll_ch_mask = 0; unsigned reg = 0; /* perform TLL soft reset, and wait until reset is complete */ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, OMAP_USBTLL_SYSCONFIG_SOFTRESET); /* Wait for TLL reset to complete */ while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS) & OMAP_USBTLL_SYSSTATUS_RESETDONE)) { cpu_relax(); if (time_after(jiffies, timeout)) { dev_dbg(omap->dev, "operation timed out\n"); return -EINVAL; } } dev_dbg(omap->dev, "TLL RESET DONE\n"); /* Enable smart-idle, wakeup */ reg = OMAP_USBTLL_SYSCONFIG_CACTIVITY | OMAP_USBTLL_SYSCONFIG_AUTOIDLE | OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | OMAP_USBTLL_SYSCONFIG_SMARTIDLE; ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, reg); /* Put UHH in NoIdle/NoStandby mode */ reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG); reg |= OMAP_UHH_SYSCONFIG_CACTIVITY | OMAP_UHH_SYSCONFIG_AUTOIDLE | OMAP_UHH_SYSCONFIG_ENAWAKEUP; reg &= ~(OMAP_UHH_SYSCONFIG_SIDLEMASK | OMAP_UHH_SYSCONFIG_MIDLEMASK); reg |= OMAP_UHH_SYSCONFIG_NOIDLE | OMAP_UHH_SYSCONFIG_NOSTDBY; ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG); /* setup ULPI bypass and burst configurations */ reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN | OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN); reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN) reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN) reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS; if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN) reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; /* Bypass the TLL module for PHY mode operation */ if (!cpu_is_omap3517() && !cpu_is_omap3505() && (omap_rev() <= OMAP3430_REV_ES2_1)) { dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1 \n"); if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) || (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) || (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY)) reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; else reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; } else { dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n"); if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; else if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; else if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY) reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; else if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL) reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; } ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg); /* * An undocumented "feature" in the OMAP3 EHCI controller, * causes suspended ports to be taken out of suspend when * the USBCMD.Run/Stop bit is cleared (for example when * we do ehci_bus_suspend). * This breaks suspend-resume if the root-hub is allowed * to suspend. Writing 1 to this undocumented register bit * disables this feature and restores normal behavior. */ ehci_omap_writel(omap->ehci_base, EHCI_INSNREG04, EHCI_INSNREG04_DISABLE_UNSUSPEND); if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) || (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) || (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)) { if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) tll_ch_mask |= OMAP_TLL_CHANNEL_1_EN_MASK; if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) tll_ch_mask |= OMAP_TLL_CHANNEL_2_EN_MASK; if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL) tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK; /* Enable UTMI mode for required TLL channels */ omap_usb_utmi_init(omap, tll_ch_mask); } if (omap->phy_reset) { /* Refer ISSUE1: * Hold the PHY in RESET for enough time till * PHY is settled and ready */ udelay(10); if (gpio_is_valid(omap->reset_gpio_port[0])) gpio_set_value(omap->reset_gpio_port[0], 1); if (gpio_is_valid(omap->reset_gpio_port[1])) gpio_set_value(omap->reset_gpio_port[1], 1); } return 0; }
/* omap_start_ehc * - Start the TI USBHOST controller */ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) { unsigned long timeout = jiffies + msecs_to_jiffies(1000); unsigned reg = 0; int ret = 0; int reset_delay; int i; dev_dbg(&omap->dev->dev, "starting TI EHCI USB Controller\n"); /* Enable Clocks for USBHOST */ omap->usbhost_ick = clk_get(&omap->dev->dev, "usbhost_ick"); if (IS_ERR(omap->usbhost_ick)) { ret = PTR_ERR(omap->usbhost_ick); goto err_host_ick; } clk_enable(omap->usbhost_ick); omap->usbhost2_120m_fck = clk_get(&omap->dev->dev, "usbhost_120m_fck"); if (IS_ERR(omap->usbhost2_120m_fck)) { ret = PTR_ERR(omap->usbhost2_120m_fck); goto err_host_120m_fck; } clk_enable(omap->usbhost2_120m_fck); omap->usbhost1_48m_fck = clk_get(&omap->dev->dev, "usbhost_48m_fck"); if (IS_ERR(omap->usbhost1_48m_fck)) { ret = PTR_ERR(omap->usbhost1_48m_fck); goto err_host_48m_fck; } clk_enable(omap->usbhost1_48m_fck); reset_delay = 0; for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { reset_delay = reset_delay > omap->port_data[i].reset_delay ? reset_delay : omap->port_data[i].reset_delay; if (omap->port_data[i].startup) { ret = omap->port_data[i].startup(omap->dev, i); if (ret < 0) return ret; } if (omap->port_data[i].reset) omap->port_data[i].reset(omap->dev, i, 0); } if (reset_delay) udelay(reset_delay); /* Configure TLL for 60Mhz clk for ULPI */ omap->usbtll_fck = clk_get(&omap->dev->dev, "usbtll_fck"); if (IS_ERR(omap->usbtll_fck)) { ret = PTR_ERR(omap->usbtll_fck); goto err_tll_fck; } clk_enable(omap->usbtll_fck); omap->usbtll_ick = clk_get(&omap->dev->dev, "usbtll_ick"); if (IS_ERR(omap->usbtll_ick)) { ret = PTR_ERR(omap->usbtll_ick); goto err_tll_ick; } clk_enable(omap->usbtll_ick); set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); #ifndef CONFIG_MAPPHONE_2NDBOOT /* perform TLL soft reset, and wait until reset is complete */ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, OMAP_USBTLL_SYSCONFIG_SOFTRESET); /* Wait for TLL reset to complete */ while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS) & OMAP_USBTLL_SYSSTATUS_RESETDONE)) { cpu_relax(); if (time_after(jiffies, timeout)) { dev_dbg(&omap->dev->dev, "operation timed out\n"); ret = -EINVAL; goto err_sys_status; } } #endif dev_dbg(&omap->dev->dev, "TLL RESET DONE\n"); /* SmartIdle mode */ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | OMAP_USBTLL_SYSCONFIG_SIDLEMODE | OMAP_USBTLL_SYSCONFIG_AUTOIDLE); /* Put UHH in NoIdle/NoStandby mode */ ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, OMAP_UHH_SYSCONFIG_ENAWAKEUP | OMAP_UHH_SYSCONFIG_NOIDLEMODE | OMAP_UHH_SYSCONFIG_NOSTBYMODE | OMAP_UHH_SYSCONFIG_AUTOIDLE); #ifdef CONFIG_MACH_MAPPHONE /* We need to suspend OHCI in order for the usbhost * domain to go standby. * OHCI would never be resumed for UMTS modem */ if (!is_cdma_phone()) omap_writel(OHCI_HC_CTRL_SUSPEND, OHCI_HC_CONTROL); #endif reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG); /* setup ULPI bypass and burst configurations */ reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN | OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN); reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; if (!(omap->port_data[0].flags & EHCI_HCD_OMAP_FLAG_ENABLED)) reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; if (!(omap->port_data[1].flags & EHCI_HCD_OMAP_FLAG_ENABLED)) reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS; if (!(omap->port_data[2].flags & EHCI_HCD_OMAP_FLAG_ENABLED)) reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; /* Bypass the TLL module for PHY mode operation */ if (omap_rev() <= OMAP3430_REV_ES2_1) { dev_dbg(&omap->dev->dev, "OMAP3 ES version <= ES2.1 \n"); if (omap_usb_port_ulpi_bypass(omap->port_data[0].mode)) reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; else reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; } else { dev_dbg(&omap->dev->dev, "OMAP3 ES version > ES2.1\n"); if (omap_usb_port_ulpi_bypass(omap->port_data[0].mode)) reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; else reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; if (omap_usb_port_ulpi_bypass(omap->port_data[1].mode)) reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; else reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; if (omap_usb_port_ulpi_bypass(omap->port_data[2].mode)) reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; else reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; } ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); dev_dbg(&omap->dev->dev, "UHH setup done, uhh_hostconfig=%x\n", reg); /* Enable UTMI mode for required TLL channels */ omap_usb_utmi_init(omap); reset_delay = 0; for (i = 0; i < OMAP3_HS_USB_PORTS; i++) { reset_delay = reset_delay > omap->port_data[i].reset_delay ? reset_delay : omap->port_data[i].reset_delay; } if (reset_delay) udelay(reset_delay); for (i = 0; i < OMAP3_HS_USB_PORTS; i++) { if (omap->port_data[i].reset) omap->port_data[i].reset(omap->dev, i, 1); } #if defined(CONFIG_MACH_MAPPHONE) /* Refer ISSUE2: LINK assumes external charge pump */ /* use Port1 VBUS to charge externally Port2: * So for PHY mode operation use Port2 only */ ehci_omap_writel(omap->ehci_base, EHCI_INSNREG05_ULPI, (0xA << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* OTG ctrl reg*/ (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/* Write */ (2 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |/* Port1 */ (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |/* Start */ (0x26)); while (!(ehci_omap_readl(omap->ehci_base, EHCI_INSNREG05_ULPI) & (1<<EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) { cpu_relax(); } #endif return 0; err_sys_status: clk_disable(omap->usbtll_ick); clk_put(omap->usbtll_ick); err_tll_ick: clk_disable(omap->usbtll_fck); clk_put(omap->usbtll_fck); err_tll_fck: clk_disable(omap->usbhost1_48m_fck); clk_put(omap->usbhost1_48m_fck); err_host_48m_fck: clk_disable(omap->usbhost2_120m_fck); clk_put(omap->usbhost2_120m_fck); err_host_120m_fck: clk_disable(omap->usbhost_ick); clk_put(omap->usbhost_ick); err_host_ick: return ret; }
/* omap_start_ehc * - Start the TI USBHOST controller */ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) { unsigned long timeout = jiffies + msecs_to_jiffies(1000); u8 tll_ch_mask = 0; unsigned reg = 0; int ret = 0; dev_dbg(omap->dev, "starting TI EHCI USB Controller\n"); /* Enable Clocks for USBHOST */ omap->usbhost_ick = clk_get(omap->dev, "usbhost_ick"); if (IS_ERR(omap->usbhost_ick)) { ret = PTR_ERR(omap->usbhost_ick); goto err_host_ick; } clk_enable(omap->usbhost_ick); omap->usbhost_hs_fck = clk_get(omap->dev, "hs_fck"); if (IS_ERR(omap->usbhost_hs_fck)) { ret = PTR_ERR(omap->usbhost_hs_fck); goto err_host_120m_fck; } clk_enable(omap->usbhost_hs_fck); omap->usbhost_fs_fck = clk_get(omap->dev, "fs_fck"); if (IS_ERR(omap->usbhost_fs_fck)) { ret = PTR_ERR(omap->usbhost_fs_fck); goto err_host_48m_fck; } clk_enable(omap->usbhost_fs_fck); if (omap->phy_reset) { /* Refer: ISSUE1 */ if (gpio_is_valid(omap->reset_gpio_port[0])) { gpio_request(omap->reset_gpio_port[0], "USB1 PHY reset"); gpio_direction_output(omap->reset_gpio_port[0], 0); } if (gpio_is_valid(omap->reset_gpio_port[1])) { gpio_request(omap->reset_gpio_port[1], "USB2 PHY reset"); gpio_direction_output(omap->reset_gpio_port[1], 0); } /* Hold the PHY in RESET for enough time till DIR is high */ udelay(10); } /* Configure TLL for 60Mhz clk for ULPI */ omap->usbtll_fck = clk_get(omap->dev, "usbtll_fck"); if (IS_ERR(omap->usbtll_fck)) { ret = PTR_ERR(omap->usbtll_fck); goto err_tll_fck; } clk_enable(omap->usbtll_fck); omap->usbtll_ick = clk_get(omap->dev, "usbtll_ick"); if (IS_ERR(omap->usbtll_ick)) { ret = PTR_ERR(omap->usbtll_ick); goto err_tll_ick; } clk_enable(omap->usbtll_ick); omap->omap_ehci_rev = ehci_omap_readl(omap->uhh_base, OMAP_UHH_REVISION); dev_dbg(omap->dev, "OMAP UHH_REVISION 0x%x\n", omap->omap_ehci_rev); /* * Enable per-port clocks as needed (newer controllers only). * - External ULPI clock for PHY mode * - Internal clocks for TLL and HSIC modes (TODO) */ if (is_omap_ehci_rev2(omap)) { switch (omap->port_mode[0]) { case EHCI_HCD_OMAP_MODE_PHY: omap->xclk60mhsp1_ck = clk_get(omap->dev, "xclk60mhsp1_ck"); if (IS_ERR(omap->xclk60mhsp1_ck)) { ret = PTR_ERR(omap->xclk60mhsp1_ck); dev_err(omap->dev, "Unable to get Port1 ULPI clock\n"); } omap->utmi_p1_fck = clk_get(omap->dev, "utmi_p1_gfclk"); if (IS_ERR(omap->utmi_p1_fck)) { ret = PTR_ERR(omap->utmi_p1_fck); dev_err(omap->dev, "Unable to get utmi_p1_fck\n"); } ret = clk_set_parent(omap->utmi_p1_fck, omap->xclk60mhsp1_ck); if (ret != 0) { dev_err(omap->dev, "Unable to set P1 f-clock\n"); } break; case EHCI_HCD_OMAP_MODE_TLL: /* TODO */ default: break; } switch (omap->port_mode[1]) { case EHCI_HCD_OMAP_MODE_PHY: omap->xclk60mhsp2_ck = clk_get(omap->dev, "xclk60mhsp2_ck"); if (IS_ERR(omap->xclk60mhsp2_ck)) { ret = PTR_ERR(omap->xclk60mhsp2_ck); dev_err(omap->dev, "Unable to get Port2 ULPI clock\n"); } omap->utmi_p2_fck = clk_get(omap->dev, "utmi_p2_gfclk"); if (IS_ERR(omap->utmi_p2_fck)) { ret = PTR_ERR(omap->utmi_p2_fck); dev_err(omap->dev, "Unable to get utmi_p2_fck\n"); } ret = clk_set_parent(omap->utmi_p2_fck, omap->xclk60mhsp2_ck); if (ret != 0) { dev_err(omap->dev, "Unable to set P2 f-clock\n"); } break; case EHCI_HCD_OMAP_MODE_TLL: /* TODO */ default: break; } } /* perform TLL soft reset, and wait until reset is complete */ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, OMAP_USBTLL_SYSCONFIG_SOFTRESET); /* Wait for TLL reset to complete */ while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS) & OMAP_USBTLL_SYSSTATUS_RESETDONE)) { cpu_relax(); if (time_after(jiffies, timeout)) { dev_dbg(omap->dev, "operation timed out\n"); ret = -EINVAL; goto err_sys_status; } } dev_dbg(omap->dev, "TLL RESET DONE\n"); /* (1<<3) = no idle mode only for initial debugging */ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | OMAP_USBTLL_SYSCONFIG_SIDLEMODE | OMAP_USBTLL_SYSCONFIG_CACTIVITY); /* Put UHH in NoIdle/NoStandby mode */ reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG); if (is_omap_ehci_rev1(omap)) { reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP | OMAP_UHH_SYSCONFIG_SIDLEMODE | OMAP_UHH_SYSCONFIG_CACTIVITY | OMAP_UHH_SYSCONFIG_MIDLEMODE); reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; } else if (is_omap_ehci_rev2(omap)) { reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR; reg |= OMAP4_UHH_SYSCONFIG_NOIDLE; reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR; reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY; } ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG); /* setup ULPI bypass and burst configurations */ reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN | OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN); reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; if (is_omap_ehci_rev1(omap)) { if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN) reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN) reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS; if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN) reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; /* Bypass the TLL module for PHY mode operation */ if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) { dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n"); if (is_ehci_phy_mode(omap->port_mode[0]) || is_ehci_phy_mode(omap->port_mode[1]) || is_ehci_phy_mode(omap->port_mode[2])) reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; else reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; } else { dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n"); if (is_ehci_phy_mode(omap->port_mode[0])) reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; else if (is_ehci_tll_mode(omap->port_mode[0])) reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; if (is_ehci_phy_mode(omap->port_mode[1])) reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; else if (is_ehci_tll_mode(omap->port_mode[1])) reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; if (is_ehci_phy_mode(omap->port_mode[2])) reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; else if (is_ehci_tll_mode(omap->port_mode[2])) reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; } } else if (is_omap_ehci_rev2(omap)) { /* Clear port mode fields for PHY mode*/ reg &= ~OMAP4_P1_MODE_CLEAR; reg &= ~OMAP4_P2_MODE_CLEAR; if (is_ehci_tll_mode(omap->port_mode[0])) reg |= OMAP4_P1_MODE_TLL; else if (is_ehci_hsic_mode(omap->port_mode[0])) reg |= OMAP4_P1_MODE_HSIC; if (is_ehci_tll_mode(omap->port_mode[1])) reg |= OMAP4_P2_MODE_TLL; else if (is_ehci_hsic_mode(omap->port_mode[1])) reg |= OMAP4_P2_MODE_HSIC; } ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg); /* * An undocumented "feature" in the OMAP3 EHCI controller, * causes suspended ports to be taken out of suspend when * the USBCMD.Run/Stop bit is cleared (for example when * we do ehci_bus_suspend). * This breaks suspend-resume if the root-hub is allowed * to suspend. Writing 1 to this undocumented register bit * disables this feature and restores normal behavior. */ ehci_omap_writel(omap->ehci_base, EHCI_INSNREG04, EHCI_INSNREG04_DISABLE_UNSUSPEND); if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) || (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) || (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)) { if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) tll_ch_mask |= OMAP_TLL_CHANNEL_1_EN_MASK; if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) tll_ch_mask |= OMAP_TLL_CHANNEL_2_EN_MASK; if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL) tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK; /* Enable UTMI mode for required TLL channels */ omap_usb_utmi_init(omap, tll_ch_mask, OMAP_TLL_CHANNEL_COUNT); } if (omap->phy_reset) { /* Refer ISSUE1: * Hold the PHY in RESET for enough time till * PHY is settled and ready */ udelay(10); if (gpio_is_valid(omap->reset_gpio_port[0])) gpio_set_value(omap->reset_gpio_port[0], 1); if (gpio_is_valid(omap->reset_gpio_port[1])) gpio_set_value(omap->reset_gpio_port[1], 1); } /* Soft reset the PHY using PHY reset command over ULPI */ if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) omap_ehci_soft_phy_reset(omap, 0); if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) omap_ehci_soft_phy_reset(omap, 1); return 0; err_sys_status: clk_disable(omap->utmi_p2_fck); clk_put(omap->utmi_p2_fck); clk_disable(omap->xclk60mhsp2_ck); clk_put(omap->xclk60mhsp2_ck); clk_disable(omap->utmi_p1_fck); clk_put(omap->utmi_p1_fck); clk_disable(omap->xclk60mhsp1_ck); clk_put(omap->xclk60mhsp1_ck); clk_disable(omap->usbtll_ick); clk_put(omap->usbtll_ick); err_tll_ick: clk_disable(omap->usbtll_fck); clk_put(omap->usbtll_fck); err_tll_fck: clk_disable(omap->usbhost_fs_fck); clk_put(omap->usbhost_fs_fck); if (omap->phy_reset) { if (gpio_is_valid(omap->reset_gpio_port[0])) gpio_free(omap->reset_gpio_port[0]); if (gpio_is_valid(omap->reset_gpio_port[1])) gpio_free(omap->reset_gpio_port[1]); } err_host_48m_fck: clk_disable(omap->usbhost_hs_fck); clk_put(omap->usbhost_hs_fck); err_host_120m_fck: clk_disable(omap->usbhost_ick); clk_put(omap->usbhost_ick); err_host_ick: return ret; }
/* omap_start_ehc * - Start the TI USBHOST controller */ static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd) { u32 uhh_hostconfig_value = 0; struct ehci_omap_clock_defs *ehci_clocks; dev_dbg(hcd->self.controller, "starting TI EHCI USB Controller\n"); ehci_clocks = (struct ehci_omap_clock_defs *)( ((char *)hcd_to_ehci(hcd)) + sizeof(struct ehci_hcd)); /* Start DPLL5 Programming: * Clock Framework is not doing this now: * This will be done in clock framework later */ /* Enable DPLL 5 : Based on Input of 13Mhz*/ cm_write_mod_reg((12 << OMAP3430ES2_PERIPH2_DPLL_DIV_SHIFT)| (120 << OMAP3430ES2_PERIPH2_DPLL_MULT_SHIFT), PLL_MOD, OMAP3430ES2_CM_CLKSEL4); cm_write_mod_reg(1 << OMAP3430ES2_DIV_120M_SHIFT, PLL_MOD, OMAP3430ES2_CM_CLKSEL5); cm_write_mod_reg((7 << OMAP3430ES2_PERIPH2_DPLL_FREQSEL_SHIFT) | (7 << OMAP3430ES2_EN_PERIPH2_DPLL_SHIFT), PLL_MOD, OMAP3430ES2_CM_CLKEN2); #if 0 /* initialization stucks here when EHCI built as module */ while (!(cm_read_mod_reg(PLL_MOD, CM_IDLEST2) & OMAP3430ES2_ST_PERIPH2_CLK_MASK)) dev_dbg(hcd->self.controller, "idlest2 = 0x%x\n", cm_read_mod_reg(PLL_MOD, CM_IDLEST2)); #endif /* End DPLL5 programming */ /* PRCM settings for USBHOST: * Interface clk un-related to domain transition */ cm_write_mod_reg(0 << OMAP3430ES2_AUTO_USBHOST_SHIFT, OMAP3430ES2_USBHOST_MOD, CM_AUTOIDLE); /* Disable sleep dependency with MPU and IVA */ cm_write_mod_reg((0 << OMAP3430ES2_EN_MPU_SHIFT) | (0 << OMAP3430ES2_EN_IVA2_SHIFT), OMAP3430ES2_USBHOST_MOD, OMAP3430_CM_SLEEPDEP); /* Disable Automatic transition of clock */ cm_write_mod_reg(0 << OMAP3430ES2_CLKTRCTRL_USBHOST_SHIFT, OMAP3430ES2_USBHOST_MOD, CM_CLKSTCTRL); /* Enable Clocks for USBHOST */ ehci_clocks->usbhost_ick_clk = clk_get(&dev->dev, USBHOST_ICKL); if (IS_ERR(ehci_clocks->usbhost_ick_clk)) return PTR_ERR(ehci_clocks->usbhost_ick_clk); clk_enable(ehci_clocks->usbhost_ick_clk); ehci_clocks->usbhost2_120m_fck_clk = clk_get(&dev->dev, USBHOST_120M_FCLK); if (IS_ERR(ehci_clocks->usbhost2_120m_fck_clk)) return PTR_ERR(ehci_clocks->usbhost2_120m_fck_clk); clk_enable(ehci_clocks->usbhost2_120m_fck_clk); ehci_clocks->usbhost1_48m_fck_clk = clk_get(&dev->dev, USBHOST_48M_FCLK); if (IS_ERR(ehci_clocks->usbhost1_48m_fck_clk)) return PTR_ERR(ehci_clocks->usbhost1_48m_fck_clk); clk_enable(ehci_clocks->usbhost1_48m_fck_clk); /* get phy reset gpio number */ EXT_PHY_RESET_GPIO_PORT2 = omap3_ehci_phy_reset_gpio; #ifdef EXTERNAL_PHY_RESET /* Refer: ISSUE1 */ #ifdef CONFIG_OMAP3430SDP_750_2083_001 gpio_request(EXT_PHY_RESET_GPIO_PORT1, "USB1 PHY reset"); gpio_direction_output(EXT_PHY_RESET_GPIO_PORT1, 0); gpio_set_value(EXT_PHY_RESET_GPIO_PORT1, 0); #endif gpio_request(EXT_PHY_RESET_GPIO_PORT2, "USB2 PHY reset"); gpio_direction_output(EXT_PHY_RESET_GPIO_PORT2, 0); gpio_set_value(EXT_PHY_RESET_GPIO_PORT2, 0); /* Hold the PHY in RESET for enough time till DIR is high */ udelay(EXT_PHY_RESET_DELAY); #endif /* Configure TLL for 60Mhz clk for ULPI */ ehci_clocks->usbtll_fck_clk = clk_get(&dev->dev, USBHOST_TLL_FCLK); if (IS_ERR(ehci_clocks->usbtll_fck_clk)) return PTR_ERR(ehci_clocks->usbtll_fck_clk); clk_enable(ehci_clocks->usbtll_fck_clk); ehci_clocks->usbtll_ick_clk = clk_get(&dev->dev, USBHOST_TLL_ICKL); if (IS_ERR(ehci_clocks->usbtll_ick_clk)) return PTR_ERR(ehci_clocks->usbtll_ick_clk); clk_enable(ehci_clocks->usbtll_ick_clk); /* Disable Auto Idle of USBTLL */ cm_write_mod_reg((0 << OMAP3430ES2_AUTO_USBTLL_SHIFT), CORE_MOD, CM_AUTOIDLE3); /* Wait for TLL to be Active */ while ((cm_read_mod_reg(CORE_MOD, OMAP2430_CM_IDLEST3) & (1 << OMAP3430ES2_ST_USBTLL_SHIFT))) cpu_relax(); /* perform TLL soft reset, and wait until reset is complete */ omap_writel(1 << OMAP_USBTLL_SYSCONFIG_SOFTRESET_SHIFT, OMAP_USBTLL_SYSCONFIG); /* Wait for TLL reset to complete */ while (!(omap_readl(OMAP_USBTLL_SYSSTATUS) & (1 << OMAP_USBTLL_SYSSTATUS_RESETDONE_SHIFT))) cpu_relax(); dev_dbg(hcd->self.controller, "TLL RESET DONE\n"); /* (1<<3) = no idle mode only for initial debugging */ omap_writel((1 << OMAP_USBTLL_SYSCONFIG_ENAWAKEUP_SHIFT) | (1 << OMAP_USBTLL_SYSCONFIG_SIDLEMODE_SHIFT) | (1 << OMAP_USBTLL_SYSCONFIG_CACTIVITY_SHIFT), OMAP_USBTLL_SYSCONFIG); /* Put UHH in NoIdle/NoStandby mode */ omap_writel((0 << OMAP_UHH_SYSCONFIG_AUTOIDLE_SHIFT) | (1 << OMAP_UHH_SYSCONFIG_ENAWAKEUP_SHIFT) | (1 << OMAP_UHH_SYSCONFIG_SIDLEMODE_SHIFT) | (1 << OMAP_UHH_SYSCONFIG_CACTIVITY_SHIFT) | (1 << OMAP_UHH_SYSCONFIG_MIDLEMODE_SHIFT), OMAP_UHH_SYSCONFIG); /* Bypass the TLL module for PHY mode operation */ uhh_hostconfig_value = (1 << OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN_SHIFT) | (1 << OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN_SHIFT) | (1 << OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN_SHIFT) | (0 << OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN_SHIFT); /* For ES 3, we have per-port control for the ULPI Bypass * The ULPI Bypass needs to be set to 0 only if the EHCI PHY Mode * is selected for that port. * ES 2 does not have per-port control. Hence it is not possible to have * EHCI in PHY Mode and OHCI both working at the same time */ if (omap_rev_ge30()) { #ifndef CONFIG_OMAP_EHCI_PHY_MODE_PORT1 uhh_hostconfig_value |= (1 << OMAP_UHH_HOSTCONFIG_P1_ULPI_BYPASS_SHIFT); #endif #ifndef CONFIG_OMAP_EHCI_PHY_MODE_PORT2 uhh_hostconfig_value |= (1 << OMAP_UHH_HOSTCONFIG_P2_ULPI_BYPASS_SHIFT); #endif #ifndef CONFIG_OMAP_EHCI_PHY_MODE_PORT3 uhh_hostconfig_value |= (1 << OMAP_UHH_HOSTCONFIG_P3_ULPI_BYPASS_SHIFT); #endif } else { #if defined(CONFIG_OMAP_EHCI_PHY_MODE_PORT1) || \ defined(CONFIG_OMAP_EHCI_PHY_MODE_PORT2) || \ defined(CONFIG_OMAP_EHCI_PHY_MODE_PORT3) uhh_hostconfig_value |= (0 << OMAP_UHH_HOSTCONFIG_P1_ULPI_BYPASS_SHIFT); #else uhh_hostconfig_value |= (1 << OMAP_UHH_HOSTCONFIG_P1_ULPI_BYPASS_SHIFT); #endif } omap_writel(uhh_hostconfig_value, OMAP_UHH_HOSTCONFIG); if (omap_rev_le21()) { /* Ensure that BYPASS is set */ while (omap_readl(OMAP_UHH_HOSTCONFIG) & (1 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT)) cpu_relax(); } dev_dbg(hcd->self.controller, "Entered ULPI PHY MODE: success\n"); #if defined(CONFIG_OMAP_EHCI_TLL_MODE_PORT1) || \ defined(CONFIG_OMAP_EHCI_TLL_MODE_PORT2) || \ defined(CONFIG_OMAP_EHCI_TLL_MODE_PORT3) /* Enable UTMI mode for all selected TLL channels */ omap_usb_utmi_init(hcd, 0 #ifdef CONFIG_OMAP_EHCI_TLL_MODE_PORT1 | OMAP_TLL_CHANNEL_1_EN_MASK #endif #ifdef CONFIG_OMAP_EHCI_TLL_MODE_PORT2 | OMAP_TLL_CHANNEL_2_EN_MASK #endif #ifdef CONFIG_OMAP_EHCI_TLL_MODE_PORT3 | OMAP_TLL_CHANNEL_3_EN_MASK #endif ); #endif #ifdef EXTERNAL_PHY_RESET /* Refer ISSUE1: * Hold the PHY in RESET for enough time till PHY is settled and ready */ udelay(EXT_PHY_RESET_DELAY); #ifdef CONFIG_OMAP3430SDP_750_2083_001 gpio_set_value(EXT_PHY_RESET_GPIO_PORT1, 1); #endif gpio_set_value(EXT_PHY_RESET_GPIO_PORT2, 1); #endif #ifdef VBUS_INTERNAL_CHARGEPUMP_HACK /* Refer ISSUE2: LINK assumes external charge pump */ /* use Port1 VBUS to charge externally Port2: * So for PHY mode operation use Port2 only */ omap_writel((0xA << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* OTG ctrl reg*/ (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/* Write */ (1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |/* Port1 */ (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |/* Start */ (0x26), EHCI_INSNREG05_ULPI); while (!(omap_readl(EHCI_INSNREG05_ULPI) & (1<<EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) cpu_relax(); #endif return 0; }