From: Mugunthan V N <mugunthan...@ti.com>

Add a TI DWC3 peripheral driver with driver model support and the
driver will be bound by the DWC3 wrapper driver based on the
dr_mode device tree entry.

Signed-off-by: Mugunthan V N <mugunthan...@ti.com>
Signed-off-by: Vignesh R <vigne...@ti.com>
---
 drivers/usb/dwc3/core.c      |  57 +++++++++++++++
 drivers/usb/dwc3/core.h      |   2 +
 drivers/usb/dwc3/dwc3-omap.c | 167 ++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 225 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 98102bd6b00a..a895f8fbddd3 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -603,6 +603,8 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc)
 
 #define DWC3_ALIGN_MASK                (16 - 1)
 
+#ifndef CONFIG_DM_USB
+
 /**
  * dwc3_uboot_init - dwc3 core uboot initialization code
  * @dwc3_dev: struct dwc3_device containing initialization data
@@ -789,3 +791,58 @@ MODULE_ALIAS("platform:dwc3");
 MODULE_AUTHOR("Felipe Balbi <ba...@ti.com>");
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");
+
+#else
+
+int dwc3_init(struct dwc3 *dwc)
+{
+       int ret;
+
+       dwc3_cache_hwparams(dwc);
+
+       ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE);
+       if (ret) {
+               dev_err(dwc->dev, "failed to allocate event buffers\n");
+               return -ENOMEM;
+       }
+
+       ret = dwc3_core_init(dwc);
+       if (ret) {
+               dev_err(dev, "failed to initialize core\n");
+               goto err0;
+       }
+
+       ret = dwc3_event_buffers_setup(dwc);
+       if (ret) {
+               dev_err(dwc->dev, "failed to setup event buffers\n");
+               goto err1;
+       }
+
+       ret = dwc3_core_init_mode(dwc);
+       if (ret)
+               goto err2;
+
+       return 0;
+
+err2:
+       dwc3_event_buffers_cleanup(dwc);
+
+err1:
+       dwc3_core_exit(dwc);
+
+err0:
+       dwc3_free_event_buffers(dwc);
+
+       return ret;
+}
+
+void dwc3_remove(struct dwc3 *dwc)
+{
+       dwc3_core_exit_mode(dwc);
+       dwc3_event_buffers_cleanup(dwc);
+       dwc3_free_event_buffers(dwc);
+       dwc3_core_exit(dwc);
+       kfree(dwc->mem);
+}
+
+#endif
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 24f03e484fd5..972628751697 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -992,6 +992,8 @@ struct dwc3_gadget_ep_cmd_params {
 
 /* prototypes */
 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);
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index 10b93eed5793..e55201a5845b 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -27,9 +27,21 @@
 #include <dwc3-uboot.h>
 
 #include "linux-compat.h"
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <ti-usb-phy-uboot.h>
+#include <usb.h>
+
+#include "core.h"
 
 #include <libfdt.h>
 #include <dm/device.h>
+#include <dm/uclass.h>
+#include <dm/lists.h>
+#include <dwc3-uboot.h>
+
+#include <asm/omap_common.h>
+#include "gadget.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -140,7 +152,11 @@ struct dwc3_omap {
        u32                     index;
 };
 
-#ifndef CONFIG_DM_USB
+struct omap_dwc3_priv {
+       struct dwc3_omap omap;
+       struct dwc3 dwc3;
+       struct ti_usb_phy_device phy_device;
+};
 
 static LIST_HEAD(dwc3_omap_list);
 
@@ -369,6 +385,8 @@ static void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap, 
int utmi_mode)
        dwc3_omap_write_utmi_status(omap, reg);
 }
 
+#ifndef CONFIG_DM_USB
+
 /**
  * dwc3_omap_uboot_init - dwc3 omap uboot initialization code
  * @dev: struct dwc3_omap_device containing initialization data
@@ -472,15 +490,155 @@ MODULE_DESCRIPTION("DesignWare USB3 OMAP Glue Layer");
 
 #else
 
+int usb_gadget_handle_interrupts(int index)
+{
+       struct omap_dwc3_priv *priv;
+       struct dwc3_omap *omap;
+       struct dwc3 *dwc;
+       struct udevice *dev;
+       u32 status;
+       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);
+       omap = &priv->omap;
+       dwc = &priv->dwc3;
+
+       status = dwc3_omap_interrupt(-1, omap);
+       if (status)
+               dwc3_gadget_uboot_handle_interrupt(dwc);
+
+       return 0;
+}
+
+static int dwc3_omap_peripheral_probe(struct udevice *dev)
+{
+       struct omap_dwc3_priv *priv = dev_get_priv(dev);
+       struct dwc3_omap *omap = &priv->omap;
+       struct dwc3 *dwc = &priv->dwc3;
+       u32 reg;
+       int ret;
+
+       enable_usb_clocks(0);
+
+       /* Initialize usb phy */
+       ret = ti_usb_phy_uboot_init(&priv->phy_device);
+       if (ret)
+               return ret;
+
+       dwc3_omap_map_offset(omap);
+       dwc3_omap_set_utmi_mode(omap, DWC3_OMAP_UTMI_MODE_SW);
+
+       /* check the DMA Status */
+       reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG);
+       omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE);
+
+       dwc3_omap_enable_irqs(omap);
+
+       dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
+
+       /* default to highest possible threshold */
+       dwc->lpm_nyet_threshold = 0xff;
+       /*
+        * default to assert utmi_sleep_n and use maximum allowed HIRD
+        * threshold value of 0b1100
+        */
+       dwc->hird_threshold = 12;
+       /* default to -3.5dB de-emphasis */
+       dwc->tx_de_emphasis = 1;
+
+       dwc->needs_fifo_resize = false;
+       dwc->index = 0;
+
+       return dwc3_init(dwc);
+}
+
+static int dwc3_omap_peripheral_remove(struct udevice *dev)
+{
+       struct omap_dwc3_priv *priv = dev_get_priv(dev);
+       struct dwc3_omap *omap = &priv->omap;
+       struct dwc3 *dwc = &priv->dwc3;
+
+       dwc3_omap_disable_irqs(omap);
+       dwc3_remove(dwc);
+
+       return 0;
+}
+
+static int dwc3_omap_ofdata_to_platdata(struct udevice *dev)
+{
+       struct omap_dwc3_priv *priv = dev_get_priv(dev);
+       const void *fdt = gd->fdt_blob;
+       int node = dev->of_offset;
+       int ctrlmodnode;
+       int physnode;
+
+       priv->omap.base = map_physmem(fdtdec_get_addr(fdt,
+                               dev->parent->of_offset, "reg"), 0,
+                               MAP_NOCACHE);
+
+       priv->dwc3.regs = dev_map_physmem(dev, 0);
+       priv->dwc3.regs += DWC3_GLOBALS_REGS_START;
+
+       physnode = fdtdec_lookup_phandle(fdt, node, "phys");
+       ctrlmodnode = fdtdec_lookup_phandle(fdt, physnode, "ctrl-module");
+       priv->phy_device.usb2_phy_power =
+               map_physmem(fdtdec_get_addr(fdt, ctrlmodnode, "reg"),
+                           0, MAP_NOCACHE);
+       priv->phy_device.index = 0;
+
+       priv->dwc3.maximum_speed = usb_get_maximum_speed(node);
+       if (priv->dwc3.maximum_speed < 0) {
+               error("Invalid usb maximum speed\n");
+               return priv->dwc3.maximum_speed;
+       }
+
+       return 0;
+}
+
+static int dwc3_omap_peripheral_ofdata_to_platdata(struct udevice *dev)
+{
+       struct omap_dwc3_priv *priv = dev_get_priv(dev);
+       int ret;
+
+       ret = dwc3_omap_ofdata_to_platdata(dev);
+       if (ret) {
+               error("platform dt parse error\n");
+               return ret;
+       }
+
+       priv->dwc3.dr_mode = USB_DR_MODE_PERIPHERAL;
+
+       return 0;
+}
+
+U_BOOT_DRIVER(dwc3_omap_peripheral) = {
+       .name   = "dwc3-omap-peripheral",
+       .id     = UCLASS_USB_DEV_GENERIC,
+       .ofdata_to_platdata = dwc3_omap_peripheral_ofdata_to_platdata,
+       .probe = dwc3_omap_peripheral_probe,
+       .remove = dwc3_omap_peripheral_remove,
+       .platdata_auto_alloc_size = sizeof(struct usb_platdata),
+       .priv_auto_alloc_size = sizeof(struct omap_dwc3_priv),
+       .flags  = DM_FLAG_ALLOC_PRIV_DMA,
+};
+
 static int ti_dwc3_wrapper_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;
 
                if (strncmp(name, "usb@", 4))
                        continue;
@@ -490,6 +648,13 @@ static int ti_dwc3_wrapper_bind(struct udevice *parent)
                case USB_DR_MODE_PERIPHERAL:
                case USB_DR_MODE_OTG:
                        /* Bind MUSB device */
+                       ret = device_bind_driver_to_node(parent,
+                                                        "dwc3-omap-peripheral",
+                                                        name, node, &dev);
+                       if (ret) {
+                               error("dwc3 - not able to bind usb device 
node\n");
+                               return ret;
+                       }
                        break;
                case USB_DR_MODE_HOST:
                        /* Bind MUSB host */
-- 
2.13.0

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to