*/
#include <common.h>
+#include <cpu_func.h>
+#include <log.h>
#include <asm-generic/io.h>
#include <dm.h>
#include <dm/device-internal.h>
#include <dm/lists.h>
#include <dwc3-uboot.h>
+#include <linux/bitops.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <malloc.h>
#include "gadget.h"
#include <reset.h>
#include <clk.h>
+#include <usb/xhci.h>
struct dwc3_generic_plat {
fdt_addr_t base;
struct dwc3_generic_priv {
void *base;
struct dwc3 dwc3;
- struct phy *phys;
- int num_phys;
+ struct phy_bulk phys;
+};
+
+struct dwc3_generic_host_priv {
+ struct xhci_ctrl xhci_ctrl;
+ struct dwc3_generic_priv gen_priv;
};
static int dwc3_generic_probe(struct udevice *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);
+ rc = dwc3_setup_phy(dev, &priv->phys);
if (rc)
return rc;
priv->base = map_physmem(plat->base, DWC3_OTG_REGS_END, MAP_NOCACHE);
dwc3->regs = priv->base + DWC3_GLOBALS_REGS_START;
- dwc3->dev = dev;
+
rc = dwc3_init(dwc3);
if (rc) {
struct dwc3 *dwc3 = &priv->dwc3;
dwc3_remove(dwc3);
- dwc3_shutdown_phy(dev, priv->phys, priv->num_phys);
+ dwc3_shutdown_phy(dev, &priv->phys);
unmap_physmem(dwc3->regs, MAP_NOCACHE);
return 0;
static int dwc3_generic_ofdata_to_platdata(struct udevice *dev)
{
struct dwc3_generic_plat *plat = dev_get_platdata(dev);
- int node = dev_of_offset(dev);
+ ofnode node = dev->node;
- plat->base = devfdt_get_addr(dev);
+ plat->base = dev_read_addr(dev);
plat->maximum_speed = usb_get_maximum_speed(node);
if (plat->maximum_speed == USB_SPEED_UNKNOWN) {
- pr_err("Invalid usb maximum speed\n");
- return -ENODEV;
+ pr_info("No USB maximum speed specified. Using super speed\n");
+ plat->maximum_speed = USB_SPEED_SUPER;
}
plat->dr_mode = usb_get_dr_mode(node);
};
#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
+
struct dwc3_glue_data {
struct clk_bulk clks;
struct reset_ctl_bulk resets;
static int dwc3_glue_bind(struct udevice *parent)
{
- const void *fdt = gd->fdt_blob;
- int node;
+ ofnode node;
int ret;
- for (node = fdt_first_subnode(fdt, dev_of_offset(parent)); node > 0;
- node = fdt_next_subnode(fdt, node)) {
- const char *name = fdt_get_name(fdt, node, NULL);
+ ofnode_for_each_subnode(node, parent->node) {
+ const char *name = ofnode_get_name(node);
enum usb_dr_mode dr_mode;
struct udevice *dev;
const char *driver = NULL;
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;
continue;
ret = device_bind_driver_to_node(parent, driver, name,
- offset_to_ofnode(node), &dev);
+ node, &dev);
if (ret) {
debug("%s: not able to bind usb device mode\n",
__func__);
int ret;
ret = reset_get_bulk(dev, &glue->resets);
- if (ret == -ENOTSUPP)
+ if (ret == -ENOTSUPP || ret == -ENOENT)
return 0;
else if (ret)
return ret;
int ret;
ret = clk_get_bulk(dev, &glue->clks);
- if (ret == -ENOSYS)
+ if (ret == -ENOSYS || ret == -ENOENT)
return 0;
if (ret)
return ret;
while (child) {
enum usb_dr_mode dr_mode;
- dr_mode = usb_get_dr_mode(dev_of_offset(child));
+ dr_mode = usb_get_dr_mode(child->node);
device_find_next_child(&child);
if (ops && ops->select_dr_mode)
ops->select_dr_mode(dev, index, dr_mode);
static const struct udevice_id dwc3_glue_ids[] = {
{ .compatible = "xlnx,zynqmp-dwc3" },
+ { .compatible = "xlnx,versal-dwc3" },
{ .compatible = "ti,keystone-dwc3"},
{ .compatible = "ti,dwc3", .data = (ulong)&ti_ops },
{ .compatible = "ti,am437x-dwc3", .data = (ulong)&ti_ops },
+ { .compatible = "ti,am654-dwc3" },
{ }
};