From: zhangsenchuan@eswincomputing.com
To: gregkh@linuxfoundation.org, robh@kernel.org, krzk+dt@kernel.org,
conor+dt@kernel.org, linux-usb@vger.kernel.org,
linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
Thinh.Nguyen@synopsys.com, p.zabel@pengutronix.de
Cc: ningyu@eswincomputing.com, linmin@eswincomputing.com,
yangwei1@eswincomputing.com,
Senchuan Zhang <zhangsenchuan@eswincomputing.com>
Subject: [PATCH v1 2/2] usb: dwc3: eic7700: Add EIC7700 usb driver
Date: Fri, 16 May 2025 17:54:07 +0800 [thread overview]
Message-ID: <20250516095408.704-1-zhangsenchuan@eswincomputing.com> (raw)
In-Reply-To: <20250516095237.1516-1-zhangsenchuan@eswincomputing.com>
From: Senchuan Zhang <zhangsenchuan@eswincomputing.com>
Add the eic7700 usb driver, which is responsible for
identifying,configuring and connecting usb devices,and
provides interfaces for accessing these devices.
Co-developed-by: Wei Yang <yangwei1@eswincomputing.com>
Signed-off-by: Wei Yang <yangwei1@eswincomputing.com>
Signed-off-by: Senchuan Zhang <zhangsenchuan@eswincomputing.com>
---
drivers/usb/dwc3/Kconfig | 11 +
drivers/usb/dwc3/Makefile | 1 +
drivers/usb/dwc3/dwc3-eic7700.c | 605 ++++++++++++++++++++++++++++++++
3 files changed, 617 insertions(+)
create mode 100644 drivers/usb/dwc3/dwc3-eic7700.c
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 310d182e10b5..19657cfb5d08 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -189,4 +189,15 @@ config USB_DWC3_RTK
or dual-role mode.
Say 'Y' or 'M' if you have such device.
+config USB_DWC3_EIC7700
+ tristate "Eswin Platforms"
+ depends on OF
+ depends on USB=y || USB=USB_DWC3
+ default USB_DWC3
+ help
+ The usb controller on eic7700 SoC.
+ support of USB2/3 functionality
+ in Eswin platforms.
+ say 'Y' or 'M' if you have one such device.
+
endif
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index 124eda2522d9..b1fc066dd92e 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -56,3 +56,4 @@ obj-$(CONFIG_USB_DWC3_IMX8MP) += dwc3-imx8mp.o
obj-$(CONFIG_USB_DWC3_XILINX) += dwc3-xilinx.o
obj-$(CONFIG_USB_DWC3_OCTEON) += dwc3-octeon.o
obj-$(CONFIG_USB_DWC3_RTK) += dwc3-rtk.o
+obj-$(CONFIG_USB_DWC3_EIC7700) += dwc3-eic7700.o
diff --git a/drivers/usb/dwc3/dwc3-eic7700.c b/drivers/usb/dwc3/dwc3-eic7700.c
new file mode 100644
index 000000000000..872c0374be0f
--- /dev/null
+++ b/drivers/usb/dwc3/dwc3-eic7700.c
@@ -0,0 +1,605 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Eswin Specific Glue layer
+ *
+ * Copyright 2024, Beijing ESWIN Computing Technology Co., Ltd.. All rights reserved.
+ *
+ * Authors: Wei Yang <yangwei1@eswincomputing.com>
+ * Senchuan Zhang <zhangsenchuan@eswincomputing.com>
+ */
+
+#include <linux/async.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
+#include <linux/extcon.h>
+#include <linux/freezer.h>
+#include <linux/iopoll.h>
+#include <linux/reset.h>
+#include <linux/usb.h>
+#include <linux/pm.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/ch9.h>
+#include <linux/extcon-provider.h>
+#include <linux/mfd/syscon.h>
+#include <linux/bitfield.h>
+#include <linux/regmap.h>
+#include <linux/gpio/consumer.h>
+#include "core.h"
+#include "io.h"
+
+#define HSP_USB_VBUS_FSEL 0x2a
+#define HSP_USB_MPLL_DEFAULT 0x0
+
+#define HSP_USB_BUS_FILTER_EN (0x1 << 0)
+#define HSP_USB_BUS_CLKEN_GM (0x1 << 9)
+#define HSP_USB_BUS_CLKEN_GS (0x1 << 16)
+#define HSP_USB_BUS_SW_RST (0x1 << 24)
+#define HSP_USB_BUS_CLK_EN (0x1 << 28)
+
+#define HSP_USB_AXI_LP_XM_CSYSREQ (0x1 << 0)
+#define HSP_USB_AXI_LP_XS_CSYSREQ (0x1 << 16)
+
+struct dwc3_eswin {
+ int num_clocks;
+ bool connected;
+ bool suspended;
+ bool force_mode;
+ bool is_phy_on;
+ struct device *dev;
+ struct clk **clks;
+ struct dwc3 *dwc;
+ struct extcon_dev *edev;
+ struct usb_hcd *hcd;
+ struct notifier_block device_nb;
+ struct notifier_block host_nb;
+ struct work_struct otg_work;
+ struct mutex lock;
+ struct reset_control *vaux_rst;
+ struct device *child_dev;
+ enum usb_role new_usb_role;
+ struct gpio_desc *hub_gpio;
+};
+
+static ssize_t dwc3_mode_show(struct device *device,
+ struct device_attribute *attr, char *buf)
+{
+ struct dwc3_eswin *eswin = dev_get_drvdata(device);
+ struct dwc3 *dwc = eswin->dwc;
+ int ret;
+
+ switch (dwc->current_dr_role) {
+ case USB_DR_MODE_HOST:
+ ret = sprintf(buf, "host\n");
+ break;
+ case USB_DR_MODE_PERIPHERAL:
+ ret = sprintf(buf, "peripheral\n");
+ break;
+ case USB_DR_MODE_OTG:
+ ret = sprintf(buf, "otg\n");
+ break;
+ default:
+ ret = sprintf(buf, "UNKNOWN\n");
+ }
+
+ return ret;
+}
+
+static ssize_t dwc3_mode_store(struct device *device,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct dwc3_eswin *eswin = dev_get_drvdata(device);
+ struct dwc3 *dwc = eswin->dwc;
+ enum usb_role new_role;
+ struct usb_role_switch *role_sw = dwc->role_sw;
+
+ if (!strncmp(buf, "1", 1) || !strncmp(buf, "host", 4)) {
+ new_role = USB_ROLE_HOST;
+ } else if (!strncmp(buf, "0", 1) || !strncmp(buf, "peripheral", 10)) {
+ new_role = USB_ROLE_DEVICE;
+ } else {
+ dev_info(eswin->dev, "illegal dr_mode\n");
+ return count;
+ }
+ eswin->force_mode = true;
+
+ mutex_lock(&eswin->lock);
+ usb_role_switch_set_role(role_sw, new_role);
+ mutex_unlock(&eswin->lock);
+
+ return count;
+}
+
+static DEVICE_ATTR_RW(dwc3_mode);
+
+static ssize_t dwc3_hub_rst_show(struct device *device,
+ struct device_attribute *attr, char *buf)
+{
+ struct dwc3_eswin *eswin = dev_get_drvdata(device);
+
+ if (!IS_ERR(eswin->hub_gpio))
+ return sprintf(buf, "%d", gpiod_get_raw_value(eswin->hub_gpio));
+
+ return sprintf(buf, "UNKONWN");
+}
+
+static ssize_t dwc3_hub_rst_store(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct dwc3_eswin *eswin = dev_get_drvdata(device);
+
+ if (!IS_ERR(eswin->hub_gpio)) {
+ if (!strncmp(buf, "0", 1))
+ gpiod_set_raw_value(eswin->hub_gpio, 0);
+ else
+ gpiod_set_raw_value(eswin->hub_gpio, 1);
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR_RW(dwc3_hub_rst);
+
+static struct attribute *dwc3_eswin_attrs[] = {
+ &dev_attr_dwc3_mode.attr,
+ &dev_attr_dwc3_hub_rst.attr,
+ NULL,
+};
+
+static struct attribute_group dwc3_eswin_attr_group = {
+ .name = NULL, /* we want them in the same directory */
+ .attrs = dwc3_eswin_attrs,
+};
+
+static int dwc3_eswin_device_notifier(struct notifier_block *nb,
+ unsigned long event, void *ptr)
+{
+ struct dwc3_eswin *eswin =
+ container_of(nb, struct dwc3_eswin, device_nb);
+
+ mutex_lock(&eswin->lock);
+ eswin->new_usb_role = USB_ROLE_DEVICE;
+ mutex_unlock(&eswin->lock);
+ if (!eswin->suspended)
+ schedule_work(&eswin->otg_work);
+
+ return NOTIFY_DONE;
+}
+
+static int dwc3_eswin_host_notifier(struct notifier_block *nb,
+ unsigned long event, void *ptr)
+{
+ struct dwc3_eswin *eswin = container_of(nb, struct dwc3_eswin, host_nb);
+
+ mutex_lock(&eswin->lock);
+ eswin->new_usb_role = USB_ROLE_HOST;
+ mutex_unlock(&eswin->lock);
+ if (!eswin->suspended)
+ schedule_work(&eswin->otg_work);
+
+ return NOTIFY_DONE;
+}
+
+static void dwc3_eswin_otg_extcon_evt_work(struct work_struct *work)
+{
+ struct dwc3_eswin *eswin =
+ container_of(work, struct dwc3_eswin, otg_work);
+ struct usb_role_switch *role_sw = eswin->dwc->role_sw;
+
+ if (true == eswin->force_mode)
+ return;
+ mutex_lock(&eswin->lock);
+ usb_role_switch_set_role(role_sw, eswin->new_usb_role);
+ mutex_unlock(&eswin->lock);
+}
+
+static int dwc3_eswin_get_extcon_dev(struct dwc3_eswin *eswin)
+{
+ struct device *dev = eswin->dev;
+ struct extcon_dev *edev;
+ s32 ret = 0;
+
+ if (device_property_read_bool(dev, "extcon")) {
+ edev = extcon_get_edev_by_phandle(dev, 0);
+ if (IS_ERR(edev)) {
+ if (PTR_ERR(edev) != -EPROBE_DEFER)
+ dev_err(dev, "couldn't get extcon device\n");
+ return PTR_ERR(edev);
+ }
+ eswin->edev = edev;
+ eswin->device_nb.notifier_call = dwc3_eswin_device_notifier;
+ ret = devm_extcon_register_notifier(dev, edev, EXTCON_USB,
+ &eswin->device_nb);
+ if (ret < 0)
+ dev_err(dev, "failed to register notifier for USB\n");
+
+ eswin->host_nb.notifier_call = dwc3_eswin_host_notifier;
+ ret = devm_extcon_register_notifier(dev, edev, EXTCON_USB_HOST,
+ &eswin->host_nb);
+ if (ret < 0)
+ dev_err(dev,
+ "failed to register notifier for USB-HOST\n");
+ }
+
+ return 0;
+}
+
+static int __init dwc3_eswin_deassert(struct dwc3_eswin *eswin)
+{
+ int rc;
+
+ if (eswin->vaux_rst) {
+ rc = reset_control_deassert(eswin->vaux_rst);
+ WARN_ON(rc != 0);
+ }
+
+ return 0;
+}
+
+static int dwc3_eswin_assert(struct dwc3_eswin *eswin)
+{
+ int rc = 0;
+
+ if (eswin->vaux_rst) {
+ rc = reset_control_assert(eswin->vaux_rst);
+ WARN_ON(rc != 0);
+ }
+
+ return 0;
+}
+
+static int dwc_usb_clk_init(struct device *dev)
+{
+ struct regmap *regmap;
+ u32 hsp_usb_bus;
+ u32 hsp_usb_axi_lp;
+ u32 hsp_usb_vbus_freq;
+ u32 hsp_usb_mpll;
+ int ret;
+
+ regmap = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "eswin,hsp_sp_csr");
+ if (IS_ERR(regmap)) {
+ dev_dbg(dev, "No hsp_sp_csr phandle specified\n");
+ return -1;
+ }
+ ret = of_property_read_u32_index(dev->of_node, "eswin,hsp_sp_csr", 1,
+ &hsp_usb_bus);
+ if (ret) {
+ dev_err(dev, "can't get usb sid cfg reg offset (%d)\n", ret);
+ return ret;
+ }
+ ret = of_property_read_u32_index(dev->of_node, "eswin,hsp_sp_csr", 2,
+ &hsp_usb_axi_lp);
+ if (ret) {
+ dev_err(dev, "can't get usb sid cfg reg offset (%d)\n", ret);
+ return ret;
+ }
+ ret = of_property_read_u32_index(dev->of_node, "eswin,hsp_sp_csr", 3,
+ &hsp_usb_vbus_freq);
+ if (ret) {
+ dev_err(dev, "can't get usb sid cfg reg offset (%d)\n", ret);
+ return ret;
+ }
+ ret = of_property_read_u32_index(dev->of_node, "eswin,hsp_sp_csr", 4,
+ &hsp_usb_mpll);
+ if (ret) {
+ dev_err(dev, "can't get usb sid cfg reg offset (%d)\n", ret);
+ return ret;
+ }
+
+ /*
+ * usb1 clock init
+ * ref clock is 24M, below need to be set to satisfy usb phy requirement(125M)
+ */
+ regmap_write(regmap, hsp_usb_vbus_freq, HSP_USB_VBUS_FSEL);
+ regmap_write(regmap, hsp_usb_mpll, HSP_USB_MPLL_DEFAULT);
+ /*
+ * reset usb core and usb phy
+ */
+ regmap_write(regmap, hsp_usb_bus,
+ HSP_USB_BUS_FILTER_EN | HSP_USB_BUS_CLKEN_GM |
+ HSP_USB_BUS_CLKEN_GS | HSP_USB_BUS_SW_RST |
+ HSP_USB_BUS_CLK_EN);
+ regmap_write(regmap, hsp_usb_axi_lp,
+ HSP_USB_AXI_LP_XM_CSYSREQ | HSP_USB_AXI_LP_XS_CSYSREQ);
+
+ return 0;
+}
+
+static int dwc3_eswin_probe(struct platform_device *pdev)
+{
+ struct dwc3_eswin *eswin;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node, *child;
+ struct platform_device *child_pdev;
+ unsigned int count;
+ int ret;
+ int i;
+ int err_desc = 0;
+
+ eswin = devm_kzalloc(dev, sizeof(*eswin), GFP_KERNEL);
+ if (!eswin)
+ return -ENOMEM;
+ eswin->hub_gpio = devm_gpiod_get(dev, "hub-rst", GPIOD_OUT_HIGH);
+ err_desc = IS_ERR(eswin->hub_gpio);
+
+ if (!err_desc)
+ gpiod_set_raw_value(eswin->hub_gpio, 1);
+
+ count = of_clk_get_parent_count(np);
+ if (!count)
+ return -ENOENT;
+
+ eswin->num_clocks = count;
+ eswin->force_mode = false;
+ eswin->clks = devm_kcalloc(dev, eswin->num_clocks, sizeof(struct clk *),
+ GFP_KERNEL);
+ if (!eswin->clks)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, eswin);
+
+ mutex_init(&eswin->lock);
+
+ eswin->dev = dev;
+
+ mutex_lock(&eswin->lock);
+
+ for (i = 0; i < eswin->num_clocks; i++) {
+ struct clk *clk;
+
+ clk = of_clk_get(np, i);
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ goto err0;
+ }
+ ret = clk_prepare_enable(clk);
+ if (ret < 0) {
+ clk_put(clk);
+ goto err0;
+ }
+
+ eswin->clks[i] = clk;
+ }
+
+ eswin->vaux_rst = devm_reset_control_get(dev, "vaux");
+ if (IS_ERR_OR_NULL(eswin->vaux_rst)) {
+ dev_err(dev, "Failed to asic0_rst handle\n");
+ return -EFAULT;
+ }
+
+ dwc3_eswin_deassert(eswin);
+ dwc_usb_clk_init(dev);
+
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+ ret = pm_runtime_get_sync(dev);
+ if (ret < 0) {
+ dev_err(dev, "get_sync failed with err %d\n", ret);
+ goto err1;
+ }
+
+ child = of_get_child_by_name(np, "dwc3");
+ if (!child) {
+ dev_err(dev, "failed to find dwc3 core node\n");
+ ret = -ENODEV;
+ goto err1;
+ }
+ /* Allocate and initialize the core */
+ ret = of_platform_populate(np, NULL, NULL, dev);
+ if (ret) {
+ dev_err(dev, "failed to create dwc3 core\n");
+ goto err1;
+ }
+
+ INIT_WORK(&eswin->otg_work, dwc3_eswin_otg_extcon_evt_work);
+ child_pdev = of_find_device_by_node(child);
+ if (!child_pdev) {
+ dev_err(dev, "failed to find dwc3 core device\n");
+ ret = -ENODEV;
+ goto err2;
+ }
+ eswin->dwc = platform_get_drvdata(child_pdev);
+ if (!eswin->dwc) {
+ dev_err(dev, "failed to get drvdata dwc3\n");
+ ret = -EPROBE_DEFER;
+ goto err2;
+ }
+ eswin->child_dev = &child_pdev->dev;
+ ret = dwc3_eswin_get_extcon_dev(eswin);
+ if (ret < 0)
+ dev_err(dev, "couldn't get extcon device: %d\n", ret);
+
+ mutex_unlock(&eswin->lock);
+ ret = sysfs_create_group(&dev->kobj, &dwc3_eswin_attr_group);
+ if (ret)
+ dev_err(dev, "failed to create sysfs group: %d\n", ret);
+
+ return ret;
+err2:
+ cancel_work_sync(&eswin->otg_work);
+ of_platform_depopulate(dev);
+
+err1:
+ pm_runtime_put_sync(dev);
+ pm_runtime_disable(dev);
+ dwc3_eswin_assert(eswin);
+err0:
+ for (i = 0; i < eswin->num_clocks && eswin->clks[i]; i++) {
+ if (!pm_runtime_status_suspended(dev))
+ clk_disable(eswin->clks[i]);
+ clk_unprepare(eswin->clks[i]);
+ clk_put(eswin->clks[i]);
+ }
+
+ mutex_unlock(&eswin->lock);
+
+ return ret;
+}
+
+static void dwc3_eswin_remove(struct platform_device *pdev)
+{
+ struct dwc3_eswin *eswin = platform_get_drvdata(pdev);
+ struct device *dev = &pdev->dev;
+ int i = 0;
+
+ cancel_work_sync(&eswin->otg_work);
+
+ sysfs_remove_group(&dev->kobj, &dwc3_eswin_attr_group);
+
+ /* Restore hcd state before unregistering xhci */
+ if (eswin->edev && !eswin->connected) {
+ struct usb_hcd *hcd = dev_get_drvdata(&eswin->dwc->xhci->dev);
+
+ pm_runtime_get_sync(dev);
+
+ /*
+ * The xhci code does not expect that HCDs have been removed.
+ * It will unconditionally call usb_remove_hcd() when the xhci
+ * driver is unloaded in of_platform_depopulate(). This results
+ * in a crash if the HCDs were already removed. To avoid this
+ * crash, add the HCDs here as dummy operation.
+ * This code should be removed after pm runtime support
+ * has been added to xhci.
+ */
+ if (hcd->state == HC_STATE_HALT) {
+ usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
+ usb_add_hcd(hcd->shared_hcd, hcd->irq, IRQF_SHARED);
+ }
+ }
+
+ of_platform_depopulate(dev);
+
+ pm_runtime_put_sync(dev);
+ pm_runtime_disable(dev);
+
+ dwc3_eswin_assert(eswin);
+ for (i = 0; i < eswin->num_clocks; i++) {
+ if (!pm_runtime_status_suspended(dev))
+ clk_disable(eswin->clks[i]);
+ clk_unprepare(eswin->clks[i]);
+ clk_put(eswin->clks[i]);
+ }
+}
+
+#ifdef CONFIG_PM
+static int dwc3_eswin_runtime_suspend(struct device *dev)
+{
+ struct dwc3_eswin *eswin = dev_get_drvdata(dev);
+ int i;
+
+ for (i = 0; i < eswin->num_clocks; i++)
+ clk_disable(eswin->clks[i]);
+
+ device_init_wakeup(dev, false);
+
+ return 0;
+}
+
+static int dwc3_eswin_runtime_resume(struct device *dev)
+{
+ struct dwc3_eswin *eswin = dev_get_drvdata(dev);
+ int i;
+
+ for (i = 0; i < eswin->num_clocks; i++)
+ clk_enable(eswin->clks[i]);
+
+ device_init_wakeup(dev, true);
+
+ return 0;
+}
+
+static int __maybe_unused dwc3_eswin_suspend(struct device *dev)
+{
+ struct dwc3_eswin *eswin = dev_get_drvdata(dev);
+ struct dwc3 *dwc = eswin->dwc;
+
+ eswin->suspended = true;
+ cancel_work_sync(&eswin->otg_work);
+
+ /*
+ * The flag of is_phy_on is only true if
+ * the DWC3 is in Host mode.
+ */
+ if (eswin->is_phy_on) {
+ phy_power_off(dwc->usb2_generic_phy[0]);
+
+ /*
+ * If link state is Rx.Detect, it means that
+ * no usb device is connecting with the DWC3
+ * Host, and need to power off the USB3 PHY.
+ */
+ dwc->link_state = dwc3_gadget_get_link_state(dwc);
+ if (dwc->link_state == DWC3_LINK_STATE_RX_DET)
+ phy_power_off(dwc->usb3_generic_phy[0]);
+ }
+
+ return 0;
+}
+
+static int __maybe_unused dwc3_eswin_resume(struct device *dev)
+{
+ struct dwc3_eswin *eswin = dev_get_drvdata(dev);
+ struct dwc3 *dwc = eswin->dwc;
+
+ eswin->suspended = false;
+
+ if (eswin->is_phy_on) {
+ phy_power_on(dwc->usb2_generic_phy[0]);
+
+ if (dwc->link_state == DWC3_LINK_STATE_RX_DET)
+ phy_power_on(dwc->usb3_generic_phy[0]);
+ }
+
+ if (eswin->edev)
+ schedule_work(&eswin->otg_work);
+
+ return 0;
+}
+
+static const struct dev_pm_ops dwc3_eswin_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(dwc3_eswin_suspend, dwc3_eswin_resume)
+ SET_RUNTIME_PM_OPS(dwc3_eswin_runtime_suspend,
+ dwc3_eswin_runtime_resume, NULL)
+};
+
+#define DEV_PM_OPS (&dwc3_eswin_dev_pm_ops)
+#else
+#define DEV_PM_OPS NULL
+#endif /* CONFIG_PM */
+
+static const struct of_device_id eswin_dwc3_match[] = {
+ { .compatible = "eswin,eic7700-dwc3" },
+ { /* Sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, eswin_dwc3_match);
+
+static struct platform_driver dwc3_eswin_driver = {
+ .probe = dwc3_eswin_probe,
+ .remove = dwc3_eswin_remove,
+ .driver = {
+ .name = "eic7700-dwc3",
+ .pm = DEV_PM_OPS,
+ .of_match_table = eswin_dwc3_match,
+ },
+};
+
+module_platform_driver(dwc3_eswin_driver);
+
+MODULE_ALIAS("platform:eic7700-dwc3");
+MODULE_AUTHOR("Wei Yang <yangwei1@eswincomputing.com");
+MODULE_AUTHOR("Senchuan Zhang <zhangsenchuan@eswincomputing.com");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DesignWare USB3 ESWIN Glue Layer");
--
2.25.1
next prev parent reply other threads:[~2025-05-16 9:54 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-16 9:52 [PATCH v1 0/2] Add driver support for Eswin eic7700 SoC Usb controller zhangsenchuan
2025-05-16 9:53 ` [PATCH v1 1/2] dt-bindings: usb: Add Eswin EIC7700 " zhangsenchuan
2025-05-16 11:26 ` Rob Herring (Arm)
2025-05-19 6:24 ` Krzysztof Kozlowski
2025-05-16 9:54 ` zhangsenchuan [this message]
2025-05-16 12:50 ` [PATCH v1 2/2] usb: dwc3: eic7700: Add EIC7700 usb driver Krzysztof Kozlowski
2025-05-17 1:15 ` kernel test robot
2025-05-17 23:28 ` kernel test robot
2025-05-20 6:20 ` Krishna Kurapati
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250516095408.704-1-zhangsenchuan@eswincomputing.com \
--to=zhangsenchuan@eswincomputing.com \
--cc=Thinh.Nguyen@synopsys.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=krzk+dt@kernel.org \
--cc=linmin@eswincomputing.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=ningyu@eswincomputing.com \
--cc=p.zabel@pengutronix.de \
--cc=robh@kernel.org \
--cc=yangwei1@eswincomputing.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.