--- /dev/null
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 NXP
+ */
+
+#include <common.h>
+#include <asm-generic/io.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <linux/usb/gadget.h>
+#include <malloc.h>
+#include <usb.h>
+#include "core.h"
+#include "gadget.h"
+#include <clk.h>
+#include <power-domain.h>
+
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+
+static int cdns3_setup_phy(struct udevice *dev,
+ struct cdns3_generic_peripheral *priv)
+{
+ int ret = 0;
+
+#if CONFIG_IS_ENABLED(POWER_DOMAIN)
+ struct udevice phy_dev;
+ int phy_off;
+
+ phy_off = fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(dev),
+ "cdns3,usbphy");
+ if (phy_off < 0)
+ return -EINVAL;
+
+ phy_dev.node = offset_to_ofnode(phy_off);
+
+ if (!power_domain_get(&phy_dev, &priv->phy_pd)) {
+ if (power_domain_on(&priv->phy_pd))
+ return -EINVAL;
+ }
+#endif
+
+#if CONFIG_IS_ENABLED(CLK)
+ ret = clk_get_by_name(&phy_dev, "main_clk", &priv->phy_clk);
+ if (ret) {
+ printf("Failed to get phy_clk\n");
+ return ret;
+ }
+ ret = clk_enable(&priv->phy_clk);
+ if (ret) {
+ printf("Failed to enable phy_clk\n");
+ return ret;
+ }
+#endif
+ return ret;
+}
+
+static int cdns3_shutdown_phy(struct udevice *dev,
+ struct cdns3_generic_peripheral *priv)
+{
+ int ret;
+
+#if CONFIG_IS_ENABLED(CLK)
+ if (priv->phy_clk.dev) {
+ ret = clk_disable(&priv->phy_clk);
+ if (ret)
+ return ret;
+
+ ret = clk_free(&priv->phy_clk);
+ if (ret)
+ return ret;
+ }
+#endif
+
+ ret = power_domain_off(&priv->phy_pd);
+ if (ret)
+ printf("conn_usb2_phy Power down failed! (error = %d)\n", ret);
+
+ return ret;
+}
+
+static int cdns3_generic_peripheral_clk_init(struct udevice *dev,
+ struct cdns3_generic_peripheral
+ *priv)
+{
+ int ret;
+
+ ret = clk_get_bulk(dev, &priv->clks);
+ if (ret)
+ return ret;
+
+#if CONFIG_IS_ENABLED(CLK)
+ ret = clk_enable_bulk(&priv->clks);
+ if (ret) {
+ clk_release_bulk(&priv->clks);
+ return ret;
+ }
+#endif
+
+ return 0;
+}
+
+int dm_usb_gadget_handle_interrupts(struct udevice *dev)
+{
+ struct cdns3_generic_peripheral *priv = dev_get_priv(dev);
+ struct cdns3 *cdns3 = &priv->cdns3;
+
+ cdns3_role_irq_handler(cdns3);
+
+ return 0;
+}
+
+static int cdns3_generic_peripheral_probe(struct udevice *dev)
+{
+ int ret;
+ struct cdns3_generic_peripheral *priv = dev_get_priv(dev);
+ struct cdns3 *cdns3 = &priv->cdns3;
+
+ cdns3->dev = dev;
+
+ cdns3_setup_phy(dev, priv);
+ ret = cdns3_generic_peripheral_clk_init(dev, priv);
+ if (ret)
+ return ret;
+
+ ret = board_usb_init(dev->seq, USB_INIT_DEVICE);
+ ret = cdns3_init(cdns3);
+ printf("cdns3_uboot_initmode %d\n", ret);
+
+ return 0;
+}
+
+static int cdns3_generic_peripheral_remove(struct udevice *dev)
+{
+ struct cdns3_generic_peripheral *priv = dev_get_priv(dev);
+ struct cdns3 *cdns3 = &priv->cdns3;
+ struct power_domain pd;
+ int ret = 0;
+
+ cdns3_exit(cdns3);
+
+ clk_release_bulk(&priv->clks);
+ cdns3_shutdown_phy(dev, priv);
+
+ if (!power_domain_get(dev, &pd)) {
+ ret = power_domain_off(&pd);
+ if (ret)
+ printf("conn_usb2 power down failed!(error = %d)\n",
+ ret);
+ }
+
+ return ret;
+}
+
+static int cdns3_generic_peripheral_ofdata_to_platdata(struct udevice *dev)
+{
+ struct cdns3_generic_peripheral *priv = dev_get_priv(dev);
+ struct cdns3 *cdns3 = &priv->cdns3;
+
+ cdns3->none_core_regs = (void __iomem *)devfdt_get_addr_index(dev, 0);
+ cdns3->xhci_regs = (void __iomem *)devfdt_get_addr_index(dev, 1);
+ cdns3->dev_regs = (void __iomem *)devfdt_get_addr_index(dev, 2);
+ cdns3->phy_regs = (void __iomem *)devfdt_get_addr_index(dev, 3);
+ cdns3->otg_regs = (void __iomem *)devfdt_get_addr_index(dev, 4);
+
+ return 0;
+}
+
+static const struct udevice_id cdns3_generic_peripheral_ids[] = {
+ { .compatible = "Cadence,usb3" },
+ {},
+};
+
+U_BOOT_DRIVER(cdns3_generic_peripheral) = {
+ .name = "cdns3-generic-peripheral",
+ .id = UCLASS_USB_GADGET_GENERIC,
+ .of_match = cdns3_generic_peripheral_ids,
+ .ofdata_to_platdata = cdns3_generic_peripheral_ofdata_to_platdata,
+ .probe = cdns3_generic_peripheral_probe,
+ .remove = cdns3_generic_peripheral_remove,
+ .priv_auto_alloc_size = sizeof(struct cdns3_generic_peripheral),
+};
+#endif
+
cdns3_gadget_remove(cdns);
}
+#if !CONFIG_IS_ENABLED(DM_USB_GADGET)
int cdns3_uboot_init(struct cdns3_device *cdns3_dev)
{
struct device *dev = NULL;
break;
}
}
+
+#else
+int cdns3_init(struct cdns3 *cdns)
+{
+ int ret;
+
+ ret = cdns3_core_init_role(cdns, USB_DR_MODE_PERIPHERAL);
+
+ cdns->role = cdns3_get_role(cdns);
+ dev_dbg(dev, "the init role is %d\n", cdns->role);
+ cdns3_set_role(cdns, cdns->role);
+ ret = cdns3_role_start(cdns, cdns->role);
+ if (ret) {
+ dev_err(dev, "can't start %s role\n", cdns3_role(cdns)->name);
+ goto err;
+ }
+
+ dev_dbg(dev, "Cadence USB3 core: probe succeed\n");
+
+ return 0;
+
+err:
+ cdns3_remove_roles(cdns);
+
+ return ret;
+}
+
+void cdns3_exit(struct cdns3 *cdns)
+{
+ cdns3_role_stop(cdns);
+ cdns3_remove_roles(cdns);
+ cdns3_reset_core(cdns);
+}
+#endif
#include <linux/usb/gadget.h>
#include <linux/usb/composite.h>
+#if !CONFIG_IS_ENABLED(DM_USB_GADGET)
#include "linux-compat.h"
+#endif
+
#include "core.h"
#include "gadget-export.h"
#include "gadget.h"
return 0;
}
+#if !CONFIG_IS_ENABLED(DM_USB_GADGET)
static void cdns3_gadget_release(struct device *dev)
{
struct usb_ss_dev *usb_ss = container_of(dev, struct usb_ss_dev, dev);
kfree(usb_ss);
}
+#endif
static int __cdns3_gadget_init(struct cdns3 *cdns)
{
struct usb_ss_dev *usb_ss;
int ret;
- struct device *dev;
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+ struct udevice *dev;
+ struct cdns3_generic_peripheral *priv = container_of(cdns,
+ struct cdns3_generic_peripheral, cdns3);
+ usb_ss = &priv->usb_ss_dev;
+ dev = &usb_ss->dev;
+ dev->parent = cdns->dev;
+ dev_set_name(dev, "gadget-cdns3-dev");
+ cdns->gadget_dev = dev;
+ usb_ss->sysdev = cdns->dev;
+#else
+ struct device *dev;
usb_ss = kzalloc(sizeof(*usb_ss), GFP_KERNEL);
if (!usb_ss)
return -ENOMEM;
dev_set_name(dev, "gadget-cdns3-dev");
cdns->gadget_dev = dev;
usb_ss->sysdev = cdns->dev;
+#endif
ret = device_register(dev);
if (ret)
goto err1;
}
/* add USB gadget device */
- ret = usb_add_gadget_udc(&usb_ss->dev, &usb_ss->gadget);
+ ret = usb_add_gadget_udc((struct device *)(&usb_ss->dev),
+ &usb_ss->gadget);
if (ret < 0) {
dev_err(dev, "Failed to register USB device controller\n");
goto err4;
#include "cdns_misc.h"
#endif
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+#include <dm.h>
+#include <clk.h>
+#include <power-domain.h>
+#endif
+
#define gadget_to_usb_ss(g) \
(container_of(g, struct usb_ss_dev, gadget))
};
struct usb_ss_dev {
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+ struct udevice dev;
+#else
struct device dev;
+#endif
struct usbss_dev_register_block_type __iomem *regs;
struct usb_gadget gadget;
u32 usb_ien;
u32 ep_ien;
int setup_pending;
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+ struct udevice *sysdev;
+#else
struct device *sysdev;
+#endif
bool start_gadget; /* The device mode is enabled */
struct list_head ep_match_list;
};
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+struct cdns3_generic_peripheral {
+ struct cdns3 cdns3;
+ struct usb_ss_dev usb_ss_dev;
+ struct clk_bulk clks;
+ struct power_domain phy_pd;
+ struct clk phy_clk;
+};
+#endif
+
#define OTG_STS_SELECTOR 0xF000 /* OTG status selector */
#endif /* __DRIVERS_CDNS3_GADGET */