
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.vivek@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,
} else { /* Disabling USBDRD_PHY */setbits_le32(&power->usbdrd_phy_control + dev_index, POWER_USB_DRD_PHY_CTRL_EN);
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");
return -ENODEV; }printf("XHCI: Can't get device node for xhci\n");
@@ -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.