From a8973731a452323e8767e8f9775c7d06921ebed5 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Wed, 11 Sep 2019 11:33:44 +0200 Subject: [PATCH 01/18] usb: host: remove the xhci-zynqmp driver This driver is not used anymore. Signed-off-by: Jean-Jacques Hiblot --- configs/avnet_ultra96_rev1_defconfig | 1 - .../xilinx_zynqmp_zc1751_xm015_dc1_defconfig | 1 - .../xilinx_zynqmp_zc1751_xm016_dc2_defconfig | 1 - .../xilinx_zynqmp_zc1751_xm017_dc3_defconfig | 1 - configs/xilinx_zynqmp_zcu100_revC_defconfig | 1 - configs/xilinx_zynqmp_zcu102_rev1_0_defconfig | 1 - configs/xilinx_zynqmp_zcu102_revA_defconfig | 1 - configs/xilinx_zynqmp_zcu102_revB_defconfig | 1 - configs/xilinx_zynqmp_zcu104_revA_defconfig | 1 - configs/xilinx_zynqmp_zcu104_revC_defconfig | 1 - configs/xilinx_zynqmp_zcu106_revA_defconfig | 1 - configs/xilinx_zynqmp_zcu111_revA_defconfig | 1 - drivers/usb/host/Kconfig | 7 - drivers/usb/host/Makefile | 1 - drivers/usb/host/xhci-zynqmp.c | 146 ------------------ 15 files changed, 166 deletions(-) delete mode 100644 drivers/usb/host/xhci-zynqmp.c diff --git a/configs/avnet_ultra96_rev1_defconfig b/configs/avnet_ultra96_rev1_defconfig index b5e61e621a..859c1f8ce8 100644 --- a/configs/avnet_ultra96_rev1_defconfig +++ b/configs/avnet_ultra96_rev1_defconfig @@ -73,7 +73,6 @@ CONFIG_ZYNQ_SPI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y -CONFIG_USB_XHCI_ZYNQMP=y CONFIG_USB_DWC3=y CONFIG_USB_DWC3_GADGET=y CONFIG_USB_DWC3_GENERIC=y diff --git a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig index bbf387a6b0..6b4cba7f80 100644 --- a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig +++ b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig @@ -84,7 +84,6 @@ CONFIG_ZYNQMP_GQSPI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y -CONFIG_USB_XHCI_ZYNQMP=y CONFIG_USB_DWC3=y CONFIG_USB_DWC3_GADGET=y CONFIG_USB_DWC3_GENERIC=y diff --git a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig index d5434eee85..a2010571e5 100644 --- a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig +++ b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig @@ -75,7 +75,6 @@ CONFIG_SPI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y -CONFIG_USB_XHCI_ZYNQMP=y CONFIG_USB_DWC3=y CONFIG_USB_DWC3_GADGET=y CONFIG_USB_DWC3_GENERIC=y diff --git a/configs/xilinx_zynqmp_zc1751_xm017_dc3_defconfig b/configs/xilinx_zynqmp_zc1751_xm017_dc3_defconfig index 4ff52292fb..0d1e0f00c9 100644 --- a/configs/xilinx_zynqmp_zc1751_xm017_dc3_defconfig +++ b/configs/xilinx_zynqmp_zc1751_xm017_dc3_defconfig @@ -72,7 +72,6 @@ CONFIG_SPI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y -CONFIG_USB_XHCI_ZYNQMP=y CONFIG_USB_DWC3=y CONFIG_USB_DWC3_GADGET=y CONFIG_USB_DWC3_GENERIC=y diff --git a/configs/xilinx_zynqmp_zcu100_revC_defconfig b/configs/xilinx_zynqmp_zcu100_revC_defconfig index fc917f0b5d..f1b63e6df9 100644 --- a/configs/xilinx_zynqmp_zcu100_revC_defconfig +++ b/configs/xilinx_zynqmp_zcu100_revC_defconfig @@ -72,7 +72,6 @@ CONFIG_ZYNQ_SPI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y -CONFIG_USB_XHCI_ZYNQMP=y CONFIG_USB_DWC3=y CONFIG_USB_DWC3_GADGET=y CONFIG_USB_DWC3_GENERIC=y diff --git a/configs/xilinx_zynqmp_zcu102_rev1_0_defconfig b/configs/xilinx_zynqmp_zcu102_rev1_0_defconfig index b64956d5f6..2791d0fce3 100644 --- a/configs/xilinx_zynqmp_zcu102_rev1_0_defconfig +++ b/configs/xilinx_zynqmp_zcu102_rev1_0_defconfig @@ -100,7 +100,6 @@ CONFIG_ZYNQMP_GQSPI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y -CONFIG_USB_XHCI_ZYNQMP=y CONFIG_USB_DWC3=y CONFIG_USB_DWC3_GADGET=y CONFIG_USB_DWC3_GENERIC=y diff --git a/configs/xilinx_zynqmp_zcu102_revA_defconfig b/configs/xilinx_zynqmp_zcu102_revA_defconfig index 8b1a1ce0a2..adebf1cf44 100644 --- a/configs/xilinx_zynqmp_zcu102_revA_defconfig +++ b/configs/xilinx_zynqmp_zcu102_revA_defconfig @@ -99,7 +99,6 @@ CONFIG_ZYNQMP_GQSPI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y -CONFIG_USB_XHCI_ZYNQMP=y CONFIG_USB_DWC3=y CONFIG_USB_DWC3_GADGET=y CONFIG_USB_DWC3_GENERIC=y diff --git a/configs/xilinx_zynqmp_zcu102_revB_defconfig b/configs/xilinx_zynqmp_zcu102_revB_defconfig index 2aab26dd3f..0f575b7135 100644 --- a/configs/xilinx_zynqmp_zcu102_revB_defconfig +++ b/configs/xilinx_zynqmp_zcu102_revB_defconfig @@ -99,7 +99,6 @@ CONFIG_ZYNQMP_GQSPI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y -CONFIG_USB_XHCI_ZYNQMP=y CONFIG_USB_DWC3=y CONFIG_USB_DWC3_GADGET=y CONFIG_USB_DWC3_GENERIC=y diff --git a/configs/xilinx_zynqmp_zcu104_revA_defconfig b/configs/xilinx_zynqmp_zcu104_revA_defconfig index 07e58b192a..a134ba603e 100644 --- a/configs/xilinx_zynqmp_zcu104_revA_defconfig +++ b/configs/xilinx_zynqmp_zcu104_revA_defconfig @@ -83,7 +83,6 @@ CONFIG_ZYNQMP_GQSPI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y -CONFIG_USB_XHCI_ZYNQMP=y CONFIG_USB_DWC3=y CONFIG_USB_DWC3_GADGET=y CONFIG_USB_DWC3_GENERIC=y diff --git a/configs/xilinx_zynqmp_zcu104_revC_defconfig b/configs/xilinx_zynqmp_zcu104_revC_defconfig index 4829df62b4..1d2010f354 100644 --- a/configs/xilinx_zynqmp_zcu104_revC_defconfig +++ b/configs/xilinx_zynqmp_zcu104_revC_defconfig @@ -87,7 +87,6 @@ CONFIG_ZYNQMP_GQSPI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y -CONFIG_USB_XHCI_ZYNQMP=y CONFIG_USB_DWC3=y CONFIG_USB_DWC3_GADGET=y CONFIG_USB_DWC3_GENERIC=y diff --git a/configs/xilinx_zynqmp_zcu106_revA_defconfig b/configs/xilinx_zynqmp_zcu106_revA_defconfig index 72b3ce16a8..4b3ea155ef 100644 --- a/configs/xilinx_zynqmp_zcu106_revA_defconfig +++ b/configs/xilinx_zynqmp_zcu106_revA_defconfig @@ -93,7 +93,6 @@ CONFIG_ZYNQMP_GQSPI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y -CONFIG_USB_XHCI_ZYNQMP=y CONFIG_USB_DWC3=y CONFIG_USB_DWC3_GADGET=y CONFIG_USB_DWC3_GENERIC=y diff --git a/configs/xilinx_zynqmp_zcu111_revA_defconfig b/configs/xilinx_zynqmp_zcu111_revA_defconfig index de739ed3b5..a84b53fe1d 100644 --- a/configs/xilinx_zynqmp_zcu111_revA_defconfig +++ b/configs/xilinx_zynqmp_zcu111_revA_defconfig @@ -85,7 +85,6 @@ CONFIG_ZYNQMP_GQSPI=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y -CONFIG_USB_XHCI_ZYNQMP=y CONFIG_USB_DWC3=y CONFIG_USB_DWC3_GADGET=y CONFIG_USB_DWC3_GENERIC=y diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 30c6b69be8..b674e330ac 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -73,13 +73,6 @@ config USB_XHCI_STI STiH407 family SoCs. This is a driver for the dwc3 to provide the glue logic to configure the controller. -config USB_XHCI_ZYNQMP - bool "Support for Xilinx ZynqMP on-chip xHCI USB controller" - depends on ARCH_ZYNQMP - depends on DM_USB - help - Enables support for the on-chip xHCI controller on Xilinx ZynqMP SoCs. - config USB_XHCI_DRA7XX_INDEX int "DRA7XX xHCI USB index" range 0 1 diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index dd13528475..7feeff679c 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -48,7 +48,6 @@ obj-$(CONFIG_USB_XHCI_HCD) += xhci.o xhci-mem.o xhci-ring.o obj-$(CONFIG_USB_XHCI_DWC3) += xhci-dwc3.o obj-$(CONFIG_USB_XHCI_DWC3_OF_SIMPLE) += dwc3-of-simple.o obj-$(CONFIG_USB_XHCI_ROCKCHIP) += xhci-rockchip.o -obj-$(CONFIG_USB_XHCI_ZYNQMP) += xhci-zynqmp.o obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o diff --git a/drivers/usb/host/xhci-zynqmp.c b/drivers/usb/host/xhci-zynqmp.c deleted file mode 100644 index e44e1ae1d9..0000000000 --- a/drivers/usb/host/xhci-zynqmp.c +++ /dev/null @@ -1,146 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright 2015 Xilinx, Inc. - * - * Zynq USB HOST xHCI Controller - * - * Author: Siva Durga Prasad Paladugu - * - * This file was reused from Freescale USB xHCI - */ - -#include -#include -#include -#include -#include -#include -#include -#include "xhci.h" - -/* Declare global data pointer */ -/* Default to the ZYNQMP XHCI defines */ -#define USB3_PWRCTL_CLK_CMD_MASK 0x3FE000 -#define USB3_PWRCTL_CLK_FREQ_MASK 0xFFC -#define USB3_PHY_PARTIAL_RX_POWERON BIT(6) -#define USB3_PHY_RX_POWERON BIT(14) -#define USB3_PHY_TX_POWERON BIT(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 BIT(17) -#define USBOTGSS_DMADISABLE BIT(16) -#define USBOTGSS_STANDBYMODE_NO_STANDBY BIT(4) -#define USBOTGSS_STANDBYMODE_SMRT BIT(5) -#define USBOTGSS_STANDBYMODE_SMRT_WKUP (0x3 << 4) -#define USBOTGSS_IDLEMODE_NOIDLE BIT(2) -#define USBOTGSS_IDLEMODE_SMRT BIT(3) -#define USBOTGSS_IDLEMODE_SMRT_WKUP (0x3 << 2) - -/* USBOTGSS_IRQENABLE_SET_0 bit */ -#define USBOTGSS_COREIRQ_EN BIT(1) - -/* USBOTGSS_IRQENABLE_SET_1 bits */ -#define USBOTGSS_IRQ_SET_1_IDPULLUP_FALL_EN BIT(1) -#define USBOTGSS_IRQ_SET_1_DISCHRGVBUS_FALL_EN BIT(3) -#define USBOTGSS_IRQ_SET_1_CHRGVBUS_FALL_EN BIT(4) -#define USBOTGSS_IRQ_SET_1_DRVVBUS_FALL_EN BIT(5) -#define USBOTGSS_IRQ_SET_1_IDPULLUP_RISE_EN BIT(8) -#define USBOTGSS_IRQ_SET_1_DISCHRGVBUS_RISE_EN BIT(11) -#define USBOTGSS_IRQ_SET_1_CHRGVBUS_RISE_EN BIT(12) -#define USBOTGSS_IRQ_SET_1_DRVVBUS_RISE_EN BIT(13) -#define USBOTGSS_IRQ_SET_1_OEVT_EN BIT(16) -#define USBOTGSS_IRQ_SET_1_DMADISABLECLR_EN BIT(17) - -struct zynqmp_xhci { - struct usb_platdata usb_plat; - struct xhci_ctrl ctrl; - struct xhci_hccr *hcd; - struct dwc3 *dwc3_reg; -}; - -struct zynqmp_xhci_platdata { - fdt_addr_t hcd_base; -}; - -static int zynqmp_xhci_core_init(struct zynqmp_xhci *zynqmp_xhci) -{ - int ret = 0; - - ret = dwc3_core_init(zynqmp_xhci->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(zynqmp_xhci->dwc3_reg, DWC3_GCTL_PRTCAP_HOST); - - return ret; -} - -void xhci_hcd_stop(int index) -{ - /* - * Currently zynqmp socs do not support PHY shutdown from - * sw. But this support may be added in future socs. - */ - - return; -} - -static int xhci_usb_probe(struct udevice *dev) -{ - struct zynqmp_xhci_platdata *plat = dev_get_platdata(dev); - struct zynqmp_xhci *ctx = dev_get_priv(dev); - struct xhci_hcor *hcor; - int ret; - - ctx->hcd = (struct xhci_hccr *)plat->hcd_base; - ctx->dwc3_reg = (struct dwc3 *)((char *)(ctx->hcd) + DWC3_REG_OFFSET); - - ret = zynqmp_xhci_core_init(ctx); - if (ret) { - puts("XHCI: failed to initialize controller\n"); - return -EINVAL; - } - - hcor = (struct xhci_hcor *)((ulong)ctx->hcd + - HC_LENGTH(xhci_readl(&ctx->hcd->cr_capbase))); - - return xhci_register(dev, ctx->hcd, hcor); -} - -static int xhci_usb_remove(struct udevice *dev) -{ - return xhci_deregister(dev); -} - -static int xhci_usb_ofdata_to_platdata(struct udevice *dev) -{ - struct zynqmp_xhci_platdata *plat = dev_get_platdata(dev); - const void *blob = gd->fdt_blob; - - /* Get the base address for XHCI controller from the device node */ - plat->hcd_base = fdtdec_get_addr(blob, dev_of_offset(dev), "reg"); - if (plat->hcd_base == FDT_ADDR_T_NONE) { - debug("Can't get the XHCI register base address\n"); - return -ENXIO; - } - - return 0; -} - -U_BOOT_DRIVER(dwc3_generic_host) = { - .name = "dwc3-generic-host", - .id = UCLASS_USB, - .ofdata_to_platdata = xhci_usb_ofdata_to_platdata, - .probe = xhci_usb_probe, - .remove = xhci_usb_remove, - .ops = &xhci_usb_ops, - .platdata_auto_alloc_size = sizeof(struct zynqmp_xhci_platdata), - .priv_auto_alloc_size = sizeof(struct zynqmp_xhci), - .flags = DM_FLAG_ALLOC_PRIV_DMA, -}; From bbe3d4a6c14e17d251029e4dde07f184244e9a4a Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Wed, 11 Sep 2019 11:33:45 +0200 Subject: [PATCH 02/18] usb: dwc3: switch to peripheral mode when exiting This allow the phy to enter idle and then suspend. the K2 platforms require the PHY to be suspended before the USB domain clock can be turned off. Signed-off-by: Jean-Jacques Hiblot --- drivers/usb/dwc3/core.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 2498f0efb1..1bd41f8bc7 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -581,6 +581,12 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) return 0; } +static void dwc3_gadget_run(struct dwc3 *dwc) +{ + dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_RUN_STOP); + mdelay(100); +} + static void dwc3_core_exit_mode(struct dwc3 *dwc) { switch (dwc->dr_mode) { @@ -598,6 +604,13 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc) /* do nothing */ break; } + + /* + * switch back to peripheral mode + * This enables the phy to enter idle and then, if enabled, suspend. + */ + dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); + dwc3_gadget_run(dwc); } #define DWC3_ALIGN_MASK (16 - 1) From 1708a12377b98397606677e117f93f07d7cd2f7e Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Wed, 11 Sep 2019 11:33:46 +0200 Subject: [PATCH 03/18] usb: xhci: move xhci.h to include usb The xhci.h header file is currently located under drivers/usb/xhci Move it to the include/usb folder to make it available to drivers that are not under drivers/usb/xhci Signed-off-by: Jean-Jacques Hiblot --- MAINTAINERS | 1 + drivers/usb/host/xhci-dwc3.c | 2 +- drivers/usb/host/xhci-exynos5.c | 2 +- drivers/usb/host/xhci-fsl.c | 2 +- drivers/usb/host/xhci-mem.c | 2 +- drivers/usb/host/xhci-mvebu.c | 2 +- drivers/usb/host/xhci-omap.c | 2 +- drivers/usb/host/xhci-pci.c | 2 +- drivers/usb/host/xhci-rcar.c | 2 +- drivers/usb/host/xhci-ring.c | 2 +- drivers/usb/host/xhci-rockchip.c | 2 +- drivers/usb/host/xhci.c | 2 +- drivers/usb/phy/omap_usb_phy.c | 2 +- {drivers/usb/host => include/usb}/xhci.h | 0 14 files changed, 13 insertions(+), 12 deletions(-) rename {drivers/usb/host => include/usb}/xhci.h (100%) diff --git a/MAINTAINERS b/MAINTAINERS index a7c355c76f..48345f895d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -851,6 +851,7 @@ M: Bin Meng S: Maintained T: git https://gitlab.denx.de/u-boot/custodians/u-boot-usb.git topic-xhci F: drivers/usb/host/xhci* +F: include/usb/xhci.h VIDEO M: Anatolij Gustschin diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c index 55a1b22cf6..c1c681ca6c 100644 --- a/drivers/usb/host/xhci-dwc3.c +++ b/drivers/usb/host/xhci-dwc3.c @@ -14,7 +14,7 @@ #include #include -#include "xhci.h" +#include #include #include #include diff --git a/drivers/usb/host/xhci-exynos5.c b/drivers/usb/host/xhci-exynos5.c index c150f520bd..25c30c24f0 100644 --- a/drivers/usb/host/xhci-exynos5.c +++ b/drivers/usb/host/xhci-exynos5.c @@ -27,7 +27,7 @@ #include #include -#include "xhci.h" +#include /* Declare global data pointer */ DECLARE_GLOBAL_DATA_PTR; diff --git a/drivers/usb/host/xhci-fsl.c b/drivers/usb/host/xhci-fsl.c index c0b98a8ec7..9e0c1b76e4 100644 --- a/drivers/usb/host/xhci-fsl.c +++ b/drivers/usb/host/xhci-fsl.c @@ -13,7 +13,7 @@ #include #include #include -#include "xhci.h" +#include #include #include #include diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 84c2c3344a..530e979bb7 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -21,7 +21,7 @@ #include #include -#include "xhci.h" +#include #define CACHELINE_SIZE CONFIG_SYS_CACHELINE_SIZE /** diff --git a/drivers/usb/host/xhci-mvebu.c b/drivers/usb/host/xhci-mvebu.c index b6c6aaf78e..2b871046ae 100644 --- a/drivers/usb/host/xhci-mvebu.c +++ b/drivers/usb/host/xhci-mvebu.c @@ -12,7 +12,7 @@ #include #include -#include "xhci.h" +#include struct mvebu_xhci_platdata { fdt_addr_t hcd_base; diff --git a/drivers/usb/host/xhci-omap.c b/drivers/usb/host/xhci-omap.c index db007af37f..25b195f7d1 100644 --- a/drivers/usb/host/xhci-omap.c +++ b/drivers/usb/host/xhci-omap.c @@ -19,7 +19,7 @@ #include #include -#include "xhci.h" +#include /* Declare global data pointer */ static struct omap_xhci omap; diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index b995aef997..c1f60da541 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -9,7 +9,7 @@ #include #include #include -#include "xhci.h" +#include static void xhci_pci_init(struct udevice *dev, struct xhci_hccr **ret_hccr, struct xhci_hcor **ret_hcor) diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c index f2e91ef0fe..c4d8811343 100644 --- a/drivers/usb/host/xhci-rcar.c +++ b/drivers/usb/host/xhci-rcar.c @@ -12,7 +12,7 @@ #include #include -#include "xhci.h" +#include #include "xhci-rcar-r8a779x_usb3_v3.h" /* Register Offset */ diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index b2cfd948f8..119b418487 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -19,7 +19,7 @@ #include #include -#include "xhci.h" +#include /** * Is this TRB a link TRB or was the last TRB the last TRB in this event ring diff --git a/drivers/usb/host/xhci-rockchip.c b/drivers/usb/host/xhci-rockchip.c index e7b0dbcca5..b67722fe45 100644 --- a/drivers/usb/host/xhci-rockchip.c +++ b/drivers/usb/host/xhci-rockchip.c @@ -13,7 +13,7 @@ #include #include -#include "xhci.h" +#include struct rockchip_xhci_platdata { fdt_addr_t hcd_base; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index b3e4dcd66f..abd23e23fd 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -28,7 +28,7 @@ #include #include #include -#include "xhci.h" +#include #ifndef CONFIG_USB_MAX_CONTROLLER_COUNT #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 diff --git a/drivers/usb/phy/omap_usb_phy.c b/drivers/usb/phy/omap_usb_phy.c index 32e5bbb8d8..897e6f19f7 100644 --- a/drivers/usb/phy/omap_usb_phy.c +++ b/drivers/usb/phy/omap_usb_phy.c @@ -19,7 +19,7 @@ #include #include -#include "../host/xhci.h" +#include #ifdef CONFIG_OMAP_USB3PHY1_HOST struct usb3_dpll_params { diff --git a/drivers/usb/host/xhci.h b/include/usb/xhci.h similarity index 100% rename from drivers/usb/host/xhci.h rename to include/usb/xhci.h From 33a99b43651b58fbb10f3778a16dd4c0a4db9708 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Wed, 11 Sep 2019 11:33:47 +0200 Subject: [PATCH 04/18] usb: dwc3: always use the inlined version of dwc3_host_init/dwc3_host_exit No one is actually implementing those functions. We could remove calls to these altogether, but it does not really hurt to keep the empty inlined version at the moment and it satisfies a symmetry with the gadget mode. Signed-off-by: Jean-Jacques Hiblot --- drivers/usb/dwc3/core.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index cfe29884e7..4c89dfcad9 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -994,15 +994,10 @@ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc); int dwc3_init(struct dwc3 *dwc); void dwc3_remove(struct dwc3 *dwc); -#ifdef CONFIG_USB_DWC3_HOST -int dwc3_host_init(struct dwc3 *dwc); -void dwc3_host_exit(struct dwc3 *dwc); -#else static inline int dwc3_host_init(struct dwc3 *dwc) { return 0; } static inline void dwc3_host_exit(struct dwc3 *dwc) { } -#endif #ifdef CONFIG_USB_DWC3_GADGET int dwc3_gadget_init(struct dwc3 *dwc); From 3a38a0adb95bfebbbd39b2bb164f04bdeb10bc03 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Wed, 11 Sep 2019 11:33:48 +0200 Subject: [PATCH 05/18] usb: dwc3-generic: use platdata Separate platform data from the private data. This is one step toward adding host support. Signed-off-by: Jean-Jacques Hiblot --- drivers/usb/dwc3/dwc3-generic.c | 37 ++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 406bf0b362..f29b93d191 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -22,17 +22,22 @@ #include #include +struct dwc3_generic_plat { + fdt_addr_t base; + u32 maximum_speed; + enum usb_dr_mode dr_mode; +}; + #if CONFIG_IS_ENABLED(DM_USB_GADGET) -struct dwc3_generic_peripheral { +struct dwc3_generic_priv { struct dwc3 dwc3; struct phy *phys; int num_phys; - fdt_addr_t base; }; int dm_usb_gadget_handle_interrupts(struct udevice *dev) { - struct dwc3_generic_peripheral *priv = dev_get_priv(dev); + struct dwc3_generic_priv *priv = dev_get_priv(dev); struct dwc3 *dwc3 = &priv->dwc3; dwc3_gadget_uboot_handle_interrupt(dwc3); @@ -43,14 +48,18 @@ int dm_usb_gadget_handle_interrupts(struct udevice *dev) static int dwc3_generic_peripheral_probe(struct udevice *dev) { int rc; - struct dwc3_generic_peripheral *priv = dev_get_priv(dev); + struct dwc3_generic_priv *priv = dev_get_priv(dev); + struct dwc3_generic_plat *plat = dev_get_platdata(dev); struct dwc3 *dwc3 = &priv->dwc3; + dwc3->maximum_speed = plat->maximum_speed; + dwc3->dr_mode = plat->dr_mode; + rc = dwc3_setup_phy(dev, &priv->phys, &priv->num_phys); if (rc) return rc; - dwc3->regs = map_physmem(priv->base, DWC3_OTG_REGS_END, MAP_NOCACHE); + dwc3->regs = map_physmem(plat->base, DWC3_OTG_REGS_END, MAP_NOCACHE); dwc3->regs += DWC3_GLOBALS_REGS_START; dwc3->dev = dev; @@ -65,7 +74,7 @@ static int dwc3_generic_peripheral_probe(struct udevice *dev) static int dwc3_generic_peripheral_remove(struct udevice *dev) { - struct dwc3_generic_peripheral *priv = dev_get_priv(dev); + struct dwc3_generic_priv *priv = dev_get_priv(dev); struct dwc3 *dwc3 = &priv->dwc3; dwc3_remove(dwc3); @@ -77,20 +86,19 @@ static int dwc3_generic_peripheral_remove(struct udevice *dev) static int dwc3_generic_peripheral_ofdata_to_platdata(struct udevice *dev) { - struct dwc3_generic_peripheral *priv = dev_get_priv(dev); - struct dwc3 *dwc3 = &priv->dwc3; + struct dwc3_generic_plat *plat = dev_get_platdata(dev); int node = dev_of_offset(dev); - priv->base = devfdt_get_addr(dev); + plat->base = devfdt_get_addr(dev); - dwc3->maximum_speed = usb_get_maximum_speed(node); - if (dwc3->maximum_speed == USB_SPEED_UNKNOWN) { + plat->maximum_speed = usb_get_maximum_speed(node); + if (plat->maximum_speed == USB_SPEED_UNKNOWN) { pr_err("Invalid usb maximum speed\n"); return -ENODEV; } - dwc3->dr_mode = usb_get_dr_mode(node); - if (dwc3->dr_mode == USB_DR_MODE_UNKNOWN) { + plat->dr_mode = usb_get_dr_mode(node); + if (plat->dr_mode == USB_DR_MODE_UNKNOWN) { pr_err("Invalid usb mode setup\n"); return -ENODEV; } @@ -104,7 +112,8 @@ U_BOOT_DRIVER(dwc3_generic_peripheral) = { .ofdata_to_platdata = dwc3_generic_peripheral_ofdata_to_platdata, .probe = dwc3_generic_peripheral_probe, .remove = dwc3_generic_peripheral_remove, - .priv_auto_alloc_size = sizeof(struct dwc3_generic_peripheral), + .priv_auto_alloc_size = sizeof(struct dwc3_generic_priv), + .platdata_auto_alloc_size = sizeof(struct dwc3_generic_plat), }; #endif From 1af590df164f88fffb6484842eec8c8d8e500e70 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Wed, 11 Sep 2019 11:33:49 +0200 Subject: [PATCH 06/18] usb: dwc3-generic: factorize code Factor code for re-usability. This is another step toward adding host support. Signed-off-by: Jean-Jacques Hiblot --- drivers/usb/dwc3/dwc3-generic.c | 55 +++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index f29b93d191..d5c71d024f 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -28,27 +28,17 @@ struct dwc3_generic_plat { enum usb_dr_mode dr_mode; }; -#if CONFIG_IS_ENABLED(DM_USB_GADGET) struct dwc3_generic_priv { + void *base; struct dwc3 dwc3; struct phy *phys; int num_phys; }; -int dm_usb_gadget_handle_interrupts(struct udevice *dev) -{ - struct dwc3_generic_priv *priv = dev_get_priv(dev); - struct dwc3 *dwc3 = &priv->dwc3; - - dwc3_gadget_uboot_handle_interrupt(dwc3); - - return 0; -} - -static int dwc3_generic_peripheral_probe(struct udevice *dev) +static int dwc3_generic_probe(struct udevice *dev, + struct dwc3_generic_priv *priv) { int rc; - struct dwc3_generic_priv *priv = dev_get_priv(dev); struct dwc3_generic_plat *plat = dev_get_platdata(dev); struct dwc3 *dwc3 = &priv->dwc3; @@ -59,22 +49,22 @@ static int dwc3_generic_peripheral_probe(struct udevice *dev) if (rc) return rc; - dwc3->regs = map_physmem(plat->base, DWC3_OTG_REGS_END, MAP_NOCACHE); - dwc3->regs += DWC3_GLOBALS_REGS_START; + priv->base = map_physmem(plat->base, DWC3_OTG_REGS_END, MAP_NOCACHE); + dwc3->regs = priv->base + DWC3_GLOBALS_REGS_START; dwc3->dev = dev; rc = dwc3_init(dwc3); if (rc) { - unmap_physmem(dwc3->regs, MAP_NOCACHE); + unmap_physmem(priv->base, MAP_NOCACHE); return rc; } return 0; } -static int dwc3_generic_peripheral_remove(struct udevice *dev) +static int dwc3_generic_remove(struct udevice *dev, + struct dwc3_generic_priv *priv) { - struct dwc3_generic_priv *priv = dev_get_priv(dev); struct dwc3 *dwc3 = &priv->dwc3; dwc3_remove(dwc3); @@ -84,7 +74,7 @@ static int dwc3_generic_peripheral_remove(struct udevice *dev) return 0; } -static int dwc3_generic_peripheral_ofdata_to_platdata(struct udevice *dev) +static int dwc3_generic_ofdata_to_platdata(struct udevice *dev) { struct dwc3_generic_plat *plat = dev_get_platdata(dev); int node = dev_of_offset(dev); @@ -106,10 +96,35 @@ static int dwc3_generic_peripheral_ofdata_to_platdata(struct udevice *dev) return 0; } +#if CONFIG_IS_ENABLED(DM_USB_GADGET) +int dm_usb_gadget_handle_interrupts(struct udevice *dev) +{ + struct dwc3_generic_priv *priv = dev_get_priv(dev); + struct dwc3 *dwc3 = &priv->dwc3; + + dwc3_gadget_uboot_handle_interrupt(dwc3); + + return 0; +} + +static int dwc3_generic_peripheral_probe(struct udevice *dev) +{ + struct dwc3_generic_priv *priv = dev_get_priv(dev); + + return dwc3_generic_probe(dev, priv); +} + +static int dwc3_generic_peripheral_remove(struct udevice *dev) +{ + struct dwc3_generic_priv *priv = dev_get_priv(dev); + + return dwc3_generic_remove(dev, priv); +} + U_BOOT_DRIVER(dwc3_generic_peripheral) = { .name = "dwc3-generic-peripheral", .id = UCLASS_USB_GADGET_GENERIC, - .ofdata_to_platdata = dwc3_generic_peripheral_ofdata_to_platdata, + .ofdata_to_platdata = dwc3_generic_ofdata_to_platdata, .probe = dwc3_generic_peripheral_probe, .remove = dwc3_generic_peripheral_remove, .priv_auto_alloc_size = sizeof(struct dwc3_generic_priv), From b575e909168ca559609f6793720c4811b1dd55fd Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Wed, 11 Sep 2019 11:33:50 +0200 Subject: [PATCH 07/18] usb: dwc3-generic: add a new host driver that uses the dwc3 core Currently the host driver used by dwc3-generic is "xhci-dwc3". This is a functional driver but it doesn't use the dwc3 core and, in particular, it lacks some bits that may be important. For example on the k2 platforms, it is important that the phy are properly suspended when the USB is not used anymore. The dwc3 core also has a partial support for quirks. The new driver can be used as a drop-in replacement for "xhci-dwc3". In terms of implementation, it may seem strange that 2 private structures dwc3_generic_host_priv and dwc3_generic_priv) are used. The reason for this is simply that the xhci layer expects a struct xhci_ctrl at the beginning of the private data and it seemed wasteful to include it also for the peripheral case. Signed-off-by: Jean-Jacques Hiblot --- drivers/usb/dwc3/core.c | 2 +- drivers/usb/dwc3/dwc3-generic.c | 54 ++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 1bd41f8bc7..bb3f9d2fc8 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -887,7 +887,7 @@ int dwc3_shutdown_phy(struct udevice *dev, struct phy *usb_phys, int num_phys) } #endif -#if CONFIG_IS_ENABLED(DM_USB_GADGET) +#if CONFIG_IS_ENABLED(DM_USB) int dwc3_init(struct dwc3 *dwc) { int ret; diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index d5c71d024f..4924d07553 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -21,6 +21,7 @@ #include "gadget.h" #include #include +#include struct dwc3_generic_plat { fdt_addr_t base; @@ -35,6 +36,11 @@ struct dwc3_generic_priv { int num_phys; }; +struct dwc3_generic_host_priv { + struct xhci_ctrl xhci_ctrl; + struct dwc3_generic_priv gen_priv; +}; + static int dwc3_generic_probe(struct udevice *dev, struct dwc3_generic_priv *priv) { @@ -132,6 +138,50 @@ U_BOOT_DRIVER(dwc3_generic_peripheral) = { }; #endif +#if defined(CONFIG_SPL_USB_HOST_SUPPORT) || !defined(CONFIG_SPL_BUILD) +static int dwc3_generic_host_probe(struct udevice *dev) +{ + struct xhci_hcor *hcor; + struct xhci_hccr *hccr; + struct dwc3_generic_host_priv *priv = dev_get_priv(dev); + int rc; + + rc = dwc3_generic_probe(dev, &priv->gen_priv); + if (rc) + return rc; + + hccr = (struct xhci_hccr *)priv->gen_priv.base; + hcor = (struct xhci_hcor *)(priv->gen_priv.base + + HC_LENGTH(xhci_readl(&(hccr)->cr_capbase))); + + return xhci_register(dev, hccr, hcor); +} + +static int dwc3_generic_host_remove(struct udevice *dev) +{ + struct dwc3_generic_host_priv *priv = dev_get_priv(dev); + int rc; + + rc = xhci_deregister(dev); + if (rc) + return rc; + + return dwc3_generic_remove(dev, &priv->gen_priv); +} + +U_BOOT_DRIVER(dwc3_generic_host) = { + .name = "dwc3-generic-host", + .id = UCLASS_USB, + .ofdata_to_platdata = dwc3_generic_ofdata_to_platdata, + .probe = dwc3_generic_host_probe, + .remove = dwc3_generic_host_remove, + .priv_auto_alloc_size = sizeof(struct dwc3_generic_host_priv), + .platdata_auto_alloc_size = sizeof(struct dwc3_generic_plat), + .ops = &xhci_usb_ops, + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; +#endif + struct dwc3_glue_data { struct clk_bulk clks; struct reset_ctl_bulk resets; @@ -252,10 +302,12 @@ static int dwc3_glue_bind(struct udevice *parent) driver = "dwc3-generic-peripheral"; #endif break; +#if defined(CONFIG_SPL_USB_HOST_SUPPORT) || !defined(CONFIG_SPL_BUILD) case USB_DR_MODE_HOST: debug("%s: dr_mode: HOST\n", __func__); - driver = "xhci-dwc3"; + driver = "dwc3-generic-host"; break; +#endif default: debug("%s: unsupported dr_mode\n", __func__); return -ENODEV; From 1a63e5e5fbfff7779ce24b404bef3b8ccddf1a8b Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Wed, 11 Sep 2019 11:33:51 +0200 Subject: [PATCH 08/18] usb: dwc3-generic: if no max speed is specified in DT, assume super speed There is no need to fail if the maximum speed is not specified. If the speed is not specified, do the same as linux and assume super speed. Signed-off-by: Jean-Jacques Hiblot --- drivers/usb/dwc3/dwc3-generic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 4924d07553..a3b65088f1 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -89,8 +89,8 @@ static int dwc3_generic_ofdata_to_platdata(struct udevice *dev) plat->maximum_speed = usb_get_maximum_speed(node); if (plat->maximum_speed == USB_SPEED_UNKNOWN) { - pr_err("Invalid usb maximum speed\n"); - return -ENODEV; + pr_info("No USB maximum speed specified. Using super speed\n"); + plat->maximum_speed = USB_SPEED_SUPER; } plat->dr_mode = usb_get_dr_mode(node); From ba6c5f7a28c8f8ac9eae194c2d37afa0ef51cb3d Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Wed, 11 Sep 2019 11:33:52 +0200 Subject: [PATCH 09/18] usb: dwc3: Add dwc3_of_parse() to get quirks information from DT Add a new function that read quirk and configuration information from the DT. The goal is to allow platforms using their own version of DWC3 driver to migrate to the generic DWC3 driver. The function is adapted from the function dwc3_get_properties() in the linux dwc3 driver introduced in commit c5ac6116db35d. Signed-off-by: Jean-Jacques Hiblot --- drivers/usb/dwc3/core.c | 65 +++++++++++++++++++++++++++++++++ drivers/usb/dwc3/core.h | 1 + drivers/usb/dwc3/dwc3-generic.c | 6 ++- 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index bb3f9d2fc8..5fe5bfae0e 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -888,6 +888,71 @@ int dwc3_shutdown_phy(struct udevice *dev, struct phy *usb_phys, int num_phys) #endif #if CONFIG_IS_ENABLED(DM_USB) +void dwc3_of_parse(struct dwc3 *dwc) +{ + const u8 *tmp; + struct udevice *dev = dwc->dev; + u8 lpm_nyet_threshold; + u8 tx_de_emphasis; + u8 hird_threshold; + + /* default to highest possible threshold */ + lpm_nyet_threshold = 0xff; + + /* default to -3.5dB de-emphasis */ + tx_de_emphasis = 1; + + /* + * default to assert utmi_sleep_n and use maximum allowed HIRD + * threshold value of 0b1100 + */ + hird_threshold = 12; + + dwc->has_lpm_erratum = dev_read_bool(dev, + "snps,has-lpm-erratum"); + tmp = dev_read_u8_array_ptr(dev, "snps,lpm-nyet-threshold", 1); + if (tmp) + lpm_nyet_threshold = *tmp; + + dwc->is_utmi_l1_suspend = dev_read_bool(dev, + "snps,is-utmi-l1-suspend"); + tmp = dev_read_u8_array_ptr(dev, "snps,hird-threshold", 1); + if (tmp) + hird_threshold = *tmp; + + dwc->disable_scramble_quirk = dev_read_bool(dev, + "snps,disable_scramble_quirk"); + dwc->u2exit_lfps_quirk = dev_read_bool(dev, + "snps,u2exit_lfps_quirk"); + dwc->u2ss_inp3_quirk = dev_read_bool(dev, + "snps,u2ss_inp3_quirk"); + dwc->req_p1p2p3_quirk = dev_read_bool(dev, + "snps,req_p1p2p3_quirk"); + dwc->del_p1p2p3_quirk = dev_read_bool(dev, + "snps,del_p1p2p3_quirk"); + dwc->del_phy_power_chg_quirk = dev_read_bool(dev, + "snps,del_phy_power_chg_quirk"); + dwc->lfps_filter_quirk = dev_read_bool(dev, + "snps,lfps_filter_quirk"); + dwc->rx_detect_poll_quirk = dev_read_bool(dev, + "snps,rx_detect_poll_quirk"); + dwc->dis_u3_susphy_quirk = dev_read_bool(dev, + "snps,dis_u3_susphy_quirk"); + dwc->dis_u2_susphy_quirk = dev_read_bool(dev, + "snps,dis_u2_susphy_quirk"); + dwc->tx_de_emphasis_quirk = dev_read_bool(dev, + "snps,tx_de_emphasis_quirk"); + tmp = dev_read_u8_array_ptr(dev, "snps,tx_de_emphasis", 1); + if (tmp) + tx_de_emphasis = *tmp; + + dwc->lpm_nyet_threshold = lpm_nyet_threshold; + dwc->tx_de_emphasis = tx_de_emphasis; + + dwc->hird_threshold = hird_threshold + | (dwc->is_utmi_l1_suspend << 4); +} + int dwc3_init(struct dwc3 *dwc) { int ret; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 4c89dfcad9..be9672266a 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -991,6 +991,7 @@ struct dwc3_gadget_ep_cmd_params { /* prototypes */ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc); +void dwc3_of_parse(struct dwc3 *dwc); int dwc3_init(struct dwc3 *dwc); void dwc3_remove(struct dwc3 *dwc); diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index a3b65088f1..023e95395b 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -48,8 +48,12 @@ static int dwc3_generic_probe(struct udevice *dev, struct dwc3_generic_plat *plat = dev_get_platdata(dev); struct dwc3 *dwc3 = &priv->dwc3; + dwc3->dev = dev; dwc3->maximum_speed = plat->maximum_speed; dwc3->dr_mode = plat->dr_mode; +#if CONFIG_IS_ENABLED(OF_CONTROL) + dwc3_of_parse(dwc3); +#endif rc = dwc3_setup_phy(dev, &priv->phys, &priv->num_phys); if (rc) @@ -57,7 +61,7 @@ static int dwc3_generic_probe(struct udevice *dev, priv->base = map_physmem(plat->base, DWC3_OTG_REGS_END, MAP_NOCACHE); dwc3->regs = priv->base + DWC3_GLOBALS_REGS_START; - dwc3->dev = dev; + rc = dwc3_init(dwc3); if (rc) { From 3e6ab7327fab329e2763fe72ea1fb041a6242ab3 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Wed, 11 Sep 2019 11:33:53 +0200 Subject: [PATCH 10/18] usb: dwc3: Kconfig: get rid of obsolete mode selection The mode selection for the DWC3 is kind of obsolete. The driver does not have to be host only or gadget only. This choice is confusing. All the remaining callers of dwc3_uboot_init() explicitly set dr_mode before calling the function, so none rely on a default behavior. Remove the choice menu and keep only the USB_DWC3_GADGET option. Enable it by default if USB_GADGET and USB_DWC3 are enabled. It must be disabled for the evb-rk3328 as it uses DWC2 for the gadget and DWC3 for the host. Signed-off-by: Jean-Jacques Hiblot --- configs/evb-rk3328_defconfig | 1 + configs/odroid-n2_defconfig | 1 + configs/rock64-rk3328_defconfig | 1 + configs/sei510_defconfig | 1 + configs/u200_defconfig | 1 + drivers/usb/dwc3/Kconfig | 18 ++---------------- drivers/usb/dwc3/core.c | 4 ++-- 7 files changed, 9 insertions(+), 18 deletions(-) diff --git a/configs/evb-rk3328_defconfig b/configs/evb-rk3328_defconfig index 37610774c1..f161c40ae7 100644 --- a/configs/evb-rk3328_defconfig +++ b/configs/evb-rk3328_defconfig @@ -86,6 +86,7 @@ CONFIG_USB_OHCI_HCD=y CONFIG_USB_OHCI_GENERIC=y CONFIG_USB_DWC2=y CONFIG_USB_DWC3=y +# CONFIG_USB_DWC3_GADGET is not set CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="Rockchip" CONFIG_USB_GADGET_VENDOR_NUM=0x2207 diff --git a/configs/odroid-n2_defconfig b/configs/odroid-n2_defconfig index abd945a975..1caa391320 100644 --- a/configs/odroid-n2_defconfig +++ b/configs/odroid-n2_defconfig @@ -44,6 +44,7 @@ CONFIG_DM_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_DWC3=y +# CONFIG_USB_DWC3_GADGET is not set CONFIG_USB_DWC3_MESON_G12A=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_VENDOR_NUM=0x1b8e diff --git a/configs/rock64-rk3328_defconfig b/configs/rock64-rk3328_defconfig index 3ab0af1158..60a0d1473c 100644 --- a/configs/rock64-rk3328_defconfig +++ b/configs/rock64-rk3328_defconfig @@ -88,6 +88,7 @@ CONFIG_USB_OHCI_HCD=y CONFIG_USB_OHCI_GENERIC=y CONFIG_USB_DWC2=y CONFIG_USB_DWC3=y +# CONFIG_USB_DWC3_GADGET is not set CONFIG_USB_GADGET=y CONFIG_USB_GADGET_MANUFACTURER="Rockchip" CONFIG_USB_GADGET_VENDOR_NUM=0x2207 diff --git a/configs/sei510_defconfig b/configs/sei510_defconfig index 9df04c345d..302480efef 100644 --- a/configs/sei510_defconfig +++ b/configs/sei510_defconfig @@ -65,6 +65,7 @@ CONFIG_DM_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_DWC3=y +# CONFIG_USB_DWC3_GADGET is not set CONFIG_USB_DWC3_MESON_G12A=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_VENDOR_NUM=0x18d1 diff --git a/configs/u200_defconfig b/configs/u200_defconfig index ced6ca84b6..009d564d6a 100644 --- a/configs/u200_defconfig +++ b/configs/u200_defconfig @@ -44,6 +44,7 @@ CONFIG_DM_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_DWC3=y +# CONFIG_USB_DWC3_GADGET is not set CONFIG_USB_DWC3_MESON_G12A=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_VENDOR_NUM=0x1b8e diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 25e1a38aee..c302486291 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -7,25 +7,11 @@ config USB_DWC3 if USB_DWC3 -choice - bool "DWC3 Mode Selection" - -config USB_DWC3_HOST - bool "Host only mode" - depends on USB - help - Select this when you want to use DWC3 in host mode only, - thereby the gadget feature will be regressed. - config USB_DWC3_GADGET - bool "Gadget only mode" + bool "USB Gadget support for DWC3" + default y depends on USB_GADGET select USB_GADGET_DUALSPEED - help - Select this when you want to use DWC3 in gadget mode only, - thereby the host feature will be regressed. - -endchoice comment "Platform Glue Driver Support" diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 5fe5bfae0e..23af60c98d 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -707,9 +707,9 @@ int dwc3_uboot_init(struct dwc3_device *dwc3_dev) return -ENOMEM; } - if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) + if (!IS_ENABLED(CONFIG_USB_DWC3_GADGET)) dwc->dr_mode = USB_DR_MODE_HOST; - else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) + else if (!IS_ENABLED(CONFIG_USB_HOST)) dwc->dr_mode = USB_DR_MODE_PERIPHERAL; if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) From 36d6a8451992b5d6066e0bfbf2584615cb65da8d Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Wed, 11 Sep 2019 11:33:54 +0200 Subject: [PATCH 11/18] ARM: keystone: increase PSC timeout Turning off the USB clocks may take longer than 100us. Increase the timeout to 100ms. Signed-off-by: Jean-Jacques Hiblot --- arch/arm/mach-keystone/include/mach/psc_defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-keystone/include/mach/psc_defs.h b/arch/arm/mach-keystone/include/mach/psc_defs.h index dfc22d5e90..f164f95bf2 100644 --- a/arch/arm/mach-keystone/include/mach/psc_defs.h +++ b/arch/arm/mach-keystone/include/mach/psc_defs.h @@ -94,7 +94,7 @@ static inline u32 boot_set_bitfield(u32 z, u32 f, u32 x, u32 y) * Timeout limit on checking PTSTAT. This is the number of times the * wait function will be called before giving up. */ -#define PSC_PTSTAT_TIMEOUT_LIMIT 100 +#define PSC_PTSTAT_TIMEOUT_LIMIT 100000 u32 psc_get_domain_num(u32 mod_num); int psc_enable_module(u32 mod_num); From f4378ca4fc24029d60995eec58d3f0592d9c1af7 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Wed, 11 Sep 2019 11:33:55 +0200 Subject: [PATCH 12/18] ARM: keystone: Do not enable the USB power domains at the board level This breaks linux boot sequence. Observed on k2e and k2l platforms. Signed-off-by: Jean-Jacques Hiblot --- board/ti/ks2_evm/board.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/board/ti/ks2_evm/board.c b/board/ti/ks2_evm/board.c index e9bc68049b..e3305fbaf6 100644 --- a/board/ti/ks2_evm/board.c +++ b/board/ti/ks2_evm/board.c @@ -67,20 +67,7 @@ struct image_header *spl_get_load_buffer(ssize_t offset, size_t size) int board_init(void) { -#if CONFIG_IS_ENABLED(DM_USB) - int rc = psc_enable_module(KS2_LPSC_USB); - - if (rc) - puts("Cannot enable USB0 module"); -#ifdef KS2_LPSC_USB_1 - rc = psc_enable_module(KS2_LPSC_USB_1); - if (rc) - puts("Cannot enable USB1 module"); -#endif -#endif - gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; - return 0; } From 2bbc1bbf5d66360d330a0358cf03512e86e49122 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Wed, 11 Sep 2019 11:33:56 +0200 Subject: [PATCH 13/18] phy: keystone-usb: handle the transition of the USB power domain There is no proper power domain support for the keystone platforms. However we need to turn off the USB domains before jumping to linux or it fail to boot (observed with k2e and k2l platforms). This can be done in the PHY driver as it is dedicated only to the keystone platforms and matches the required on/off sequence. Signed-off-by: Jean-Jacques Hiblot --- drivers/phy/keystone-usb-phy.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/phy/keystone-usb-phy.c b/drivers/phy/keystone-usb-phy.c index e8146cabfa..14ac6bbbb2 100644 --- a/drivers/phy/keystone-usb-phy.c +++ b/drivers/phy/keystone-usb-phy.c @@ -9,6 +9,7 @@ #include #include #include +#include /* USB PHY control register offsets */ #define USB_PHY_CTL_UTMI 0x0000 @@ -22,15 +23,25 @@ #define PHY_REF_SSP_EN BIT(29) struct keystone_usb_phy { + u32 psc_domain; void __iomem *reg; }; static int keystone_usb_init(struct phy *phy) { u32 val; + int rc; struct udevice *dev = phy->dev; struct keystone_usb_phy *keystone = dev_get_priv(dev); + /* Release USB from reset */ + rc = psc_enable_module(keystone->psc_domain); + if (rc) { + debug("Cannot enable USB module"); + return -rc; + } + mdelay(10); + /* * VBUSVLDEXTSEL has a default value of 1 in BootCfg but shouldn't. * It should always be cleared because our USB PHY has an onchip VBUS @@ -72,13 +83,24 @@ static int keystone_usb_power_off(struct phy *phy) static int keystone_usb_exit(struct phy *phy) { + struct udevice *dev = phy->dev; + struct keystone_usb_phy *keystone = dev_get_priv(dev); + + if (psc_disable_module(keystone->psc_domain)) + debug("failed to disable USB module!\n"); + return 0; } static int keystone_usb_phy_probe(struct udevice *dev) { + int rc; struct keystone_usb_phy *keystone = dev_get_priv(dev); + rc = dev_read_u32(dev, "psc-domain", &keystone->psc_domain); + if (rc) + return rc; + keystone->reg = dev_remap_addr_index(dev, 0); if (!keystone->reg) { pr_err("unable to remap usb phy\n"); From 2e1d8cfaf1558171c1eda58f5af78aefe1ce2417 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Wed, 11 Sep 2019 11:33:57 +0200 Subject: [PATCH 14/18] configs: k2g_evm_defconfig: disable XHCI_DWC3 and enable KEYSTONE_USB_PHY KEYSTONE_USB_PHY is now required for proper USB operations. XHCI_DWC3 can be disabled as the xhci-dwc3 is not used anymore USB_DWC3_GADGET can also be removed, it is now selected automatically. Signed-off-by: Jean-Jacques Hiblot --- configs/k2g_evm_defconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configs/k2g_evm_defconfig b/configs/k2g_evm_defconfig index 27804517fe..865a643abe 100644 --- a/configs/k2g_evm_defconfig +++ b/configs/k2g_evm_defconfig @@ -63,6 +63,7 @@ CONFIG_MII=y CONFIG_DRIVER_TI_KEYSTONE_NET=y CONFIG_PHY=y CONFIG_NOP_PHY=y +CONFIG_KEYSTONE_USB_PHY=y CONFIG_REMOTEPROC_TI_POWER=y CONFIG_DM_SERIAL=y CONFIG_SYS_NS16550=y @@ -73,9 +74,7 @@ CONFIG_USB=y CONFIG_DM_USB=y CONFIG_DM_USB_GADGET=y CONFIG_USB_XHCI_HCD=y -CONFIG_USB_XHCI_DWC3=y CONFIG_USB_DWC3=y -CONFIG_USB_DWC3_GADGET=y CONFIG_USB_DWC3_GENERIC=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_DOWNLOAD=y From 78830364b8e0ef2f6de59e21252efdadb4b77763 Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Wed, 11 Sep 2019 11:33:58 +0200 Subject: [PATCH 15/18] ARM: DTS: keystone: complete the description of the USB PHY devices As the PHY driver now handles the transitions of USB power domain, we must add this information in the node of each PHY. Also, the phy are expected in the "phys" property, not "usb-phys". Also add the aliases for the USB ports on boards with more than a single port. Signed-off-by: Jean-Jacques Hiblot --- arch/arm/dts/keystone-k2e-evm-u-boot.dtsi | 32 ++++++++++++++++++++++ arch/arm/dts/keystone-k2g-evm-u-boot.dtsi | 28 +++++++++++++++++++ arch/arm/dts/keystone-k2hk-evm-u-boot.dtsi | 14 ++++++++++ arch/arm/dts/keystone-k2l-evm-u-boot.dtsi | 18 ++++++++++++ 4 files changed, 92 insertions(+) create mode 100644 arch/arm/dts/keystone-k2l-evm-u-boot.dtsi diff --git a/arch/arm/dts/keystone-k2e-evm-u-boot.dtsi b/arch/arm/dts/keystone-k2e-evm-u-boot.dtsi index aecb4dde68..c94165ffe7 100644 --- a/arch/arm/dts/keystone-k2e-evm-u-boot.dtsi +++ b/arch/arm/dts/keystone-k2e-evm-u-boot.dtsi @@ -7,8 +7,40 @@ soc { u-boot,dm-pre-reloc; }; + aliases { + usb0 = &usb; + usb1 = &usb1; + }; }; &i2c1 { u-boot,dm-pre-reloc; }; + +&usb_phy { + #phy-cells = <0>; + psc-domain = <2>; +}; + +&usb { + dwc3@2690000 { + phys = <&usb_phy>; + dr_mode = "host"; + snps,u2ss_inp3_quirk; + status = "okay"; + }; +}; + +&usb1_phy { + #phy-cells = <0>; + psc-domain = <1>; +}; + +&usb1 { + dwc3@25010000 { + phys = <&usb1_phy>; + dr_mode = "peripheral"; + snps,u2ss_inp3_quirk; + status = "okay"; + }; +}; diff --git a/arch/arm/dts/keystone-k2g-evm-u-boot.dtsi b/arch/arm/dts/keystone-k2g-evm-u-boot.dtsi index 80f1f60045..e8e70096ea 100644 --- a/arch/arm/dts/keystone-k2g-evm-u-boot.dtsi +++ b/arch/arm/dts/keystone-k2g-evm-u-boot.dtsi @@ -7,6 +7,10 @@ soc { u-boot,dm-pre-reloc; }; + aliases { + usb0 = &usb0; + usb1 = &usb1; + }; }; &i2c0 { @@ -16,3 +20,27 @@ &i2c1 { u-boot,dm-pre-reloc; }; + +&usb0_phy { + compatible = "ti,keystone-usbphy"; + #phy-cells = <0>; + reg = <0x2620738 24>; + psc-domain = <25>; +}; + +&usb0 { + phys = <&usb0_phy>; + snps,u2ss_inp3_quirk; +}; + +&usb1_phy { + compatible = "ti,keystone-usbphy"; + #phy-cells = <0>; + reg = <0x2620750 24>; + psc-domain = <26>; +}; + +&usb1 { + phys = <&usb1_phy>; + snps,u2ss_inp3_quirk; +}; diff --git a/arch/arm/dts/keystone-k2hk-evm-u-boot.dtsi b/arch/arm/dts/keystone-k2hk-evm-u-boot.dtsi index aecb4dde68..1c2f349f5c 100644 --- a/arch/arm/dts/keystone-k2hk-evm-u-boot.dtsi +++ b/arch/arm/dts/keystone-k2hk-evm-u-boot.dtsi @@ -12,3 +12,17 @@ &i2c1 { u-boot,dm-pre-reloc; }; + +&usb_phy { + #phy-cells = <0>; + psc-domain = <2>; +}; + +&usb { + dwc3@2690000 { + phys = <&usb_phy>; + dr_mode = "host"; + snps,u2ss_inp3_quirk; + status = "okay"; + }; +}; diff --git a/arch/arm/dts/keystone-k2l-evm-u-boot.dtsi b/arch/arm/dts/keystone-k2l-evm-u-boot.dtsi new file mode 100644 index 0000000000..0a507d0210 --- /dev/null +++ b/arch/arm/dts/keystone-k2l-evm-u-boot.dtsi @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + */ + +&usb_phy { + #phy-cells = <0>; + psc-domain = <2>; +}; + +&usb { + dwc3@2690000 { + phys = <&usb_phy>; + dr_mode = "host"; + snps,u2ss_inp3_quirk; + status = "okay"; + }; +}; From 733ff952c3a54f59a74dbf446c250dace4cc44aa Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Thu, 24 Oct 2019 10:15:40 +0200 Subject: [PATCH 16/18] configs: sei610: khadas-vim3 : disable Gadget support for the DWC3 Those platform use the DWC2 controller for the gadget support and the DWC3 for host-only operations. Signed-off-by: Jean-Jacques Hiblot --- configs/khadas-vim3_defconfig | 1 + configs/sei610_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/configs/khadas-vim3_defconfig b/configs/khadas-vim3_defconfig index cd37f7840e..81ac42e599 100644 --- a/configs/khadas-vim3_defconfig +++ b/configs/khadas-vim3_defconfig @@ -44,6 +44,7 @@ CONFIG_DM_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_DWC3=y +# CONFIG_USB_DWC3_GADGET is not set CONFIG_USB_DWC3_MESON_G12A=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_VENDOR_NUM=0x1b8e diff --git a/configs/sei610_defconfig b/configs/sei610_defconfig index 520a683d2e..1f36722a8e 100644 --- a/configs/sei610_defconfig +++ b/configs/sei610_defconfig @@ -62,6 +62,7 @@ CONFIG_DM_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_DWC3=y +# CONFIG_USB_DWC3_GADGET is not set CONFIG_USB_DWC3_MESON_G12A=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_VENDOR_NUM=0x18d1 From 1198a104d37b10064cd90f36d472787d549eda02 Mon Sep 17 00:00:00 2001 From: Igor Opaniuk Date: Thu, 10 Oct 2019 16:09:35 +0300 Subject: [PATCH 17/18] usb: ehci-mx6: Fix bus enumeration for iMX7 SoCs This fixes the issues with calculation of controller indexes in ehci_usb_bind() for iMX7, as USB controllers on iMX7 SoCs aren't placed next to each other, and their addresses incremented by 0x10000. Example of USB nodes for iMX7S/D: usbotg1: usb@30b10000 { compatible = "fsl,imx7d-usb", "fsl,imx27-usb"; reg = <0x30b10000 0x200>; ^^^^^^^^^^ .... usbotg2: usb@30b20000 { compatible = "fsl,imx7d-usb", "fsl,imx27-usb"; reg = <0x30b20000 0x200>; ^^^^^^^^^^ .... usbh: usb@30b30000 { compatible = "fsl,imx7d-usb", "fsl,imx27-usb"; reg = <0x30b30000 0x200>; ^^^^^^^^^^ .... Which was leading to usb enumeration issues: Colibri iMX7 # usb start starting USB... Bus usb@30b10000: USB EHCI 1.00 Bus usb@30b20000: probe failed, error -22 scanning bus usb@30b10000 for devices... 1 USB Device(s) found scanning usb for storage devices... 0 Storage Device(s) found Fixes: 501547cec1("usb: ehci-mx6: Fix bus enumeration for DM case") Signed-off-by: Igor Opaniuk --- drivers/usb/host/ehci-mx6.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index e9e6ed596d..7d46091f94 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -513,10 +513,11 @@ static int ehci_usb_bind(struct udevice *dev) * from which it derives offsets in the PHY and ANATOP register sets. * * Here we attempt to calculate these indexes from DT information as - * well as we can. The USB controllers on all existing iMX6/iMX7 SoCs - * are placed next to each other, at addresses incremented by 0x200. - * Thus, the index is derived from the multiple of 0x200 offset from - * the first controller address. + * well as we can. The USB controllers on all existing iMX6 SoCs + * are placed next to each other, at addresses incremented by 0x200, + * and iMX7 their addresses are shifted by 0x10000. + * Thus, the index is derived from the multiple of 0x200 (0x10000 for + * iMX7) offset from the first controller address. * * However, to complete conversion of this driver to DT probing, the * following has to be done: @@ -531,10 +532,10 @@ static int ehci_usb_bind(struct udevice *dev) * With these changes in place, the ad-hoc indexing goes away and * the driver is fully converted to DT probing. */ - fdt_size_t size; - fdt_addr_t addr = devfdt_get_addr_size_index(dev, 0, &size); + u32 controller_spacing = is_mx7() ? 0x10000 : 0x200; + fdt_addr_t addr = devfdt_get_addr_index(dev, 0); - dev->req_seq = (addr - USB_BASE_ADDR) / size; + dev->req_seq = (addr - USB_BASE_ADDR) / controller_spacing; return 0; } From 235f5e158e336371759f98ffbf265fe078cda251 Mon Sep 17 00:00:00 2001 From: Ye Li Date: Thu, 24 Oct 2019 10:29:32 -0300 Subject: [PATCH 18/18] ehci-mx6: Update EHCI driver to support OTG0 on i.MX7ULP The ULP has two USB controllers. These two controllers have similar NC registers layout as i.MX7D. But OTG0 uses UTMI PHY simliar as i.MX6, not the integrated PHY on i.MX7D. The OTG1 needs off-chip HSIC PHY or ULPI PHY to work. This patch only supports OTG0 with UTMI PHY. Signed-off-by: Ye Li Signed-off-by: Fabio Estevam --- drivers/usb/host/Kconfig | 6 ++--- drivers/usb/host/ehci-mx6.c | 53 ++++++++++++++++++++++++++++--------- 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index b674e330ac..0987ff25b1 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -134,8 +134,8 @@ config USB_EHCI_MX5 Enables support for the on-chip EHCI controller on i.MX5 SoCs. config USB_EHCI_MX6 - bool "Support for i.MX6 on-chip EHCI USB controller" - depends on ARCH_MX6 + bool "Support for i.MX6/i.MX7ULP on-chip EHCI USB controller" + depends on ARCH_MX6 || ARCH_MX7ULP default y ---help--- Enables support for the on-chip EHCI controller on i.MX6 SoCs. @@ -162,7 +162,7 @@ config USB_EHCI_VF help Enables support for the on-chip EHCI controller on Vybrid SoCs. -if USB_EHCI_MX7 +if USB_EHCI_MX6 || USB_EHCI_MX7 config MXC_USB_OTG_HACTIVE bool "USB Power pin high active" diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index 7d46091f94..1993ad620a 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -64,10 +64,12 @@ DECLARE_GLOBAL_DATA_PTR; #define UCMD_RUN_STOP (1 << 0) /* controller run/stop */ #define UCMD_RESET (1 << 1) /* controller reset */ -#if defined(CONFIG_MX6) +#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) static const unsigned phy_bases[] = { USB_PHY0_BASE_ADDR, +#if defined(USB_PHY1_BASE_ADDR) USB_PHY1_BASE_ADDR, +#endif }; static void usb_internal_phy_clock_gate(int index, int on) @@ -84,6 +86,20 @@ static void usb_internal_phy_clock_gate(int index, int on) static void usb_power_config(int index) { +#if defined(CONFIG_MX7ULP) + struct usbphy_regs __iomem *usbphy = + (struct usbphy_regs __iomem *)USB_PHY0_BASE_ADDR; + + if (index > 0) + return; + + writel(ANADIG_USB2_CHRG_DETECT_EN_B | + ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, + &usbphy->usb1_chrg_detect); + + scg_enable_usb_pll(true); + +#else struct anatop_regs __iomem *anatop = (struct anatop_regs __iomem *)ANATOP_BASE_ADDR; void __iomem *chrg_detect; @@ -123,6 +139,8 @@ static void usb_power_config(int index) ANADIG_USB2_PLL_480_CTRL_POWER | ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS, pll_480_ctrl_set); + +#endif } /* Return 0 : host node, <>0 : device mode */ @@ -185,6 +203,14 @@ int usb_phy_mode(int port) return USB_INIT_HOST; } +#if defined(CONFIG_MX7ULP) +struct usbnc_regs { + u32 ctrl1; + u32 ctrl2; + u32 reserve0[2]; + u32 hsic_ctrl; +}; +#else /* Base address for this IP block is 0x02184800 */ struct usbnc_regs { u32 ctrl[4]; /* otg/host1-3 */ @@ -193,6 +219,8 @@ struct usbnc_regs { u32 otg_phy_ctrl_0; u32 uh1_phy_ctrl_0; }; +#endif + #elif defined(CONFIG_MX7) struct usbnc_regs { u32 ctrl1; @@ -213,20 +241,12 @@ 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); - void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl1); /* * Clear the ACAENB to enable usb_otg_id detection, * otherwise it is the ACA detection enabled. */ clrbits_le32(phy_cfg2, USBNC_PHYCFG2_ACAENB); - - /* Set power polarity to high active */ -#ifdef CONFIG_MXC_USB_OTG_HACTIVE - setbits_le32(ctrl, UCTRL_PWR_POL); -#else - clrbits_le32(ctrl, UCTRL_PWR_POL); -#endif } int usb_phy_mode(int port) @@ -251,7 +271,7 @@ 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]); -#elif defined(CONFIG_MX7) +#elif defined(CONFIG_MX7) || defined(CONFIG_MX7ULP) struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR + (0x10000 * index) + USBNC_OFFSET); void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl1); @@ -265,6 +285,13 @@ static void usb_oc_config(int index) #endif setbits_le32(ctrl, UCTRL_OVER_CUR_DIS); + + /* Set power polarity to high active */ +#ifdef CONFIG_MXC_USB_OTG_HACTIVE + setbits_le32(ctrl, UCTRL_PWR_POL); +#else + clrbits_le32(ctrl, UCTRL_PWR_POL); +#endif } /** @@ -328,7 +355,7 @@ int ehci_mx6_common_init(struct usb_ehci *ehci, int index) usb_power_config(index); usb_oc_config(index); -#if defined(CONFIG_MX6) +#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) usb_internal_phy_clock_gate(index, 1); usb_phy_enable(index, ehci); #endif @@ -343,7 +370,7 @@ int ehci_hcd_init(int index, enum usb_init_type init, enum usb_init_type type; #if defined(CONFIG_MX6) u32 controller_spacing = 0x200; -#elif defined(CONFIG_MX7) +#elif defined(CONFIG_MX7) || defined(CONFIG_MX7ULP) u32 controller_spacing = 0x10000; #endif struct usb_ehci *ehci = (struct usb_ehci *)(USB_BASE_ADDR + @@ -446,7 +473,7 @@ static int ehci_usb_phy_mode(struct udevice *dev) * About fsl,usbphy, Refer to * Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt. */ - if (is_mx6()) { + if (is_mx6() || is_mx7ulp()) { phy_off = fdtdec_lookup_phandle(blob, offset, "fsl,usbphy");