aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/dwc3/dwc3-generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/dwc3/dwc3-generic.c')
-rw-r--r--drivers/usb/dwc3/dwc3-generic.c146
1 files changed, 113 insertions, 33 deletions
diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c
index 406bf0b..023e953 100644
--- a/drivers/usb/dwc3/dwc3-generic.c
+++ b/drivers/usb/dwc3/dwc3-generic.c
@@ -21,51 +21,60 @@
#include "gadget.h"
#include <reset.h>
#include <clk.h>
+#include <usb/xhci.h>
-#if CONFIG_IS_ENABLED(DM_USB_GADGET)
-struct dwc3_generic_peripheral {
+struct dwc3_generic_plat {
+ fdt_addr_t base;
+ u32 maximum_speed;
+ enum usb_dr_mode dr_mode;
+};
+
+struct dwc3_generic_priv {
+ void *base;
struct dwc3 dwc3;
struct phy *phys;
int num_phys;
- fdt_addr_t base;
};
-int dm_usb_gadget_handle_interrupts(struct udevice *dev)
-{
- struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
- struct dwc3 *dwc3 = &priv->dwc3;
-
- dwc3_gadget_uboot_handle_interrupt(dwc3);
-
- return 0;
-}
+struct dwc3_generic_host_priv {
+ struct xhci_ctrl xhci_ctrl;
+ struct dwc3_generic_priv gen_priv;
+};
-static int dwc3_generic_peripheral_probe(struct udevice *dev)
+static int dwc3_generic_probe(struct udevice *dev,
+ struct dwc3_generic_priv *priv)
{
int rc;
- struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
+ struct dwc3_generic_plat *plat = dev_get_platdata(dev);
struct dwc3 *dwc3 = &priv->dwc3;
+ dwc3->dev = dev;
+ dwc3->maximum_speed = plat->maximum_speed;
+ dwc3->dr_mode = plat->dr_mode;
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+ dwc3_of_parse(dwc3);
+#endif
+
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;
+ priv->base = map_physmem(plat->base, DWC3_OTG_REGS_END, MAP_NOCACHE);
+ dwc3->regs = priv->base + DWC3_GLOBALS_REGS_START;
+
rc = dwc3_init(dwc3);
if (rc) {
- unmap_physmem(dwc3->regs, MAP_NOCACHE);
+ unmap_physmem(priv->base, MAP_NOCACHE);
return rc;
}
return 0;
}
-static int dwc3_generic_peripheral_remove(struct udevice *dev)
+static int dwc3_generic_remove(struct udevice *dev,
+ struct dwc3_generic_priv *priv)
{
- struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
struct dwc3 *dwc3 = &priv->dwc3;
dwc3_remove(dwc3);
@@ -75,22 +84,21 @@ static int dwc3_generic_peripheral_remove(struct udevice *dev)
return 0;
}
-static int dwc3_generic_peripheral_ofdata_to_platdata(struct udevice *dev)
+static int dwc3_generic_ofdata_to_platdata(struct udevice *dev)
{
- struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
- struct dwc3 *dwc3 = &priv->dwc3;
+ struct dwc3_generic_plat *plat = dev_get_platdata(dev);
int node = dev_of_offset(dev);
- priv->base = devfdt_get_addr(dev);
+ plat->base = devfdt_get_addr(dev);
- dwc3->maximum_speed = usb_get_maximum_speed(node);
- if (dwc3->maximum_speed == USB_SPEED_UNKNOWN) {
- pr_err("Invalid usb maximum speed\n");
- return -ENODEV;
+ plat->maximum_speed = usb_get_maximum_speed(node);
+ if (plat->maximum_speed == USB_SPEED_UNKNOWN) {
+ pr_info("No USB maximum speed specified. Using super speed\n");
+ plat->maximum_speed = USB_SPEED_SUPER;
}
- dwc3->dr_mode = usb_get_dr_mode(node);
- if (dwc3->dr_mode == USB_DR_MODE_UNKNOWN) {
+ plat->dr_mode = usb_get_dr_mode(node);
+ if (plat->dr_mode == USB_DR_MODE_UNKNOWN) {
pr_err("Invalid usb mode setup\n");
return -ENODEV;
}
@@ -98,13 +106,83 @@ static int dwc3_generic_peripheral_ofdata_to_platdata(struct udevice *dev)
return 0;
}
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+int dm_usb_gadget_handle_interrupts(struct udevice *dev)
+{
+ struct dwc3_generic_priv *priv = dev_get_priv(dev);
+ struct dwc3 *dwc3 = &priv->dwc3;
+
+ dwc3_gadget_uboot_handle_interrupt(dwc3);
+
+ return 0;
+}
+
+static int dwc3_generic_peripheral_probe(struct udevice *dev)
+{
+ struct dwc3_generic_priv *priv = dev_get_priv(dev);
+
+ return dwc3_generic_probe(dev, priv);
+}
+
+static int dwc3_generic_peripheral_remove(struct udevice *dev)
+{
+ struct dwc3_generic_priv *priv = dev_get_priv(dev);
+
+ return dwc3_generic_remove(dev, priv);
+}
+
U_BOOT_DRIVER(dwc3_generic_peripheral) = {
.name = "dwc3-generic-peripheral",
.id = UCLASS_USB_GADGET_GENERIC,
- .ofdata_to_platdata = dwc3_generic_peripheral_ofdata_to_platdata,
+ .ofdata_to_platdata = dwc3_generic_ofdata_to_platdata,
.probe = dwc3_generic_peripheral_probe,
.remove = dwc3_generic_peripheral_remove,
- .priv_auto_alloc_size = sizeof(struct dwc3_generic_peripheral),
+ .priv_auto_alloc_size = sizeof(struct dwc3_generic_priv),
+ .platdata_auto_alloc_size = sizeof(struct dwc3_generic_plat),
+};
+#endif
+
+#if defined(CONFIG_SPL_USB_HOST_SUPPORT) || !defined(CONFIG_SPL_BUILD)
+static int dwc3_generic_host_probe(struct udevice *dev)
+{
+ struct xhci_hcor *hcor;
+ struct xhci_hccr *hccr;
+ struct dwc3_generic_host_priv *priv = dev_get_priv(dev);
+ int rc;
+
+ rc = dwc3_generic_probe(dev, &priv->gen_priv);
+ if (rc)
+ return rc;
+
+ hccr = (struct xhci_hccr *)priv->gen_priv.base;
+ hcor = (struct xhci_hcor *)(priv->gen_priv.base +
+ HC_LENGTH(xhci_readl(&(hccr)->cr_capbase)));
+
+ return xhci_register(dev, hccr, hcor);
+}
+
+static int dwc3_generic_host_remove(struct udevice *dev)
+{
+ struct dwc3_generic_host_priv *priv = dev_get_priv(dev);
+ int rc;
+
+ rc = xhci_deregister(dev);
+ if (rc)
+ return rc;
+
+ return dwc3_generic_remove(dev, &priv->gen_priv);
+}
+
+U_BOOT_DRIVER(dwc3_generic_host) = {
+ .name = "dwc3-generic-host",
+ .id = UCLASS_USB,
+ .ofdata_to_platdata = dwc3_generic_ofdata_to_platdata,
+ .probe = dwc3_generic_host_probe,
+ .remove = dwc3_generic_host_remove,
+ .priv_auto_alloc_size = sizeof(struct dwc3_generic_host_priv),
+ .platdata_auto_alloc_size = sizeof(struct dwc3_generic_plat),
+ .ops = &xhci_usb_ops,
+ .flags = DM_FLAG_ALLOC_PRIV_DMA,
};
#endif
@@ -228,10 +306,12 @@ static int dwc3_glue_bind(struct udevice *parent)
driver = "dwc3-generic-peripheral";
#endif
break;
+#if defined(CONFIG_SPL_USB_HOST_SUPPORT) || !defined(CONFIG_SPL_BUILD)
case USB_DR_MODE_HOST:
debug("%s: dr_mode: HOST\n", __func__);
- driver = "xhci-dwc3";
+ driver = "dwc3-generic-host";
break;
+#endif
default:
debug("%s: unsupported dr_mode\n", __func__);
return -ENODEV;