summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/Kconfig14
-rw-r--r--drivers/usb/dwc3/Kconfig7
-rw-r--r--drivers/usb/dwc3/core.c89
-rw-r--r--drivers/usb/dwc3/dwc3-generic.c293
-rw-r--r--drivers/usb/dwc3/ep0.c2
-rw-r--r--drivers/usb/gadget/ether.c40
-rw-r--r--drivers/usb/gadget/udc/Makefile4
-rw-r--r--drivers/usb/gadget/udc/udc-core.c3
-rw-r--r--drivers/usb/gadget/udc/udc-uclass.c58
-rw-r--r--drivers/usb/host/xhci-dwc3.c95
-rw-r--r--drivers/usb/musb-new/omap2430.c2
-rw-r--r--drivers/usb/musb-new/sunxi.c2
12 files changed, 431 insertions, 178 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index d456beb43fc..98f83433bed 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -52,6 +52,20 @@ config SPL_DM_USB
depends on DM_USB
default y
+config DM_USB_GADGET
+ bool "Enable driver model for USB Gadget"
+ depends on DM_USB
+ help
+ Enable driver model for USB Gadget (Peripheral
+ mode)
+
+config SPL_DM_USB_GADGET
+ bool "Enable driver model for USB Gadget in sPL"
+ depends on SPL_DM_USB
+ help
+ Enable driver model for USB Gadget in SPL
+ (Peripheral mode)
+
source "drivers/usb/host/Kconfig"
source "drivers/usb/dwc3/Kconfig"
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 943b7630eba..bbd8105c06f 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -38,10 +38,11 @@ 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
+ bool "Generic implementation of a DWC3 wrapper (aka dwc3 glue)"
+ depends on DM_USB && USB_DWC3 && MISC
help
- Some platforms can reuse this DWC3 generic implementation.
+ Select this for Xilinx ZynqMP and similar Platforms.
+ This wrapper supports Host and Peripheral operation modes.
config USB_DWC3_UNIPHIER
bool "DesignWare USB3 Host Support on UniPhier Platforms"
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index f1ca6191ce4..56e2a046bf0 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -19,7 +19,7 @@
#include <asm/dma-mapping.h>
#include <linux/ioport.h>
#include <dm.h>
-
+#include <generic-phy.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
@@ -789,8 +789,92 @@ MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");
-#if CONFIG_IS_ENABLED(DM_USB)
+#if CONFIG_IS_ENABLED(PHY) && CONFIG_IS_ENABLED(DM_USB)
+int dwc3_setup_phy(struct udevice *dev, struct phy **array, int *num_phys)
+{
+ int i, ret, count;
+ struct phy *usb_phys;
+
+ /* Return if no phy declared */
+ if (!dev_read_prop(dev, "phys", NULL))
+ return 0;
+ count = dev_count_phandle_with_args(dev, "phys", "#phy-cells");
+ if (count <= 0)
+ return count;
+
+ usb_phys = devm_kcalloc(dev, count, sizeof(struct phy),
+ GFP_KERNEL);
+ if (!usb_phys)
+ return -ENOMEM;
+
+ for (i = 0; i < count; i++) {
+ ret = generic_phy_get_by_index(dev, i, &usb_phys[i]);
+ if (ret && ret != -ENOENT) {
+ pr_err("Failed to get USB PHY%d for %s\n",
+ i, dev->name);
+ return ret;
+ }
+ }
+
+ for (i = 0; i < count; i++) {
+ ret = generic_phy_init(&usb_phys[i]);
+ if (ret) {
+ pr_err("Can't init USB PHY%d for %s\n",
+ i, dev->name);
+ goto phys_init_err;
+ }
+ }
+
+ for (i = 0; i < count; i++) {
+ ret = generic_phy_power_on(&usb_phys[i]);
+ if (ret) {
+ pr_err("Can't power USB PHY%d for %s\n",
+ i, dev->name);
+ goto phys_poweron_err;
+ }
+ }
+
+ *array = usb_phys;
+ *num_phys = count;
+ return 0;
+
+phys_poweron_err:
+ for (i = count - 1; i >= 0; i--)
+ generic_phy_power_off(&usb_phys[i]);
+ for (i = 0; i < count; i++)
+ generic_phy_exit(&usb_phys[i]);
+
+ return ret;
+
+phys_init_err:
+ for (; i >= 0; i--)
+ generic_phy_exit(&usb_phys[i]);
+
+ return ret;
+}
+
+int dwc3_shutdown_phy(struct udevice *dev, struct phy *usb_phys, int num_phys)
+{
+ int i, ret;
+
+ for (i = 0; i < num_phys; i++) {
+ if (!generic_phy_valid(&usb_phys[i]))
+ continue;
+
+ ret = generic_phy_power_off(&usb_phys[i]);
+ ret |= generic_phy_exit(&usb_phys[i]);
+ if (ret) {
+ pr_err("Can't shutdown USB PHY%d for %s\n",
+ i, dev->name);
+ }
+ }
+
+ return 0;
+}
+#endif
+
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
int dwc3_init(struct dwc3 *dwc)
{
int ret;
@@ -841,5 +925,4 @@ void dwc3_remove(struct dwc3 *dwc)
dwc3_core_exit(dwc);
kfree(dwc->mem);
}
-
#endif
diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c
index 56c9fd657fb..bc6bba198e9 100644
--- a/drivers/usb/dwc3/dwc3-generic.c
+++ b/drivers/usb/dwc3/dwc3-generic.c
@@ -8,72 +8,89 @@
*/
#include <common.h>
+#include <asm-generic/io.h>
#include <dm.h>
#include <dm/device-internal.h>
#include <dm/lists.h>
-#include <linux/usb/otg.h>
-#include <linux/compat.h>
+#include <dwc3-uboot.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"
+#include <reset.h>
+#include <clk.h>
-DECLARE_GLOBAL_DATA_PTR;
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+struct dwc3_generic_peripheral {
+ struct dwc3 dwc3;
+ struct phy *phys;
+ int num_phys;
+ fdt_addr_t base;
+};
-int usb_gadget_handle_interrupts(int index)
+int dm_usb_gadget_handle_interrupts(struct udevice *dev)
{
- 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);
+ struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
+ struct dwc3 *dwc3 = &priv->dwc3;
- dwc3_gadget_uboot_handle_interrupt(priv);
+ dwc3_gadget_uboot_handle_interrupt(dwc3);
return 0;
}
static int dwc3_generic_peripheral_probe(struct udevice *dev)
{
- struct dwc3 *priv = dev_get_priv(dev);
+ int rc;
+ struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
+ struct dwc3 *dwc3 = &priv->dwc3;
- return dwc3_init(priv);
+ rc = dwc3_setup_phy(dev, &priv->phys, &priv->num_phys);
+ if (rc)
+ return rc;
+
+ dwc3->regs = map_physmem(priv->base, DWC3_OTG_REGS_END, MAP_NOCACHE);
+ dwc3->regs += DWC3_GLOBALS_REGS_START;
+ dwc3->dev = dev;
+
+ rc = dwc3_init(dwc3);
+ if (rc) {
+ unmap_physmem(dwc3->regs, MAP_NOCACHE);
+ return rc;
+ }
+
+ return 0;
}
static int dwc3_generic_peripheral_remove(struct udevice *dev)
{
- struct dwc3 *priv = dev_get_priv(dev);
+ struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
+ struct dwc3 *dwc3 = &priv->dwc3;
- dwc3_remove(priv);
+ dwc3_remove(dwc3);
+ dwc3_shutdown_phy(dev, priv->phys, priv->num_phys);
+ unmap_physmem(dwc3->regs, MAP_NOCACHE);
return 0;
}
static int dwc3_generic_peripheral_ofdata_to_platdata(struct udevice *dev)
{
- struct dwc3 *priv = dev_get_priv(dev);
+ struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
+ struct dwc3 *dwc3 = &priv->dwc3;
int node = dev_of_offset(dev);
- priv->regs = (void *)devfdt_get_addr(dev);
- priv->regs += DWC3_GLOBALS_REGS_START;
+ priv->base = devfdt_get_addr(dev);
- priv->maximum_speed = usb_get_maximum_speed(node);
- if (priv->maximum_speed == USB_SPEED_UNKNOWN) {
+ dwc3->maximum_speed = usb_get_maximum_speed(node);
+ if (dwc3->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) {
+ dwc3->dr_mode = usb_get_dr_mode(node);
+ if (dwc3->dr_mode == USB_DR_MODE_UNKNOWN) {
pr_err("Invalid usb mode setup\n");
return -ENODEV;
}
@@ -81,24 +98,112 @@ static int dwc3_generic_peripheral_ofdata_to_platdata(struct udevice *dev)
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,
+ .id = UCLASS_USB_GADGET_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,
+ .priv_auto_alloc_size = sizeof(struct dwc3_generic_peripheral),
+};
+#endif
+
+struct dwc3_glue_data {
+ struct clk_bulk clks;
+ struct reset_ctl_bulk resets;
+ fdt_addr_t regs;
};
-static int dwc3_generic_bind(struct udevice *parent)
+struct dwc3_glue_ops {
+ void (*select_dr_mode)(struct udevice *dev, int index,
+ enum usb_dr_mode mode);
+};
+
+void dwc3_ti_select_dr_mode(struct udevice *dev, int index,
+ enum usb_dr_mode mode)
+{
+#define USBOTGSS_UTMI_OTG_STATUS 0x0084
+#define USBOTGSS_UTMI_OTG_OFFSET 0x0480
+
+/* UTMI_OTG_STATUS REGISTER */
+#define USBOTGSS_UTMI_OTG_STATUS_SW_MODE BIT(31)
+#define USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT BIT(9)
+#define USBOTGSS_UTMI_OTG_STATUS_TXBITSTUFFENABLE BIT(8)
+#define USBOTGSS_UTMI_OTG_STATUS_IDDIG BIT(4)
+#define USBOTGSS_UTMI_OTG_STATUS_SESSEND BIT(3)
+#define USBOTGSS_UTMI_OTG_STATUS_SESSVALID BIT(2)
+#define USBOTGSS_UTMI_OTG_STATUS_VBUSVALID BIT(1)
+enum dwc3_omap_utmi_mode {
+ DWC3_OMAP_UTMI_MODE_UNKNOWN = 0,
+ DWC3_OMAP_UTMI_MODE_HW,
+ DWC3_OMAP_UTMI_MODE_SW,
+};
+
+ u32 use_id_pin;
+ u32 host_mode;
+ u32 reg;
+ u32 utmi_mode;
+ u32 utmi_status_offset = USBOTGSS_UTMI_OTG_STATUS;
+
+ struct dwc3_glue_data *glue = dev_get_platdata(dev);
+ void *base = map_physmem(glue->regs, 0x10000, MAP_NOCACHE);
+
+ if (device_is_compatible(dev, "ti,am437x-dwc3"))
+ utmi_status_offset += USBOTGSS_UTMI_OTG_OFFSET;
+
+ utmi_mode = dev_read_u32_default(dev, "utmi-mode",
+ DWC3_OMAP_UTMI_MODE_UNKNOWN);
+ if (utmi_mode != DWC3_OMAP_UTMI_MODE_HW) {
+ debug("%s: OTG is not supported. defaulting to PERIPHERAL\n",
+ dev->name);
+ mode = USB_DR_MODE_PERIPHERAL;
+ }
+
+ switch (mode) {
+ case USB_DR_MODE_PERIPHERAL:
+ use_id_pin = 0;
+ host_mode = 0;
+ break;
+ case USB_DR_MODE_HOST:
+ use_id_pin = 0;
+ host_mode = 1;
+ break;
+ case USB_DR_MODE_OTG:
+ default:
+ use_id_pin = 1;
+ host_mode = 0;
+ break;
+ }
+
+ reg = readl(base + utmi_status_offset);
+
+ reg &= ~(USBOTGSS_UTMI_OTG_STATUS_SW_MODE);
+ if (!use_id_pin)
+ reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+
+ writel(reg, base + utmi_status_offset);
+
+ reg &= ~(USBOTGSS_UTMI_OTG_STATUS_SESSEND |
+ USBOTGSS_UTMI_OTG_STATUS_VBUSVALID |
+ USBOTGSS_UTMI_OTG_STATUS_IDDIG);
+
+ reg |= USBOTGSS_UTMI_OTG_STATUS_SESSVALID |
+ USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT;
+
+ if (!host_mode)
+ reg |= USBOTGSS_UTMI_OTG_STATUS_IDDIG |
+ USBOTGSS_UTMI_OTG_STATUS_VBUSVALID;
+
+ writel(reg, base + utmi_status_offset);
+
+ unmap_physmem(base, MAP_NOCACHE);
+}
+
+struct dwc3_glue_ops ti_ops = {
+ .select_dr_mode = dwc3_ti_select_dr_mode,
+};
+
+static int dwc3_glue_bind(struct udevice *parent)
{
const void *fdt = gd->fdt_blob;
int node;
@@ -109,29 +214,32 @@ static int dwc3_generic_bind(struct udevice *parent)
const char *name = fdt_get_name(fdt, node, NULL);
enum usb_dr_mode dr_mode;
struct udevice *dev;
- const char *driver;
+ const char *driver = NULL;
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:
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
debug("%s: dr_mode: OTG or Peripheral\n", __func__);
driver = "dwc3-generic-peripheral";
+#endif
break;
case USB_DR_MODE_HOST:
debug("%s: dr_mode: HOST\n", __func__);
- driver = "dwc3-generic-host";
+ driver = "xhci-dwc3";
break;
default:
debug("%s: unsupported dr_mode\n", __func__);
return -ENODEV;
};
+ if (!driver)
+ continue;
+
ret = device_bind_driver_to_node(parent, driver, name,
offset_to_ofnode(node), &dev);
if (ret) {
@@ -144,14 +252,107 @@ static int dwc3_generic_bind(struct udevice *parent)
return 0;
}
-static const struct udevice_id dwc3_generic_ids[] = {
+static int dwc3_glue_reset_init(struct udevice *dev,
+ struct dwc3_glue_data *glue)
+{
+ int ret;
+
+ ret = reset_get_bulk(dev, &glue->resets);
+ if (ret == -ENOTSUPP)
+ return 0;
+ else if (ret)
+ return ret;
+
+ ret = reset_deassert_bulk(&glue->resets);
+ if (ret) {
+ reset_release_bulk(&glue->resets);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int dwc3_glue_clk_init(struct udevice *dev,
+ struct dwc3_glue_data *glue)
+{
+ int ret;
+
+ ret = clk_get_bulk(dev, &glue->clks);
+ if (ret == -ENOSYS)
+ return 0;
+ if (ret)
+ return ret;
+
+#if CONFIG_IS_ENABLED(CLK)
+ ret = clk_enable_bulk(&glue->clks);
+ if (ret) {
+ clk_release_bulk(&glue->clks);
+ return ret;
+ }
+#endif
+
+ return 0;
+}
+
+static int dwc3_glue_probe(struct udevice *dev)
+{
+ struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(dev);
+ struct dwc3_glue_data *glue = dev_get_platdata(dev);
+ struct udevice *child = NULL;
+ int index = 0;
+ int ret;
+
+ glue->regs = dev_read_addr(dev);
+
+ ret = dwc3_glue_clk_init(dev, glue);
+ if (ret)
+ return ret;
+
+ ret = dwc3_glue_reset_init(dev, glue);
+ if (ret)
+ return ret;
+
+ ret = device_find_first_child(dev, &child);
+ if (ret)
+ return ret;
+
+ while (child) {
+ enum usb_dr_mode dr_mode;
+
+ dr_mode = usb_get_dr_mode(dev_of_offset(child));
+ device_find_next_child(&child);
+ if (ops && ops->select_dr_mode)
+ ops->select_dr_mode(dev, index, dr_mode);
+ index++;
+ }
+
+ return 0;
+}
+
+static int dwc3_glue_remove(struct udevice *dev)
+{
+ struct dwc3_glue_data *glue = dev_get_platdata(dev);
+
+ reset_release_bulk(&glue->resets);
+
+ clk_release_bulk(&glue->clks);
+
+ return dm_scan_fdt_dev(dev);
+}
+
+static const struct udevice_id dwc3_glue_ids[] = {
{ .compatible = "xlnx,zynqmp-dwc3" },
+ { .compatible = "ti,dwc3", .data = (ulong)&ti_ops },
{ }
};
U_BOOT_DRIVER(dwc3_generic_wrapper) = {
.name = "dwc3-generic-wrapper",
.id = UCLASS_MISC,
- .of_match = dwc3_generic_ids,
- .bind = dwc3_generic_bind,
+ .of_match = dwc3_glue_ids,
+ .bind = dwc3_glue_bind,
+ .probe = dwc3_glue_probe,
+ .remove = dwc3_glue_remove,
+ .platdata_auto_alloc_size = sizeof(struct dwc3_glue_data),
+
};
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 4f68887b8d5..818efb3e8d7 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -12,7 +12,7 @@
*
* commit c00552ebaf : Merge 3.18-rc7 into usb-next
*/
-
+#include <common.h>
#include <linux/kernel.h>
#include <linux/list.h>
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 193583b437c..3b3d9af6810 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -100,9 +100,6 @@ struct eth_dev {
struct usb_gadget *gadget;
struct usb_request *req; /* for control responses */
struct usb_request *stat_req; /* for cdc & rndis status */
-#if CONFIG_IS_ENABLED(DM_USB)
- struct udevice *usb_udev;
-#endif
u8 config;
struct usb_ep *in_ep, *out_ep, *status_ep;
@@ -2336,40 +2333,17 @@ fail:
}
/*-------------------------------------------------------------------------*/
-
-#if CONFIG_IS_ENABLED(DM_USB)
-int dm_usb_init(struct eth_dev *e_dev)
-{
- struct udevice *dev = NULL;
- int ret;
-
- ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &dev);
- if (!dev || ret) {
- pr_err("No USB device found\n");
- return -ENODEV;
- }
-
- e_dev->usb_udev = dev;
-
- return ret;
-}
-#endif
-
static int _usb_eth_init(struct ether_priv *priv)
{
struct eth_dev *dev = &priv->ethdev;
struct usb_gadget *gadget;
unsigned long ts;
+ int ret;
unsigned long timeout = USB_CONNECT_TIMEOUT;
-#if CONFIG_IS_ENABLED(DM_USB)
- if (dm_usb_init(dev)) {
- pr_err("USB ether not found\n");
- return -ENODEV;
- }
-#else
- board_usb_init(0, USB_INIT_DEVICE);
-#endif
+ ret = usb_gadget_initialize(0);
+ if (ret)
+ return ret;
/* Configure default mac-addresses for the USB ethernet device */
#ifdef CONFIG_USBNET_DEV_ADDR
@@ -2541,9 +2515,7 @@ void _usb_eth_halt(struct ether_priv *priv)
}
usb_gadget_unregister_driver(&priv->eth_driver);
-#if !CONFIG_IS_ENABLED(DM_USB)
- board_usb_cleanup(0, USB_INIT_DEVICE);
-#endif
+ usb_gadget_release(0);
}
#ifndef CONFIG_DM_ETH
@@ -2699,7 +2671,7 @@ int usb_ether_init(void)
struct udevice *usb_dev;
int ret;
- ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &usb_dev);
+ ret = uclass_first_device(UCLASS_USB_GADGET_GENERIC, &usb_dev);
if (!usb_dev || ret) {
pr_err("No USB device found\n");
return ret;
diff --git a/drivers/usb/gadget/udc/Makefile b/drivers/usb/gadget/udc/Makefile
index 449339f2c44..38ac2dd475e 100644
--- a/drivers/usb/gadget/udc/Makefile
+++ b/drivers/usb/gadget/udc/Makefile
@@ -2,4 +2,8 @@
#
# USB peripheral controller drivers
+ifndef CONFIG_$(SPL_)DM_USB_GADGET
obj-$(CONFIG_USB_DWC3_GADGET) += udc-core.o
+endif
+
+obj-$(CONFIG_$(SPL_)DM_USB_GADGET) += udc-uclass.o udc-core.o
diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c
index f5c30dd7507..62b47781ddc 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -18,7 +18,8 @@
#include <asm/cache.h>
#include <asm/dma-mapping.h>
#include <common.h>
-
+#include <dm.h>
+#include <dm/device-internal.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
diff --git a/drivers/usb/gadget/udc/udc-uclass.c b/drivers/usb/gadget/udc/udc-uclass.c
new file mode 100644
index 00000000000..062051857a9
--- /dev/null
+++ b/drivers/usb/gadget/udc/udc-uclass.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com
+ * Written by Jean-Jacques Hiblot <jjhiblot@ti.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <linux/usb/gadget.h>
+
+#define MAX_UDC_DEVICES 4
+static struct udevice *dev_array[MAX_UDC_DEVICES];
+int usb_gadget_initialize(int index)
+{
+ int ret;
+ struct udevice *dev = NULL;
+
+ if (index < 0 || index >= ARRAY_SIZE(dev_array))
+ return -EINVAL;
+ if (dev_array[index])
+ return 0;
+ ret = uclass_get_device(UCLASS_USB_GADGET_GENERIC, index, &dev);
+ if (!dev || ret) {
+ pr_err("No USB device found\n");
+ return -ENODEV;
+ }
+ dev_array[index] = dev;
+ return 0;
+}
+
+int usb_gadget_release(int index)
+{
+#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
+ int ret;
+ if (index < 0 || index >= ARRAY_SIZE(dev_array))
+ return -EINVAL;
+
+ ret = device_remove(dev_array[index], DM_REMOVE_NORMAL);
+ if (!ret)
+ dev_array[index] = NULL;
+ return ret;
+#else
+ return -ENOTSUPP;
+#endif
+}
+
+int usb_gadget_handle_interrupts(int index)
+{
+ if (index < 0 || index >= ARRAY_SIZE(dev_array))
+ return -EINVAL;
+ return dm_usb_gadget_handle_interrupts(dev_array[index]);
+}
+
+UCLASS_DRIVER(usb_gadget_generic) = {
+ .id = UCLASS_USB_GADGET_GENERIC,
+ .name = "usb_gadget_generic",
+};
diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c
index dd0d156027e..83b9f119e71 100644
--- a/drivers/usb/host/xhci-dwc3.c
+++ b/drivers/usb/host/xhci-dwc3.c
@@ -12,6 +12,7 @@
#include <fdtdec.h>
#include <generic-phy.h>
#include <usb.h>
+#include <dwc3-uboot.h>
#include "xhci.h"
#include <asm/io.h>
@@ -110,105 +111,21 @@ void dwc3_set_fladj(struct dwc3 *dwc3_reg, u32 val)
}
#if CONFIG_IS_ENABLED(DM_USB)
-static int xhci_dwc3_setup_phy(struct udevice *dev)
-{
- struct xhci_dwc3_platdata *plat = dev_get_platdata(dev);
- int i, ret, count;
-
- /* Return if no phy declared */
- if (!dev_read_prop(dev, "phys", NULL))
- return 0;
-
- count = dev_count_phandle_with_args(dev, "phys", "#phy-cells");
- if (count <= 0)
- return count;
-
- plat->usb_phys = devm_kcalloc(dev, count, sizeof(struct phy),
- GFP_KERNEL);
- if (!plat->usb_phys)
- return -ENOMEM;
-
- for (i = 0; i < count; i++) {
- ret = generic_phy_get_by_index(dev, i, &plat->usb_phys[i]);
- if (ret && ret != -ENOENT) {
- pr_err("Failed to get USB PHY%d for %s\n",
- i, dev->name);
- return ret;
- }
-
- ++plat->num_phys;
- }
-
- for (i = 0; i < plat->num_phys; i++) {
- ret = generic_phy_init(&plat->usb_phys[i]);
- if (ret) {
- pr_err("Can't init USB PHY%d for %s\n",
- i, dev->name);
- goto phys_init_err;
- }
- }
-
- for (i = 0; i < plat->num_phys; i++) {
- ret = generic_phy_power_on(&plat->usb_phys[i]);
- if (ret) {
- pr_err("Can't power USB PHY%d for %s\n",
- i, dev->name);
- goto phys_poweron_err;
- }
- }
-
- return 0;
-
-phys_poweron_err:
- for (; i >= 0; i--)
- generic_phy_power_off(&plat->usb_phys[i]);
-
- for (i = 0; i < plat->num_phys; i++)
- generic_phy_exit(&plat->usb_phys[i]);
-
- return ret;
-
-phys_init_err:
- for (; i >= 0; i--)
- generic_phy_exit(&plat->usb_phys[i]);
-
- return ret;
-}
-
-static int xhci_dwc3_shutdown_phy(struct udevice *dev)
-{
- struct xhci_dwc3_platdata *plat = dev_get_platdata(dev);
- int i, ret;
-
- for (i = 0; i < plat->num_phys; i++) {
- if (!generic_phy_valid(&plat->usb_phys[i]))
- continue;
-
- ret = generic_phy_power_off(&plat->usb_phys[i]);
- ret |= generic_phy_exit(&plat->usb_phys[i]);
- if (ret) {
- pr_err("Can't shutdown USB PHY%d for %s\n",
- i, dev->name);
- }
- }
-
- return 0;
-}
-
static int xhci_dwc3_probe(struct udevice *dev)
{
struct xhci_hcor *hcor;
struct xhci_hccr *hccr;
struct dwc3 *dwc3_reg;
enum usb_dr_mode dr_mode;
+ struct xhci_dwc3_platdata *plat = dev_get_platdata(dev);
int ret;
hccr = (struct xhci_hccr *)((uintptr_t)dev_read_addr(dev));
hcor = (struct xhci_hcor *)((uintptr_t)hccr +
HC_LENGTH(xhci_readl(&(hccr)->cr_capbase)));
- ret = xhci_dwc3_setup_phy(dev);
- if (ret)
+ ret = dwc3_setup_phy(dev, &plat->usb_phys, &plat->num_phys);
+ if (ret && (ret != -ENOTSUPP))
return ret;
dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET);
@@ -227,7 +144,9 @@ static int xhci_dwc3_probe(struct udevice *dev)
static int xhci_dwc3_remove(struct udevice *dev)
{
- xhci_dwc3_shutdown_phy(dev);
+ struct xhci_dwc3_platdata *plat = dev_get_platdata(dev);
+
+ dwc3_shutdown_phy(dev, plat->usb_phys, plat->num_phys);
return xhci_deregister(dev);
}
diff --git a/drivers/usb/musb-new/omap2430.c b/drivers/usb/musb-new/omap2430.c
index 58aed72b7d3..32743aa72c5 100644
--- a/drivers/usb/musb-new/omap2430.c
+++ b/drivers/usb/musb-new/omap2430.c
@@ -263,7 +263,7 @@ U_BOOT_DRIVER(omap2430_musb) = {
#ifdef CONFIG_USB_MUSB_HOST
.id = UCLASS_USB,
#else
- .id = UCLASS_USB_DEV_GENERIC,
+ .id = UCLASS_USB_GADGET_GENERIC,
#endif
.of_match = omap2430_musb_ids,
.ofdata_to_platdata = omap2430_musb_ofdata_to_platdata,
diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c
index 6cf9826cda1..d7170a3078c 100644
--- a/drivers/usb/musb-new/sunxi.c
+++ b/drivers/usb/musb-new/sunxi.c
@@ -535,7 +535,7 @@ U_BOOT_DRIVER(usb_musb) = {
#ifdef CONFIG_USB_MUSB_HOST
.id = UCLASS_USB,
#else
- .id = UCLASS_USB_DEV_GENERIC,
+ .id = UCLASS_USB_GADGET_GENERIC,
#endif
.of_match = sunxi_musb_ids,
.probe = musb_usb_probe,