From mboxrd@z Thu Jan 1 00:00:00 1970 From: Vignesh R Date: Tue, 23 May 2017 17:25:42 +0530 Subject: [U-Boot] [PATCH 07/11] drivers: usb: dwc3: add ti dwc3 peripheral driver with driver model support In-Reply-To: <20170523115546.399-1-vigneshr@ti.com> References: <20170523115546.399-1-vigneshr@ti.com> Message-ID: <20170523115546.399-8-vigneshr@ti.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de From: Mugunthan V N 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 Signed-off-by: Vignesh R --- 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 "); 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 #include "linux-compat.h" +#include +#include +#include +#include + +#include "core.h" #include #include +#include +#include +#include + +#include +#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