* [PATCH 1/5] usb: dwc3: export dwc3_core_probe/dwc3_core_remove like Linux
2026-01-05 19:12 [PATCH 0/5] usb: dwc3: add fsl,ls1028a-dwc3 glue driver Ahmad Fatoum
@ 2026-01-05 19:12 ` Ahmad Fatoum
2026-01-05 19:12 ` [PATCH 2/5] usb: dwc3: add support for Global SoC Bus Configuration Register Ahmad Fatoum
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Ahmad Fatoum @ 2026-01-05 19:12 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Traditionally, platforms-specific glue was abstracted as a separate
parent device tree node for the snps,dwc3 node. For some newer
integrations, this is no longer the case and there is only a single
(flattened) node. To prepare support for these drivers, export the probe
and remove functions with the Linux semantics.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/usb/dwc3/core.c | 78 ++++++++++++++++++++++++++++-------------
drivers/usb/dwc3/glue.h | 49 ++++++++++++++++++++++++++
2 files changed, 102 insertions(+), 25 deletions(-)
create mode 100644 drivers/usb/dwc3/glue.h
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 7f2cb6c4a70a..472630c95392 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -17,6 +17,7 @@
#include <linux/reset.h>
#include <linux/usb/of.h>
+#include "glue.h"
#include "core.h"
#include "gadget.h"
#include "io.h"
@@ -1402,41 +1403,43 @@ static void dwc3_check_params(struct dwc3 *dwc)
}
}
-static int dwc3_probe(struct device *dev)
+int dwc3_core_probe(const struct dwc3_probe_data *data)
{
- struct dwc3 *dwc;
+ struct dwc3 *dwc = data->dwc;
+ struct device *dev = dwc->dev;
+ struct resource *res = data->res;
int ret;
- dwc = xzalloc(sizeof(*dwc));
dev->priv = dwc;
- dwc->dev = dev;
- dwc->regs = dev_get_mem_region(dwc->dev, 0) + DWC3_GLOBALS_REGS_START;
+ dwc->regs = IOMEM(res->start) + DWC3_GLOBALS_REGS_START;
dwc3_get_properties(dwc);
- if (dev->of_node) {
- ret = clk_bulk_get_all(dev, &dwc->clks);
- if (ret < 0)
+ if (!data->ignore_clocks_and_resets) {
+ if (dev->of_node) {
+ ret = clk_bulk_get_all(dev, &dwc->clks);
+ if (ret < 0)
+ return ret;
+
+ dwc->num_clks = ret;
+ }
+
+ ret = clk_bulk_enable(dwc->num_clks, dwc->clks);
+ if (ret)
return ret;
- dwc->num_clks = ret;
+ dwc->reset = reset_control_get(dev, NULL);
+ if (IS_ERR(dwc->reset)) {
+ dev_err(dev, "Failed to get reset control: %pe\n", dwc->reset);
+ return PTR_ERR(dwc->reset);
+ }
+
+ reset_control_assert(dwc->reset);
+ mdelay(1);
+ reset_control_deassert(dwc->reset);
}
- ret = clk_bulk_enable(dwc->num_clks, dwc->clks);
- if (ret)
- return ret;
-
- dwc->reset = reset_control_get(dev, NULL);
- if (IS_ERR(dwc->reset)) {
- dev_err(dev, "Failed to get reset control: %pe\n", dwc->reset);
- return PTR_ERR(dwc->reset);
- }
-
- reset_control_assert(dwc->reset);
- mdelay(1);
- reset_control_deassert(dwc->reset);
-
if (!dwc3_core_is_valid(dwc)) {
dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
return -ENODEV;
@@ -1476,10 +1479,30 @@ static int dwc3_probe(struct device *dev)
return 0;
}
-static void dwc3_remove(struct device *dev)
+static int dwc3_probe(struct device *dev)
{
- struct dwc3 *dwc = dev->priv;
+ struct dwc3_probe_data probe_data = {};
+ struct resource *res;
+ struct dwc3 *dwc;
+ res = dev_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "missing memory resource\n");
+ return -ENODEV;
+ }
+
+ dwc = xzalloc(sizeof(*dwc));
+
+ dwc->dev = dev;
+
+ probe_data.dwc = dwc;
+ probe_data.res = res;
+
+ return dwc3_core_probe(&probe_data);
+}
+
+void dwc3_core_remove(struct dwc3 *dwc)
+{
dwc3_core_exit_mode(dwc);
dwc3_core_exit(dwc);
clk_bulk_put(dwc->num_clks, dwc->clks);
@@ -1487,6 +1510,11 @@ static void dwc3_remove(struct device *dev)
dwc3_free_scratch_buffers(dwc);
}
+static void dwc3_remove(struct device *dev)
+{
+ dwc3_core_remove(dev->priv);
+}
+
static const struct of_device_id of_dwc3_match[] = {
{
.compatible = "snps,dwc3",
diff --git a/drivers/usb/dwc3/glue.h b/drivers/usb/dwc3/glue.h
new file mode 100644
index 000000000000..05d6d2723d19
--- /dev/null
+++ b/drivers/usb/dwc3/glue.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * glue.h - DesignWare USB3 DRD glue header
+ */
+
+#ifndef __DRIVERS_USB_DWC3_GLUE_H
+#define __DRIVERS_USB_DWC3_GLUE_H
+
+#include <linux/types.h>
+#include "core.h"
+
+/**
+ * dwc3_probe_data: Initialization parameters passed to dwc3_core_probe()
+ * @dwc: Reference to dwc3 context structure
+ * @res: resource for the DWC3 core mmio region
+ * @ignore_clocks_and_resets: clocks and resets defined for the device should
+ * be ignored by the DWC3 core, as they are managed by the glue
+ */
+struct dwc3_probe_data {
+ struct dwc3 *dwc;
+ struct resource *res;
+ bool ignore_clocks_and_resets;
+};
+
+/**
+ * dwc3_core_probe - Initialize the core dwc3 driver
+ * @data: Initialization and configuration parameters for the controller
+ *
+ * Initializes the DesignWare USB3 core driver by setting up resources,
+ * registering interrupts, performing hardware setup, and preparing
+ * the controller for operation in the appropriate mode (host, gadget,
+ * or OTG). This is the main initialization function called by glue
+ * layer drivers to set up the core controller.
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+int dwc3_core_probe(const struct dwc3_probe_data *data);
+
+/**
+ * dwc3_core_remove - Deinitialize and remove the core dwc3 driver
+ * @dwc: Pointer to DWC3 controller context
+ *
+ * Cleans up resources and disables the dwc3 core driver. This should be called
+ * during driver removal or when the glue layer needs to shut down the
+ * controller completely.
+ */
+void dwc3_core_remove(struct dwc3 *dwc);
+
+#endif
--
2.47.3
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH 2/5] usb: dwc3: add support for Global SoC Bus Configuration Register
2026-01-05 19:12 [PATCH 0/5] usb: dwc3: add fsl,ls1028a-dwc3 glue driver Ahmad Fatoum
2026-01-05 19:12 ` [PATCH 1/5] usb: dwc3: export dwc3_core_probe/dwc3_core_remove like Linux Ahmad Fatoum
@ 2026-01-05 19:12 ` Ahmad Fatoum
2026-01-05 19:12 ` [PATCH 3/5] clk: implement and use clk_bulk_get_all_enabled helper Ahmad Fatoum
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Ahmad Fatoum @ 2026-01-05 19:12 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Quoting kernel commit d504bfa6cfd1 ("usb: dwc3: enable CCI support for
AMD-xilinx DWC3 controller"):
The GSBUSCFG0 register bits [31:16] are used to configure the cache type
settings of the descriptor and data write/read transfers (Cacheable,
Bufferable/Posted). When CCI is enabled in the design, DWC3 core GSBUSCFG0
cache bits must be updated to support CCI enabled transfers in USB.
We don't operate the ZynqMP in cache-coherent mode in barebox, but we do
operate the 64-bit Layerscape SoCs in this mode, so prepare for being
able to set this register.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/usb/dwc3/core.c | 37 +++++++++++++++++++++++++++++++++++++
drivers/usb/dwc3/core.h | 8 ++++++++
drivers/usb/dwc3/glue.h | 14 ++++++++++++++
3 files changed, 59 insertions(+)
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 472630c95392..cb22f19e39cc 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -445,6 +445,18 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc)
parms->hwparams9 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS9);
}
+static void dwc3_config_soc_bus(struct dwc3 *dwc)
+{
+ if (dwc->gsbuscfg0_reqinfo != DWC3_GSBUSCFG0_REQINFO_UNSPECIFIED) {
+ u32 reg;
+
+ reg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG0);
+ reg &= ~DWC3_GSBUSCFG0_REQINFO(~0);
+ reg |= DWC3_GSBUSCFG0_REQINFO(dwc->gsbuscfg0_reqinfo);
+ dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, reg);
+ }
+}
+
static int dwc3_core_ulpi_init(struct dwc3 *dwc)
{
int intf;
@@ -903,6 +915,8 @@ static int dwc3_core_init(struct dwc3 *dwc)
dwc3_set_incr_burst_type(dwc);
+ dwc3_config_soc_bus(dwc);
+
usb_phy_set_suspend(dwc->usb2_phy, 0);
usb_phy_set_suspend(dwc->usb3_phy, 0);
ret = phy_power_on(dwc->usb2_generic_phy);
@@ -1147,6 +1161,26 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc)
dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE);
}
+static void dwc3_get_software_properties(struct dwc3 *dwc,
+ const struct dwc3_properties *properties)
+{
+ dwc->gsbuscfg0_reqinfo = DWC3_GSBUSCFG0_REQINFO_UNSPECIFIED;
+
+ if (properties->gsbuscfg0_reqinfo !=
+ DWC3_GSBUSCFG0_REQINFO_UNSPECIFIED) {
+ dwc->gsbuscfg0_reqinfo = properties->gsbuscfg0_reqinfo;
+ return;
+ }
+
+ /*
+ * TODO: Iterate over all parent nodes for finding swnode properties
+ * and non-DT (non-ABI) properties once we have device properties..
+ *
+ * In Linux, this is used for Xilinx ZynqMP, which we don't configure
+ * here.
+ */
+}
+
static void dwc3_get_properties(struct dwc3 *dwc)
{
struct device *dev = dwc->dev;
@@ -1416,6 +1450,8 @@ int dwc3_core_probe(const struct dwc3_probe_data *data)
dwc3_get_properties(dwc);
+ dwc3_get_software_properties(dwc, &data->properties);
+
if (!data->ignore_clocks_and_resets) {
if (dev->of_node) {
ret = clk_bulk_get_all(dev, &dwc->clks);
@@ -1497,6 +1533,7 @@ static int dwc3_probe(struct device *dev)
probe_data.dwc = dwc;
probe_data.res = res;
+ probe_data.properties = DWC3_DEFAULT_PROPERTIES;
return dwc3_core_probe(&probe_data);
}
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 52853a4370ce..d49feb9918b7 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -168,6 +168,10 @@
#define DWC3_GSBUSCFG0_INCRBRSTENA (1 << 0) /* undefined length enable */
#define DWC3_GSBUSCFG0_INCRBRST_MASK 0xff
+/* Global SoC Bus Configuration Register: AHB-prot/AXI-cache/OCP-ReqInfo */
+#define DWC3_GSBUSCFG0_REQINFO(n) (((n) & 0xffff) << 16)
+#define DWC3_GSBUSCFG0_REQINFO_UNSPECIFIED 0xffffffff
+
/* Global Debug LSP MUX Select */
#define DWC3_GDBGLSPMUX_ENDBC BIT(15) /* Host only */
#define DWC3_GDBGLSPMUX_HOSTSELECT(n) ((n) & 0x3fff)
@@ -1103,6 +1107,9 @@ struct dwc3_scratchpad_array {
* @num_ep_resized: carries the current number endpoints which have had its tx
* fifo resized.
* @debug_root: root debugfs directory for this device to put its files in.
+ * @gsbuscfg0_reqinfo: store GSBUSCFG0.DATRDREQINFO, DESRDREQINFO,
+ * DATWRREQINFO, and DESWRREQINFO value passed from
+ * glue driver.
*/
struct dwc3 {
struct work_struct drd_work;
@@ -1318,6 +1325,7 @@ struct dwc3 {
int last_fifo_depth;
int num_ep_resized;
struct dentry *debug_root;
+ u32 gsbuscfg0_reqinfo;
};
#define INCRX_BURST_MODE 0
diff --git a/drivers/usb/dwc3/glue.h b/drivers/usb/dwc3/glue.h
index 05d6d2723d19..f7842b42dfac 100644
--- a/drivers/usb/dwc3/glue.h
+++ b/drivers/usb/dwc3/glue.h
@@ -9,17 +9,31 @@
#include <linux/types.h>
#include "core.h"
+/**
+ * dwc3_properties: DWC3 core properties
+ * @gsbuscfg0_reqinfo: Value to be programmed in the GSBUSCFG0.REQINFO field
+ */
+struct dwc3_properties {
+ u32 gsbuscfg0_reqinfo;
+};
+
+#define DWC3_DEFAULT_PROPERTIES ((struct dwc3_properties){ \
+ .gsbuscfg0_reqinfo = DWC3_GSBUSCFG0_REQINFO_UNSPECIFIED, \
+ })
+
/**
* dwc3_probe_data: Initialization parameters passed to dwc3_core_probe()
* @dwc: Reference to dwc3 context structure
* @res: resource for the DWC3 core mmio region
* @ignore_clocks_and_resets: clocks and resets defined for the device should
* be ignored by the DWC3 core, as they are managed by the glue
+ * @properties: dwc3 software manage properties
*/
struct dwc3_probe_data {
struct dwc3 *dwc;
struct resource *res;
bool ignore_clocks_and_resets;
+ struct dwc3_properties properties;
};
/**
--
2.47.3
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH 3/5] clk: implement and use clk_bulk_get_all_enabled helper
2026-01-05 19:12 [PATCH 0/5] usb: dwc3: add fsl,ls1028a-dwc3 glue driver Ahmad Fatoum
2026-01-05 19:12 ` [PATCH 1/5] usb: dwc3: export dwc3_core_probe/dwc3_core_remove like Linux Ahmad Fatoum
2026-01-05 19:12 ` [PATCH 2/5] usb: dwc3: add support for Global SoC Bus Configuration Register Ahmad Fatoum
@ 2026-01-05 19:12 ` Ahmad Fatoum
2026-01-05 19:12 ` [PATCH 4/5] usb: dwc3: add DesignWare USB3 generic platform driver Ahmad Fatoum
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Ahmad Fatoum @ 2026-01-05 19:12 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Linux has a devm_clk_bulk_get_all_enabled helper for drivers that just
want to get and enable all clocks associated with a device.
Import it to barebox and make use of it where applicable, except for
dwc3-of-simple.c: The upstream Linux driver doesn't make use of it and
we will want to sync DWC3 against Linux anyway, so this will reduce
churn a tiny little bit.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/bus/simple-pm-bus.c | 6 +-----
drivers/clk/clk-bulk.c | 19 +++++++++++++++++++
drivers/usb/dwc3/core.c | 6 +-----
drivers/usb/host/ehci-hcd.c | 5 +----
include/linux/clk.h | 16 ++++++++++++++++
5 files changed, 38 insertions(+), 14 deletions(-)
diff --git a/drivers/bus/simple-pm-bus.c b/drivers/bus/simple-pm-bus.c
index 8536982b69c4..caafee1e407e 100644
--- a/drivers/bus/simple-pm-bus.c
+++ b/drivers/bus/simple-pm-bus.c
@@ -16,13 +16,9 @@ static int simple_pm_bus_probe(struct device *dev)
int num_clks;
if (deep_probe_is_supported()) {
- num_clks = clk_bulk_get_all(dev, &clks);
+ num_clks = clk_bulk_get_all_enabled(dev, &clks);
if (num_clks < 0)
return dev_err_probe(dev, num_clks, "failed to get clocks\n");
-
- num_clks = clk_bulk_prepare_enable(num_clks, clks);
- if (num_clks)
- return dev_err_probe(dev, num_clks, "failed to enable clocks\n");
}
of_platform_populate(np, NULL, dev);
diff --git a/drivers/clk/clk-bulk.c b/drivers/clk/clk-bulk.c
index db775dc40b39..c16fed282b21 100644
--- a/drivers/clk/clk-bulk.c
+++ b/drivers/clk/clk-bulk.c
@@ -153,6 +153,25 @@ int __must_check clk_bulk_get_all(struct device *dev,
}
EXPORT_SYMBOL(clk_bulk_get_all);
+int __must_check clk_bulk_get_all_enabled(struct device *dev,
+ struct clk_bulk_data **clks)
+{
+ int ret, num_clks;
+
+ num_clks = clk_bulk_get_all(dev, clks);
+ if (num_clks <= 0)
+ return num_clks;
+
+ ret = clk_bulk_prepare_enable(num_clks, *clks);
+ if (ret < 0) {
+ clk_bulk_put_all(num_clks, *clks);
+ return ret;
+ }
+
+ return num_clks;
+}
+EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all_enabled);
+
/**
* clk_bulk_disable - gate a set of clocks
* @num_clks: the number of clk_bulk_data
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index cb22f19e39cc..747245f908a4 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1454,17 +1454,13 @@ int dwc3_core_probe(const struct dwc3_probe_data *data)
if (!data->ignore_clocks_and_resets) {
if (dev->of_node) {
- ret = clk_bulk_get_all(dev, &dwc->clks);
+ ret = clk_bulk_get_all_enabled(dev, &dwc->clks);
if (ret < 0)
return ret;
dwc->num_clks = ret;
}
- ret = clk_bulk_enable(dwc->num_clks, dwc->clks);
- if (ret)
- return ret;
-
dwc->reset = reset_control_get(dev, NULL);
if (IS_ERR(dwc->reset)) {
dev_err(dev, "Failed to get reset control: %pe\n", dwc->reset);
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 5fde8d2a4abd..51b9e52a4ffe 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1442,14 +1442,11 @@ static int ehci_probe(struct device *dev)
if (ret)
return ret;
- ret = clk_bulk_get_all(dev, &clks);
+ ret = clk_bulk_get_all_enabled(dev, &clks);
if (ret < 0)
return ret;
num_clocks = ret;
- ret = clk_bulk_enable(num_clocks, clks);
- if (ret)
- return ret;
iores = dev_request_mem_resource(dev, 0);
if (IS_ERR(iores))
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 526641927754..7673937a0a82 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -1032,6 +1032,22 @@ int __must_check clk_bulk_get_optional(struct device *dev, int num_clks,
int __must_check clk_bulk_get_all(struct device *dev,
struct clk_bulk_data **clks);
+/**
+ * devm_clk_bulk_get_all_enabled - Get and enable all clocks of the consumer
+ * @dev: device for clock "consumer"
+ * @clks: pointer to the clk_bulk_data table of consumer
+ *
+ * Returns a positive value for the number of clocks obtained while the
+ * clock references are stored in the clk_bulk_data table in @clks field.
+ * Returns 0 if there're none and a negative value if something failed.
+ *
+ * This helper function allows drivers to get all clocks of the
+ * consumer and enables them in one operation.
+ */
+
+int __must_check clk_bulk_get_all_enabled(struct device *dev,
+ struct clk_bulk_data **clks);
+
/**
* clk_bulk_put - "free" the clock source
* @num_clks: the number of clk_bulk_data
--
2.47.3
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH 4/5] usb: dwc3: add DesignWare USB3 generic platform driver
2026-01-05 19:12 [PATCH 0/5] usb: dwc3: add fsl,ls1028a-dwc3 glue driver Ahmad Fatoum
` (2 preceding siblings ...)
2026-01-05 19:12 ` [PATCH 3/5] clk: implement and use clk_bulk_get_all_enabled helper Ahmad Fatoum
@ 2026-01-05 19:12 ` Ahmad Fatoum
2026-01-05 19:12 ` [PATCH 5/5] Revert "ARM64: dts: Layerscape: workaround v6.19-rc1 DT sync DWC3 breakage" Ahmad Fatoum
2026-01-06 8:12 ` [PATCH 0/5] usb: dwc3: add fsl,ls1028a-dwc3 glue driver Sascha Hauer
5 siblings, 0 replies; 7+ messages in thread
From: Ahmad Fatoum @ 2026-01-05 19:12 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Linux seems to move towards not having glue device tree nodes separate
from the DWC3 nodes. Import the Linux generic driver for use with
Layerscape and other platforms that may be migrated in future.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
drivers/usb/dwc3/Kconfig | 11 +++
drivers/usb/dwc3/Makefile | 1 +
drivers/usb/dwc3/dwc3-generic-plat.c | 125 +++++++++++++++++++++++++++
3 files changed, 137 insertions(+)
create mode 100644 drivers/usb/dwc3/dwc3-generic-plat.c
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index bed629776227..4c97ed556a48 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -68,4 +68,15 @@ config USB_DWC3_AM62
in USB 2.0 mode only.
Say 'Y' or 'M' here if you have one such device
+config USB_DWC3_GENERIC_PLAT
+ tristate "DWC3 Generic Platform Driver"
+ depends on OF && COMMON_CLK
+ default ARCH_LAYERSCAPE
+ help
+ Support USB3 functionality in simple SoC integrations.
+ Currently supports SpacemiT and Layerscape DWC USB3. Platforms using
+ dwc3-of-simple can easily switch to dwc3-generic by flattening
+ the dwc3 child node in the device tree.
+ Say 'Y' or 'M' here if your platform integrates DWC3 in a similar way.
+
endif
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index 31acda1825f5..cd7e217c7c9b 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -15,3 +15,4 @@ endif
obj-$(CONFIG_USB_DWC3_OF_SIMPLE) += dwc3-of-simple.o
obj-$(CONFIG_USB_DWC3_AM62) += dwc3-am62.o
obj-$(CONFIG_USB_DWC3_IMX8MP) += dwc3-imx8mp.o
+obj-$(CONFIG_USB_DWC3_GENERIC_PLAT) += dwc3-generic-plat.o
diff --git a/drivers/usb/dwc3/dwc3-generic-plat.c b/drivers/usb/dwc3/dwc3-generic-plat.c
new file mode 100644
index 000000000000..f3ab8a312696
--- /dev/null
+++ b/drivers/usb/dwc3/dwc3-generic-plat.c
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * dwc3-generic-plat.c - DesignWare USB3 generic platform driver
+ *
+ * Copyright (C) 2025 Ze Huang <huang.ze@linux.dev>
+ *
+ * Inspired by dwc3-qcom.c and dwc3-of-simple.c
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/reset.h>
+#include <linux/regmap.h>
+#include <mfd/syscon.h>
+#include "of_device.h"
+#include "glue.h"
+
+struct dwc3_generic {
+ struct device *dev;
+ struct dwc3 dwc;
+ struct clk_bulk_data *clks;
+ int num_clocks;
+ struct reset_control *resets;
+};
+
+struct dwc3_generic_config {
+ int (*init)(struct dwc3_generic *dwc3g);
+ struct dwc3_properties properties;
+};
+
+#define to_dwc3_generic(d) container_of((d), struct dwc3_generic, dwc)
+
+static int dwc3_generic_probe(struct device *dev)
+{
+ const struct dwc3_generic_config *plat_config;
+ struct dwc3_probe_data probe_data = {};
+ struct dwc3_generic *dwc3g;
+ struct resource *res;
+ int ret;
+
+ dwc3g = xzalloc(sizeof(*dwc3g));
+
+ dwc3g->dev = dev;
+
+ res = dev_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "missing memory resource\n");
+ return -ENODEV;
+ }
+
+ dwc3g->resets = reset_control_array_get(dev);
+ if (IS_ERR(dwc3g->resets))
+ return dev_err_probe(dev, PTR_ERR(dwc3g->resets), "failed to get resets\n");
+
+ ret = reset_control_assert(dwc3g->resets);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to assert resets\n");
+
+ /* Not strict timing, just for safety */
+ udelay(2);
+
+ ret = reset_control_deassert(dwc3g->resets);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to deassert resets\n");
+
+ ret = clk_bulk_get_all_enabled(dwc3g->dev, &dwc3g->clks);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to get clocks\n");
+
+ dwc3g->num_clocks = ret;
+ dwc3g->dwc.dev = dev;
+ probe_data.dwc = &dwc3g->dwc;
+ probe_data.res = res;
+ probe_data.ignore_clocks_and_resets = true;
+
+ 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,
+ "failed to init platform\n");
+ }
+
+core_probe:
+ ret = dwc3_core_probe(&probe_data);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to register DWC3 Core\n");
+
+ return 0;
+}
+
+static void dwc3_generic_remove(struct device *dev)
+{
+ struct dwc3 *dwc = dev_get_drvdata(dev);
+
+ dwc3_core_remove(dwc);
+}
+
+static const struct dwc3_generic_config fsl_ls1028_dwc3 = {
+ .properties.gsbuscfg0_reqinfo = 0x2222,
+};
+
+static const struct of_device_id dwc3_generic_of_match[] = {
+ { .compatible = "spacemit,k1-dwc3", },
+ { .compatible = "fsl,ls1028a-dwc3", &fsl_ls1028_dwc3},
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, dwc3_generic_of_match);
+
+static struct driver dwc3_generic_driver = {
+ .probe = dwc3_generic_probe,
+ .remove = dwc3_generic_remove,
+ .name = "dwc3-generic-plat",
+ .of_match_table = dwc3_generic_of_match,
+};
+device_platform_driver(dwc3_generic_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DesignWare USB3 generic platform driver");
--
2.47.3
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH 5/5] Revert "ARM64: dts: Layerscape: workaround v6.19-rc1 DT sync DWC3 breakage"
2026-01-05 19:12 [PATCH 0/5] usb: dwc3: add fsl,ls1028a-dwc3 glue driver Ahmad Fatoum
` (3 preceding siblings ...)
2026-01-05 19:12 ` [PATCH 4/5] usb: dwc3: add DesignWare USB3 generic platform driver Ahmad Fatoum
@ 2026-01-05 19:12 ` Ahmad Fatoum
2026-01-06 8:12 ` [PATCH 0/5] usb: dwc3: add fsl,ls1028a-dwc3 glue driver Sascha Hauer
5 siblings, 0 replies; 7+ messages in thread
From: Ahmad Fatoum @ 2026-01-05 19:12 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Now that we have a proper LS1028 DWC3 driver in place, drop our
compatible overrides to make use of it.
This reverts commit acc9a8c3dcdd5515a2901f9e4c74ae37cd32ad6c.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
arch/arm/dts/fsl-ls1028a.dtsi | 9 ---------
arch/arm/dts/fsl-ls1046a.dtsi | 13 -------------
2 files changed, 22 deletions(-)
diff --git a/arch/arm/dts/fsl-ls1028a.dtsi b/arch/arm/dts/fsl-ls1028a.dtsi
index f3032752a09c..a15a219cfa1c 100644
--- a/arch/arm/dts/fsl-ls1028a.dtsi
+++ b/arch/arm/dts/fsl-ls1028a.dtsi
@@ -5,12 +5,3 @@ psci {
method = "smc";
};
};
-
-/* Temporary workaround pending fsl,ls1028a-dwc3 driver support */
-&usb0 {
- compatible = "snps,dwc3";
-};
-
-&usb1 {
- compatible = "snps,dwc3";
-};
diff --git a/arch/arm/dts/fsl-ls1046a.dtsi b/arch/arm/dts/fsl-ls1046a.dtsi
index badc600cab55..2dc24ba8c723 100644
--- a/arch/arm/dts/fsl-ls1046a.dtsi
+++ b/arch/arm/dts/fsl-ls1046a.dtsi
@@ -10,16 +10,3 @@ psci {
method = "smc";
};
};
-
-/* Temporary workaround pending fsl,ls1028a-dwc3 driver support */
-&usb0 {
- compatible = "snps,dwc3";
-};
-
-&usb1 {
- compatible = "snps,dwc3";
-};
-
-&usb2 {
- compatible = "snps,dwc3";
-};
--
2.47.3
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH 0/5] usb: dwc3: add fsl,ls1028a-dwc3 glue driver
2026-01-05 19:12 [PATCH 0/5] usb: dwc3: add fsl,ls1028a-dwc3 glue driver Ahmad Fatoum
` (4 preceding siblings ...)
2026-01-05 19:12 ` [PATCH 5/5] Revert "ARM64: dts: Layerscape: workaround v6.19-rc1 DT sync DWC3 breakage" Ahmad Fatoum
@ 2026-01-06 8:12 ` Sascha Hauer
5 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2026-01-06 8:12 UTC (permalink / raw)
To: barebox, Ahmad Fatoum
On Mon, 05 Jan 2026 20:12:51 +0100, Ahmad Fatoum wrote:
> Linux seems to move towards not having glue device tree nodes separate
> from the DWC3 nodes. Import the Linux generic driver for use with
> Layerscape and other platforms that may be migrated in future.
>
> This meant for next and applies on top of the temporary workaround in
> master at
> https://lore.barebox.org/barebox/20260105151921.224540-1-a.fatoum@pengutronix.de/T/#u
>
> [...]
Applied, thanks!
[1/5] usb: dwc3: export dwc3_core_probe/dwc3_core_remove like Linux
https://git.pengutronix.de/cgit/barebox/commit/?id=f36ec7051dc4 (link may not be stable)
[2/5] usb: dwc3: add support for Global SoC Bus Configuration Register
https://git.pengutronix.de/cgit/barebox/commit/?id=cb4e575ec7b2 (link may not be stable)
[3/5] clk: implement and use clk_bulk_get_all_enabled helper
https://git.pengutronix.de/cgit/barebox/commit/?id=e7a0dc15e85c (link may not be stable)
[4/5] usb: dwc3: add DesignWare USB3 generic platform driver
https://git.pengutronix.de/cgit/barebox/commit/?id=6d072e926d20 (link may not be stable)
[5/5] Revert "ARM64: dts: Layerscape: workaround v6.19-rc1 DT sync DWC3 breakage"
https://git.pengutronix.de/cgit/barebox/commit/?id=46f0a50848e9 (link may not be stable)
Best regards,
--
Sascha Hauer <s.hauer@pengutronix.de>
^ permalink raw reply [flat|nested] 7+ messages in thread