[U-Boot] [u-boot][PATCH v2 0/4] am57xx: am43xx: get usb host working

Hi,
I was under the wrong impression earlier that CONFIG_USB_DWC3 is needed for USB HOST operation, but it seems it is not so. Just CONFIG_XHCI_DWC3 and CONFIG_XHCI_OMAP are sufficient to get USB host working.
So the real problem was that some offending commits didn't define enable_usb_clocks() and board_usb_init for the XHCI host only case.
Patches 1 and 2 fix this and get USB host working on am57xx and am43xx. NOTE: my am437xx is broken so I've only tested this on am57xx-evm.
The remaining 2 patches attempt to fix USB3 PHY to get Super-Speed host functional but I haven't yet got Super-Speed working in u-boot. Patch 4 does fix an issue with Kernel failing to detect Super-Speed devices.
cheers, -roger
Roger Quadros (4): ARM: OMAP5+: Provide enable/disable_usb_clocks() for CONFIG_USB_XHCI_OMAP ARM: AM57xx: AM43xx: Fix USB host dra7xx: Enable USB_PHY3 32KHz clock usb: phy: omap_usb_phy: Fix USB3_PHY DPLL configuration
arch/arm/cpu/armv7/am33xx/clock_am43xx.c | 2 +- arch/arm/cpu/armv7/omap5/hw_data.c | 16 +++++++-- arch/arm/cpu/armv7/omap5/prcm-regs.c | 1 + arch/arm/include/asm/omap_common.h | 1 + board/ti/am43xx/board.c | 58 ++++++++++++++++---------------- board/ti/am57xx/board.c | 54 ++++++++++++++--------------- drivers/usb/phy/omap_usb_phy.c | 56 +++++++++++++++++++++--------- 7 files changed, 112 insertions(+), 76 deletions(-)

CONFIG_USB_XHCI_OMAP is enabled for host mode independent of CONFIG_USB_DWC3 which is meant for gadget mode only. We need enable/disbale_usb_clocks() for host mode as well so provide for it.
Fixes: 09cc14f4bcbf ("ARM: AM43xx: Add functions to enable and disable USB clocks" Signed-off-by: Roger Quadros rogerq@ti.com --- arch/arm/cpu/armv7/am33xx/clock_am43xx.c | 2 +- arch/arm/cpu/armv7/omap5/hw_data.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/cpu/armv7/am33xx/clock_am43xx.c b/arch/arm/cpu/armv7/am33xx/clock_am43xx.c index 5c2a2ab..73ea955 100644 --- a/arch/arm/cpu/armv7/am33xx/clock_am43xx.c +++ b/arch/arm/cpu/armv7/am33xx/clock_am43xx.c @@ -160,7 +160,7 @@ void disable_edma3_clocks(void) } #endif
-#ifdef CONFIG_USB_DWC3 +#if defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_XHCI_OMAP) void enable_usb_clocks(int index) { u32 *usbclkctrl = 0; diff --git a/arch/arm/cpu/armv7/omap5/hw_data.c b/arch/arm/cpu/armv7/omap5/hw_data.c index 88e8920..8734815 100644 --- a/arch/arm/cpu/armv7/omap5/hw_data.c +++ b/arch/arm/cpu/armv7/omap5/hw_data.c @@ -602,7 +602,7 @@ void disable_edma3_clocks(void) } #endif
-#ifdef CONFIG_USB_DWC3 +#if defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_XHCI_OMAP) void enable_usb_clocks(int index) { u32 cm_l3init_usb_otg_ss_clkctrl = 0;

On Mon, May 23, 2016 at 05:37:47PM +0300, Roger Quadros wrote:
CONFIG_USB_XHCI_OMAP is enabled for host mode independent of CONFIG_USB_DWC3 which is meant for gadget mode only. We need enable/disbale_usb_clocks() for host mode as well so provide for it.
Fixes: 09cc14f4bcbf ("ARM: AM43xx: Add functions to enable and disable USB clocks" Signed-off-by: Roger Quadros rogerq@ti.com
Applied to u-boot/master, thanks!

CONFIG_USB_XHCI_OMAP can be set for host mode without setting CONFIG_USB_DWC3 which is meant for gadget mode only. board_usb_init() was not being defined for CONFIG_USB_XHCI_OMAP resulting in a data abort on usb start.
Define board_usb_init() for CONFIG_USB_XHCI_OMAP case. Move gadget specific handling to within CONFIG_USB_DWC3.
Fixes: 6f1af1e358b7 ("board: ti: invoke clock API to enable and disable clocks") Signed-off-by: Roger Quadros rogerq@ti.com --- board/ti/am43xx/board.c | 58 ++++++++++++++++++++++++------------------------- board/ti/am57xx/board.c | 54 ++++++++++++++++++++++----------------------- 2 files changed, 55 insertions(+), 57 deletions(-)
diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c index d208d2f..1a3d70a 100644 --- a/board/ti/am43xx/board.c +++ b/board/ti/am43xx/board.c @@ -678,71 +678,71 @@ static struct ti_usb_phy_device usb_phy2_device = { .index = 1, };
+int usb_gadget_handle_interrupts(int index) +{ + u32 status; + + status = dwc3_omap_uboot_interrupt_status(index); + if (status) + dwc3_uboot_handle_interrupt(index); + + return 0; +} +#endif /* CONFIG_USB_DWC3 */ + +#if defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_XHCI_OMAP) int board_usb_init(int index, enum usb_init_type init) { enable_usb_clocks(index); +#ifdef CONFIG_USB_DWC3 switch (index) { case 0: if (init == USB_INIT_DEVICE) { usb_otg_ss1.dr_mode = USB_DR_MODE_PERIPHERAL; usb_otg_ss1_glue.vbus_id_status = OMAP_DWC3_VBUS_VALID; - } else { - usb_otg_ss1.dr_mode = USB_DR_MODE_HOST; - usb_otg_ss1_glue.vbus_id_status = OMAP_DWC3_ID_GROUND; + dwc3_omap_uboot_init(&usb_otg_ss1_glue); + ti_usb_phy_uboot_init(&usb_phy1_device); + dwc3_uboot_init(&usb_otg_ss1); } - - dwc3_omap_uboot_init(&usb_otg_ss1_glue); - ti_usb_phy_uboot_init(&usb_phy1_device); - dwc3_uboot_init(&usb_otg_ss1); break; case 1: if (init == USB_INIT_DEVICE) { usb_otg_ss2.dr_mode = USB_DR_MODE_PERIPHERAL; usb_otg_ss2_glue.vbus_id_status = OMAP_DWC3_VBUS_VALID; - } else { - usb_otg_ss2.dr_mode = USB_DR_MODE_HOST; - usb_otg_ss2_glue.vbus_id_status = OMAP_DWC3_ID_GROUND; + ti_usb_phy_uboot_init(&usb_phy2_device); + dwc3_omap_uboot_init(&usb_otg_ss2_glue); + dwc3_uboot_init(&usb_otg_ss2); } - - ti_usb_phy_uboot_init(&usb_phy2_device); - dwc3_omap_uboot_init(&usb_otg_ss2_glue); - dwc3_uboot_init(&usb_otg_ss2); break; default: printf("Invalid Controller Index\n"); } +#endif
return 0; }
int board_usb_cleanup(int index, enum usb_init_type init) { +#ifdef CONFIG_USB_DWC3 switch (index) { case 0: case 1: - ti_usb_phy_uboot_exit(index); - dwc3_uboot_exit(index); - dwc3_omap_uboot_exit(index); + if (init == USB_INIT_DEVICE) { + ti_usb_phy_uboot_exit(index); + dwc3_uboot_exit(index); + dwc3_omap_uboot_exit(index); + } break; default: printf("Invalid Controller Index\n"); } +#endif disable_usb_clocks(index);
return 0; } - -int usb_gadget_handle_interrupts(int index) -{ - u32 status; - - status = dwc3_omap_uboot_interrupt_status(index); - if (status) - dwc3_uboot_handle_interrupt(index); - - return 0; -} -#endif +#endif /* defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_XHCI_OMAP) */
#ifdef CONFIG_DRIVER_TI_CPSW
diff --git a/board/ti/am57xx/board.c b/board/ti/am57xx/board.c index 86b8f6e..c9165ac 100644 --- a/board/ti/am57xx/board.c +++ b/board/ti/am57xx/board.c @@ -439,6 +439,19 @@ static struct ti_usb_phy_device usb_phy2_device = { .index = 1, };
+int usb_gadget_handle_interrupts(int index) +{ + u32 status; + + status = dwc3_omap_uboot_interrupt_status(index); + if (status) + dwc3_uboot_handle_interrupt(index); + + return 0; +} +#endif /* CONFIG_USB_DWC3 */ + +#if defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_XHCI_OMAP) int board_usb_init(int index, enum usb_init_type init) { enable_usb_clocks(index); @@ -448,31 +461,23 @@ int board_usb_init(int index, enum usb_init_type init) printf("port %d can't be used as device\n", index); disable_usb_clocks(index); return -EINVAL; - } else { - usb_otg_ss1.dr_mode = USB_DR_MODE_HOST; - usb_otg_ss1_glue.vbus_id_status = OMAP_DWC3_ID_GROUND; - setbits_le32((*prcm)->cm_l3init_usb_otg_ss1_clkctrl, - OTG_SS_CLKCTRL_MODULEMODE_HW | - OPTFCLKEN_REFCLK960M); } - - ti_usb_phy_uboot_init(&usb_phy1_device); - dwc3_omap_uboot_init(&usb_otg_ss1_glue); - dwc3_uboot_init(&usb_otg_ss1); break; case 1: if (init == USB_INIT_DEVICE) { +#ifdef CONFIG_USB_DWC3 usb_otg_ss2.dr_mode = USB_DR_MODE_PERIPHERAL; usb_otg_ss2_glue.vbus_id_status = OMAP_DWC3_VBUS_VALID; + ti_usb_phy_uboot_init(&usb_phy2_device); + dwc3_omap_uboot_init(&usb_otg_ss2_glue); + dwc3_uboot_init(&usb_otg_ss2); +#endif } else { printf("port %d can't be used as host\n", index); disable_usb_clocks(index); return -EINVAL; }
- ti_usb_phy_uboot_init(&usb_phy2_device); - dwc3_omap_uboot_init(&usb_otg_ss2_glue); - dwc3_uboot_init(&usb_otg_ss2); break; default: printf("Invalid Controller Index\n"); @@ -483,31 +488,24 @@ int board_usb_init(int index, enum usb_init_type init)
int board_usb_cleanup(int index, enum usb_init_type init) { +#ifdef CONFIG_USB_DWC3 switch (index) { case 0: case 1: - ti_usb_phy_uboot_exit(index); - dwc3_uboot_exit(index); - dwc3_omap_uboot_exit(index); + if (init == USB_INIT_DEVICE) { + ti_usb_phy_uboot_exit(index); + dwc3_uboot_exit(index); + dwc3_omap_uboot_exit(index); + } break; default: printf("Invalid Controller Index\n"); } +#endif disable_usb_clocks(index); return 0; } - -int usb_gadget_handle_interrupts(int index) -{ - u32 status; - - status = dwc3_omap_uboot_interrupt_status(index); - if (status) - dwc3_uboot_handle_interrupt(index); - - return 0; -} -#endif +#endif /* defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_XHCI_OMAP) */
#ifdef CONFIG_DRIVER_TI_CPSW

On Mon, May 23, 2016 at 05:37:48PM +0300, Roger Quadros wrote:
CONFIG_USB_XHCI_OMAP can be set for host mode without setting CONFIG_USB_DWC3 which is meant for gadget mode only. board_usb_init() was not being defined for CONFIG_USB_XHCI_OMAP resulting in a data abort on usb start.
Define board_usb_init() for CONFIG_USB_XHCI_OMAP case. Move gadget specific handling to within CONFIG_USB_DWC3.
Fixes: 6f1af1e358b7 ("board: ti: invoke clock API to enable and disable clocks") Signed-off-by: Roger Quadros rogerq@ti.com
Applied to u-boot/master, thanks!

DRA7xx has a 32KHz PHY clock for USB_PHY3 that must be enabled for USB1 instance in Super-Speed.
Signed-off-by: Roger Quadros rogerq@ti.com --- arch/arm/cpu/armv7/omap5/hw_data.c | 14 ++++++++++++-- arch/arm/cpu/armv7/omap5/prcm-regs.c | 1 + arch/arm/include/asm/omap_common.h | 1 + 3 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/arch/arm/cpu/armv7/omap5/hw_data.c b/arch/arm/cpu/armv7/omap5/hw_data.c index 8734815..fe59c25 100644 --- a/arch/arm/cpu/armv7/omap5/hw_data.c +++ b/arch/arm/cpu/armv7/omap5/hw_data.c @@ -614,9 +614,14 @@ void enable_usb_clocks(int index) setbits_le32((*prcm)->cm_l3init_usb_otg_ss1_clkctrl, OPTFCLKEN_REFCLK960M);
- /* Enable 32 KHz clock for dwc3 */ + /* Enable 32 KHz clock for USB_PHY1 */ setbits_le32((*prcm)->cm_coreaon_usb_phy1_core_clkctrl, USBPHY_CORE_CLKCTRL_OPTFCLKEN_CLK32K); + + /* Enable 32 KHz clock for USB_PHY3 */ + if (is_dra7xx()) + setbits_le32((*prcm)->cm_coreaon_usb_phy3_core_clkctrl, + USBPHY_CORE_CLKCTRL_OPTFCLKEN_CLK32K); } else if (index == 1) { cm_l3init_usb_otg_ss_clkctrl = (*prcm)->cm_l3init_usb_otg_ss2_clkctrl; @@ -664,9 +669,14 @@ void disable_usb_clocks(int index) clrbits_le32((*prcm)->cm_l3init_usb_otg_ss1_clkctrl, OPTFCLKEN_REFCLK960M);
- /* Disable 32 KHz clock for dwc3 */ + /* Disable 32 KHz clock for USB_PHY1 */ clrbits_le32((*prcm)->cm_coreaon_usb_phy1_core_clkctrl, USBPHY_CORE_CLKCTRL_OPTFCLKEN_CLK32K); + + /* Disable 32 KHz clock for USB_PHY3 */ + if (is_dra7xx()) + clrbits_le32((*prcm)->cm_coreaon_usb_phy3_core_clkctrl, + USBPHY_CORE_CLKCTRL_OPTFCLKEN_CLK32K); } else if (index == 1) { cm_l3init_usb_otg_ss_clkctrl = (*prcm)->cm_l3init_usb_otg_ss2_clkctrl; diff --git a/arch/arm/cpu/armv7/omap5/prcm-regs.c b/arch/arm/cpu/armv7/omap5/prcm-regs.c index 655e92b..b5f1d70 100644 --- a/arch/arm/cpu/armv7/omap5/prcm-regs.c +++ b/arch/arm/cpu/armv7/omap5/prcm-regs.c @@ -820,6 +820,7 @@ struct prcm_regs const dra7xx_prcm = { .cm_clkmode_dpll_gmac = 0x4a0052a8, .cm_coreaon_usb_phy1_core_clkctrl = 0x4a008640, .cm_coreaon_usb_phy2_core_clkctrl = 0x4a008688, + .cm_coreaon_usb_phy3_core_clkctrl = 0x4a008698, .cm_coreaon_l3init_60m_gfclk_clkctrl = 0x4a0086c0,
/* cm1.mpu */ diff --git a/arch/arm/include/asm/omap_common.h b/arch/arm/include/asm/omap_common.h index 8fb05e1..7871adf 100644 --- a/arch/arm/include/asm/omap_common.h +++ b/arch/arm/include/asm/omap_common.h @@ -145,6 +145,7 @@ struct prcm_regs { u32 cm_ssc_modfreqdiv_dpll_unipro; u32 cm_coreaon_usb_phy1_core_clkctrl; u32 cm_coreaon_usb_phy2_core_clkctrl; + u32 cm_coreaon_usb_phy3_core_clkctrl; u32 cm_coreaon_l3init_60m_gfclk_clkctrl;
/* cm2.core */

On Mon, May 23, 2016 at 05:37:49PM +0300, Roger Quadros wrote:
DRA7xx has a 32KHz PHY clock for USB_PHY3 that must be enabled for USB1 instance in Super-Speed.
Signed-off-by: Roger Quadros rogerq@ti.com
Applied to u-boot/master, thanks!

The index returned by get_sys_clk_index() is not exactly what we expect. Let's not rely on that and use get_sys_clk_freq() instead.
This fixes missing USB3 devices in the Linux kernel when USB is started in u-boot. It still doesn't fix missing USB3 devices in u-boot though.
Signed-off-by: Roger Quadros rogerq@ti.com --- drivers/usb/phy/omap_usb_phy.c | 56 +++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 15 deletions(-)
diff --git a/drivers/usb/phy/omap_usb_phy.c b/drivers/usb/phy/omap_usb_phy.c index f9069c7..1993da1 100644 --- a/drivers/usb/phy/omap_usb_phy.c +++ b/drivers/usb/phy/omap_usb_phy.c @@ -23,7 +23,7 @@ #include "../host/xhci.h"
#ifdef CONFIG_OMAP_USB3PHY1_HOST -struct usb_dpll_params { +struct usb3_dpll_params { u16 m; u8 n; u8 freq:3; @@ -31,17 +31,39 @@ struct usb_dpll_params { u32 mf; };
-#define NUM_USB_CLKS 6 +struct usb3_dpll_map { + unsigned long rate; + struct usb3_dpll_params params; + struct usb3_dpll_map *dpll_map; +};
-static struct usb_dpll_params omap_usb3_dpll_params[NUM_USB_CLKS] = { - {1250, 5, 4, 20, 0}, /* 12 MHz */ - {3125, 20, 4, 20, 0}, /* 16.8 MHz */ - {1172, 8, 4, 20, 65537}, /* 19.2 MHz */ - {1250, 12, 4, 20, 0}, /* 26 MHz */ - {3125, 47, 4, 20, 92843}, /* 38.4 MHz */ - {1000, 7, 4, 10, 0}, /* 20 MHz */ +static struct usb3_dpll_map dpll_map_usb[] = { + {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */ + {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */ + {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */ + {20000000, {1000, 7, 4, 10, 0} }, /* 20 MHz */ + {26000000, {1250, 12, 4, 20, 0} }, /* 26 MHz */ + {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */ + { }, /* Terminator */ };
+static struct usb3_dpll_params *omap_usb3_get_dpll_params(void) +{ + unsigned long rate; + struct usb3_dpll_map *dpll_map = dpll_map_usb; + + rate = get_sys_clk_freq(); + + for (; dpll_map->rate; dpll_map++) { + if (rate == dpll_map->rate) + return &dpll_map->params; + } + + dev_err(phy->dev, "No DPLL configuration for %lu Hz SYS CLK\n", rate); + + return NULL; +} + static void omap_usb_dpll_relock(struct omap_usb3_phy *phy_regs) { u32 val; @@ -56,32 +78,36 @@ static void omap_usb_dpll_relock(struct omap_usb3_phy *phy_regs)
static void omap_usb_dpll_lock(struct omap_usb3_phy *phy_regs) { - u32 clk_index = get_sys_clk_index(); + struct usb3_dpll_params *dpll_params; u32 val;
+ dpll_params = omap_usb3_get_dpll_params(); + if (!dpll_params) + return; + val = readl(&phy_regs->pll_config_1); val &= ~PLL_REGN_MASK; - val |= omap_usb3_dpll_params[clk_index].n << PLL_REGN_SHIFT; + val |= dpll_params->n << PLL_REGN_SHIFT; writel(val, &phy_regs->pll_config_1);
val = readl(&phy_regs->pll_config_2); val &= ~PLL_SELFREQDCO_MASK; - val |= omap_usb3_dpll_params[clk_index].freq << PLL_SELFREQDCO_SHIFT; + val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT; writel(val, &phy_regs->pll_config_2);
val = readl(&phy_regs->pll_config_1); val &= ~PLL_REGM_MASK; - val |= omap_usb3_dpll_params[clk_index].m << PLL_REGM_SHIFT; + val |= dpll_params->m << PLL_REGM_SHIFT; writel(val, &phy_regs->pll_config_1);
val = readl(&phy_regs->pll_config_4); val &= ~PLL_REGM_F_MASK; - val |= omap_usb3_dpll_params[clk_index].mf << PLL_REGM_F_SHIFT; + val |= dpll_params->mf << PLL_REGM_F_SHIFT; writel(val, &phy_regs->pll_config_4);
val = readl(&phy_regs->pll_config_3); val &= ~PLL_SD_MASK; - val |= omap_usb3_dpll_params[clk_index].sd << PLL_SD_SHIFT; + val |= dpll_params->sd << PLL_SD_SHIFT; writel(val, &phy_regs->pll_config_3);
omap_usb_dpll_relock(phy_regs);

On Mon, May 23, 2016 at 05:37:50PM +0300, Roger Quadros wrote:
The index returned by get_sys_clk_index() is not exactly what we expect. Let's not rely on that and use get_sys_clk_freq() instead.
This fixes missing USB3 devices in the Linux kernel when USB is started in u-boot. It still doesn't fix missing USB3 devices in u-boot though.
Signed-off-by: Roger Quadros rogerq@ti.com
Applied to u-boot/master, thanks!
participants (2)
-
Roger Quadros
-
Tom Rini