]> git.sur5r.net Git - u-boot/commitdiff
usb: dwc3: add UniPhier specific glue layer
authorMasahiro Yamada <yamada.masahiro@socionext.com>
Thu, 28 Sep 2017 13:01:00 +0000 (22:01 +0900)
committerMarek Vasut <marex@denx.de>
Sun, 1 Oct 2017 14:32:55 +0000 (16:32 +0200)
Add UniPhier platform specific glue layer to support USB3 Host mode
on Synopsys DWC3 IP.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Reviewed-by: Marek Vasut <marex@denx.de>
drivers/usb/dwc3/Kconfig
drivers/usb/dwc3/Makefile
drivers/usb/dwc3/dwc3-uniphier.c [new file with mode: 0644]

index a291ceb6ae0b8ae1acb905d9bb01832c09834588..ae7fc1c6304d4138a4475cae7b897a0cea1bb8d2 100644 (file)
@@ -37,6 +37,13 @@ config USB_DWC3_OMAP
 
          Say 'Y' here if you have one such device
 
+config USB_DWC3_UNIPHIER
+       bool "DesignWare USB3 Host Support on UniPhier Platforms"
+       depends on ARCH_UNIPHIER && USB_XHCI_DWC3
+       help
+         Support of USB2/3 functionality in Socionext UniPhier platforms.
+         Say 'Y' here if you have one such device.
+
 menu "PHY Subsystem"
 
 config USB_DWC3_PHY_OMAP
index 2964bae0d8f4b7245a9faca3595543f7f096a5e4..51497768b21d43a30e6e38232a0f4779deadfa2e 100644 (file)
@@ -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_UNIPHIER)                += dwc3-uniphier.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-uniphier.c b/drivers/usb/dwc3/dwc3-uniphier.c
new file mode 100644 (file)
index 0000000..0d13770
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * UniPhier Specific Glue Layer for DWC3
+ *
+ * Copyright (C) 2016-2017 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+
+#define UNIPHIER_PRO4_DWC3_RESET       0x40
+#define   UNIPHIER_PRO4_DWC3_RESET_XIOMMU      BIT(5)
+#define   UNIPHIER_PRO4_DWC3_RESET_XLINK       BIT(4)
+#define   UNIPHIER_PRO4_DWC3_RESET_PHY_SS      BIT(2)
+
+#define UNIPHIER_PRO5_DWC3_RESET       0x00
+#define   UNIPHIER_PRO5_DWC3_RESET_PHY_S1      BIT(17)
+#define   UNIPHIER_PRO5_DWC3_RESET_PHY_S0      BIT(16)
+#define   UNIPHIER_PRO5_DWC3_RESET_XLINK       BIT(15)
+#define   UNIPHIER_PRO5_DWC3_RESET_XIOMMU      BIT(14)
+
+#define UNIPHIER_PXS2_DWC3_RESET       0x00
+#define   UNIPHIER_PXS2_DWC3_RESET_XLINK       BIT(15)
+
+static int uniphier_pro4_dwc3_init(void __iomem *regs)
+{
+       u32 tmp;
+
+       tmp = readl(regs + UNIPHIER_PRO4_DWC3_RESET);
+       tmp &= ~UNIPHIER_PRO4_DWC3_RESET_PHY_SS;
+       tmp |= UNIPHIER_PRO4_DWC3_RESET_XIOMMU | UNIPHIER_PRO4_DWC3_RESET_XLINK;
+       writel(tmp, regs + UNIPHIER_PRO4_DWC3_RESET);
+
+       return 0;
+}
+
+static int uniphier_pro5_dwc3_init(void __iomem *regs)
+{
+       u32 tmp;
+
+       tmp = readl(regs + UNIPHIER_PRO5_DWC3_RESET);
+       tmp &= ~(UNIPHIER_PRO5_DWC3_RESET_PHY_S1 |
+                UNIPHIER_PRO5_DWC3_RESET_PHY_S0);
+       tmp |= UNIPHIER_PRO5_DWC3_RESET_XLINK | UNIPHIER_PRO5_DWC3_RESET_XIOMMU;
+       writel(tmp, regs + UNIPHIER_PRO5_DWC3_RESET);
+
+       return 0;
+}
+
+static int uniphier_pxs2_dwc3_init(void __iomem *regs)
+{
+       u32 tmp;
+
+       tmp = readl(regs + UNIPHIER_PXS2_DWC3_RESET);
+       tmp |= UNIPHIER_PXS2_DWC3_RESET_XLINK;
+       writel(tmp, regs + UNIPHIER_PXS2_DWC3_RESET);
+
+       return 0;
+}
+
+static int uniphier_dwc3_probe(struct udevice *dev)
+{
+       fdt_addr_t base;
+       void __iomem *regs;
+       int (*init)(void __iomem *regs);
+       int ret;
+
+       base = devfdt_get_addr(dev);
+       if (base == FDT_ADDR_T_NONE)
+               return -EINVAL;
+
+       regs = ioremap(base, SZ_32K);
+       if (!regs)
+               return -ENOMEM;
+
+       init = (typeof(init))dev_get_driver_data(dev);
+       ret = init(regs);
+       if (ret)
+               dev_err(dev, "failed to init glue layer\n");
+
+       iounmap(regs);
+
+       return ret;
+}
+
+static const struct udevice_id uniphier_dwc3_match[] = {
+       {
+               .compatible = "socionext,uniphier-pro4-dwc3",
+               .data = (ulong)uniphier_pro4_dwc3_init,
+       },
+       {
+               .compatible = "socionext,uniphier-pro5-dwc3",
+               .data = (ulong)uniphier_pro5_dwc3_init,
+       },
+       {
+               .compatible = "socionext,uniphier-pxs2-dwc3",
+               .data = (ulong)uniphier_pxs2_dwc3_init,
+       },
+       {
+               .compatible = "socionext,uniphier-ld20-dwc3",
+               .data = (ulong)uniphier_pxs2_dwc3_init,
+       },
+       {
+               .compatible = "socionext,uniphier-pxs3-dwc3",
+               .data = (ulong)uniphier_pxs2_dwc3_init,
+       },
+       { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(usb_xhci) = {
+       .name = "uniphier-dwc3",
+       .id = UCLASS_SIMPLE_BUS,
+       .of_match = uniphier_dwc3_match,
+       .probe = uniphier_dwc3_probe,
+};