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 | 6 ++ drivers/usb/dwc3/dwc3-omap.c | 167 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 230 insertions(+) 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 72d2fcdd3f42..972628751697 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -713,7 +713,11 @@ struct dwc3 { /* device lock */ spinlock_t lock; +#ifndef CONFIG_DM_USB struct device *dev; +#else + struct udevice *dev; +#endif struct platform_device *xhci; struct resource xhci_resources[DWC3_XHCI_RESOURCES_NUM]; @@ -988,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 f18884f13392..b4dde726c6f3 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -27,6 +27,23 @@ #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; /* * All these registers belong to OMAP's Wrapper around the @@ -135,6 +152,12 @@ struct dwc3_omap { u32 index; }; +struct omap_dwc3_priv { + struct dwc3_omap omap; + struct dwc3 dwc3; + struct ti_usb_phy_device phy_device; +}; + static LIST_HEAD(dwc3_omap_list); static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset) @@ -362,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 @@ -462,3 +487,145 @@ MODULE_ALIAS("platform:omap-dwc3"); MODULE_AUTHOR("Felipe Balbi <ba...@ti.com>"); MODULE_LICENSE("GPL v2"); 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(dev); + int ctrlmodnode; + int physnode; + + priv->omap.base = map_physmem(fdtdec_get_addr(fdt, + dev_of_offset(dev->parent), "reg"), 0, + MAP_NOCACHE); + + priv->dwc3.regs = devfdt_map_physmem(dev, + sizeof(priv->dwc3.regs_size)); + 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, +}; +#endif /* CONFIG_DM_USB */ -- 2.13.0 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot