dwc3-uniphier depends on xhci-dwc3 framework, however, it is preferable to use dwc3-generic.
This driver calls the exported dwc3-generic functions and redefine the SoC-dependent operations to fit dwc3-generic. Signed-off-by: Kunihiko Hayashi <hayashi.kunih...@socionext.com> Reviewed-by: Marek Vasut <ma...@denx.de> --- drivers/usb/dwc3/Kconfig | 4 +- drivers/usb/dwc3/dwc3-uniphier.c | 116 ++++++++++++++++++++----------- 2 files changed, 78 insertions(+), 42 deletions(-) diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index f010291d02..7ddfa94e51 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -55,7 +55,9 @@ config USB_DWC3_MESON_GXL config USB_DWC3_UNIPHIER bool "DesignWare USB3 Host Support on UniPhier Platforms" - depends on ARCH_UNIPHIER && USB_XHCI_DWC3 + depends on ARCH_UNIPHIER && USB_DWC3 + select USB_DWC3_GENERIC + select PHY_UNIPHIER_USB3 help Support of USB2/3 functionality in Socionext UniPhier platforms. Say 'Y' here if you have one such device. diff --git a/drivers/usb/dwc3/dwc3-uniphier.c b/drivers/usb/dwc3/dwc3-uniphier.c index 54b52dcd66..ab85428a70 100644 --- a/drivers/usb/dwc3/dwc3-uniphier.c +++ b/drivers/usb/dwc3/dwc3-uniphier.c @@ -4,14 +4,17 @@ * * Copyright (C) 2016-2017 Socionext Inc. * Author: Masahiro Yamada <yamada.masah...@socionext.com> + * Author: Kunihiko Hayashi <hayashi.kunih...@socionext.com> */ #include <dm.h> -#include <dm/device_compat.h> +#include <dm/lists.h> #include <linux/bitops.h> -#include <linux/errno.h> -#include <linux/io.h> -#include <linux/sizes.h> +#include <linux/usb/gadget.h> + +#include "core.h" +#include "gadget.h" +#include "dwc3-generic.h" #define UNIPHIER_PRO4_DWC3_RESET 0x40 #define UNIPHIER_PRO4_DWC3_RESET_XIOMMU BIT(5) @@ -27,8 +30,11 @@ #define UNIPHIER_PXS2_DWC3_RESET 0x00 #define UNIPHIER_PXS2_DWC3_RESET_XLINK BIT(15) -static int uniphier_pro4_dwc3_init(void __iomem *regs) +static void uniphier_pro4_dwc3_init(struct udevice *dev, int index, + enum usb_dr_mode mode) { + struct dwc3_glue_data *glue = dev_get_plat(dev); + void *regs = map_physmem(glue->regs, glue->size, MAP_NOCACHE); u32 tmp; tmp = readl(regs + UNIPHIER_PRO4_DWC3_RESET); @@ -36,11 +42,14 @@ static int uniphier_pro4_dwc3_init(void __iomem *regs) tmp |= UNIPHIER_PRO4_DWC3_RESET_XIOMMU | UNIPHIER_PRO4_DWC3_RESET_XLINK; writel(tmp, regs + UNIPHIER_PRO4_DWC3_RESET); - return 0; + unmap_physmem(regs, MAP_NOCACHE); } -static int uniphier_pro5_dwc3_init(void __iomem *regs) +static void uniphier_pro5_dwc3_init(struct udevice *dev, int index, + enum usb_dr_mode mode) { + struct dwc3_glue_data *glue = dev_get_plat(dev); + void *regs = map_physmem(glue->regs, glue->size, MAP_NOCACHE); u32 tmp; tmp = readl(regs + UNIPHIER_PRO5_DWC3_RESET); @@ -49,72 +58,97 @@ static int uniphier_pro5_dwc3_init(void __iomem *regs) tmp |= UNIPHIER_PRO5_DWC3_RESET_XLINK | UNIPHIER_PRO5_DWC3_RESET_XIOMMU; writel(tmp, regs + UNIPHIER_PRO5_DWC3_RESET); - return 0; + unmap_physmem(regs, MAP_NOCACHE); } -static int uniphier_pxs2_dwc3_init(void __iomem *regs) +static void uniphier_pxs2_dwc3_init(struct udevice *dev, int index, + enum usb_dr_mode mode) { + struct dwc3_glue_data *glue = dev_get_plat(dev); + void *regs = map_physmem(glue->regs, glue->size, MAP_NOCACHE); u32 tmp; tmp = readl(regs + UNIPHIER_PXS2_DWC3_RESET); tmp |= UNIPHIER_PXS2_DWC3_RESET_XLINK; writel(tmp, regs + UNIPHIER_PXS2_DWC3_RESET); - return 0; + unmap_physmem(regs, MAP_NOCACHE); } -static int uniphier_dwc3_probe(struct udevice *dev) +static int dwc3_uniphier_glue_get_ctrl_dev(struct udevice *dev, ofnode *node) { - fdt_addr_t base; - void __iomem *regs; - int (*init)(void __iomem *regs); - int ret; + struct udevice *child; + const char *name; + ofnode subnode; + + /* + * "controller reset" belongs to glue logic, and it should be + * accessible in .glue_configure() before access to the controller + * begins. + */ + ofnode_for_each_subnode(subnode, dev_ofnode(dev)) { + name = ofnode_get_name(subnode); + if (!strncmp(name, "reset", 5)) + device_bind_driver_to_node(dev, "uniphier-reset", + name, subnode, &child); + } + + /* Get controller node that is placed separately from the glue node */ + *node = ofnode_by_compatible(dev_ofnode(dev->parent), + "socionext,uniphier-dwc3"); - base = dev_read_addr(dev); - if (base == FDT_ADDR_T_NONE) - return -EINVAL; - - regs = ioremap(base, SZ_32K); - if (!regs) - return -ENOMEM; + return 0; +} - init = (typeof(init))dev_get_driver_data(dev); - ret = init(regs); - if (ret) - dev_err(dev, "failed to init glue layer\n"); +static const struct dwc3_glue_ops uniphier_pro4_dwc3_ops = { + .glue_get_ctrl_dev = dwc3_uniphier_glue_get_ctrl_dev, + .glue_configure = uniphier_pro4_dwc3_init, +}; - iounmap(regs); +static const struct dwc3_glue_ops uniphier_pro5_dwc3_ops = { + .glue_get_ctrl_dev = dwc3_uniphier_glue_get_ctrl_dev, + .glue_configure = uniphier_pro5_dwc3_init, +}; - return ret; -} +static const struct dwc3_glue_ops uniphier_pxs2_dwc3_ops = { + .glue_get_ctrl_dev = dwc3_uniphier_glue_get_ctrl_dev, + .glue_configure = uniphier_pxs2_dwc3_init, +}; static const struct udevice_id uniphier_dwc3_match[] = { { - .compatible = "socionext,uniphier-pro4-dwc3", - .data = (ulong)uniphier_pro4_dwc3_init, + .compatible = "socionext,uniphier-pro4-dwc3-glue", + .data = (ulong)&uniphier_pro4_dwc3_ops, + }, + { + .compatible = "socionext,uniphier-pro5-dwc3-glue", + .data = (ulong)&uniphier_pro5_dwc3_ops, }, { - .compatible = "socionext,uniphier-pro5-dwc3", - .data = (ulong)uniphier_pro5_dwc3_init, + .compatible = "socionext,uniphier-pxs2-dwc3-glue", + .data = (ulong)&uniphier_pxs2_dwc3_ops, }, { - .compatible = "socionext,uniphier-pxs2-dwc3", - .data = (ulong)uniphier_pxs2_dwc3_init, + .compatible = "socionext,uniphier-ld20-dwc3-glue", + .data = (ulong)&uniphier_pxs2_dwc3_ops, }, { - .compatible = "socionext,uniphier-ld20-dwc3", - .data = (ulong)uniphier_pxs2_dwc3_init, + .compatible = "socionext,uniphier-pxs3-dwc3-glue", + .data = (ulong)&uniphier_pxs2_dwc3_ops, }, { - .compatible = "socionext,uniphier-pxs3-dwc3", - .data = (ulong)uniphier_pxs2_dwc3_init, + .compatible = "socionext,uniphier-nx1-dwc3-glue", + .data = (ulong)&uniphier_pxs2_dwc3_ops, }, { /* sentinel */ } }; -U_BOOT_DRIVER(usb_xhci) = { +U_BOOT_DRIVER(dwc3_uniphier_wrapper) = { .name = "uniphier-dwc3", .id = UCLASS_SIMPLE_BUS, .of_match = uniphier_dwc3_match, - .probe = uniphier_dwc3_probe, + .bind = dwc3_glue_bind, + .probe = dwc3_glue_probe, + .remove = dwc3_glue_remove, + .plat_auto = sizeof(struct dwc3_glue_data), }; -- 2.25.1