
This patch series adds the OMAP5 xHCI support.
It is has dependencies on the following patches
http://patchwork.ozlabs.org/patch/268797/ http://patchwork.ozlabs.org/patch/268766/
At this time the uBoot USB engine does not allow more then one stack to be enabled at a time. Since the ethernet port is on the eHCI port I have opt'd to keep the eHCI enabled over the xHCI.
To enable the xHCI stack for OMAP add the following configs in addition to the standard USB defines. NOTE: eHCI must be disabled
CONFIG_USB_XHCI CONFIG_USB_XHCI_OMAP CONFIG_PALMAS_USB_SS_PWR

Add new functionality to turn on SMPS10 regulator. This supplies the VBUS to devices connected to the USB host ports
Signed-off-by: Dan Murphy dmurphy@ti.com --- drivers/power/palmas.c | 15 +++++++++++++++ include/palmas.h | 6 ++++++ 2 files changed, 21 insertions(+)
diff --git a/drivers/power/palmas.c b/drivers/power/palmas.c index c7b0cbe..cfbc9dc 100644 --- a/drivers/power/palmas.c +++ b/drivers/power/palmas.c @@ -127,6 +127,21 @@ int twl603x_audio_power(u8 on) } #endif
+#ifdef CONFIG_PALMAS_USB_SS_PWR +/** + * @brief palmas_enable_ss_ldo - Configure EVM board specific configurations + * for the USB Super speed SMPS10 regulator. + * + * @return 0 + */ +int palmas_enable_ss_ldo(void) +{ + /* Enable smps10 regulator */ + return palmas_i2c_write_u8(TWL603X_CHIP_P1, SMPS10_CTRL, + SMPS10_MODE_ACTIVE_D); +} +#endif + /* * Enable/disable back-up battery (or super cap) charging on TWL6035/37. * Please use defined BB_xxx values. diff --git a/include/palmas.h b/include/palmas.h index f74f08e..eaf3670 100644 --- a/include/palmas.h +++ b/include/palmas.h @@ -31,6 +31,7 @@ /* LDOUSB control/voltage */ #define LDOUSB_CTRL 0x64 #define LDOUSB_VOLTAGE 0x65 +#define LDO_CTRL 0x6a
/* Control of 32 kHz audio clock */ #define CLK32KGAUDIO_CTRL 0xd5 @@ -62,6 +63,10 @@ #define SMPS9_CTRL 0x38 #define SMPS9_VOLTAGE 0x3b
+/* SMPS10_CTRL */ +#define SMPS10_CTRL 0x3c +#define SMPS10_MODE_ACTIVE_D 0x0d + /* Bit field definitions for SMPSx_CTRL */ #define SMPS_MODE_ACT_AUTO 1 #define SMPS_MODE_ACT_ECO 2 @@ -114,5 +119,6 @@ int palmas_mmc1_poweron_ldo(void); int twl603x_mmc1_set_ldo9(u8 vsel); int twl603x_audio_power(u8 on); int twl603x_enable_bb_charge(u8 bb_fields); +int palmas_enable_ss_ldo(void);
#endif /* PALMAS_H */

Add the prcm registers and the bit definitions to enable the USB SS port of the OMAP5 device.
Signed-off-by: Dan Murphy dmurphy@ti.com --- arch/arm/cpu/armv7/omap-common/clocks-common.c | 4 ++-- arch/arm/cpu/armv7/omap5/prcm-regs.c | 4 ++++ arch/arm/include/asm/arch-omap5/clock.h | 10 ++++++++++ arch/arm/include/asm/omap_common.h | 4 ++++ 4 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/arch/arm/cpu/armv7/omap-common/clocks-common.c b/arch/arm/cpu/armv7/omap-common/clocks-common.c index 7580594..b470bb0 100644 --- a/arch/arm/cpu/armv7/omap-common/clocks-common.c +++ b/arch/arm/cpu/armv7/omap-common/clocks-common.c @@ -339,7 +339,7 @@ void configure_mpu_dpll(void) debug("MPU DPLL locked\n"); }
-#ifdef CONFIG_USB_EHCI_OMAP +#if defined(CONFIG_USB_EHCI_OMAP) || defined(CONFIG_USB_XHCI_OMAP) static void setup_usb_dpll(void) { const struct dpll_params *params; @@ -404,7 +404,7 @@ static void setup_dplls(void) /* MPU dpll */ configure_mpu_dpll();
-#ifdef CONFIG_USB_EHCI_OMAP +#if defined(CONFIG_USB_EHCI_OMAP) || defined(CONFIG_USB_XHCI_OMAP) setup_usb_dpll(); #endif params = get_ddr_dpll_params(*dplls_data); diff --git a/arch/arm/cpu/armv7/omap5/prcm-regs.c b/arch/arm/cpu/armv7/omap5/prcm-regs.c index 579818d..ff81204 100644 --- a/arch/arm/cpu/armv7/omap5/prcm-regs.c +++ b/arch/arm/cpu/armv7/omap5/prcm-regs.c @@ -301,6 +301,7 @@ struct prcm_regs const omap5_es1_prcm = { struct omap_sys_ctrl_regs const omap5_ctrl = { .control_status = 0x4A002134, .control_std_fuse_opp_vdd_mpu_2 = 0x4A0021B4, + .control_phy_power_usb = 0x4A002370, .control_padconf_core_base = 0x4A002800, .control_paconf_global = 0x4A002DA0, .control_paconf_mode = 0x4A002DA4, @@ -575,6 +576,7 @@ struct prcm_regs const omap5_es2_prcm = { .cm_div_m2_dpll_unipro = 0x4a0081d0, .cm_ssc_deltamstep_dpll_unipro = 0x4a0081e8, .cm_ssc_modfreqdiv_dpll_unipro = 0x4a0081ec, + .cm_coreaon_usb_phy_core_clkctrl = 0x4A008640, .cm_coreaon_bandgap_clkctrl = 0x4a008648, .cm_coreaon_io_srcomp_clkctrl = 0x4a008650,
@@ -706,6 +708,8 @@ struct prcm_regs const omap5_es2_prcm = { .cm_l3init_p1500_clkctrl = 0x4a009678, .cm_l3init_fsusb_clkctrl = 0x4a0096d0, .cm_l3init_ocp2scp1_clkctrl = 0x4a0096e0, + .cm_l3init_ocp2scp3_clkctrl = 0x4a0096e8, + .cm_l3init_usb_otg_ss_clkctrl = 0x4a0096f0,
/* prm irqstatus regs */ .prm_irqstatus_mpu_2 = 0x4ae06014, diff --git a/arch/arm/include/asm/arch-omap5/clock.h b/arch/arm/include/asm/arch-omap5/clock.h index 9a2166c..5cbbc44 100644 --- a/arch/arm/include/asm/arch-omap5/clock.h +++ b/arch/arm/include/asm/arch-omap5/clock.h @@ -166,6 +166,16 @@ #define OPTFCLKEN_USB_CH1_CLK_ENABLE (1 << 9) #define OPTFCLKEN_USB_CH2_CLK_ENABLE (1 << 10)
+/* CM_COREAON_USB_PHY_CORE_CLKCTRL */ +#define USBPHY_CORE_CLKCTRL_OPTFCLKEN_CLK32K (1 << 8) + +/* CM_L3INIT_USB_OTG_SS_CLKCTRL */ +#define OTG_SS_CLKCTRL_MODULEMODE_HW (1 << 0) +#define OPTFCLKEN_REFCLK960M (1 << 8) + +/* CM_L3INIT_OCP2SCP1_CLKCTRL */ +#define OCP2SCP1_CLKCTRL_MODULEMODE_HW (1 << 0) + /* CM_MPU_MPU_CLKCTRL */ #define MPU_CLKCTRL_CLKSEL_EMIF_DIV_MODE_SHIFT 24 #define MPU_CLKCTRL_CLKSEL_EMIF_DIV_MODE_MASK (3 << 24) diff --git a/arch/arm/include/asm/omap_common.h b/arch/arm/include/asm/omap_common.h index 66f416f..31ccc03 100644 --- a/arch/arm/include/asm/omap_common.h +++ b/arch/arm/include/asm/omap_common.h @@ -143,6 +143,7 @@ struct prcm_regs { u32 cm_div_m2_dpll_unipro; u32 cm_ssc_deltamstep_dpll_unipro; u32 cm_ssc_modfreqdiv_dpll_unipro; + u32 cm_coreaon_usb_phy_core_clkctrl;
/* cm2.core */ u32 cm_coreaon_bandgap_clkctrl; @@ -226,6 +227,8 @@ struct prcm_regs { u32 cm_l3init_p1500_clkctrl; u32 cm_l3init_fsusb_clkctrl; u32 cm_l3init_ocp2scp1_clkctrl; + u32 cm_l3init_ocp2scp3_clkctrl; + u32 cm_l3init_usb_otg_ss_clkctrl;
u32 prm_irqstatus_mpu_2;
@@ -353,6 +356,7 @@ struct omap_sys_ctrl_regs { u32 control_core_mac_id_1_lo; u32 control_core_mac_id_1_hi; u32 control_std_fuse_opp_vdd_mpu_2; + u32 control_phy_power_usb; u32 control_core_mmr_lock1; u32 control_core_mmr_lock2; u32 control_core_mmr_lock3;

Add the asm/io.h header to resolve implicit declaration of readl/writel
Signed-off-by: Dan Murphy dmurphy@ti.com --- drivers/usb/host/xhci.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 467afe0..91935f0 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -27,6 +27,8 @@ #ifndef HOST_XHCI_H_ #define HOST_XHCI_H_
+#include <asm/io.h> + #include <asm/cache.h> #include <linux/list.h>

Dear Dan Murphy,
Add the asm/io.h header to resolve implicit declaration of readl/writel
Signed-off-by: Dan Murphy dmurphy@ti.com
drivers/usb/host/xhci.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 467afe0..91935f0 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -27,6 +27,8 @@ #ifndef HOST_XHCI_H_ #define HOST_XHCI_H_
+#include <asm/io.h>
#include <asm/cache.h> #include <linux/list.h>
I think this can be merged into Vivek's next round?
Best regards, Marek Vasut

Marek On 09/04/2013 09:17 AM, Marek Vasut wrote:
Dear Dan Murphy,
Add the asm/io.h header to resolve implicit declaration of readl/writel
Signed-off-by: Dan Murphy dmurphy@ti.com
drivers/usb/host/xhci.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 467afe0..91935f0 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -27,6 +27,8 @@ #ifndef HOST_XHCI_H_ #define HOST_XHCI_H_
+#include <asm/io.h>
#include <asm/cache.h> #include <linux/list.h>
I think this can be merged into Vivek's next round?
Best regards, Marek Vasut
I hope so this was one of my comments as the asm/io.h showed up in the xhci top level so not sure why it was not included in the global header.
So if v3 has this in xhci.h I am OK with gettin rid of this patch
Dan

Add the OMAP file for the xHCI Host controller This code will initilialize the proper components within the OMAP5 to enable the xHCI host controller.
Signed-off-by: Dan Murphy dmurphy@ti.com --- arch/arm/include/asm/arch-omap5/xhci-omap.h | 124 ++++++++++ drivers/usb/host/Makefile | 1 + drivers/usb/host/xhci-omap.c | 326 +++++++++++++++++++++++++++ 3 files changed, 451 insertions(+) create mode 100644 arch/arm/include/asm/arch-omap5/xhci-omap.h create mode 100644 drivers/usb/host/xhci-omap.c
diff --git a/arch/arm/include/asm/arch-omap5/xhci-omap.h b/arch/arm/include/asm/arch-omap5/xhci-omap.h new file mode 100644 index 0000000..b557a43 --- /dev/null +++ b/arch/arm/include/asm/arch-omap5/xhci-omap.h @@ -0,0 +1,124 @@ +/* + * (C) Copyright 2013 + * Texas Instruments Inc, <www.ti.com> + * + * Author: Dan Murphy dmurphy@ti.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _ASM_ARCH_XHCI_OMAP_H_ +#define _ASM_ARCH_XHCI_OMAP_H_ + +#define OMAP_XHCI_BASE 0x4a030000 +#define OMAP_OCP1_SCP_BASE 0x4a084c00 +#define OMAP_OTG_WRAPPER_BASE 0x4A020000 + +/* Phy register MACRO definitions */ +#define PLL_REGM_MASK 0x001FFE00 +#define PLL_REGM_SHIFT 0x9 +#define PLL_REGM_F_MASK 0x0003FFFF +#define PLL_REGM_F_SHIFT 0x0 +#define PLL_REGN_MASK 0x000001FE +#define PLL_REGN_SHIFT 0x1 +#define PLL_SELFREQDCO_MASK 0x0000000E +#define PLL_SELFREQDCO_SHIFT 0x1 +#define PLL_SD_MASK 0x0003FC00 +#define PLL_SD_SHIFT 0x9 +#define SET_PLL_GO 0x1 +#define PLL_TICOPWDN 0x10000 +#define PLL_LOCK 0x2 +#define PLL_IDLE 0x1 + +#define USB3_PWRCTL_CLK_CMD_MASK 0x3FE000 +#define USB3_PWRCTL_CLK_FREQ_MASK 0xFFC +#define USB3_PHY_PARTIAL_RX_POWERON (1 << 6) +#define USB3_PHY_RX_POWERON (1 << 14) +#define USB3_PHY_TX_POWERON (1 << 15) +#define USB3_PHY_TX_RX_POWERON (USB3_PHY_RX_POWERON | USB3_PHY_TX_POWERON) +#define USB3_PWRCTL_CLK_CMD_SHIFT 14 +#define USB3_PWRCTL_CLK_FREQ_SHIFT 22 + +/* USBOTGSS_WRAPPER definitions */ +#define USBOTGSS_WRAPRESET (1 << 17) +#define USBOTGSS_DMADISABLE (1 << 16) +#define USBOTGSS_STANDBYMODE_NO_STANDBY (1 << 4) +#define USBOTGSS_STANDBYMODE_SMRT (1 << 5) +#define USBOTGSS_STANDBYMODE_SMRT_WKUP (0x3 << 4) +#define USBOTGSS_IDLEMODE_NOIDLE (1 << 2) +#define USBOTGSS_IDLEMODE_SMRT (1 << 3) +#define USBOTGSS_IDLEMODE_SMRT_WKUP (0x3 << 2) + +/* USBOTGSS_IRQENABLE_SET_0 bit */ +#define USBOTGSS_COREIRQ_EN (1 << 0) + +/* USBOTGSS_IRQENABLE_SET_1 bits */ +#define USBOTGSS_IRQ_SET_1_IDPULLUP_FALL_EN (1 << 0) +#define USBOTGSS_IRQ_SET_1_DISCHRGVBUS_FALL_EN (1 << 3) +#define USBOTGSS_IRQ_SET_1_CHRGVBUS_FALL_EN (1 << 4) +#define USBOTGSS_IRQ_SET_1_DRVVBUS_FALL_EN (1 << 5) +#define USBOTGSS_IRQ_SET_1_IDPULLUP_RISE_EN (1 << 8) +#define USBOTGSS_IRQ_SET_1_DISCHRGVBUS_RISE_EN (1 << 11) +#define USBOTGSS_IRQ_SET_1_CHRGVBUS_RISE_EN (1 << 12) +#define USBOTGSS_IRQ_SET_1_DRVVBUS_RISE_EN (1 << 13) +#define USBOTGSS_IRQ_SET_1_OEVT_EN (1 << 16) +#define USBOTGSS_IRQ_SET_1_DMADISABLECLR_EN (1 << 17) + +/* + * USBOTGSS_WRAPPER registers + */ +struct omap_dwc_wrapper { + u32 revision; + + u32 reserve_1[3]; + + u32 sysconfig; /* offset of 0x10 */ + + u32 reserve_2[3]; + u16 reserve_3; + + u32 irqstatus_raw_0; /* offset of 0x24 */ + u32 irqstatus_0; + u32 irqenable_set_0; + u32 irqenable_clr_0; + + u32 irqstatus_raw_1; /* offset of 0x34 */ + u32 irqstatus_1; + u32 irqenable_set_1; + u32 irqenable_clr_1; + + u32 reserve_4[15]; + + u32 utmi_otg_ctrl; /* offset of 0x80 */ + u32 utmi_otg_status; + + u32 reserve_5[30]; + + u32 mram_offset; /* offset of 0x100 */ + u32 fladj; + u32 dbg_config; + u32 dbg_data; + u32 dev_ebc_en; +}; + +/* XHCI PHY register structure */ +struct omap_usb3_phy { + u32 reserve1; + u32 pll_status; + u32 pll_go; + u32 pll_config_1; + u32 pll_config_2; + u32 pll_config_3; + u32 pll_ssc_config_1; + u32 pll_ssc_config_2; + u32 pll_config_4; +}; + +struct omap_xhci { + struct omap_dwc_wrapper *otg_wrapper; + struct omap_usb3_phy *usb3_phy; + struct xhci_hccr *hcd; + struct dwc3 *dwc3_reg; +}; + +#endif /* _ASM_ARCH_XHCI_OMAP_H_ */ diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index eb50bc1..328752c 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -45,6 +45,7 @@ COBJS-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o # xhci COBJS-$(CONFIG_USB_XHCI) += xhci.o xhci-mem.o xhci-ring.o COBJS-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o +COBJS-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o
COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/usb/host/xhci-omap.c b/drivers/usb/host/xhci-omap.c new file mode 100644 index 0000000..f4e41fd --- /dev/null +++ b/drivers/usb/host/xhci-omap.c @@ -0,0 +1,326 @@ +/* + * OMAP USB HOST xHCI Controller + * + * (C) Copyright 2013 + * Texas Instruments, <www.ti.com> + * + * Author: Dan Murphy dmurphy@ti.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <usb.h> +#include <asm-generic/errno.h> +#include <asm/omap_common.h> +#include <asm/arch/cpu.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/xhci-omap.h> + +#include <linux/compat.h> +#include <linux/usb/dwc3.h> + +#include "xhci.h" + +/* Declare global data pointer */ +DECLARE_GLOBAL_DATA_PTR; + +static struct omap_xhci omap; + +struct usb_dpll_params { + u16 m; + u8 n; + u8 freq:3; + u8 sd; + u32 mf; +}; + +#define NUM_USB_CLKS 6 + +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 void omap_usb_dpll_relock(struct omap_usb3_phy *phy_regs) +{ + u32 val; + + writel(SET_PLL_GO, &phy_regs->pll_go); + do { + val = readl(&phy_regs->pll_status); + if (val & PLL_LOCK) + break; + } while (1); +} + +static void omap_usb_dpll_lock(struct omap_usb3_phy *phy_regs) +{ + u32 clk_index = get_sys_clk_index(); + u32 val; + + val = readl(&phy_regs->pll_config_1); + val &= ~PLL_REGN_MASK; + val |= omap_usb3_dpll_params[clk_index].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; + 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; + 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; + 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; + writel(val, &phy_regs->pll_config_3); + + omap_usb_dpll_relock(phy_regs); +} + +static void usb3_phy_partial_powerup(struct omap_usb3_phy *phy_regs) +{ + u32 rate = get_sys_clk_freq()/1000000; + u32 val; + + val = readl((*ctrl)->control_phy_power_usb); + val &= ~(USB3_PWRCTL_CLK_CMD_MASK | USB3_PWRCTL_CLK_FREQ_MASK); + val |= (USB3_PHY_PARTIAL_RX_POWERON | USB3_PHY_TX_RX_POWERON); + val |= rate << USB3_PWRCTL_CLK_FREQ_SHIFT; + + writel(val, (*ctrl)->control_phy_power_usb); +} + +static void usb3_phy_power(int on) +{ + u32 val; + + val = readl((*ctrl)->control_phy_power_usb); + if (on) { + val &= ~USB3_PWRCTL_CLK_CMD_MASK; + val |= USB3_PHY_TX_RX_POWERON; + } else { + val &= (~USB3_PWRCTL_CLK_CMD_MASK & ~USB3_PHY_TX_RX_POWERON); + } + + writel(val, (*ctrl)->control_phy_power_usb); +} + +static void dwc_usb3_phy_init(struct omap_usb3_phy *phy_regs) +{ + omap_usb_dpll_lock(phy_regs); + + usb3_phy_partial_powerup(phy_regs); + /* + * Give enough time for the PHY to partially power-up before + * powering it up completely. delay value suggested by the HW + * team. + */ + mdelay(100); + usb3_phy_power(1); +} + +static void omap_enable_phy_clocks(struct omap_xhci *omap) +{ + u32 val; + + /* Setting OCP2SCP1 register */ + setbits_le32((*prcm)->cm_l3init_ocp2scp1_clkctrl, + OCP2SCP1_CLKCTRL_MODULEMODE_HW); + + /* Turn on 32K AON clk */ + setbits_le32((*prcm)->cm_coreaon_usb_phy_core_clkctrl, + USBPHY_CORE_CLKCTRL_OPTFCLKEN_CLK32K); + + /* Setting CM_L3INIT_CLKSTCTRL to 0x0 i.e NO sleep */ + writel(0x0, (*prcm)->cm_l3init_clkstctrl); + + val = (USBOTGSS_DMADISABLE | + USBOTGSS_STANDBYMODE_SMRT_WKUP | + USBOTGSS_IDLEMODE_NOIDLE); + writel(val, &omap->otg_wrapper->sysconfig); + + /* Clear the utmi OTG status */ + val = readl(&omap->otg_wrapper->utmi_otg_status); + writel(val, &omap->otg_wrapper->utmi_otg_status); + + /* Enable interrupts */ + writel(USBOTGSS_COREIRQ_EN, &omap->otg_wrapper->irqenable_set_0); + val = (USBOTGSS_IRQ_SET_1_IDPULLUP_FALL_EN | + USBOTGSS_IRQ_SET_1_DISCHRGVBUS_FALL_EN | + USBOTGSS_IRQ_SET_1_CHRGVBUS_FALL_EN | + USBOTGSS_IRQ_SET_1_DRVVBUS_FALL_EN | + USBOTGSS_IRQ_SET_1_IDPULLUP_RISE_EN | + USBOTGSS_IRQ_SET_1_DISCHRGVBUS_RISE_EN | + USBOTGSS_IRQ_SET_1_CHRGVBUS_RISE_EN | + USBOTGSS_IRQ_SET_1_DRVVBUS_RISE_EN | + USBOTGSS_IRQ_SET_1_OEVT_EN); + writel(val, &omap->otg_wrapper->irqenable_set_1); + + /* Clear the IRQ status */ + val = readl(&omap->otg_wrapper->irqstatus_1); + writel(val, &omap->otg_wrapper->irqstatus_1); + val = readl(&omap->otg_wrapper->irqstatus_0); + writel(val, &omap->otg_wrapper->irqstatus_0); + + /* Enable the USB OTG Super speed clocks */ + val = (OPTFCLKEN_REFCLK960M | OTG_SS_CLKCTRL_MODULEMODE_HW); + setbits_le32((*prcm)->cm_l3init_usb_otg_ss_clkctrl, val); + +}; + +inline int __board_usb_init(void) +{ + return 0; +} +int board_usb_init(void) __attribute__((weak, alias("__board_usb_init"))); + +static void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) +{ + clrsetbits_le32(&dwc3_reg->g_ctl, + DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG), + DWC3_GCTL_PRTCAPDIR(mode)); +} + +static void dwc3_core_soft_reset(struct dwc3 *dwc3_reg) +{ + /* Before Resetting PHY, put Core in Reset */ + setbits_le32(&dwc3_reg->g_ctl, DWC3_GCTL_CORESOFTRESET); + + /* Assert USB3 PHY reset */ + setbits_le32(&dwc3_reg->g_usb3pipectl[0], DWC3_GUSB3PIPECTL_PHYSOFTRST); + + /* Assert USB2 PHY reset */ + setbits_le32(&dwc3_reg->g_usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); + + mdelay(100); + + /* Clear USB3 PHY reset */ + clrbits_le32(&dwc3_reg->g_usb3pipectl[0], DWC3_GUSB3PIPECTL_PHYSOFTRST); + + /* Clear USB2 PHY reset */ + clrbits_le32(&dwc3_reg->g_usb2phycfg, DWC3_GUSB2PHYCFG_PHYSOFTRST); + + /* After PHYs are stable we can take Core out of reset state */ + clrbits_le32(&dwc3_reg->g_ctl, DWC3_GCTL_CORESOFTRESET); +} + +static int dwc3_core_init(struct dwc3 *dwc3_reg) +{ + u32 reg; + u32 revision; + unsigned int dwc3_hwparams1; + + revision = readl(&dwc3_reg->g_snpsid); + /* This should read as U3 followed by revision number */ + if ((revision & DWC3_GSNPSID_MASK) != 0x55330000) { + puts("this is not a DesignWare USB3 DRD Core\n"); + return -1; + } + + dwc3_core_soft_reset(dwc3_reg); + + dwc3_hwparams1 = readl(&dwc3_reg->g_hwparams1); + + reg = readl(&dwc3_reg->g_ctl); + reg &= ~DWC3_GCTL_SCALEDOWN_MASK; + reg &= ~DWC3_GCTL_DISSCRAMBLE; + switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc3_hwparams1)) { + case DWC3_GHWPARAMS1_EN_PWROPT_CLK: + reg &= ~DWC3_GCTL_DSBLCLKGTNG; + break; + default: + debug("No power optimization available\n"); + } + + /* + * WORKAROUND: DWC3 revisions <1.90a have a bug + * where the device can fail to connect at SuperSpeed + * and falls back to high-speed mode which causes + * the device to enter a Connect/Disconnect loop + */ + if ((revision & DWC3_REVISION_MASK) < 0x190a) + reg |= DWC3_GCTL_U2RSTECN; + + writel(reg, &dwc3_reg->g_ctl); + + return 0; +} + +static int omap_xhci_core_init(struct omap_xhci *omap) +{ + int ret = 0; + + omap_enable_phy_clocks(omap); + + dwc_usb3_phy_init(omap->usb3_phy); + + ret = dwc3_core_init(omap->dwc3_reg); + if (ret) { + debug("%s:failed to initialize core\n", __func__); + return ret; + } + + /* We are hard-coding DWC3 core to Host Mode */ + dwc3_set_mode(omap->dwc3_reg, DWC3_GCTL_PRTCAP_HOST); + + return ret; +} + +static void omap_xhci_core_exit(struct omap_xhci *omap) +{ + usb3_phy_power(0); +} + +int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor) +{ + struct omap_xhci *ctx = &omap; + int ret = 0; + + ctx->hcd = (struct xhci_hccr *)OMAP_XHCI_BASE; + ctx->dwc3_reg = (struct dwc3 *)((char *)(ctx->hcd) + DWC3_REG_OFFSET); + ctx->usb3_phy = (struct omap_usb3_phy *)OMAP_OCP1_SCP_BASE; + ctx->otg_wrapper = (struct omap_dwc_wrapper *)OMAP_OTG_WRAPPER_BASE; + + ret = board_usb_init(); + if (ret != 0) { + puts("Failed to initialize board for USB\n"); + return ret; + } + + ret = omap_xhci_core_init(ctx); + if (ret < 0) { + puts("Failed to initialize xhci\n"); + return ret; + } + + *hccr = (struct xhci_hccr *)(OMAP_XHCI_BASE); + *hcor = (struct xhci_hcor *)((uint32_t) *hccr + + HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); + + debug("omap-xhci: init hccr %x and hcor %x hc_length %d\n", + (uint32_t)*hccr, (uint32_t)*hcor, + (uint32_t)HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); + + return ret; +} + +void xhci_hcd_stop(int index) +{ + struct omap_xhci *ctx = &omap; + + omap_xhci_core_exit(ctx); +}

Add the call back into the board file for to enable the SMPS10 VBUS regulator.
Signed-off-by: Dan Murphy dmurphy@ti.com --- board/ti/omap5_uevm/evm.c | 74 +++++++++++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 23 deletions(-)
diff --git a/board/ti/omap5_uevm/evm.c b/board/ti/omap5_uevm/evm.c index 4706330..5fc3473 100644 --- a/board/ti/omap5_uevm/evm.c +++ b/board/ti/omap5_uevm/evm.c @@ -14,7 +14,7 @@
#include "mux_data.h"
-#ifdef CONFIG_USB_EHCI +#if defined(CONFIG_USB_EHCI) || defined(CONFIG_USB_XHCI_OMAP) #include <usb.h> #include <asm/gpio.h> #include <asm/arch/clock.h> @@ -72,6 +72,35 @@ int board_eth_init(bd_t *bis) return 0; }
+#if defined(CONFIG_USB_EHCI) || defined(CONFIG_USB_XHCI_OMAP) +static void enable_host_clocks(void) +{ + int auxclk; + int hs_clk_ctrl_val = (OPTFCLKEN_HSIC60M_P3_CLK | + OPTFCLKEN_HSIC480M_P3_CLK | + OPTFCLKEN_HSIC60M_P2_CLK | + OPTFCLKEN_HSIC480M_P2_CLK | + OPTFCLKEN_UTMI_P3_CLK | OPTFCLKEN_UTMI_P2_CLK); + + /* Enable port 2 and 3 clocks*/ + setbits_le32((*prcm)->cm_l3init_hsusbhost_clkctrl, hs_clk_ctrl_val); + + /* Enable port 2 and 3 usb host ports tll clocks*/ + setbits_le32((*prcm)->cm_l3init_hsusbtll_clkctrl, + (OPTFCLKEN_USB_CH1_CLK_ENABLE | OPTFCLKEN_USB_CH2_CLK_ENABLE)); +#ifdef CONFIG_USB_XHCI_OMAP + /* Enable the USB OTG Super speed clocks */ + setbits_le32((*prcm)->cm_l3init_usb_otg_ss_clkctrl, + (OPTFCLKEN_REFCLK960M | OTG_SS_CLKCTRL_MODULEMODE_HW)); +#endif + + auxclk = readl((*prcm)->scrm_auxclk1); + /* Request auxilary clock */ + auxclk |= AUXCLK_ENABLE_MASK; + writel(auxclk, (*prcm)->scrm_auxclk1); +} +#endif + /** * @brief misc_init_r - Configure EVM board specific configurations * such as power configurations, ethernet initialization as phase2 of @@ -84,6 +113,7 @@ int misc_init_r(void) #ifdef CONFIG_PALMAS_POWER palmas_init_settings(); #endif + return 0; }
@@ -129,26 +159,9 @@ static struct omap_usbhs_board_data usbhs_bdata = { .port_mode[2] = OMAP_EHCI_PORT_MODE_HSIC, };
-static void enable_host_clocks(void) -{ - int hs_clk_ctrl_val = (OPTFCLKEN_HSIC60M_P3_CLK | - OPTFCLKEN_HSIC480M_P3_CLK | - OPTFCLKEN_HSIC60M_P2_CLK | - OPTFCLKEN_HSIC480M_P2_CLK | - OPTFCLKEN_UTMI_P3_CLK | OPTFCLKEN_UTMI_P2_CLK); - - /* Enable port 2 and 3 clocks*/ - setbits_le32((*prcm)->cm_l3init_hsusbhost_clkctrl, hs_clk_ctrl_val); - - /* Enable port 2 and 3 usb host ports tll clocks*/ - setbits_le32((*prcm)->cm_l3init_hsusbtll_clkctrl, - (OPTFCLKEN_USB_CH1_CLK_ENABLE | OPTFCLKEN_USB_CH2_CLK_ENABLE)); -} - int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor) { int ret; - int auxclk; int reg; uint8_t device_mac[6];
@@ -171,11 +184,6 @@ int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor) eth_setenv_enetaddr("usbethaddr", device_mac); }
- auxclk = readl((*prcm)->scrm_auxclk1); - /* Request auxilary clock */ - auxclk |= AUXCLK_ENABLE_MASK; - writel(auxclk, (*prcm)->scrm_auxclk1); - ret = omap_ehci_hcd_init(&usbhs_bdata, hccr, hcor); if (ret < 0) { puts("Failed to initialize ehci\n"); @@ -203,3 +211,23 @@ void usb_hub_reset_devices(int port) } } #endif + +#ifdef CONFIG_USB_XHCI_OMAP +/** + * @brief board_usb_init - Configure EVM board specific configurations + * for the LDO's and clocks for the USB blocks. + * + * @return 0 + */ +int board_usb_init(void) +{ + int ret; +#ifdef CONFIG_PALMAS_USB_SS_PWR + ret = palmas_enable_ss_ldo(); +#endif + + enable_host_clocks(); + + return 0; +} +#endif
participants (2)
-
Dan Murphy
-
Marek Vasut