All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] usb: dwc3: add Layerscape SoC support
@ 2021-10-13 17:44 Michael Walle
  2021-10-13 17:44 ` [PATCH 1/8] dm: core: add ofnode_for_each_compatible_node() Michael Walle
                   ` (7 more replies)
  0 siblings, 8 replies; 10+ messages in thread
From: Michael Walle @ 2021-10-13 17:44 UTC (permalink / raw)
  To: u-boot; +Cc: Marek Vasut, Simon Glass, Ran Wang, Michael Walle

Primarily, this will add support for peripheral mode on Layerscape SoCs.
For this to work, we have to backport two fixes from linux and fix the
fixup code for the DWC3 controller (which enables snooping because the SoC
has wrong startup defaults).

As a first user of the driver, enable it on the Kontron SL28 board, where
both host and peripheral mode was tested.

OTG mode is not supported. For this to work, one would need to read the
hardware status of the OTG pin in the bind() op. But it isn't allowed to
access the hardware in the bind() op (if I understand Simon correctly).

Michael Walle (8):
  dm: core: add ofnode_for_each_compatible_node()
  armv8: fsl-layerscape: rework the dwc3 snooping enable code
  usb: common: silence dubious errors
  usb: dwc3: Add frame length adjustment quirk
  usb: dwc3: Enable undefined length INCR burst type
  usb: dwc3: add layerscape support
  board: sl28: switch to dwc3 driver
  board: sl28: enable USB periheral support and gadgets

 arch/arm/cpu/armv8/fsl-layerscape/soc.c |  28 ++-
 configs/kontron_sl28_defconfig          |   9 +-
 drivers/usb/common/common.c             |   4 +-
 drivers/usb/dwc3/Kconfig                |  10 ++
 drivers/usb/dwc3/Makefile               |   1 +
 drivers/usb/dwc3/core.c                 |  95 ++++++++++
 drivers/usb/dwc3/core.h                 |  22 +++
 drivers/usb/dwc3/dwc3-layerscape.c      | 222 ++++++++++++++++++++++++
 include/dm/ofnode.h                     |  24 +++
 9 files changed, 397 insertions(+), 18 deletions(-)
 create mode 100644 drivers/usb/dwc3/dwc3-layerscape.c

-- 
2.30.2


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/8] dm: core: add ofnode_for_each_compatible_node()
  2021-10-13 17:44 [PATCH 0/8] usb: dwc3: add Layerscape SoC support Michael Walle
@ 2021-10-13 17:44 ` Michael Walle
  2021-10-14 15:11   ` Simon Glass
  2021-10-13 17:44 ` [PATCH 2/8] armv8: fsl-layerscape: rework the dwc3 snooping enable code Michael Walle
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 10+ messages in thread
From: Michael Walle @ 2021-10-13 17:44 UTC (permalink / raw)
  To: u-boot; +Cc: Marek Vasut, Simon Glass, Ran Wang, Michael Walle

Add a helper to iterate over all nodes with a given compatible string.

Signed-off-by: Michael Walle <michael@walle.cc>
---
 include/dm/ofnode.h | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 6a714d0c7b..0f680e5aa6 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -1009,6 +1009,30 @@ ofnode ofnode_by_prop_value(ofnode from, const char *propname,
 	     ofnode_valid(node); \
 	     node = ofnode_next_subnode(node))
 
+/**
+ * ofnode_for_each_compatible_node() - iterate over all nodes with a given
+ *				       compatible string
+ *
+ * @node:       child node (ofnode, lvalue)
+ * @compat:     compatible string to match
+ *
+ * This is a wrapper around a for loop and is used like so:
+ *
+ *	ofnode node;
+ *
+ *	ofnode_for_each_compatible_node(node, parent, compatible) {
+ *		Use node
+ *		...
+ *	}
+ *
+ * Note that this is implemented as a macro and @node is used as
+ * iterator in the loop.
+ */
+#define ofnode_for_each_compatible_node(node, compat) \
+	for (node = ofnode_by_compatible(ofnode_null(), compat); \
+	     ofnode_valid(node); \
+	     node = ofnode_by_compatible(node, compat))
+
 /**
  * ofnode_get_child_count() - get the child count of a ofnode
  *
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/8] armv8: fsl-layerscape: rework the dwc3 snooping enable code
  2021-10-13 17:44 [PATCH 0/8] usb: dwc3: add Layerscape SoC support Michael Walle
  2021-10-13 17:44 ` [PATCH 1/8] dm: core: add ofnode_for_each_compatible_node() Michael Walle
@ 2021-10-13 17:44 ` Michael Walle
  2021-10-13 17:44 ` [PATCH 3/8] usb: common: silence dubious errors Michael Walle
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Michael Walle @ 2021-10-13 17:44 UTC (permalink / raw)
  To: u-boot; +Cc: Marek Vasut, Simon Glass, Ran Wang, Michael Walle

Instead of looking at all USB (host) devices, just search all DWC3
device tree nodes. This will (1) fix a panic if of_match is zero and (2)
also apply the fixup if the controller is in peripheral mode. Both
happen when the DWC3 USB controller driver is used.

Signed-off-by: Michael Walle <michael@walle.cc>
---
 arch/arm/cpu/armv8/fsl-layerscape/soc.c | 28 ++++++++++++-------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
index 41f3e95019..55b0bb50f3 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/soc.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
@@ -919,25 +919,23 @@ __weak int fsl_board_late_init(void)
 #define DWC3_GSBUSCFG0_CACHETYPE(n)        (((n) & 0xffff)            \
 	<< DWC3_GSBUSCFG0_CACHETYPE_SHIFT)
 
-void enable_dwc3_snooping(void)
+static void enable_dwc3_snooping(void)
 {
-	int ret;
-	u32 val;
-	struct udevice *bus;
-	struct uclass *uc;
+	static const char * const compatibles[] = {
+	    "fsl,layerscape-dwc3",
+	    "fsl,ls1028a-dwc3",
+	};
 	fdt_addr_t dwc3_base;
+	ofnode node;
+	u32 val;
+	int i;
 
-	ret = uclass_get(UCLASS_USB, &uc);
-	if (ret)
-		return;
-
-	uclass_foreach_dev(bus, uc) {
-		if (!strcmp(bus->driver->of_match->compatible, "fsl,layerscape-dwc3")) {
-			dwc3_base = devfdt_get_addr(bus);
-			if (dwc3_base == FDT_ADDR_T_NONE) {
-				dev_err(bus, "dwc3 regs missing\n");
+	for (i = 0; i < ARRAY_SIZE(compatibles); i++) {
+		ofnode_for_each_compatible_node(node, compatibles[i]) {
+			dwc3_base = ofnode_get_addr(node);
+			if (dwc3_base == FDT_ADDR_T_NONE)
 				continue;
-			}
+
 			val = in_le32(dwc3_base + DWC3_GSBUSCFG0);
 			val &= ~DWC3_GSBUSCFG0_CACHETYPE(~0);
 			val |= DWC3_GSBUSCFG0_CACHETYPE(0x2222);
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/8] usb: common: silence dubious errors
  2021-10-13 17:44 [PATCH 0/8] usb: dwc3: add Layerscape SoC support Michael Walle
  2021-10-13 17:44 ` [PATCH 1/8] dm: core: add ofnode_for_each_compatible_node() Michael Walle
  2021-10-13 17:44 ` [PATCH 2/8] armv8: fsl-layerscape: rework the dwc3 snooping enable code Michael Walle
@ 2021-10-13 17:44 ` Michael Walle
  2021-10-13 17:44 ` [PATCH 4/8] usb: dwc3: Add frame length adjustment quirk Michael Walle
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Michael Walle @ 2021-10-13 17:44 UTC (permalink / raw)
  To: u-boot; +Cc: Marek Vasut, Simon Glass, Ran Wang, Michael Walle

Both dr_mode and maximum-speed properties are usually optional. Drivers
will still try to fetch the properties nonetheless, which leads to error
messages, although they are no errors. Change pr_err() to pr_debug().

Signed-off-by: Michael Walle <michael@walle.cc>
---
 drivers/usb/common/common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c
index 43564c9fba..ee0c064f1f 100644
--- a/drivers/usb/common/common.c
+++ b/drivers/usb/common/common.c
@@ -29,7 +29,7 @@ enum usb_dr_mode usb_get_dr_mode(ofnode node)
 
 	dr_mode = ofnode_read_string(node, "dr_mode");
 	if (!dr_mode) {
-		pr_err("usb dr_mode not found\n");
+		pr_debug("usb dr_mode not found\n");
 		return USB_DR_MODE_UNKNOWN;
 	}
 
@@ -64,7 +64,7 @@ enum usb_device_speed usb_get_maximum_speed(ofnode node)
 
 	max_speed = ofnode_read_string(node, "maximum-speed");
 	if (!max_speed) {
-		pr_err("usb maximum-speed not found\n");
+		pr_debug("usb maximum-speed not found\n");
 		return USB_SPEED_UNKNOWN;
 	}
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/8] usb: dwc3: Add frame length adjustment quirk
  2021-10-13 17:44 [PATCH 0/8] usb: dwc3: add Layerscape SoC support Michael Walle
                   ` (2 preceding siblings ...)
  2021-10-13 17:44 ` [PATCH 3/8] usb: common: silence dubious errors Michael Walle
@ 2021-10-13 17:44 ` Michael Walle
  2021-10-13 17:44 ` [PATCH 5/8] usb: dwc3: Enable undefined length INCR burst type Michael Walle
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Michael Walle @ 2021-10-13 17:44 UTC (permalink / raw)
  To: u-boot; +Cc: Marek Vasut, Simon Glass, Ran Wang, Michael Walle

[backport from linux commit db2be4e9e30c6e43e48c5749d3fc74cee0a6bbb3]

Add adjust_frame_length_quirk for writing to fladj register
which adjusts (micro)frame length to value provided by
"snps,quirk-frame-length-adjustment" property thus avoiding
USB 2.0 devices to time-out over a longer run

Signed-off-by: Michael Walle <michael@walle.cc>
---
 drivers/usb/dwc3/core.c | 26 ++++++++++++++++++++++++++
 drivers/usb/dwc3/core.h |  6 ++++++
 2 files changed, 32 insertions(+)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index dfd7cf683f..4fb6b59d50 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -93,6 +93,27 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
 	return 0;
 }
 
+/*
+ * dwc3_frame_length_adjustment - Adjusts frame length if required
+ * @dwc3: Pointer to our controller context structure
+ * @fladj: Value of GFLADJ_30MHZ to adjust frame length
+ */
+static void dwc3_frame_length_adjustment(struct dwc3 *dwc, u32 fladj)
+{
+	u32 reg;
+
+	if (dwc->revision < DWC3_REVISION_250A)
+		return;
+
+	if (fladj == 0)
+		return;
+
+	reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
+	reg &= ~DWC3_GFLADJ_30MHZ_MASK;
+	reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | fladj;
+	dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
+}
+
 /**
  * dwc3_free_one_event_buffer - Frees one event buffer
  * @dwc: Pointer to our controller context structure
@@ -569,6 +590,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
 	if (ret)
 		goto err1;
 
+	/* Adjust Frame Length */
+	dwc3_frame_length_adjustment(dwc, dwc->fladj);
+
 	return 0;
 
 err1:
@@ -958,6 +982,8 @@ void dwc3_of_parse(struct dwc3 *dwc)
 
 	dwc->hird_threshold = hird_threshold
 		| (dwc->is_utmi_l1_suspend << 4);
+
+	dev_read_u32(dev, "snps,quirk-frame-length-adjustment", &dwc->fladj);
 }
 
 int dwc3_init(struct dwc3 *dwc)
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 1502cb859a..62e4df74fa 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -115,6 +115,7 @@
 #define DWC3_GEVNTCOUNT(n)	(0xc40c + (n * 0x10))
 
 #define DWC3_GHWPARAMS8		0xc600
+#define DWC3_GFLADJ		0xc630
 
 /* Device Registers */
 #define DWC3_DCFG		0xc700
@@ -233,6 +234,10 @@
 /* Global HWPARAMS6 Register */
 #define DWC3_GHWPARAMS6_EN_FPGA			(1 << 7)
 
+/* Global Frame Length Adjustment Register */
+#define DWC3_GFLADJ_30MHZ_SDBND_SEL		(1 << 7)
+#define DWC3_GFLADJ_30MHZ_MASK			0x3f
+
 /* Device Configuration Register */
 #define DWC3_DCFG_DEVADDR(addr)	((addr) << 3)
 #define DWC3_DCFG_DEVADDR_MASK	DWC3_DCFG_DEVADDR(0x7f)
@@ -812,6 +817,7 @@ struct dwc3 {
 	u8			test_mode_nr;
 	u8			lpm_nyet_threshold;
 	u8			hird_threshold;
+	u32			fladj;
 
 	unsigned		delayed_status:1;
 	unsigned		ep0_bounced:1;
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 5/8] usb: dwc3: Enable undefined length INCR burst type
  2021-10-13 17:44 [PATCH 0/8] usb: dwc3: add Layerscape SoC support Michael Walle
                   ` (3 preceding siblings ...)
  2021-10-13 17:44 ` [PATCH 4/8] usb: dwc3: Add frame length adjustment quirk Michael Walle
@ 2021-10-13 17:44 ` Michael Walle
  2021-10-13 17:44 ` [PATCH 6/8] usb: dwc3: add layerscape support Michael Walle
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Michael Walle @ 2021-10-13 17:44 UTC (permalink / raw)
  To: u-boot; +Cc: Marek Vasut, Simon Glass, Ran Wang, Michael Walle

[backport from linux commit d9612c2f0449e24983a8b689603210486a930c90]

Enable the undefined length INCR burst type and set INCRx.
Different platform may has the different burst size type.
In order to get best performance, we need to tune the burst
size to one special value, instead of the default value.

Signed-off-by: Michael Walle <michael@walle.cc>
---
 drivers/usb/dwc3/core.c | 69 +++++++++++++++++++++++++++++++++++++++++
 drivers/usb/dwc3/core.h | 16 ++++++++++
 2 files changed, 85 insertions(+)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 4fb6b59d50..ce1c0e88c2 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -462,6 +462,53 @@ static void dwc3_phy_setup(struct dwc3 *dwc)
 	mdelay(100);
 }
 
+/* set global incr burst type configuration registers */
+static void dwc3_set_incr_burst_type(struct dwc3 *dwc)
+{
+	struct udevice *dev = dwc->dev;
+	u32 cfg;
+
+	if (!dwc->incrx_size)
+		return;
+
+	cfg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG0);
+
+	/* Enable Undefined Length INCR Burst and Enable INCRx Burst */
+	cfg &= ~DWC3_GSBUSCFG0_INCRBRST_MASK;
+	if (dwc->incrx_mode)
+		cfg |= DWC3_GSBUSCFG0_INCRBRSTENA;
+	switch (dwc->incrx_size) {
+	case 256:
+		cfg |= DWC3_GSBUSCFG0_INCR256BRSTENA;
+		break;
+	case 128:
+		cfg |= DWC3_GSBUSCFG0_INCR128BRSTENA;
+		break;
+	case 64:
+		cfg |= DWC3_GSBUSCFG0_INCR64BRSTENA;
+		break;
+	case 32:
+		cfg |= DWC3_GSBUSCFG0_INCR32BRSTENA;
+		break;
+	case 16:
+		cfg |= DWC3_GSBUSCFG0_INCR16BRSTENA;
+		break;
+	case 8:
+		cfg |= DWC3_GSBUSCFG0_INCR8BRSTENA;
+		break;
+	case 4:
+		cfg |= DWC3_GSBUSCFG0_INCR4BRSTENA;
+		break;
+	case 1:
+		break;
+	default:
+		dev_err(dev, "Invalid property\n");
+		break;
+	}
+
+	dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, cfg);
+}
+
 /**
  * dwc3_core_init - Low-level initialization of DWC3 Core
  * @dwc: Pointer to our controller context structure
@@ -593,6 +640,8 @@ static int dwc3_core_init(struct dwc3 *dwc)
 	/* Adjust Frame Length */
 	dwc3_frame_length_adjustment(dwc, dwc->fladj);
 
+	dwc3_set_incr_burst_type(dwc);
+
 	return 0;
 
 err1:
@@ -916,6 +965,8 @@ void dwc3_of_parse(struct dwc3 *dwc)
 	u8 lpm_nyet_threshold;
 	u8 tx_de_emphasis;
 	u8 hird_threshold;
+	u32 val;
+	int i;
 
 	/* default to highest possible threshold */
 	lpm_nyet_threshold = 0xff;
@@ -984,6 +1035,24 @@ void dwc3_of_parse(struct dwc3 *dwc)
 		| (dwc->is_utmi_l1_suspend << 4);
 
 	dev_read_u32(dev, "snps,quirk-frame-length-adjustment", &dwc->fladj);
+
+	/*
+	 * Handle property "snps,incr-burst-type-adjustment".
+	 * Get the number of value from this property:
+	 * result <= 0, means this property is not supported.
+	 * result = 1, means INCRx burst mode supported.
+	 * result > 1, means undefined length burst mode supported.
+	 */
+	dwc->incrx_mode = INCRX_BURST_MODE;
+	dwc->incrx_size = 0;
+	for (i = 0; i < 8; i++) {
+		if (dev_read_u32_index(dev, "snps,incr-burst-type-adjustment",
+				       i, &val))
+			break;
+
+		dwc->incrx_mode = INCRX_UNDEF_LENGTH_BURST_MODE;
+		dwc->incrx_size = max(dwc->incrx_size, val);
+	}
 }
 
 int dwc3_init(struct dwc3 *dwc)
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 62e4df74fa..d7cce3a861 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -139,6 +139,17 @@
 
 /* Bit fields */
 
+/* Global SoC Bus Configuration INCRx Register 0 */
+#define DWC3_GSBUSCFG0_INCR256BRSTENA	(1 << 7) /* INCR256 burst */
+#define DWC3_GSBUSCFG0_INCR128BRSTENA	(1 << 6) /* INCR128 burst */
+#define DWC3_GSBUSCFG0_INCR64BRSTENA	(1 << 5) /* INCR64 burst */
+#define DWC3_GSBUSCFG0_INCR32BRSTENA	(1 << 4) /* INCR32 burst */
+#define DWC3_GSBUSCFG0_INCR16BRSTENA	(1 << 3) /* INCR16 burst */
+#define DWC3_GSBUSCFG0_INCR8BRSTENA	(1 << 2) /* INCR8 burst */
+#define DWC3_GSBUSCFG0_INCR4BRSTENA	(1 << 1) /* INCR4 burst */
+#define DWC3_GSBUSCFG0_INCRBRSTENA	(1 << 0) /* undefined length enable */
+#define DWC3_GSBUSCFG0_INCRBRST_MASK	0xff
+
 /* Global Configuration Register */
 #define DWC3_GCTL_PWRDNSCALE(n)	((n) << 19)
 #define DWC3_GCTL_U2RSTECN	(1 << 16)
@@ -818,6 +829,8 @@ struct dwc3 {
 	u8			lpm_nyet_threshold;
 	u8			hird_threshold;
 	u32			fladj;
+	u8			incrx_mode;
+	u32			incrx_size;
 
 	unsigned		delayed_status:1;
 	unsigned		ep0_bounced:1;
@@ -855,6 +868,9 @@ struct dwc3 {
 	struct list_head        list;
 };
 
+#define INCRX_BURST_MODE 0
+#define INCRX_UNDEF_LENGTH_BURST_MODE 1
+
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 6/8] usb: dwc3: add layerscape support
  2021-10-13 17:44 [PATCH 0/8] usb: dwc3: add Layerscape SoC support Michael Walle
                   ` (4 preceding siblings ...)
  2021-10-13 17:44 ` [PATCH 5/8] usb: dwc3: Enable undefined length INCR burst type Michael Walle
@ 2021-10-13 17:44 ` Michael Walle
  2021-10-13 17:44 ` [PATCH 7/8] board: sl28: switch to dwc3 driver Michael Walle
  2021-10-13 17:44 ` [PATCH 8/8] board: sl28: enable USB periheral support and gadgets Michael Walle
  7 siblings, 0 replies; 10+ messages in thread
From: Michael Walle @ 2021-10-13 17:44 UTC (permalink / raw)
  To: u-boot; +Cc: Marek Vasut, Simon Glass, Ran Wang, Michael Walle

Add support for the proper dwc3 device tree binding support as specified
in the offical device tree spec.

Initially, add support for the LS1028A support. Other SoCs should be
easy to add by just adding the corresponding compatible string.
Unfortunately, the device trees of all other layerscape SoCs are not
converted and uses a wrong compatible string only known in u-boot.

To maintain backwards compatibility with current u-boot device trees,
add the generic "fsl,layerscape-dwc3" compatible string.

OTG mode is not supported yet. The dr_mode in the devicetree will either
have to be set to peripheral or host.

Signed-off-by: Michael Walle <michael@walle.cc>
---
 drivers/usb/dwc3/Kconfig           |  10 ++
 drivers/usb/dwc3/Makefile          |   1 +
 drivers/usb/dwc3/dwc3-layerscape.c | 222 +++++++++++++++++++++++++++++
 3 files changed, 233 insertions(+)
 create mode 100644 drivers/usb/dwc3/dwc3-layerscape.c

diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 93707e05fb..62aa65bf0c 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -53,6 +53,16 @@ config USB_DWC3_UNIPHIER
 	  Support of USB2/3 functionality in Socionext UniPhier platforms.
 	  Say 'Y' here if you have one such device.
 
+config USB_DWC3_LAYERSCAPE
+	bool "Freescale Layerscape platform support"
+	depends on DM_USB && USB_DWC3
+	depends on !USB_XHCI_FSL
+	help
+	  Select this for Freescale Layerscape Platforms.
+
+	  Host and Peripheral operation modes are supported. OTG is not
+	  supported.
+
 menu "PHY Subsystem"
 
 config USB_DWC3_PHY_OMAP
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index 6e3e024e97..0dd1ba87cd 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -11,5 +11,6 @@ obj-$(CONFIG_USB_DWC3_MESON_G12A)	+= dwc3-meson-g12a.o
 obj-$(CONFIG_USB_DWC3_MESON_GXL)	+= dwc3-meson-gxl.o
 obj-$(CONFIG_USB_DWC3_GENERIC)		+= dwc3-generic.o
 obj-$(CONFIG_USB_DWC3_UNIPHIER)		+= dwc3-uniphier.o
+obj-$(CONFIG_USB_DWC3_LAYERSCAPE)	+= dwc3-layerscape.o
 obj-$(CONFIG_USB_DWC3_PHY_OMAP)		+= ti_usb_phy.o
 obj-$(CONFIG_USB_DWC3_PHY_SAMSUNG)	+= samsung_usb_phy.o
diff --git a/drivers/usb/dwc3/dwc3-layerscape.c b/drivers/usb/dwc3/dwc3-layerscape.c
new file mode 100644
index 0000000000..79cf71f7a8
--- /dev/null
+++ b/drivers/usb/dwc3/dwc3-layerscape.c
@@ -0,0 +1,222 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Layerscape DWC3 Glue layer
+ *
+ * Copyright (C) 2021 Michael Walle <michael@walle.cc>
+ *
+ * Based on dwc3-generic.c.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dwc3-uboot.h>
+#include <linux/usb/gadget.h>
+#include <usb.h>
+#include "core.h"
+#include "gadget.h"
+#include <usb/xhci.h>
+
+struct dwc3_layerscape_plat {
+	fdt_addr_t base;
+	u32 maximum_speed;
+	enum usb_dr_mode dr_mode;
+};
+
+struct dwc3_layerscape_priv {
+	void *base;
+	struct dwc3 dwc3;
+	struct phy_bulk phys;
+};
+
+struct dwc3_layerscape_host_priv {
+	struct xhci_ctrl xhci_ctrl;
+	struct dwc3_layerscape_priv gen_priv;
+};
+
+static int dwc3_layerscape_probe(struct udevice *dev,
+				 struct dwc3_layerscape_priv *priv)
+{
+	int rc;
+	struct dwc3_layerscape_plat *plat = dev_get_plat(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);
+
+	rc = dwc3_setup_phy(dev, &priv->phys);
+	if (rc && rc != -ENOTSUPP)
+		return rc;
+
+	priv->base = map_physmem(plat->base, DWC3_OTG_REGS_END, MAP_NOCACHE);
+	dwc3->regs = priv->base + DWC3_GLOBALS_REGS_START;
+
+	rc =  dwc3_init(dwc3);
+	if (rc) {
+		unmap_physmem(priv->base, MAP_NOCACHE);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int dwc3_layerscape_remove(struct udevice *dev,
+				  struct dwc3_layerscape_priv *priv)
+{
+	struct dwc3 *dwc3 = &priv->dwc3;
+
+	dwc3_remove(dwc3);
+	dwc3_shutdown_phy(dev, &priv->phys);
+	unmap_physmem(dwc3->regs, MAP_NOCACHE);
+
+	return 0;
+}
+
+static int dwc3_layerscape_of_to_plat(struct udevice *dev)
+{
+	struct dwc3_layerscape_plat *plat = dev_get_plat(dev);
+	ofnode node = dev_ofnode(dev);
+
+	plat->base = dev_read_addr(dev);
+
+	plat->maximum_speed = usb_get_maximum_speed(node);
+	if (plat->maximum_speed == USB_SPEED_UNKNOWN) {
+		dev_dbg(dev, "No USB maximum speed specified. Using super speed\n");
+		plat->maximum_speed = USB_SPEED_SUPER;
+	}
+
+	plat->dr_mode = usb_get_dr_mode(node);
+	if (plat->dr_mode == USB_DR_MODE_UNKNOWN) {
+		dev_err(dev, "Invalid usb mode setup\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+int dm_usb_gadget_handle_interrupts(struct udevice *dev)
+{
+	struct dwc3_layerscape_priv *priv = dev_get_priv(dev);
+
+	dwc3_gadget_uboot_handle_interrupt(&priv->dwc3);
+
+	return 0;
+}
+
+static int dwc3_layerscape_peripheral_probe(struct udevice *dev)
+{
+	struct dwc3_layerscape_priv *priv = dev_get_priv(dev);
+
+	return dwc3_layerscape_probe(dev, priv);
+}
+
+static int dwc3_layerscape_peripheral_remove(struct udevice *dev)
+{
+	struct dwc3_layerscape_priv *priv = dev_get_priv(dev);
+
+	return dwc3_layerscape_remove(dev, priv);
+}
+
+U_BOOT_DRIVER(dwc3_layerscape_peripheral) = {
+	.name	= "dwc3-layerscape-peripheral",
+	.id	= UCLASS_USB_GADGET_GENERIC,
+	.of_to_plat = dwc3_layerscape_of_to_plat,
+	.probe = dwc3_layerscape_peripheral_probe,
+	.remove = dwc3_layerscape_peripheral_remove,
+	.priv_auto	= sizeof(struct dwc3_layerscape_priv),
+	.plat_auto	= sizeof(struct dwc3_layerscape_plat),
+};
+#endif
+
+#if defined(CONFIG_SPL_USB_HOST_SUPPORT) || \
+	!defined(CONFIG_SPL_BUILD) && defined(CONFIG_USB_HOST)
+static int dwc3_layerscape_host_probe(struct udevice *dev)
+{
+	struct xhci_hcor *hcor;
+	struct xhci_hccr *hccr;
+	struct dwc3_layerscape_host_priv *priv = dev_get_priv(dev);
+	int rc;
+
+	rc = dwc3_layerscape_probe(dev, &priv->gen_priv);
+	if (rc)
+		return rc;
+
+	hccr = priv->gen_priv.base;
+	hcor = priv->gen_priv.base + HC_LENGTH(xhci_readl(&hccr->cr_capbase));
+
+	return xhci_register(dev, hccr, hcor);
+}
+
+static int dwc3_layerscape_host_remove(struct udevice *dev)
+{
+	struct dwc3_layerscape_host_priv *priv = dev_get_priv(dev);
+	int rc;
+
+	rc = xhci_deregister(dev);
+	if (rc)
+		return rc;
+
+	return dwc3_layerscape_remove(dev, &priv->gen_priv);
+}
+
+U_BOOT_DRIVER(dwc3_layerscape_host) = {
+	.name	= "dwc3-layerscape-host",
+	.id	= UCLASS_USB,
+	.of_to_plat = dwc3_layerscape_of_to_plat,
+	.probe = dwc3_layerscape_host_probe,
+	.remove = dwc3_layerscape_host_remove,
+	.priv_auto	= sizeof(struct dwc3_layerscape_host_priv),
+	.plat_auto	= sizeof(struct dwc3_layerscape_plat),
+	.ops = &xhci_usb_ops,
+	.flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
+#endif
+
+static int dwc3_layerscape_bind(struct udevice *dev)
+{
+	ofnode node = dev_ofnode(dev);
+	const char *name = ofnode_get_name(node);
+	enum usb_dr_mode dr_mode;
+	char *driver;
+
+	dr_mode = usb_get_dr_mode(node);
+
+	switch (dr_mode) {
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+	case USB_DR_MODE_PERIPHERAL:
+		dev_dbg(dev, "Using peripheral mode\n");
+		driver = "dwc3-layerscape-peripheral";
+		break;
+#endif
+#if defined(CONFIG_SPL_USB_HOST_SUPPORT) || !defined(CONFIG_SPL_BUILD)
+	case USB_DR_MODE_HOST:
+		dev_dbg(dev, "Using host mode\n");
+		driver = "dwc3-layerscape-host";
+		break;
+#endif
+	default:
+		dev_dbg(dev, "Unsupported dr_mode\n");
+		return -ENODEV;
+	};
+
+	return device_bind_driver_to_node(dev, driver, name, node, NULL);
+}
+
+static const struct udevice_id dwc3_layerscape_ids[] = {
+	{ .compatible = "fsl,layerscape-dwc3" },
+	{ .compatible = "fsl,ls1028a-dwc3" },
+	{ }
+};
+
+U_BOOT_DRIVER(dwc3_layerscape_wrapper) = {
+	.name	= "dwc3-layerscape-wrapper",
+	.id	= UCLASS_NOP,
+	.of_match = dwc3_layerscape_ids,
+	.bind = dwc3_layerscape_bind,
+};
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 7/8] board: sl28: switch to dwc3 driver
  2021-10-13 17:44 [PATCH 0/8] usb: dwc3: add Layerscape SoC support Michael Walle
                   ` (5 preceding siblings ...)
  2021-10-13 17:44 ` [PATCH 6/8] usb: dwc3: add layerscape support Michael Walle
@ 2021-10-13 17:44 ` Michael Walle
  2021-10-13 17:44 ` [PATCH 8/8] board: sl28: enable USB periheral support and gadgets Michael Walle
  7 siblings, 0 replies; 10+ messages in thread
From: Michael Walle @ 2021-10-13 17:44 UTC (permalink / raw)
  To: u-boot; +Cc: Marek Vasut, Simon Glass, Ran Wang, Michael Walle

Now that the DWC3 USB driver has support for the layerscape platform,
use it. This will have the benefit that peripheral mode will work.

Signed-off-by: Michael Walle <michael@walle.cc>
---
 configs/kontron_sl28_defconfig | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/configs/kontron_sl28_defconfig b/configs/kontron_sl28_defconfig
index 4e25dafaaf..5b3ba58d39 100644
--- a/configs/kontron_sl28_defconfig
+++ b/configs/kontron_sl28_defconfig
@@ -91,6 +91,8 @@ CONFIG_NXP_FSPI=y
 CONFIG_USB=y
 # CONFIG_SPL_DM_USB is not set
 CONFIG_USB_XHCI_HCD=y
-CONFIG_USB_XHCI_DWC3=y
+# CONFIG_USB_XHCI_FSL is not set
+CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_LAYERSCAPE=y
 CONFIG_OF_LIBFDT_ASSUME_MASK=0x0
 CONFIG_OF_LIBFDT_OVERLAY=y
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 8/8] board: sl28: enable USB periheral support and gadgets
  2021-10-13 17:44 [PATCH 0/8] usb: dwc3: add Layerscape SoC support Michael Walle
                   ` (6 preceding siblings ...)
  2021-10-13 17:44 ` [PATCH 7/8] board: sl28: switch to dwc3 driver Michael Walle
@ 2021-10-13 17:44 ` Michael Walle
  7 siblings, 0 replies; 10+ messages in thread
From: Michael Walle @ 2021-10-13 17:44 UTC (permalink / raw)
  To: u-boot; +Cc: Marek Vasut, Simon Glass, Ran Wang, Michael Walle

Enable support to update the board via the DFU protocol and make it
possible to export the block devices via USB mass storage protocol.

This will not work out of the box, yet. You have to change the dr_mode
of the usb0 controller to peripheral manually to make it work. True, OTG
support will hopefully coming soon.

Signed-off-by: Michael Walle <michael@walle.cc>
---
 configs/kontron_sl28_defconfig | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/configs/kontron_sl28_defconfig b/configs/kontron_sl28_defconfig
index 5b3ba58d39..0da31a4e54 100644
--- a/configs/kontron_sl28_defconfig
+++ b/configs/kontron_sl28_defconfig
@@ -39,12 +39,14 @@ CONFIG_SYS_SPI_U_BOOT_OFFS=0x230000
 CONFIG_CMD_ASKENV=y
 CONFIG_CMD_GREPENV=y
 CONFIG_CMD_NVEDIT_EFI=y
+CONFIG_CMD_DFU=y
 CONFIG_CMD_DM=y
 CONFIG_CMD_GPT=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_PCI=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_EFIDEBUG=y
 CONFIG_CMD_RNG=y
@@ -90,9 +92,12 @@ CONFIG_FSL_DSPI=y
 CONFIG_NXP_FSPI=y
 CONFIG_USB=y
 # CONFIG_SPL_DM_USB is not set
+CONFIG_DM_USB_GADGET=y
 CONFIG_USB_XHCI_HCD=y
 # CONFIG_USB_XHCI_FSL is not set
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_LAYERSCAPE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_OF_LIBFDT_ASSUME_MASK=0x0
 CONFIG_OF_LIBFDT_OVERLAY=y
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/8] dm: core: add ofnode_for_each_compatible_node()
  2021-10-13 17:44 ` [PATCH 1/8] dm: core: add ofnode_for_each_compatible_node() Michael Walle
@ 2021-10-14 15:11   ` Simon Glass
  0 siblings, 0 replies; 10+ messages in thread
From: Simon Glass @ 2021-10-14 15:11 UTC (permalink / raw)
  To: Michael Walle; +Cc: U-Boot Mailing List, Marek Vasut, Ran Wang

On Wed, 13 Oct 2021 at 11:44, Michael Walle <michael@walle.cc> wrote:
>
> Add a helper to iterate over all nodes with a given compatible string.
>
> Signed-off-by: Michael Walle <michael@walle.cc>
> ---
>  include/dm/ofnode.h | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>

Reviewed-by: Simon Glass <sjg@chromium.org>

Can you add a test for it in test/dm/ofnode.c?

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2021-10-14 15:17 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-13 17:44 [PATCH 0/8] usb: dwc3: add Layerscape SoC support Michael Walle
2021-10-13 17:44 ` [PATCH 1/8] dm: core: add ofnode_for_each_compatible_node() Michael Walle
2021-10-14 15:11   ` Simon Glass
2021-10-13 17:44 ` [PATCH 2/8] armv8: fsl-layerscape: rework the dwc3 snooping enable code Michael Walle
2021-10-13 17:44 ` [PATCH 3/8] usb: common: silence dubious errors Michael Walle
2021-10-13 17:44 ` [PATCH 4/8] usb: dwc3: Add frame length adjustment quirk Michael Walle
2021-10-13 17:44 ` [PATCH 5/8] usb: dwc3: Enable undefined length INCR burst type Michael Walle
2021-10-13 17:44 ` [PATCH 6/8] usb: dwc3: add layerscape support Michael Walle
2021-10-13 17:44 ` [PATCH 7/8] board: sl28: switch to dwc3 driver Michael Walle
2021-10-13 17:44 ` [PATCH 8/8] board: sl28: enable USB periheral support and gadgets Michael Walle

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.