diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 15 | ||||
-rw-r--r-- | drivers/usb/host/ehci-mx5.c | 15 | ||||
-rw-r--r-- | drivers/usb/host/ehci-omap.c | 60 | ||||
-rw-r--r-- | drivers/usb/host/ehci.h | 13 |
4 files changed, 66 insertions, 37 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 706cf0cb7d..fdad739724 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -36,16 +36,7 @@ #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 #endif -static struct ehci_ctrl { - struct ehci_hccr *hccr; /* R/O registers, not need for volatile */ - struct ehci_hcor *hcor; - int rootdev; - uint16_t portreset; - struct QH qh_list __aligned(USB_DMA_MINALIGN); - struct QH periodic_queue __aligned(USB_DMA_MINALIGN); - uint32_t *periodic_list; - int ntds; -} ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT]; +static struct ehci_ctrl ehcic[CONFIG_USB_MAX_CONTROLLER_COUNT]; #define ALIGN_END_ADDR(type, ptr, size) \ ((uint32_t)(ptr) + roundup((size) * sizeof(type), USB_DMA_MINALIGN)) @@ -954,7 +945,9 @@ int usb_lowlevel_init(int index, void **controller) * Split Transactions will be spread across microframes using * S-mask and C-mask. */ - ehcic[index].periodic_list = memalign(4096, 1024*4); + if (ehcic[index].periodic_list == NULL) + ehcic[index].periodic_list = memalign(4096, 1024 * 4); + if (!ehcic[index].periodic_list) return -ENOMEM; for (i = 0; i < 1024; i++) { diff --git a/drivers/usb/host/ehci-mx5.c b/drivers/usb/host/ehci-mx5.c index 3548620eca..dd11f535ad 100644 --- a/drivers/usb/host/ehci-mx5.c +++ b/drivers/usb/host/ehci-mx5.c @@ -221,21 +221,12 @@ void __weak board_ehci_hcd_postinit(struct usb_ehci *ehci, int port) int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor) { struct usb_ehci *ehci; -#ifdef CONFIG_MX53 - struct clkctl *sc_regs = (struct clkctl *)CCM_BASE_ADDR; - u32 reg; - - reg = __raw_readl(&sc_regs->cscmr1) & ~(1 << 26); - /* derive USB PHY clock multiplexer from PLL3 */ - reg |= 1 << 26; - __raw_writel(reg, &sc_regs->cscmr1); -#endif set_usboh3_clk(); - enable_usboh3_clk(1); + enable_usboh3_clk(true); set_usb_phy_clk(); - enable_usb_phy1_clk(1); - enable_usb_phy2_clk(1); + enable_usb_phy1_clk(true); + enable_usb_phy2_clk(true); mdelay(1); /* Do board specific initialization */ diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index a47e078f62..3c58f9e656 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -28,18 +28,21 @@ static struct omap_ehci *const ehci = (struct omap_ehci *)OMAP_EHCI_BASE; static int omap_uhh_reset(void) { - unsigned long init = get_timer(0); - - /* perform UHH soft reset, and wait until reset is complete */ - writel(OMAP_UHH_SYSCONFIG_SOFTRESET, &uhh->sysc); - - /* Wait for UHH reset to complete */ - while (!(readl(&uhh->syss) & OMAP_UHH_SYSSTATUS_EHCI_RESETDONE)) - if (get_timer(init) > CONFIG_SYS_HZ) { - debug("OMAP UHH error: timeout resetting ehci\n"); - return -EL3RST; - } - +/* + * Soft resetting the UHH module causes instability issues on + * all OMAPs so we just avoid it. + * + * See OMAP36xx Errata + * i571: USB host EHCI may stall when entering smart-standby mode + * i660: USBHOST Configured In Smart-Idle Can Lead To a Deadlock + * + * On OMAP4/5, soft-resetting the UHH module will put it into + * Smart-Idle mode and lead to a deadlock. + * + * On OMAP3, this doesn't seem to be the case but still instabilities + * are observed on beagle (3530 ES1.0) if soft-reset is used. + * e.g. NFS root failures with Linux kernel. + */ return 0; } @@ -76,6 +79,7 @@ static void omap_usbhs_hsic_init(int port) writel(reg, &usbtll->channel_conf + port); } +#ifdef CONFIG_USB_ULPI static void omap_ehci_soft_phy_reset(int port) { struct ulpi_viewport ulpi_vp; @@ -85,6 +89,12 @@ static void omap_ehci_soft_phy_reset(int port) ulpi_reset(&ulpi_vp); } +#else +static void omap_ehci_soft_phy_reset(int port) +{ + return; +} +#endif inline int __board_usb_init(void) { @@ -93,7 +103,8 @@ inline int __board_usb_init(void) int board_usb_init(void) __attribute__((weak, alias("__board_usb_init"))); #if defined(CONFIG_OMAP_EHCI_PHY1_RESET_GPIO) || \ - defined(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO) + defined(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO) || \ + defined(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO) /* controls PHY(s) reset signal(s) */ static inline void omap_ehci_phy_reset(int on, int delay) { @@ -112,6 +123,10 @@ static inline void omap_ehci_phy_reset(int on, int delay) gpio_request(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO, "USB PHY2 reset"); gpio_direction_output(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO, !on); #endif +#ifdef CONFIG_OMAP_EHCI_PHY3_RESET_GPIO + gpio_request(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO, "USB PHY3 reset"); + gpio_direction_output(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO, !on); +#endif /* Hold the PHY in RESET for enough time till DIR is high */ /* Refer: ISSUE1 */ @@ -195,10 +210,27 @@ int omap_ehci_hcd_init(struct omap_usbhs_board_data *usbhs_pdata, else setbits_le32(®, OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS); } else if (rev == OMAP_USBHS_REV2) { + clrsetbits_le32(®, (OMAP_P1_MODE_CLEAR | OMAP_P2_MODE_CLEAR), OMAP4_UHH_HOSTCONFIG_APP_START_CLK); - /* Clear port mode fields for PHY mode*/ + /* Clear port mode fields for PHY mode */ + + if (is_ehci_hsic_mode(usbhs_pdata->port_mode[0])) + setbits_le32(®, OMAP_P1_MODE_HSIC); + + if (is_ehci_hsic_mode(usbhs_pdata->port_mode[1])) + setbits_le32(®, OMAP_P2_MODE_HSIC); + + } else if (rev == OMAP_USBHS_REV2_1) { + + clrsetbits_le32(®, + (OMAP_P1_MODE_CLEAR | + OMAP_P2_MODE_CLEAR | + OMAP_P3_MODE_CLEAR), + OMAP4_UHH_HOSTCONFIG_APP_START_CLK); + + /* Clear port mode fields for PHY mode */ if (is_ehci_hsic_mode(usbhs_pdata->port_mode[0])) setbits_le32(®, OMAP_P1_MODE_HSIC); diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index d090f0a53e..bd52afe262 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -22,6 +22,8 @@ #ifndef USB_EHCI_H #define USB_EHCI_H +#include <usb.h> + #if !defined(CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) #define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 2 #endif @@ -252,6 +254,17 @@ struct QH { }; }; +struct ehci_ctrl { + struct ehci_hccr *hccr; /* R/O registers, not need for volatile */ + struct ehci_hcor *hcor; + int rootdev; + uint16_t portreset; + struct QH qh_list __aligned(USB_DMA_MINALIGN); + struct QH periodic_queue __aligned(USB_DMA_MINALIGN); + uint32_t *periodic_list; + int ntds; +}; + /* Low level init functions */ int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor); int ehci_hcd_stop(int index); |