Dear Vivek Gautam, On 06/01/14 18:29, Vivek Gautam wrote: > Add required support to use multiple USB 3.0 controllers available > on exynos5420 SoC. > > Signed-off-by: Vivek Gautam <gautam.vi...@samsung.com> > --- > arch/arm/cpu/armv7/exynos/power.c | 18 ++++-- > arch/arm/include/asm/arch-exynos/cpu.h | 10 ++++ > arch/arm/include/asm/arch-exynos/power.h | 2 +- > drivers/usb/host/xhci-exynos5.c | 91 > +++++++++++++++++++++--------- > drivers/usb/host/xhci.c | 4 -- > drivers/usb/host/xhci.h | 4 ++ > 6 files changed, 91 insertions(+), 38 deletions(-) > > diff --git a/arch/arm/cpu/armv7/exynos/power.c > b/arch/arm/cpu/armv7/exynos/power.c > index 563abd7..0f8aa98 100644 > --- a/arch/arm/cpu/armv7/exynos/power.c > +++ b/arch/arm/cpu/armv7/exynos/power.c > @@ -59,26 +59,34 @@ void set_usbhost_phy_ctrl(unsigned int enable) > exynos5_set_usbhost_phy_ctrl(enable); > } > > -static void exynos5_set_usbdrd_phy_ctrl(unsigned int enable) > +static void exynos5_set_usbdrd_phy_ctrl(unsigned int enable, int dev_index) > { > struct exynos5_power *power = > (struct exynos5_power *)samsung_get_base_power(); > > + /* > + * Assuming here that the DRD_PHY_CONTROL registers > + * are contiguous, so that : > + * addressof(DRD_PHY1_CONTROL) = addressof(DRD_PHY_CONTROL) + 0x4; > + * which is the case with exynos5420. > + * For exynos5250 this should work out of box, since dev_index will > + * always be '0' in that case > + */ > if (enable) { > /* Enabling USBDRD_PHY */ > - setbits_le32(&power->usbdrd_phy_control, > + setbits_le32(&power->usbdrd_phy_control + dev_index, > POWER_USB_DRD_PHY_CTRL_EN); > } else { > /* Disabling USBDRD_PHY */ > - clrbits_le32(&power->usbdrd_phy_control, > + clrbits_le32(&power->usbdrd_phy_control + dev_index, > POWER_USB_DRD_PHY_CTRL_EN); > } > } > > -void set_usbdrd_phy_ctrl(unsigned int enable) > +void set_usbdrd_phy_ctrl(unsigned int enable, int dev_index) > { > if (cpu_is_exynos5()) > - exynos5_set_usbdrd_phy_ctrl(enable); > + exynos5_set_usbdrd_phy_ctrl(enable, dev_index); > } > > static void exynos5_dp_phy_control(unsigned int enable) > diff --git a/arch/arm/include/asm/arch-exynos/cpu.h > b/arch/arm/include/asm/arch-exynos/cpu.h > index 718940b..d93cba9 100644 > --- a/arch/arm/include/asm/arch-exynos/cpu.h > +++ b/arch/arm/include/asm/arch-exynos/cpu.h > @@ -54,6 +54,8 @@ > #define EXYNOS4_USB_HOST_XHCI_BASE DEVICE_NOT_AVAILABLE > #define EXYNOS4_USB3PHY_BASE DEVICE_NOT_AVAILABLE > #define EXYNOS4_DMC_TZASC_BASE DEVICE_NOT_AVAILABLE > +#define EXYNOS4_USB_HOST_XHCI_1_BASE DEVICE_NOT_AVAILABLE > +#define EXYNOS4_USB3PHY_1_BASE DEVICE_NOT_AVAILABLE > > /* EXYNOS4X12 */ > #define EXYNOS4X12_GPIO_PART3_BASE 0x03860000 > @@ -93,6 +95,8 @@ > #define EXYNOS4X12_USB_HOST_XHCI_BASE DEVICE_NOT_AVAILABLE > #define EXYNOS4X12_USB3PHY_BASE DEVICE_NOT_AVAILABLE > #define EXYNOS4X12_DMC_TZASC_BASE DEVICE_NOT_AVAILABLE > +#define EXYNOS4X12_USB_HOST_XHCI_1_BASE DEVICE_NOT_AVAILABLE > +#define EXYNOS4X12_USB3PHY_1_BASE DEVICE_NOT_AVAILABLE > > /* EXYNOS5 */ > #define EXYNOS5_I2C_SPACING 0x10000 > @@ -132,6 +136,8 @@ > #define EXYNOS5_ADC_BASE DEVICE_NOT_AVAILABLE > #define EXYNOS5_MODEM_BASE DEVICE_NOT_AVAILABLE > #define EXYNOS5_DMC_TZASC_BASE DEVICE_NOT_AVAILABLE > +#define EXYNOS5_USB_HOST_XHCI_1_BASE DEVICE_NOT_AVAILABLE > +#define EXYNOS5_USB3PHY_1_BASE DEVICE_NOT_AVAILABLE > > /* EXYNOS5420 */ > #define EXYNOS5420_AUDIOSS_BASE 0x03810000 > @@ -153,6 +159,8 @@ > #define EXYNOS5420_USBPHY_BASE 0x12130000 > #define EXYNOS5420_MMC_BASE 0x12200000 > #define EXYNOS5420_SROMC_BASE 0x12250000 > +#define EXYNOS5420_USB_HOST_XHCI_1_BASE 0x12400000 > +#define EXYNOS5420_USB3PHY_1_BASE 0x12500000
No. we don't have to add phy_1 and xhci_1. It looks weird. please access phy1 and xhci1 by offset. > #define EXYNOS5420_UART_BASE 0x12C00000 > #define EXYNOS5420_I2C_BASE 0x12C60000 > #define EXYNOS5420_I2C_8910_BASE 0x12E00000 > @@ -276,8 +284,10 @@ SAMSUNG_BASE(timer, PWMTIMER_BASE) > SAMSUNG_BASE(uart, UART_BASE) > SAMSUNG_BASE(usb_phy, USBPHY_BASE) > SAMSUNG_BASE(usb3_phy, USB3PHY_BASE) > +SAMSUNG_BASE(usb3_phy_1, USB3PHY_1_BASE) > SAMSUNG_BASE(usb_ehci, USB_HOST_EHCI_BASE) > SAMSUNG_BASE(usb_xhci, USB_HOST_XHCI_BASE) > +SAMSUNG_BASE(usb_xhci_1, USB_HOST_XHCI_1_BASE) > SAMSUNG_BASE(usb_otg, USBOTG_BASE) > SAMSUNG_BASE(watchdog, WATCHDOG_BASE) > SAMSUNG_BASE(power, POWER_BASE) > diff --git a/arch/arm/include/asm/arch-exynos/power.h > b/arch/arm/include/asm/arch-exynos/power.h > index c9609a2..c3f2ef0 100644 > --- a/arch/arm/include/asm/arch-exynos/power.h > +++ b/arch/arm/include/asm/arch-exynos/power.h > @@ -1684,7 +1684,7 @@ void set_hw_thermal_trip(void); > #define POWER_USB_HOST_PHY_CTRL_EN (1 << 0) > #define POWER_USB_HOST_PHY_CTRL_DISABLE (0 << 0) > > -void set_usbdrd_phy_ctrl(unsigned int enable); > +void set_usbdrd_phy_ctrl(unsigned int enable, int dev_index); > > #define POWER_USB_DRD_PHY_CTRL_EN (1 << 0) > #define POWER_USB_DRD_PHY_CTRL_DISABLE (0 << 0) > diff --git a/drivers/usb/host/xhci-exynos5.c b/drivers/usb/host/xhci-exynos5.c > index 1146d10..b5fce40 100644 > --- a/drivers/usb/host/xhci-exynos5.c > +++ b/drivers/usb/host/xhci-exynos5.c > @@ -43,18 +43,30 @@ struct exynos_xhci { > struct fdt_gpio_state vbus_gpio; > }; > > -static struct exynos_xhci exynos; > +static struct exynos_xhci reg_bases[CONFIG_USB_MAX_CONTROLLER_COUNT]; > > #ifdef CONFIG_OF_CONTROL > -static int exynos_usb3_parse_dt(const void *blob, struct exynos_xhci *exynos) > +static int exynos_usb3_parse_dt(const void *blob, > + struct exynos_xhci *base, > + int index) > { > fdt_addr_t addr; > - unsigned int node; > - int depth; > + int depth, count; > + unsigned int node = 0; = 0; unnecessary. > + int nodes[CONFIG_USB_MAX_CONTROLLER_COUNT]; > + > + /* First find all the compatible nodes */ > + count = fdtdec_find_aliases_for_id(blob, "xhci", > + COMPAT_SAMSUNG_EXYNOS5_XHCI, nodes, > + CONFIG_USB_MAX_CONTROLLER_COUNT); > + if (count < 0) { > + printf("XHCI: Can't get device node for xhci\n"); > + return -ENODEV; > + } > > - node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_XHCI); > + node = nodes[index]; > if (node <= 0) { > - debug("XHCI: Can't get device node for xhci\n"); > + printf("XHCI: Can't get device node for xhci\n"); > return -ENODEV; > } > > @@ -66,10 +78,10 @@ static int exynos_usb3_parse_dt(const void *blob, struct > exynos_xhci *exynos) > debug("Can't get the XHCI register base address\n"); > return -ENXIO; > } > - exynos->hcd = (struct xhci_hccr *)addr; > + base->hcd = (struct xhci_hccr *)addr; > > /* Vbus gpio */ > - fdtdec_decode_gpio(blob, node, "samsung,vbus-gpio", &exynos->vbus_gpio); > + fdtdec_decode_gpio(blob, node, "samsung,vbus-gpio", &base->vbus_gpio); > > depth = 0; > node = fdtdec_next_compatible_subnode(blob, node, > @@ -82,9 +94,9 @@ static int exynos_usb3_parse_dt(const void *blob, struct > exynos_xhci *exynos) > /* > * Get the base address for usbphy from the device node > */ > - exynos->usb3_phy = (struct exynos_usb3_phy *)fdtdec_get_addr(blob, node, > + base->usb3_phy = (struct exynos_usb3_phy *)fdtdec_get_addr(blob, node, > "reg"); > - if (exynos->usb3_phy == NULL) { > + if (base->usb3_phy == NULL) { > debug("Can't get the usbphy register address\n"); > return -ENXIO; > } > @@ -97,9 +109,6 @@ static void exynos5_usb3_phy_init(struct exynos_usb3_phy > *phy) > { > u32 reg; > > - /* enabling usb_drd phy */ > - set_usbdrd_phy_ctrl(POWER_USB_DRD_PHY_CTRL_EN); > - > /* Reset USB 3.0 PHY */ > writel(0x0, &phy->phy_reg0); > > @@ -176,9 +185,6 @@ static void exynos5_usb3_phy_exit(struct exynos_usb3_phy > *phy) > setbits_le32(&phy->phy_test, > PHYTEST_POWERDOWN_SSP | > PHYTEST_POWERDOWN_HSP); > - > - /* disabling usb_drd phy */ > - set_usbdrd_phy_ctrl(POWER_USB_DRD_PHY_CTRL_DISABLE); > } > > void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) > @@ -259,41 +265,64 @@ static int dwc3_core_init(struct dwc3 *dwc3_reg) > return 0; > } > > -static int exynos_xhci_core_init(struct exynos_xhci *exynos) > +static int exynos_xhci_core_init(struct exynos_xhci *base) > { > int ret; > > - exynos5_usb3_phy_init(exynos->usb3_phy); > + exynos5_usb3_phy_init(base->usb3_phy); > > - ret = dwc3_core_init(exynos->dwc3_reg); > + ret = dwc3_core_init(base->dwc3_reg); > if (ret) { > debug("failed to initialize core\n"); > return -EINVAL; > } > > - /* We are hard-coding DWC3 core to Host Mode */ > - dwc3_set_mode(exynos->dwc3_reg, DWC3_GCTL_PRTCAP_HOST); > + /* > + * TODO: We are hard-coding DWC3 core to Host Mode; > + * when we have complete DWC3 support we may want to > + * have both device as well as host mode, so this will > + * vanish off then. > + */ > + dwc3_set_mode(base->dwc3_reg, DWC3_GCTL_PRTCAP_HOST); > > return 0; > } > > -static void exynos_xhci_core_exit(struct exynos_xhci *exynos) > +static void exynos_xhci_core_exit(struct exynos_xhci *base) > { > - exynos5_usb3_phy_exit(exynos->usb3_phy); > + exynos5_usb3_phy_exit(base->usb3_phy); > } > > int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor > **hcor) > { > - struct exynos_xhci *ctx = &exynos; > + struct exynos_xhci *ctx = ®_bases[index]; > int ret; > > #ifdef CONFIG_OF_CONTROL > - exynos_usb3_parse_dt(gd->fdt_blob, ctx); > + exynos_usb3_parse_dt(gd->fdt_blob, ctx, index); > #else > - ctx->usb3_phy = (struct exynos_usb3_phy *)samsung_get_base_usb3_phy(); > - ctx->hcd = (struct xhci_hccr *)samsung_get_base_usb_xhci(); > + /* > + * right now we only have h/w with 2 controllers, so limiting the > + * index to two here: either 0 or 1. > + */ > + if (index == 0) { > + ctx->usb3_phy = (struct exynos_usb3_phy *) > + samsung_get_base_usb3_phy(); > + ctx->hcd = (struct xhci_hccr *) > + samsung_get_base_usb_xhci(); > + } else if (index == 1) { > + ctx->usb3_phy = (struct exynos_usb3_phy *) > + samsung_get_base_usb3_phy_1(); > + ctx->hcd = (struct xhci_hccr *) > + samsung_get_base_usb_xhci_1(); > + } > #endif > > + if (!ctx->hcd || !ctx->usb3_phy) { > + printf("XHCI: Unable to find Host controller\n"); > + return -ENODEV; > + } > + > ctx->dwc3_reg = (struct dwc3 *)((char *)(ctx->hcd) + DWC3_REG_OFFSET); > > #ifdef CONFIG_OF_CONTROL > @@ -302,6 +331,9 @@ int xhci_hcd_init(int index, struct xhci_hccr **hccr, > struct xhci_hcor **hcor) > gpio_direction_output(ctx->vbus_gpio.gpio, 1); > #endif > > + /* Power-on usb_drd phy */ > + set_usbdrd_phy_ctrl(POWER_USB_DRD_PHY_CTRL_EN, index); > + > ret = exynos_xhci_core_init(ctx); > if (ret) { > puts("XHCI: failed to initialize controller\n"); > @@ -321,7 +353,10 @@ int xhci_hcd_init(int index, struct xhci_hccr **hccr, > struct xhci_hcor **hcor) > > void xhci_hcd_stop(int index) > { > - struct exynos_xhci *ctx = &exynos; > + struct exynos_xhci *ctx = ®_bases[index]; > > exynos_xhci_core_exit(ctx); > + > + /* Power-off usb_drd phy */ > + set_usbdrd_phy_ctrl(POWER_USB_DRD_PHY_CTRL_DISABLE, index); > } > diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c > index d1c2e5c..24175e6 100644 > --- a/drivers/usb/host/xhci.c > +++ b/drivers/usb/host/xhci.c > @@ -30,10 +30,6 @@ > #include <asm-generic/errno.h> > #include "xhci.h" > > -#ifndef CONFIG_USB_MAX_CONTROLLER_COUNT > -#define CONFIG_USB_MAX_CONTROLLER_COUNT 1 > -#endif > - > static struct descriptor { > struct usb_hub_descriptor hub; > struct usb_device_descriptor device; > diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h > index ceb1573..612bf79 100644 > --- a/drivers/usb/host/xhci.h > +++ b/drivers/usb/host/xhci.h > @@ -21,6 +21,10 @@ > #include <asm/io.h> > #include <linux/list.h> > > +#ifndef CONFIG_USB_MAX_CONTROLLER_COUNT > +#define CONFIG_USB_MAX_CONTROLLER_COUNT 1 > +#endif > + > #define upper_32_bits(n) (u32)((n) >> 32) > #define lower_32_bits(n) (u32)(n) > > Thanks, Minkyu Kang. _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot