From e38ff30a556fa02fd406cf73387e227b459cc49a Mon Sep 17 00:00:00 2001 From: Adrian Alonso Date: Thu, 6 Aug 2015 15:43:15 -0500 Subject: [PATCH 01/11] imx: usb: ehci-mx6: reg accessor cleanups Cleanup read/write register access, use clr/set bits_le32 Signed-off-by: Adrian Alonso --- drivers/usb/host/ehci-mx6.c | 51 +++++++++++++------------------------ 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index 951dd3b25f..0f94c8b6fb 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -67,7 +67,7 @@ static void usb_internal_phy_clock_gate(int index, int on) phy_reg = (void __iomem *)phy_bases[index]; phy_reg += on ? USBPHY_CTRL_CLR : USBPHY_CTRL_SET; - __raw_writel(USBPHY_CTRL_CLKGATE, phy_reg); + writel(USBPHY_CTRL_CLKGATE, phy_reg); } static void usb_power_config(int index) @@ -100,14 +100,14 @@ static void usb_power_config(int index) * is totally controlled by IC, so the Software only needs * to enable them at initializtion. */ - __raw_writel(ANADIG_USB2_CHRG_DETECT_EN_B | + writel(ANADIG_USB2_CHRG_DETECT_EN_B | ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, chrg_detect); - __raw_writel(ANADIG_USB2_PLL_480_CTRL_BYPASS, + writel(ANADIG_USB2_PLL_480_CTRL_BYPASS, pll_480_ctrl_clr); - __raw_writel(ANADIG_USB2_PLL_480_CTRL_ENABLE | + writel(ANADIG_USB2_PLL_480_CTRL_ENABLE | ANADIG_USB2_PLL_480_CTRL_POWER | ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS, pll_480_ctrl_set); @@ -119,7 +119,6 @@ static int usb_phy_enable(int index, struct usb_ehci *ehci) void __iomem *phy_reg; void __iomem *phy_ctrl; void __iomem *usb_cmd; - u32 val; if (index >= ARRAY_SIZE(phy_bases)) return 0; @@ -129,36 +128,27 @@ static int usb_phy_enable(int index, struct usb_ehci *ehci) usb_cmd = (void __iomem *)&ehci->usbcmd; /* Stop then Reset */ - val = __raw_readl(usb_cmd); - val &= ~UCMD_RUN_STOP; - __raw_writel(val, usb_cmd); - while (__raw_readl(usb_cmd) & UCMD_RUN_STOP) + clrbits_le32(usb_cmd, UCMD_RUN_STOP); + while (readl(usb_cmd) & UCMD_RUN_STOP) ; - val = __raw_readl(usb_cmd); - val |= UCMD_RESET; - __raw_writel(val, usb_cmd); - while (__raw_readl(usb_cmd) & UCMD_RESET) + setbits_le32(usb_cmd, UCMD_RESET); + while (readl(usb_cmd) & UCMD_RESET) ; /* Reset USBPHY module */ - val = __raw_readl(phy_ctrl); - val |= USBPHY_CTRL_SFTRST; - __raw_writel(val, phy_ctrl); + setbits_le32(phy_ctrl, USBPHY_CTRL_SFTRST); udelay(10); /* Remove CLKGATE and SFTRST */ - val = __raw_readl(phy_ctrl); - val &= ~(USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST); - __raw_writel(val, phy_ctrl); + clrbits_le32(phy_ctrl, USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST); udelay(10); /* Power up the PHY */ - __raw_writel(0, phy_reg + USBPHY_PWD); + writel(0, phy_reg + USBPHY_PWD); /* enable FS/LS device */ - val = __raw_readl(phy_ctrl); - val |= (USBPHY_CTRL_ENUTMILEVEL2 | USBPHY_CTRL_ENUTMILEVEL3); - __raw_writel(val, phy_ctrl); + setbits_le32(phy_ctrl, USBPHY_CTRL_ENUTMILEVEL2 | + USBPHY_CTRL_ENUTMILEVEL3); return 0; } @@ -177,20 +167,15 @@ static void usb_oc_config(int index) struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR + USB_OTHERREGS_OFFSET); void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl[index]); - u32 val; - val = __raw_readl(ctrl); #if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2 /* mx6qarm2 seems to required a different setting*/ - val &= ~UCTRL_OVER_CUR_POL; + clrbits_le32(ctrl, UCTRL_OVER_CUR_POL); #else - val |= UCTRL_OVER_CUR_POL; + setbits_le32(ctrl, UCTRL_OVER_CUR_POL); #endif - __raw_writel(val, ctrl); - val = __raw_readl(ctrl); - val |= UCTRL_OVER_CUR_DIS; - __raw_writel(val, ctrl); + setbits_le32(ctrl, UCTRL_OVER_CUR_DIS); } int usb_phy_mode(int port) @@ -202,7 +187,7 @@ int usb_phy_mode(int port) phy_reg = (void __iomem *)phy_bases[port]; phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL); - val = __raw_readl(phy_ctrl); + val = readl(phy_ctrl); if (val & USBPHY_CTRL_OTG_ID) return USB_INIT_DEVICE; @@ -257,7 +242,7 @@ int ehci_hcd_init(int index, enum usb_init_type init, if (type == USB_INIT_DEVICE) return 0; setbits_le32(&ehci->usbmode, CM_HOST); - __raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); + writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); setbits_le32(&ehci->portsc, USB_EN); mdelay(10); From 74f0610eb4852f97e57cdec5c86828dd8076be94 Mon Sep 17 00:00:00 2001 From: Adrian Alonso Date: Thu, 6 Aug 2015 15:43:16 -0500 Subject: [PATCH 02/11] imx: usb: ehci-mx6: document board specific functions Document target board specific functions board_ehci_hcd_init - override usb phy mode board_ehci_hcd_init - set usb vbus voltage board_ehci_power - enables/disables usb vbus voltage Signed-off-by: Adrian Alonso --- drivers/usb/host/ehci-mx6.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index 0f94c8b6fb..1f5b0560db 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -195,16 +195,47 @@ int usb_phy_mode(int port) return USB_INIT_HOST; } +/** + * board_ehci_hcd_init - override usb phy mode + * @port: usb host/otg port + * + * Target board specific, override usb_phy_mode. + * When usb-otg is used as usb host port, iomux pad usb_otg_id can be + * left disconnected in this case usb_phy_mode will not be able to identify + * the phy mode that usb port is used. + * Machine file overrides board_usb_phy_mode. + * + * Return: USB_INIT_DEVICE or USB_INIT_HOST + */ int __weak board_usb_phy_mode(int port) { return usb_phy_mode(port); } +/** + * board_ehci_hcd_init - set usb vbus voltage + * @port: usb otg port + * + * Target board specific, setup iomux pad to setup supply vbus voltage + * for usb otg port. Machine board file overrides board_ehci_hcd_init + * + * Return: 0 Success + */ int __weak board_ehci_hcd_init(int port) { return 0; } +/** + * board_ehci_power - enables/disables usb vbus voltage + * @port: usb otg port + * @on: on/off vbus voltage + * + * Enables/disables supply vbus voltage for usb otg port. + * Machine board file overrides board_ehci_power + * + * Return: 0 Success + */ int __weak board_ehci_power(int port, int on) { return 0; From 35554fc9a194802a43d50b16e92f4efc7f72bd94 Mon Sep 17 00:00:00 2001 From: Adrian Alonso Date: Thu, 6 Aug 2015 15:43:17 -0500 Subject: [PATCH 03/11] imx: usb: ehci-mx6: add usb support for imx7d soc Extend ehci-mx6 usb driver to support imx7d usb Signed-off-by: Adrian Alonso --- drivers/usb/host/Makefile | 1 + drivers/usb/host/ehci-mx6.c | 116 +++++++++++++++++++++++++++--------- 2 files changed, 90 insertions(+), 27 deletions(-) diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 7f07d7734a..f70f38c9e8 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o obj-$(CONFIG_USB_EHCI_MXS) += ehci-mxs.o obj-$(CONFIG_USB_EHCI_MX5) += ehci-mx5.o obj-$(CONFIG_USB_EHCI_MX6) += ehci-mx6.o +obj-$(CONFIG_USB_EHCI_MX7) += ehci-mx6.o obj-$(CONFIG_USB_EHCI_OMAP) += ehci-omap.o obj-$(CONFIG_USB_EHCI_PPC4XX) += ehci-ppc4xx.o obj-$(CONFIG_USB_EHCI_MARVELL) += ehci-marvell.o diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index 1f5b0560db..54f868420d 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -45,7 +45,10 @@ #define ANADIG_USB2_PLL_480_CTRL_POWER 0x00001000 #define ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS 0x00000040 - +#define USBNC_OFFSET 0x200 +#define USBNC_PHYSTATUS_ID_DIG (1 << 4) /* otg_id status */ +#define USBNC_PHYCFG2_ACAENB (1 << 4) /* otg_id detection enable */ +#define UCTRL_PM (1 << 9) /* OTG Power Mask */ #define UCTRL_OVER_CUR_POL (1 << 8) /* OTG Polarity of Overcurrent */ #define UCTRL_OVER_CUR_DIS (1 << 7) /* Disable OTG Overcurrent Detection */ @@ -53,6 +56,7 @@ #define UCMD_RUN_STOP (1 << 0) /* controller run/stop */ #define UCMD_RESET (1 << 1) /* controller reset */ +#if defined(CONFIG_MX6) static const unsigned phy_bases[] = { USB_PHY0_BASE_ADDR, USB_PHY1_BASE_ADDR, @@ -153,31 +157,6 @@ static int usb_phy_enable(int index, struct usb_ehci *ehci) return 0; } -/* Base address for this IP block is 0x02184800 */ -struct usbnc_regs { - u32 ctrl[4]; /* otg/host1-3 */ - u32 uh2_hsic_ctrl; - u32 uh3_hsic_ctrl; - u32 otg_phy_ctrl_0; - u32 uh1_phy_ctrl_0; -}; - -static void usb_oc_config(int index) -{ - struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR + - USB_OTHERREGS_OFFSET); - void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl[index]); - -#if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2 - /* mx6qarm2 seems to required a different setting*/ - clrbits_le32(ctrl, UCTRL_OVER_CUR_POL); -#else - setbits_le32(ctrl, UCTRL_OVER_CUR_POL); -#endif - - setbits_le32(ctrl, UCTRL_OVER_CUR_DIS); -} - int usb_phy_mode(int port) { void __iomem *phy_reg; @@ -195,6 +174,80 @@ int usb_phy_mode(int port) return USB_INIT_HOST; } +/* Base address for this IP block is 0x02184800 */ +struct usbnc_regs { + u32 ctrl[4]; /* otg/host1-3 */ + u32 uh2_hsic_ctrl; + u32 uh3_hsic_ctrl; + u32 otg_phy_ctrl_0; + u32 uh1_phy_ctrl_0; +}; +#elif defined(CONFIG_MX7) +struct usbnc_regs { + u32 ctrl1; + u32 ctrl2; + u32 reserve1[10]; + u32 phy_cfg1; + u32 phy_cfg2; + u32 phy_status; + u32 reserve2[4]; + u32 adp_cfg1; + u32 adp_cfg2; + u32 adp_status; +}; + +static void usb_power_config(int index) +{ + struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR + + (0x10000 * index) + USBNC_OFFSET); + void __iomem *phy_cfg2 = (void __iomem *)(&usbnc->phy_cfg2); + + /* Enable usb_otg_id detection */ + setbits_le32(phy_cfg2, USBNC_PHYCFG2_ACAENB); +} + +int usb_phy_mode(int port) +{ + struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR + + (0x10000 * port) + USBNC_OFFSET); + void __iomem *status = (void __iomem *)(&usbnc->phy_status); + u32 val; + + val = readl(status); + + if (val & USBNC_PHYSTATUS_ID_DIG) + return USB_INIT_DEVICE; + else + return USB_INIT_HOST; +} +#endif + +static void usb_oc_config(int index) +{ +#if defined(CONFIG_MX6) + struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR + + USB_OTHERREGS_OFFSET); + void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl[index]); +#elif defined(CONFIG_MX7) + struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR + + (0x10000 * index) + USBNC_OFFSET); + void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl1); +#endif + +#if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2 + /* mx6qarm2 seems to required a different setting*/ + clrbits_le32(ctrl, UCTRL_OVER_CUR_POL); +#else + setbits_le32(ctrl, UCTRL_OVER_CUR_POL); +#endif + +#if defined(CONFIG_MX6) + setbits_le32(ctrl, UCTRL_OVER_CUR_DIS); +#elif defined(CONFIG_MX7) + setbits_le32(ctrl, UCTRL_OVER_CUR_DIS | UCTRL_PM); +#endif +} + /** * board_ehci_hcd_init - override usb phy mode * @port: usb host/otg port @@ -245,8 +298,13 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, struct ehci_hcor **hcor) { enum usb_init_type type; +#if defined(CONFIG_MX6) + u32 controller_spacing = 0x200; +#elif defined(CONFIG_MX7) + u32 controller_spacing = 0x10000; +#endif struct usb_ehci *ehci = (struct usb_ehci *)(USB_BASE_ADDR + - (0x200 * index)); + (controller_spacing * index)); if (index > 3) return -EINVAL; @@ -258,8 +316,11 @@ int ehci_hcd_init(int index, enum usb_init_type init, usb_power_config(index); usb_oc_config(index); + +#if defined(CONFIG_MX6) usb_internal_phy_clock_gate(index, 1); usb_phy_enable(index, ehci); +#endif type = board_usb_phy_mode(index); *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); @@ -272,6 +333,7 @@ int ehci_hcd_init(int index, enum usb_init_type init, return -ENODEV; if (type == USB_INIT_DEVICE) return 0; + setbits_le32(&ehci->usbmode, CM_HOST); writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); setbits_le32(&ehci->portsc, USB_EN); From f0c89d5463d9d27679ca66b5bb86c161da15a3f7 Mon Sep 17 00:00:00 2001 From: Adrian Alonso Date: Thu, 6 Aug 2015 15:46:03 -0500 Subject: [PATCH 04/11] imx: usb: ehci-mx6: wait_for_bit to check reg status Add wait_for_bit to check reg bit status and replace unbounded loops to check usb command status Signed-off-by: Adrian Alonso --- drivers/usb/host/ehci-mx6.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index 54f868420d..2666351391 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -117,12 +117,39 @@ static void usb_power_config(int index) pll_480_ctrl_set); } +static int wait_for_bit(u32 *reg, const u32 mask, bool set) +{ + u32 val; + const unsigned int timeout = 10000; + unsigned long start = get_timer(0); + + while(1) { + val = readl(reg); + if (!set) + val = ~val; + + if ((val & mask) == mask) + return 0; + + if (get_timer(start) > timeout) + break; + + udelay(1); + } + + debug("%s: Timeout (reg=%p mask=%08x wait_set=%i)\n", + __func__, reg, mask, set); + + return -ETIMEDOUT; +} + /* Return 0 : host node, <>0 : device mode */ static int usb_phy_enable(int index, struct usb_ehci *ehci) { void __iomem *phy_reg; void __iomem *phy_ctrl; void __iomem *usb_cmd; + int ret; if (index >= ARRAY_SIZE(phy_bases)) return 0; @@ -133,12 +160,14 @@ static int usb_phy_enable(int index, struct usb_ehci *ehci) /* Stop then Reset */ clrbits_le32(usb_cmd, UCMD_RUN_STOP); - while (readl(usb_cmd) & UCMD_RUN_STOP) - ; + ret = wait_for_bit(usb_cmd, UCMD_RUN_STOP, 0); + if (ret) + return ret; setbits_le32(usb_cmd, UCMD_RESET); - while (readl(usb_cmd) & UCMD_RESET) - ; + ret = wait_for_bit(usb_cmd, UCMD_RESET, 0); + if (ret) + return ret; /* Reset USBPHY module */ setbits_le32(phy_ctrl, USBPHY_CTRL_SFTRST); From e8d056989a7302eda4e3ed263a375fd175a4e15f Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 18 Aug 2015 09:27:18 +0200 Subject: [PATCH 05/11] usb: spear: Add support for both SPEAr600 EHCI controllers USB EHCI on SPEAr600 has not been tested for a while. The base controller addresses are missing. This patch adds the defines to the header. And adds the missing code. Signed-off-by: Stefan Roese Cc: Viresh Kumar Cc: Vipin Kumar Cc: Marek Vasut --- arch/arm/cpu/arm926ejs/spear/cpu.c | 4 +++ arch/arm/include/asm/arch-spear/hardware.h | 2 ++ drivers/usb/host/ehci-spear.c | 38 ++++++++++++++++++++-- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/arch/arm/cpu/arm926ejs/spear/cpu.c b/arch/arm/cpu/arm926ejs/spear/cpu.c index 1ce9db7a7d..3037084b29 100644 --- a/arch/arm/cpu/arm926ejs/spear/cpu.c +++ b/arch/arm/cpu/arm926ejs/spear/cpu.c @@ -47,8 +47,12 @@ int arch_cpu_init(void) #if defined(CONFIG_NAND_FSMC) periph1_clken |= MISC_FSMCENB; #endif +#if defined(CONFIG_USB_EHCI_SPEAR) + periph1_clken |= PERIPH_USBH1 | PERIPH_USBH2; +#endif writel(periph1_clken, &misc_p->periph1_clken); + return 0; } diff --git a/arch/arm/include/asm/arch-spear/hardware.h b/arch/arm/include/asm/arch-spear/hardware.h index c6da405cc0..065360ab35 100644 --- a/arch/arm/include/asm/arch-spear/hardware.h +++ b/arch/arm/include/asm/arch-spear/hardware.h @@ -11,6 +11,8 @@ #define CONFIG_SYS_USBD_BASE 0xE1100000 #define CONFIG_SYS_PLUG_BASE 0xE1200000 #define CONFIG_SYS_FIFO_BASE 0xE1000800 +#define CONFIG_SYS_UHC0_EHCI_BASE 0xE1800000 +#define CONFIG_SYS_UHC1_EHCI_BASE 0xE2000000 #define CONFIG_SYS_SMI_BASE 0xFC000000 #define CONFIG_SPEAR_SYSCNTLBASE 0xFCA00000 #define CONFIG_SPEAR_TIMERBASE 0xFC800000 diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c index 210ee9e88e..9e90e18cfe 100644 --- a/drivers/usb/host/ehci-spear.c +++ b/drivers/usb/host/ehci-spear.c @@ -14,7 +14,21 @@ #include #include "ehci.h" #include +#include +static void spear6xx_usbh_stop(void) +{ + struct misc_regs *const misc_p = + (struct misc_regs *)CONFIG_SPEAR_MISCBASE; + u32 periph1_rst = readl(misc_p->periph1_rst); + + periph1_rst |= PERIPH_USBH1 | PERIPH_USBH2; + writel(periph1_rst, misc_p->periph1_rst); + + udelay(1000); + periph1_rst &= ~(PERIPH_USBH1 | PERIPH_USBH2); + writel(periph1_rst, misc_p->periph1_rst); +} /* * Create the appropriate control structures to manage @@ -23,9 +37,23 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, struct ehci_hcor **hcor) { - *hccr = (struct ehci_hccr *)(CONFIG_SYS_UHC0_EHCI_BASE + 0x100); - *hcor = (struct ehci_hcor *)((uint32_t)*hccr - + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); + u32 ehci = 0; + + switch (index) { + case 0: + ehci = CONFIG_SYS_UHC0_EHCI_BASE; + break; + case 1: + ehci = CONFIG_SYS_UHC1_EHCI_BASE; + break; + default: + printf("ERROR: wrong controller index!\n"); + break; + }; + + *hccr = (struct ehci_hccr *)(ehci + 0x100); + *hcor = (struct ehci_hcor *)((uint32_t) *hccr + + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); debug("SPEAr-ehci: init hccr %x and hcor %x hc_length %d\n", (uint32_t)*hccr, (uint32_t)*hcor, @@ -40,5 +68,9 @@ int ehci_hcd_init(int index, enum usb_init_type init, */ int ehci_hcd_stop(int index) { +#if defined(CONFIG_SPEAR600) + spear6xx_usbh_stop(); +#endif + return 0; } From a5ccda47f1587180b70c634ba4cb7f8d151f408a Mon Sep 17 00:00:00 2001 From: Sergey Temerkhanov Date: Mon, 17 Aug 2015 15:38:07 +0300 Subject: [PATCH 06/11] usb: xhci: Fix a potential NULL pointer dereference This patch fixes a potential NULL pointer dereference arising on non-present/non-initialized xHCI controllers and adds some error handling to xHCI code Signed-off-by: Sergey Temerkhanov Signed-off-by: Radha Mohan Chintakuntla --- drivers/usb/host/xhci.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 0b09643e09..307e1a6f61 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -199,7 +199,7 @@ int xhci_reset(struct xhci_hcor *hcor) int ret; /* Halting the Host first */ - debug("// Halt the HC\n"); + debug("// Halt the HC: %p\n", hcor); state = xhci_readl(&hcor->or_usbsts) & STS_HALT; if (!state) { cmd = xhci_readl(&hcor->or_usbcmd); @@ -1064,6 +1064,8 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) struct xhci_ctrl *ctrl; int ret; + *controller = NULL; + if (xhci_hcd_init(index, &hccr, (struct xhci_hcor **)&hcor) != 0) return -ENODEV; @@ -1077,7 +1079,12 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller) ret = xhci_lowlevel_init(ctrl); - *controller = &xhcic[index]; + if (ret) { + ctrl->hccr = NULL; + ctrl->hcor = NULL; + } else { + *controller = &xhcic[index]; + } return ret; } @@ -1093,9 +1100,11 @@ int usb_lowlevel_stop(int index) { struct xhci_ctrl *ctrl = (xhcic + index); - xhci_lowlevel_stop(ctrl); - xhci_hcd_stop(index); - xhci_cleanup(ctrl); + if (ctrl->hcor) { + xhci_lowlevel_stop(ctrl); + xhci_hcd_stop(index); + xhci_cleanup(ctrl); + } return 0; } From 8bfc288c395584101f4a7fb545c4e79f3fb85c3e Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Wed, 19 Aug 2015 13:49:46 +0530 Subject: [PATCH 07/11] usb: gadget: ether: Perform board initialization from ethernet gadget driver Ethernet gadget driver can be used both by both SPL and u-boot. Since usb_eth_init() is the entry point for ethernet gadget driver, perform board initialization there. Also perform the cleanup in usb_eth_halt. Signed-off-by: Kishon Vijay Abraham I Acked-by: Marek Vasut Reviewed-by: Tom Rini Reviewed-by: Lukasz Majewski --- drivers/usb/gadget/ether.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 141ff8be59..850ba029ab 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -2312,6 +2313,8 @@ static int usb_eth_init(struct eth_device *netdev, bd_t *bd) goto fail; } + board_usb_init(0, USB_INIT_DEVICE); + /* Configure default mac-addresses for the USB ethernet device */ #ifdef CONFIG_USBNET_DEV_ADDR strlcpy(dev_addr, CONFIG_USBNET_DEV_ADDR, sizeof(dev_addr)); @@ -2492,6 +2495,7 @@ void usb_eth_halt(struct eth_device *netdev) } usb_gadget_unregister_driver(ð_driver); + board_usb_cleanup(0, USB_INIT_DEVICE); } static struct usb_gadget_driver eth_driver = { From f18114436137f43fff7d325b4f5d9c6b5ba9551c Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Wed, 19 Aug 2015 13:49:47 +0530 Subject: [PATCH 08/11] usb: host: xhci-omap: invoke board_usb_cleanup in xhci_hcd_stop xhci omap driver has board_usb_init in xhci_hcd_init but doesn't have the corresponding cleanup function in xhci_hcd_stop. Fix it here by invoking board_usb_cleanup() in xhci_hcd_stop(). Signed-off-by: Kishon Vijay Abraham I Acked-by: Marek Vasut Reviewed-by: Tom Rini Reviewed-by: Lukasz Majewski --- drivers/usb/host/xhci-omap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/xhci-omap.c b/drivers/usb/host/xhci-omap.c index 3a55208384..104e7a7282 100644 --- a/drivers/usb/host/xhci-omap.c +++ b/drivers/usb/host/xhci-omap.c @@ -96,4 +96,5 @@ void xhci_hcd_stop(int index) struct omap_xhci *ctx = &omap; omap_xhci_core_exit(ctx); + board_usb_cleanup(index, USB_INIT_HOST); } From 5df131521194a9ae361930089fb340d712c54eee Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Wed, 19 Aug 2015 13:49:48 +0530 Subject: [PATCH 09/11] usb: gadget: ether: populate _reset_ callback populate _reset_ callback to the USB ethernet gadget since UDC core expects every gadget driver to have the reset callback. This shouldn't be needed once the ethernet gadget driver is adapted to use the composite driver. Signed-off-by: Kishon Vijay Abraham I Reviewed-by: Tom Rini Reviewed-by: Lukasz Majewski --- drivers/usb/gadget/ether.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 850ba029ab..53f4672291 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -2505,6 +2505,7 @@ static struct usb_gadget_driver eth_driver = { .unbind = eth_unbind, .setup = eth_setup, + .reset = eth_disconnect, .disconnect = eth_disconnect, .suspend = eth_suspend, From f522f9475f86c27bc0dd8733d029833a3845d725 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 12 Aug 2015 22:19:14 +0200 Subject: [PATCH 10/11] usb: dwc2: Add original Synopsys compat string Add the Synopsys compatible string. This is used in SoCFPGA DT files. Signed-off-by: Marek Vasut --- drivers/usb/host/dwc2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index 09f91f190a..7b291345f6 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -1113,6 +1113,7 @@ struct dm_usb_ops dwc2_usb_ops = { static const struct udevice_id dwc2_usb_ids[] = { { .compatible = "brcm,bcm2835-usb" }, + { .compatible = "snps,dwc2" }, { } }; From 7a1386f96bca550240670fa3461d3a0dc060aa01 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 12 Aug 2015 22:19:15 +0200 Subject: [PATCH 11/11] usb: dwc2: Rename to dwc2_usb This driver is not used only on exynos, but also on Altera SoCFPGA, HiSilicon SoCs, RPi etc, so rename it accordingly to prevent confusion. Signed-off-by: Marek Vasut --- drivers/usb/host/dwc2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index 7b291345f6..85236aeb2a 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -1118,7 +1118,7 @@ static const struct udevice_id dwc2_usb_ids[] = { }; U_BOOT_DRIVER(usb_dwc2) = { - .name = "dwc2_exynos", + .name = "dwc2_usb", .id = UCLASS_USB, .of_match = dwc2_usb_ids, .ofdata_to_platdata = dwc2_usb_ofdata_to_platdata,