usb: dwc3: Add generic DWC3 glue logic driver
authorMichal Simek <michal.simek@xilinx.com>
Fri, 18 May 2018 11:15:06 +0000 (13:15 +0200)
committerMarek Vasut <marex@denx.de>
Fri, 18 May 2018 11:23:10 +0000 (13:23 +0200)
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 <michal.simek@xilinx.com>
drivers/usb/dwc3/Kconfig
drivers/usb/dwc3/Makefile
drivers/usb/dwc3/dwc3-generic.c [new file with mode: 0644]

index ae7fc1c6304d4138a4475cae7b897a0cea1bb8d2..943b7630eba4da22a5dfe3303103321f7e5789c0 100644 (file)
@@ -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.
+
 config USB_DWC3_UNIPHIER
        bool "DesignWare USB3 Host Support on UniPhier Platforms"
        depends on ARCH_UNIPHIER && USB_XHCI_DWC3
index cd18b8d9ec025df174dc0ed6ad62c436bad1bf46..60b5515a67da9f4e7a35b1e8261df84124bd3330 100644 (file)
@@ -7,6 +7,7 @@ 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_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-generic.c b/drivers/usb/dwc3/dwc3-generic.c
new file mode 100644 (file)
index 0000000..ca63eac
--- /dev/null
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier:     GPL-2.0
+/*
+ * Generic DWC3 Glue layer
+ *
+ * Copyright (C) 2016 - 2018 Xilinx, Inc.
+ *
+ * Based on dwc3-omap.c.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <linux/usb/otg.h>
+#include <linux/compat.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <malloc.h>
+#include <usb.h>
+#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) {
+               pr_err("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(dev);
+
+       priv->regs = (void *)devfdt_get_addr(dev);
+       priv->regs += DWC3_GLOBALS_REGS_START;
+
+       priv->maximum_speed = usb_get_maximum_speed(node);
+       if (priv->maximum_speed == USB_SPEED_UNKNOWN) {
+               pr_err("Invalid usb maximum speed\n");
+               return -ENODEV;
+       }
+
+       priv->dr_mode = usb_get_dr_mode(node);
+       if (priv->dr_mode == USB_DR_MODE_UNKNOWN) {
+               pr_err("Invalid usb mode setup\n");
+               return -ENODEV;
+       }
+
+       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, dev_of_offset(parent)); 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;
+               const char *driver;
+
+               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__);
+                       driver = "dwc3-generic-peripheral";
+                       break;
+               case USB_DR_MODE_HOST:
+                       debug("%s: dr_mode: HOST\n", __func__);
+                       driver = "dwc3-generic-host";
+                       break;
+               default:
+                       debug("%s: unsupported dr_mode\n", __func__);
+                       return -ENODEV;
+               };
+
+               ret = device_bind_driver_to_node(parent, driver, name,
+                                                offset_to_ofnode(node), &dev);
+               if (ret) {
+                       debug("%s: not able to bind usb device mode\n",
+                             __func__);
+                       return ret;
+               }
+       }
+
+       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,
+};