[U-Boot] [PATCH v2 06/13] drivers: usb: dwc3: add ti dwc3 peripheral driver with driver model support

Marek Vasut marex at denx.de
Tue Jun 13 14:03:32 UTC 2017


On 06/13/2017 02:10 PM, Vignesh R wrote:
> From: Mugunthan V N <mugunthanvnm at 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 <mugunthanvnm at ti.com>
> Signed-off-by: Vignesh R <vigneshr at 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 <balbi at 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:

Use more descriptive label names please ...

> +	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 <balbi at ti.com>");
>  MODULE_LICENSE("GPL v2");
>  MODULE_DESCRIPTION("DesignWare USB3 OMAP Glue Layer");
> +
> +#else
> +
> +int usb_gadget_handle_interrupts(int index)

Can this be made somehow more generic , so that the core code would
contain the basic interrupt handling and probe routines and the various
SoC-specific drivers would add their specific bits to it ?

> +{
> +	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 */
> 


-- 
Best regards,
Marek Vasut


More information about the U-Boot mailing list