From: Michal Simek Date: Thu, 31 Mar 2016 11:53:58 +0000 (+0200) Subject: drivers: usb: Add DWC3 Xilinx ZynqMP glue logic X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2edab57221072d6ff0aecba1bb819ffd559b573a;p=thirdparty%2Fu-boot.git drivers: usb: Add DWC3 Xilinx ZynqMP glue logic By enabling BLK by default this is the next driver which needs to get support for DM_USB. Adding generic DWC3 glue logic which only parse nodes and read device mode. Based on it probe proper host/peripheral DWC3 drivers for it. Signed-off-by: Michal Simek --- diff --git a/arch/arm/dts/zynqmp-zcu100-revA.dts b/arch/arm/dts/zynqmp-zcu100-revA.dts index 053b7985b14..11c7b6b2fac 100644 --- a/arch/arm/dts/zynqmp-zcu100-revA.dts +++ b/arch/arm/dts/zynqmp-zcu100-revA.dts @@ -459,6 +459,7 @@ dr_mode = "peripheral"; /* phy-names = "usb3-phy"; phys = <&lane2 PHY_TYPE_USB3 0 0 26000000>; */ + maximum-speed = "high-speed"; /* super-speed */ }; /* ULPI SMSC USB3320 */ @@ -471,6 +472,7 @@ dr_mode = "host"; /* phy-names = "usb3-phy"; phys = <&lane3 PHY_TYPE_USB3 1 0 26000000>; */ + maximum-speed = "high-speed"; /* super-speed */ }; &xilinx_drm { diff --git a/arch/arm/dts/zynqmp-zcu100.dts b/arch/arm/dts/zynqmp-zcu100.dts index 0c4d2c6f95c..761a92586ba 100644 --- a/arch/arm/dts/zynqmp-zcu100.dts +++ b/arch/arm/dts/zynqmp-zcu100.dts @@ -418,6 +418,7 @@ dr_mode = "peripheral"; /* phy-names = "usb3-phy"; phys = <&lane2 PHY_TYPE_USB3 0 0 26000000>; */ + maximum-speed = "high-speed"; /* super-speed */ }; /* ULPI SMSC USB3320 */ @@ -430,6 +431,7 @@ dr_mode = "host"; /* phy-names = "usb3-phy"; phys = <&lane3 PHY_TYPE_USB3 1 0 26000000>; */ + maximum-speed = "high-speed"; /* super-speed */ }; &xilinx_drm { diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index b7ceb3a736e..d5747037b63 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -318,56 +318,3 @@ int checkboard(void) puts("Board: Xilinx ZynqMP\n"); return 0; } - -#ifndef CONFIG_DM_USB -#ifdef CONFIG_USB_DWC3 -static struct dwc3_device dwc3_device_data0 = { - .maximum_speed = USB_SPEED_HIGH, - .base = ZYNQMP_USB0_XHCI_BASEADDR, - .dr_mode = USB_DR_MODE_PERIPHERAL, - .index = 0, -}; - -static struct dwc3_device dwc3_device_data1 = { - .maximum_speed = USB_SPEED_HIGH, - .base = ZYNQMP_USB1_XHCI_BASEADDR, - .dr_mode = USB_DR_MODE_PERIPHERAL, - .index = 1, -}; - -int usb_gadget_handle_interrupts(int index) -{ - dwc3_uboot_handle_interrupt(index); - return 0; -} - -int board_usb_init(int index, enum usb_init_type init) -{ - debug("%s: index %x\n", __func__, index); - -#if defined(CONFIG_USB_GADGET_DOWNLOAD) - g_dnl_set_serialnumber(CONFIG_SYS_CONFIG_NAME); -#endif - - switch (index) { - case 0: - return dwc3_uboot_init(&dwc3_device_data0); - case 1: - return dwc3_uboot_init(&dwc3_device_data1); - }; - - return -1; -} - -int board_usb_cleanup(int index, enum usb_init_type init) -{ - dwc3_uboot_exit(index); - return 0; -} -#endif -#else -int usb_gadget_handle_interrupts(int index) -{ - return 0; -} -#endif diff --git a/configs/xilinx_zynqmp_ep_defconfig b/configs/xilinx_zynqmp_ep_defconfig index d7d17a71b2d..b072a185347 100644 --- a/configs/xilinx_zynqmp_ep_defconfig +++ b/configs/xilinx_zynqmp_ep_defconfig @@ -57,6 +57,7 @@ CONFIG_FPGA_ZYNQMPPL=y CONFIG_DM_GPIO=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_CADENCE=y +CONFIG_MISC=y CONFIG_DM_MMC=y CONFIG_ZYNQ_SDHCI=y CONFIG_NAND_ARASAN=y @@ -78,6 +79,7 @@ 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_STORAGE=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_DOWNLOAD=y diff --git a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig index f51641c56bc..c6ab8408375 100644 --- a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig +++ b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig @@ -48,6 +48,7 @@ CONFIG_FPGA_ZYNQMPPL=y CONFIG_DM_GPIO=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_CADENCE=y +CONFIG_MISC=y CONFIG_DM_MMC=y CONFIG_ZYNQ_SDHCI=y CONFIG_DM_SPI_FLASH=y @@ -68,6 +69,7 @@ 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_ULPI_VIEWPORT=y CONFIG_USB_ULPI=y CONFIG_USB_STORAGE=y diff --git a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig index e8a587f204e..1cb1af820d8 100644 --- a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig +++ b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig @@ -49,6 +49,7 @@ CONFIG_FPGA_ZYNQMPPL=y CONFIG_DM_GPIO=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_CADENCE=y +CONFIG_MISC=y CONFIG_DM_MMC=y CONFIG_NAND_ARASAN=y CONFIG_SPI_FLASH=y @@ -66,6 +67,7 @@ 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_ULPI_VIEWPORT=y CONFIG_USB_ULPI=y CONFIG_USB_STORAGE=y diff --git a/configs/xilinx_zynqmp_zc1751_xm017_dc3_defconfig b/configs/xilinx_zynqmp_zc1751_xm017_dc3_defconfig index ffb1c9478a3..70743680352 100644 --- a/configs/xilinx_zynqmp_zc1751_xm017_dc3_defconfig +++ b/configs/xilinx_zynqmp_zc1751_xm017_dc3_defconfig @@ -40,11 +40,13 @@ CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y CONFIG_DM_GPIO=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_CADENCE=y +CONFIG_MISC=y CONFIG_DM_MMC=y CONFIG_ZYNQ_SDHCI=y CONFIG_NAND_ARASAN=y @@ -60,6 +62,7 @@ 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_ULPI_VIEWPORT=y CONFIG_USB_ULPI=y CONFIG_USB_STORAGE=y diff --git a/configs/xilinx_zynqmp_zcu100_defconfig b/configs/xilinx_zynqmp_zcu100_defconfig index 6604e77989d..ed5368f47d4 100644 --- a/configs/xilinx_zynqmp_zcu100_defconfig +++ b/configs/xilinx_zynqmp_zcu100_defconfig @@ -41,9 +41,11 @@ CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y CONFIG_DM_GPIO=y +CONFIG_MISC=y CONFIG_DM_MMC=y CONFIG_ZYNQ_SDHCI=y CONFIG_DM_SPI_FLASH=y @@ -64,6 +66,7 @@ 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_ULPI_VIEWPORT=y CONFIG_USB_ULPI=y CONFIG_USB_STORAGE=y diff --git a/configs/xilinx_zynqmp_zcu100_revA_defconfig b/configs/xilinx_zynqmp_zcu100_revA_defconfig index ac8a3b76c63..26d09ec17b3 100644 --- a/configs/xilinx_zynqmp_zcu100_revA_defconfig +++ b/configs/xilinx_zynqmp_zcu100_revA_defconfig @@ -43,9 +43,11 @@ CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y CONFIG_DM_GPIO=y +CONFIG_MISC=y CONFIG_DM_MMC=y CONFIG_ZYNQ_SDHCI=y CONFIG_DM_SPI_FLASH=y @@ -65,6 +67,7 @@ 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_ULPI_VIEWPORT=y CONFIG_USB_ULPI=y CONFIG_USB_STORAGE=y diff --git a/configs/xilinx_zynqmp_zcu102_defconfig b/configs/xilinx_zynqmp_zcu102_defconfig index b57bc281fb8..986f70e006a 100644 --- a/configs/xilinx_zynqmp_zcu102_defconfig +++ b/configs/xilinx_zynqmp_zcu102_defconfig @@ -48,6 +48,7 @@ CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y CONFIG_DM_GPIO=y +CONFIG_MISC=y CONFIG_DM_MMC=y CONFIG_ZYNQ_SDHCI=y CONFIG_DM_SPI_FLASH=y @@ -68,6 +69,7 @@ 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_ULPI_VIEWPORT=y CONFIG_USB_ULPI=y CONFIG_USB_STORAGE=y diff --git a/configs/xilinx_zynqmp_zcu102_revB_defconfig b/configs/xilinx_zynqmp_zcu102_revB_defconfig index f99bdd431eb..cb99454e3c4 100644 --- a/configs/xilinx_zynqmp_zcu102_revB_defconfig +++ b/configs/xilinx_zynqmp_zcu102_revB_defconfig @@ -47,6 +47,7 @@ CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y CONFIG_DM_GPIO=y +CONFIG_MISC=y CONFIG_DM_MMC=y CONFIG_ZYNQ_SDHCI=y CONFIG_DM_SPI_FLASH=y @@ -67,6 +68,7 @@ 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_ULPI_VIEWPORT=y CONFIG_USB_ULPI=y CONFIG_USB_STORAGE=y diff --git a/configs/xilinx_zynqmp_zcu106_defconfig b/configs/xilinx_zynqmp_zcu106_defconfig index dbff165c068..0da63bf8995 100644 --- a/configs/xilinx_zynqmp_zcu106_defconfig +++ b/configs/xilinx_zynqmp_zcu106_defconfig @@ -41,9 +41,11 @@ CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_DFU_RAM=y CONFIG_FPGA_XILINX=y CONFIG_FPGA_ZYNQMPPL=y CONFIG_DM_GPIO=y +CONFIG_MISC=y CONFIG_DM_MMC=y CONFIG_ZYNQ_SDHCI=y CONFIG_DM_SPI_FLASH=y @@ -64,6 +66,7 @@ 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_ULPI_VIEWPORT=y CONFIG_USB_ULPI=y CONFIG_USB_STORAGE=y diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index e93398fe7c1..89357e48f3f 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -37,6 +37,12 @@ config USB_DWC3_OMAP Say 'Y' here if you have one such device +config USB_DWC3_GENERIC + bool "Xilinx ZynqMP and similar Platforms" + depends on DM_USB && USB_DWC3 + help + Some platforms can reuse this DWC3 generic implementation. + menu "PHY Subsystem" config USB_DWC3_PHY_OMAP diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index 2964bae0d8f..e7d91815928 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -9,5 +9,6 @@ dwc3-y := core.o obj-$(CONFIG_USB_DWC3_GADGET) += gadget.o ep0.o obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-omap.o +obj-$(CONFIG_USB_DWC3_GENERIC) += dwc3-generic.o obj-$(CONFIG_USB_DWC3_PHY_OMAP) += ti_usb_phy.o obj-$(CONFIG_USB_DWC3_PHY_SAMSUNG) += samsung_usb_phy.o diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c new file mode 100644 index 00000000000..a372cbb9a83 --- /dev/null +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -0,0 +1,158 @@ +/** + * dwc3-generic.c - Generic DWC3 Glue layer + * + * Copyright (C) 2016 Xilinx, Inc. + * + * Based on dwc3-omap.c. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "core.h" +#include "gadget.h" +#include "linux-compat.h" + +DECLARE_GLOBAL_DATA_PTR; + +int usb_gadget_handle_interrupts(int index) +{ + struct dwc3 *priv; + struct udevice *dev; + int ret; + + ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &dev); + if (!dev || ret) { + error("No USB device found\n"); + return -ENODEV; + } + + priv = dev_get_priv(dev); + + dwc3_gadget_uboot_handle_interrupt(priv); + + return 0; +} + +static int dwc3_generic_peripheral_probe(struct udevice *dev) +{ + struct dwc3 *priv = dev_get_priv(dev); + + return dwc3_init(priv); +} + +static int dwc3_generic_peripheral_remove(struct udevice *dev) +{ + struct dwc3 *priv = dev_get_priv(dev); + + dwc3_remove(priv); + + return 0; +} + +static int dwc3_generic_peripheral_ofdata_to_platdata(struct udevice *dev) +{ + struct dwc3 *priv = dev_get_priv(dev); + int node = dev->of_offset; + + priv->regs = (void *)dev_get_addr(dev); + priv->regs += DWC3_GLOBALS_REGS_START; + + priv->maximum_speed = usb_get_maximum_speed(node); + if (priv->maximum_speed < 0) { + error("Invalid usb maximum speed\n"); + return priv->maximum_speed; + } + + priv->dr_mode = USB_DR_MODE_PERIPHERAL; + + return 0; +} + +static int dwc3_generic_peripheral_bind(struct udevice *dev) +{ + return device_probe(dev); +} + +U_BOOT_DRIVER(dwc3_generic_peripheral) = { + .name = "dwc3-generic-peripheral", + .id = UCLASS_USB_DEV_GENERIC, + .ofdata_to_platdata = dwc3_generic_peripheral_ofdata_to_platdata, + .probe = dwc3_generic_peripheral_probe, + .remove = dwc3_generic_peripheral_remove, + .bind = dwc3_generic_peripheral_bind, + .platdata_auto_alloc_size = sizeof(struct usb_platdata), + .priv_auto_alloc_size = sizeof(struct dwc3), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; + +static int dwc3_generic_bind(struct udevice *parent) +{ + const void *fdt = gd->fdt_blob; + int node; + int ret; + + for (node = fdt_first_subnode(fdt, parent->of_offset); node > 0; + node = fdt_next_subnode(fdt, node)) { + const char *name = fdt_get_name(fdt, node, NULL); + enum usb_dr_mode dr_mode; + struct udevice *dev; + + debug("%s: subnode name: %s\n", __func__, name); + if (strncmp(name, "dwc3@", 4)) + continue; + + dr_mode = usb_get_dr_mode(node); + + switch (dr_mode) { + case USB_DR_MODE_PERIPHERAL: + case USB_DR_MODE_OTG: + debug("%s: dr_mode: OTG or Peripheral\n", __func__); + ret = device_bind_driver_to_node(parent, + "dwc3-generic-peripheral", + name, node, &dev); + if (ret) { + debug("%s: not able to bind usb device mode\n", + __func__); + return ret; + } + break; + case USB_DR_MODE_HOST: + debug("%s: dr_mode: HOST\n", __func__); + ret = device_bind_driver_to_node(parent, + "dwc3-generic-host", + name, node, &dev); + if (ret) { + debug("%s: not able to bind usb host mode\n", + __func__); + return ret; + } + break; + default: + break; + }; + } + + return 0; +} + +static const struct udevice_id dwc3_generic_ids[] = { + { .compatible = "xlnx,zynqmp-dwc3" }, + { } +}; + +U_BOOT_DRIVER(dwc3_generic_wrapper) = { + .name = "dwc3-generic-wrapper", + .id = UCLASS_MISC, + .of_match = dwc3_generic_ids, + .bind = dwc3_generic_bind, +}; diff --git a/drivers/usb/host/xhci-zynqmp.c b/drivers/usb/host/xhci-zynqmp.c index cec1bc46d0a..09753ebab54 100644 --- a/drivers/usb/host/xhci-zynqmp.c +++ b/drivers/usb/host/xhci-zynqmp.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -57,13 +58,23 @@ DECLARE_GLOBAL_DATA_PTR; #define USBOTGSS_IRQ_SET_1_DMADISABLECLR_EN BIT(17) struct zynqmp_xhci { +#ifdef CONFIG_DM_USB + struct usb_platdata usb_plat; +#endif + struct xhci_ctrl ctrl; struct xhci_hccr *hcd; struct dwc3 *dwc3_reg; }; +#ifdef CONFIG_DM_USB +struct zynqmp_xhci_platdata { + fdt_addr_t hcd_base; +}; +#else static struct zynqmp_xhci zynqmp_xhci; unsigned long ctr_addr[] = CONFIG_ZYNQMP_XHCI_LIST; +#endif static int zynqmp_xhci_core_init(struct zynqmp_xhci *zynqmp_xhci) { @@ -81,6 +92,7 @@ static int zynqmp_xhci_core_init(struct zynqmp_xhci *zynqmp_xhci) return ret; } +#ifndef CONFIG_DM_USB int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor) { struct zynqmp_xhci *ctx = &zynqmp_xhci; @@ -114,6 +126,7 @@ int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor) return ret; } +#endif void xhci_hcd_stop(int index) { @@ -124,3 +137,60 @@ void xhci_hcd_stop(int index) return; } + +#ifdef CONFIG_DM_USB +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, "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, +}; +#endif