Skip to contentSkip to conversation

Add driver support for ESWIN EIC7700 SoC USB controller

PATCH Superseded [email protected] 4 participants 7 messages Nov 4, 2025 – Nov 5, 2025

Subsystems (3)

v5 of 8 Superseded Latest is v8 →

lore
Share & tools
lore
#0 lore raw

v5 cover Add driver support for ESWIN EIC7700 SoC USB controller

From: Hang Cao <[email protected]>

Add support for ESWIN EIC7700 USB driver controller.

Changes in v5->v4:
- Updates:
- Rebase kernel source to usb-testing branch of gregkh/usb.git.

- Updates: eswin,eic7700-usb.yaml
- Remove the unnecessary properties about quirks.

- Updates: dwc3-generic-plat.c
- Add eic7700 pre init in probe function.
- Removed .data
- Link to V4:https://lore.kernel.org/all/[email protected]/
- Link to gregkh/usb.git:https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git/tree/?h=usb-next

Changes in v4->v3:
- Updates:
- Removed config option patch dependency from cover letter, because the patch was applied.
- Remove dwc3-eic7700.c instead of dwc3-generic-plat.c.

- Updates: eswin,eic7700-usb.yaml
- Add usb_en clock.
- Add usb_rst reset.
- Update eswin,hsp-sp-csr description.
- Remove the last two unused items of eswin,hsp-sp-csr.

- Updates: dwc3-generic-plat.c
- Add eswin,eic7700-dwc3 to the compatible table.
- Add the dwc3_generic_match_data structure.
- Add the eic7700_dwc3_bus_init function to initialize the bus.
- Add the init_ops callback in the probe function.
- Link to V3: https://lore.kernel.org/all/[email protected]/

Changes in v3->v2:
- Updates: eswin,eic7700-usb.yaml
- Sort the attributes according to the DTS coding style.
- Remove the #address-cells and #size-cells attributes.
- Fold the child node into the parent.
- Update commit message.

- Updates: dwc3-eic7700.c
- Use dwc3 core as a library.
- Add system and runtime pm.
- Use pm_ptr and remove the __maybe_unused tags.
- Add new author name
- Add prepare and complete function
- Update commit message.
- Link to V2: https://lore.kernel.org/lkml/[email protected]/

Changes in v2->v1:
- Updates: eswin,eic7700-usb.yaml
- Drop the redundant descriptions.
- Supplement the constraints of resets.
- Replace "eswin,hsp_sp_csr" with "eswin,hsp-sp-csr" and add items description.
- Drop numa-node-id, This is not necessary.
- Add patternProperties and match the rules defined in the "snps,dwc3.yaml" file.
- Add "#address-cells" "#size-cells".
- Update the space indentation, remove the redundant labels, and sort the attributes according to the DTS encoding style.
- Drop the "status = "disabled" attribute.
- Update the common usb node names and fold the child nodes into the parent nodes.
- The warning detected by the robot has been resolved.

- Updates: dwc3-eic7700.c
- Remove dwc3_mode_show dwc3_mode_store dwc3_eswin_get_extcon_dev, dwc3_eswin_device_notifier and dwc3_eswin_host_notifier, usb role
detection and switching are not supported.
- Remove the hub-rst attribute, remove the dwc3_hub_rst_show and dwc3_hub_rst_store functions, this feature is not supported.
- Use syscon_regmap_lookup_by_phandle_args instead of the syscon_regmap_lookup_by_phandle function.
- Use dev_err_probe in probe function.
- Drop mutex_lock, which is not required.
- Remove clk_prepare_enable and of_clk_get, and manage multiple
clocks using devm_clk_bulk_get_all_enabled.
- Remove the device_init_wakeup related functions, which were
used incorrectly.
- Remove MODULE_ALIAS, which is used incorrectly.
- The warning detected by the robot has been resolved.
- Link to V1: https://lore.kernel.org/lkml/[email protected]/

Hang Cao (2):
dt-bindings: usb: Add ESWIN EIC7700 USB controller
usb: dwc3: eic7700: Add EIC7700 USB driver

 .../bindings/usb/eswin,eic7700-usb.yaml       | 94 +++++++++++++++++++
 drivers/usb/dwc3/dwc3-generic-plat.c          | 43 +++++++++
 2 files changed, 137 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/eswin,eic7700-usb.yaml

--
2.34.1

#1 lore raw

PATCH v5 1/2 dt-bindings: usb: Add ESWIN EIC7700 USB controller

From: Hang Cao <[email protected]>

Add Device Tree binding documentation for the ESWIN EIC7700 usb controller module.

---
 .../bindings/usb/eswin,eic7700-usb.yaml       | 94 +++++++++++++++++++
 1 file changed, 94 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/eswin,eic7700-usb.yaml
Documentation/devicetree/bindings/usb/eswin,eic7700-usb.yaml new file +94 -0
new file mode 100644
index 000000000000..41c3b1b98991
@@ -0,0 +1,94 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/eswin,eic7700-usb.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ESWIN EIC7700 SoC Usb Controller
+
+maintainers:
+  - Wei Yang <[email protected]>
+  - Senchuan Zhang <[email protected]>
+  - Hang Cao <[email protected]>
+
+description:
+  The Usb controller on EIC7700 SoC.
+
+allOf:
+  - $ref: snps,dwc3-common.yaml#
+
+properties:
+  compatible:
+    const: eswin,eic7700-dwc3
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  interrupt-names:
+    items:
+      - const: peripheral
+
+  clocks:
+    maxItems: 3
+
+  clock-names:
+    items:
+      - const: aclk
+      - const: cfg
+      - const: usb_en
+
+  resets:
+    maxItems: 2
+
+  reset-names:
+    items:
+      - const: vaux
+      - const: usb_rst
+
+  eswin,hsp-sp-csr:
+    description:
+      HSP CSR is to control and get status of different high-speed peripherals
+      (such as Ethernet, USB, SATA, etc.) via register, which can tune
+      board-level's parameters of PHY, etc.
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    items:
+      - items:
+          - description: phandle to HSP Register Controller hsp_sp_csr node.
+          - description: USB bus register offset.
+          - description: AXI low power register offset.
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - interrupts
+  - interrupt-names
+  - resets
+  - reset-names
+  - eswin,hsp-sp-csr
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    usb@50480000 {
+        compatible = "eswin,eic7700-dwc3";
+        reg = <0x50480000 0x10000>;
+        clocks = <&clock 135>,
+                 <&clock 136>,
+                 <&hspcrg 18>;
+        clock-names = "aclk", "cfg", "usb_en";
+        interrupt-parent = <&plic>;
+        interrupts = <85>;
+        interrupt-names = "peripheral";
+        resets = <&reset 84>, <&hspcrg 2>;
+        reset-names = "vaux", "usb_rst";
+        dr_mode = "peripheral";
+        maximum-speed = "high-speed";
+        phy_type = "utmi";
+        eswin,hsp-sp-csr = <&hsp_sp_csr 0x800 0x818>;
+    };
Signature · 1 line
2.34.1
#2 lore raw

Re: [PATCH v5 1/2] dt-bindings: usb: Add ESWIN EIC7700 USB controller

Quoted 5 lines · On Tue, 04 Nov 2025 14:52:02 +0800, [email protected] wrote:

From: Hang Cao <[email protected]>

Add Device Tree binding documentation for the ESWIN EIC7700 usb controller module.

Quoted 7 lines
---
 .../bindings/usb/eswin,eic7700-usb.yaml       | 94 +++++++++++++++++++
 1 file changed, 94 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/eswin,eic7700-usb.yaml

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/net/eswin,eic7700-eth.example.dtb: ethernet@50400000 (eswin,eic7700-qos-eth): eswin,hsp-sp-csr: [[4294967295, 256], [264, 280]] is too short
from schema $id: http://devicetree.org/schemas/net/eswin,eic7700-eth.yaml

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/[email protected]

The base for the series is generally the latest rc1. A different dependency should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note that DT_SCHEMA_FILES can be set to your schema file to speed up checking your schema. However, it must be unset to test all examples with your schema.

#3 lore raw

PATCH v5 2/2 usb: dwc3: eic7700: Add EIC7700 USB driver

In reply to [email protected]

From: Hang Cao <[email protected]>

Add the eic7700 usb driver, which is responsible for identifying,configuring and connecting usb devices.

---
 drivers/usb/dwc3/dwc3-generic-plat.c | 43 ++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)
drivers/usb/dwc3/dwc3-generic-plat.c +43 -0
index 770fedc16bb8..89ad952a4a4c 100644
@@ -10,8 +10,16 @@
 #include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/reset.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
 #include "glue.h"
 
+#define EIC7700_HSP_BUS_FILTER_EN	BIT(0)
+#define EIC7700_HSP_BUS_CLKEN_GM	BIT(9)
+#define EIC7700_HSP_BUS_CLKEN_GS	BIT(16)
+#define EIC7700_HSP_AXI_LP_XM_CSYSREQ	BIT(0)
+#define EIC7700_HSP_AXI_LP_XS_CSYSREQ	BIT(16)
+
 struct dwc3_generic {
 	struct device		*dev;
 	struct dwc3		dwc;
@@ -27,6 +35,34 @@ static void dwc3_generic_reset_control_assert(void *data)
 	reset_control_assert(data);
 }
 
+static int dwc3_eic7700_pre_init(struct device *dev)
+{
+	struct regmap *regmap;
+	u32 hsp_usb_axi_lp;
+	u32 hsp_usb_bus;
+	u32 args[2];
+	u32 val;
+
+	regmap = syscon_regmap_lookup_by_phandle_args(dev->of_node,
+						      "eswin,hsp-sp-csr",
+						      ARRAY_SIZE(args), args);
+	if (IS_ERR(regmap)) {
+		dev_err(dev, "No hsp-sp-csr phandle specified\n");
+		return PTR_ERR(regmap);
+	}
+
+	hsp_usb_bus       = args[0];
+	hsp_usb_axi_lp    = args[1];
+
+	regmap_read(regmap, hsp_usb_bus, &val);
+	regmap_write(regmap, hsp_usb_bus, val | EIC7700_HSP_BUS_FILTER_EN |
+		     EIC7700_HSP_BUS_CLKEN_GM | EIC7700_HSP_BUS_CLKEN_GS);
+
+	regmap_write(regmap, hsp_usb_axi_lp, EIC7700_HSP_AXI_LP_XM_CSYSREQ |
+		     EIC7700_HSP_AXI_LP_XS_CSYSREQ);
+	return 0;
+}
+
 static int dwc3_generic_probe(struct platform_device *pdev)
 {
 	const struct dwc3_properties *properties;
@@ -83,6 +119,12 @@ static int dwc3_generic_probe(struct platform_device *pdev)
 	else
 		probe_data.properties = DWC3_DEFAULT_PROPERTIES;
 
+	if (of_device_is_compatible(dev->of_node, "eswin,eic7700-dwc3")) {
+		ret = dwc3_eic7700_pre_init(dev);
+		if (ret)
+			return dev_err_probe(dev, ret, "eic7700 init fail\n");
+	}
+
 	ret = dwc3_core_probe(&probe_data);
 	if (ret)
 		return dev_err_probe(dev, ret, "failed to register DWC3 Core\n");
@@ -160,6 +202,7 @@ static const struct dwc3_properties fsl_ls1028_dwc3 = {
 static const struct of_device_id dwc3_generic_of_match[] = {
 	{ .compatible = "spacemit,k1-dwc3", },
 	{ .compatible = "fsl,ls1028a-dwc3", &fsl_ls1028_dwc3},
+	{ .compatible = "eswin,eic7700-dwc3",},
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, dwc3_generic_of_match);
Signature · 1 line
2.34.1
#4 lore raw

Re: [PATCH v5 2/2] usb: dwc3: eic7700: Add EIC7700 USB driver

Quoted 7 lines · On 04/11/2025 07:52, [email protected] wrote:

From: Hang Cao <[email protected]>

Add the eic7700 usb driver, which is responsible for identifying,configuring and connecting usb devices.

...

drivers/usb/dwc3/dwc3-generic-plat.c static int dwc3_generic_probe(struct platform_device *pdev) · line 122

Quoted 9 lines
drivers/usb/dwc3/dwc3-generic-plat.c +2 -0
+
 static int dwc3_generic_probe(struct platform_device *pdev)
 {
 	const struct dwc3_properties *properties;
@@ -83,6 +119,12 @@ static int dwc3_generic_probe(struct platform_device *pdev)
 	else
 		probe_data.properties = DWC3_DEFAULT_PROPERTIES;
 
+	if (of_device_is_compatible(dev->of_node, "eswin,eic7700-dwc3")) {

No, you have driver match data for that.

Best regards,
Krzysztof

author
#5 lore raw

Re: Re: [PATCH v5 2/2] usb: dwc3: eic7700: Add EIC7700 USB driver

Hi, Krzysztof and Thinh:

Quoted 9 lines
Quoted 9 lines
drivers/usb/dwc3/dwc3-generic-plat.c +1 -0
+
 static int dwc3_generic_probe(struct platform_device *pdev)
 {
 	const struct dwc3_properties *properties;
@@ -83,6 +119,12 @@ static int dwc3_generic_probe(struct platform_device *pdev)
 	else
 		probe_data.properties = DWC3_DEFAULT_PROPERTIES;
 
Quoted 4 lines

drivers/usb/dwc3/dwc3-generic-plat.c static int dwc3_generic_probe(struct platform_device *pdev) · line 122

Quoted 1 line
drivers/usb/dwc3/dwc3-generic-plat.c +1 -0
+	if (of_device_is_compatible(dev->of_node, "eswin,eic7700-dwc3")) {

No, you have driver match data for that.

We implemented it with driver match data in v4 patch.
https://lore.kernel.org/all/[email protected]/

However, Thinh suggested using direct function calls instead, noting that this is a function call rather than data.
We are not sure if we’ve fully understood his feedback correctly.

Our driver requires special handling for USB bus initialization, which does involve function calls.

So we’d really appreciate it if you and Thinh could share further thoughts on which approach would be more suitable for our driver’s needs.

Best regards,
Hang Cao

maintainer
#6 lore raw

Re: [PATCH v5 2/2] usb: dwc3: eic7700: Add EIC7700 USB driver

Hi Hang,

Quoted 21 lines · Hang Cao

Hi, Krzysztof and Thinh:

Quoted 9 lines
Quoted 9 lines
(quoted diff) +1 -0
+
 static int dwc3_generic_probe(struct platform_device *pdev)
 {
 	const struct dwc3_properties *properties;
@@ -83,6 +119,12 @@ static int dwc3_generic_probe(struct platform_device *pdev)
 	else
 		probe_data.properties = DWC3_DEFAULT_PROPERTIES;
 
Quoted 4 lines

Review static int dwc3_generic_probe(struct platform_device *pdev) · line 122

Quoted 1 line
(quoted diff) +1 -0
+	if (of_device_is_compatible(dev->of_node, "eswin,eic7700-dwc3")) {

No, you have driver match data for that.

We implemented it with driver match data in v4 patch.
https://urldefense.com/v3/__https://lore.kernel.org/all/[email protected]/__;!!A4F2R9G_pg!bnU1bsEHivo93LGmhV68yL2IecKrcNCZfKvMRBDFZsvpkszq5uEaNlbvSmSjjgk_riIJALl21T0yq5yhBn9G0gCeWPQ$

However, Thinh suggested using direct function calls instead, noting that this is a function call rather than data.
We are not sure if we’ve fully understood his feedback correctly.

Quoted 6 lines

Our driver requires special handling for USB bus initialization, which does involve function calls.

So we’d really appreciate it if you and Thinh could share further thoughts on which approach would be more suitable for our driver’s needs.

I wanted to avoid modifying the struct dwc3_probe_data. It's only meant to be used for passing data to the core. If we want to get the custom init function through the driver match data within the same glue driver, we can just create a new struct to pass that. This keeps the code a bit cleaner.

You can try the following (not tested):

drivers/usb/dwc3/dwc3-generic-plat.c +33 -7
index e869c7de7bc8..c3541fefe959 100644
@@ -20,6 +20,11 @@ struct dwc3_generic {
 	struct reset_control	*resets;
 };
 
+struct dwc3_plat_config {
+	int (*init)(struct dwc3_generic *dwc3g);
+	struct dwc3_properties properties;
+};
+
 #define to_dwc3_generic(d) container_of((d), struct dwc3_generic, dwc)
 
 static void dwc3_generic_reset_control_assert(void *data)
@@ -27,9 +32,15 @@ static void dwc3_generic_reset_control_assert(void *data)
 	reset_control_assert(data);
 }
 
+static int dwc3_eic7700_init(struct dwc3_generic *dwc3g)
+{
+	/* init code goes here */
+	return 0;
+}
+
 static int dwc3_generic_probe(struct platform_device *pdev)
 {
-	const struct dwc3_properties *properties;
+	const struct dwc3_plat_config *plat_config;
 	struct dwc3_probe_data probe_data = {};
 	struct device *dev = &pdev->dev;
 	struct dwc3_generic *dwc3g;
@@ -77,12 +88,21 @@ static int dwc3_generic_probe(struct platform_device *pdev)
 	probe_data.res = res;
 	probe_data.ignore_clocks_and_resets = true;
 
-	properties = of_device_get_match_data(dev);
-	if (properties)
-		probe_data.properties = *properties;
-	else
+	plat_config = of_device_get_match_data(dev);
+	if (!plat_config) {
 		probe_data.properties = DWC3_DEFAULT_PROPERTIES;
+		goto core_probe;
+	}
+
+	probe_data.properties = plat_config->properties;
+
+	if (plat_config->init) {
+		ret = plat_config->init(dwc3g);
+		if (ret)
+			return dev_err_probe(dev, ret, "platform init failed\n");
+	}
 
+core_probe:
 	ret = dwc3_core_probe(&probe_data);
 	if (ret)
 		return dev_err_probe(dev, ret, "failed to register DWC3 Core\n");
@@ -150,13 +170,19 @@ static const struct dev_pm_ops dwc3_generic_dev_pm_ops = {
 		       dwc3_generic_runtime_idle)
 };
 
-static const struct dwc3_properties fsl_ls1028_dwc3 = {
-	.gsbuscfg0_reqinfo = 0x2222,
+static const struct dwc3_plat_config fsl_ls1028_dwc3 = {
+	.properties.gsbuscfg0_reqinfo = 0x2222,
+};
+
+static const struct dwc3_plat_config eic7700_dwc3 = {
+	.init = dwc3_eic7700_init,
+	.properties = DWC3_DEFAULT_PROPERTIES,
 };
 
 static const struct of_device_id dwc3_generic_of_match[] = {
 	{ .compatible = "spacemit,k1-dwc3", },
 	{ .compatible = "fsl,ls1028a-dwc3", &fsl_ls1028_dwc3},
+	{ .compatible = "eswin,eic7700-dwc3", &eic7700_dwc3},
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, dwc3_generic_of_match);

---

Side note, can you provide more context in the commit message of this new device? (e.g. DWC_usb3 IP, device mode only, highspeed etc.). It'd help whenever I need to revisit or considering new changes.

Thanks,
Thinh