mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Rob Herring <robh@kernel.org>,
	Krzysztof Kozlowski <krzk+dt@kernel.org>,
	Conor Dooley <conor+dt@kernel.org>,
	Felipe Balbi <balbi@kernel.org>,
	Wesley Cheng <quic_wcheng@quicinc.com>,
	Saravana Kannan <saravanak@google.com>,
	Thinh Nguyen <Thinh.Nguyen@synopsys.com>,
	Philipp Zabel <p.zabel@pengutronix.de>,
	Bjorn Andersson <andersson@kernel.org>,
	Konrad Dybcio <konradybcio@kernel.org>,
	Frank Li <Frank.li@nxp.com>
Cc: linux-arm-msm@vger.kernel.org, linux-usb@vger.kernel.org,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
Subject: [PATCH v3 04/12] of: overlays: Introduce dwc3 flattening overlay
Date: Mon, 13 Jan 2025 21:11:37 -0800	[thread overview]
Message-ID: <20250113-dwc3-refactor-v3-4-d1722075df7b@oss.qualcomm.com> (raw)
In-Reply-To: <20250113-dwc3-refactor-v3-0-d1722075df7b@oss.qualcomm.com>

The Synopsys DWC3 core is often found together with vendor glue logic.
While being a single piece of hardware this has been expressed as two
independent (although with parent/child relationship) nodes in
DeviceTree - but they are not separate components, and the separation
prevents implementation of certain features (such as role switching,
when this involved both parts).

The newly introduced qcom,snps-dwc3 binding changes this representation
of the Qualcomm implementation to a single node, and in an upcoming
change the implementation follows suite - combining the two separate
drivers into a single device instance.

In order to avoid two separate implementations of the Qualcomm DWC3 glue
driver, and/or continue to live with the documented race conditions in
the driver, the driver will be changed to only operate on the new -
flattened - DeviceTree binding.

As both the Qualcomm glue driver and the dwc3 core driver is parsing
DeviceTree, the only sensible way to handle this - while maintaining
backwards compatibility with exiting DeviceTree blobs, is to convert the
representation at runtime.

The conversion between qcom,dwc3 and qcom,snps-dwc3 is performed here in
the form of an independent overlay-based mechanism, to avoid sprinkling
DeviceTree-translation code into the glue driver, which over time is
expected to allow hiding some internals of the OF-code. But this should
also make it suitable for other (than Qualcomm) vendors to reuse the
translation logic as they flatten their glue/dwc3 implementations.

The migration is implemented using two steps:
1) SoC/board integration is migrated using embedded overlays, which are
   applied based on machine compatible matching. This handles the
   complex cases such as merging "reg" and "interrupt" properties.
2) Standard snps properties, which might be board-specific, are migrated
   using of_changeset logic. Notably the of_graph is migrated this way,
   to avoid having to provide overlays for every single board dtb out
   there.

The migration code can only be enabled once the dwc3 glue driver
supports the new binding, but in order to avoid having to support both
bindings in the dwc3 glue a kill-switch is left in place, to be removed
at the instant the driver is converted.

The newly introduced Kconfig option is defaulted to follow USB_DWC3_QCOM
in order to maximize the chances of people not losing USB functionality
in defconfig or distro builds. Over time this can probably be phased
out, followed by the overlay solution itself.

Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
---
 drivers/of/Kconfig                                 |   2 +
 drivers/of/Makefile                                |   2 +
 drivers/of/overlays/Kconfig                        |  15 ++
 drivers/of/overlays/Makefile                       |   3 +
 drivers/of/overlays/dwc3-flattening/Makefile       |   4 +
 .../of/overlays/dwc3-flattening/dwc3-flattening.c  | 160 +++++++++++++++++++++
 .../of/overlays/dwc3-flattening/dwc3-flattening.h  |   7 +
 7 files changed, 193 insertions(+)

diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 50697cc3b07e..b5f3cd69bad9 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -126,4 +126,6 @@ config OF_OVERLAY_KUNIT_TEST
 config OF_NUMA
 	bool
 
+source "drivers/of/overlays/Kconfig"
+
 endif # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index 379a0afcbdc0..1ff9d0befb38 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -25,3 +25,5 @@ obj-$(CONFIG_OF_OVERLAY_KUNIT_TEST) += overlay-test.o
 overlay-test-y := overlay_test.o kunit_overlay_test.dtbo.o
 
 obj-$(CONFIG_OF_UNITTEST) += unittest-data/
+
+obj-y += overlays/
diff --git a/drivers/of/overlays/Kconfig b/drivers/of/overlays/Kconfig
new file mode 100644
index 000000000000..8f07e6db3dc3
--- /dev/null
+++ b/drivers/of/overlays/Kconfig
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config OF_OVERLAYS_DWC3_FLATTENING
+	bool "DeviceTree overlay for migrating DWC3 glue bindings"
+	depends on OF
+	select OF_DYNAMIC
+	select OF_OVERLAY
+	default USB_DWC3_QCOM
+	help
+	  This option enables the migration of the loaded DeviceTree from the
+	  binding that splits DWC3 representation in glue and core nodes (such
+	  as "qcom,dwc3"), to the unified binding ("qcom,snps-dwc3").
+
+	  Enable this if you intend to boot the Linux kernel on a system with a
+	  DeviceTree blob using the non-flattened binding.
diff --git a/drivers/of/overlays/Makefile b/drivers/of/overlays/Makefile
new file mode 100644
index 000000000000..44dd5c09ac8d
--- /dev/null
+++ b/drivers/of/overlays/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_OF_OVERLAYS_DWC3_FLATTENING) += dwc3-flattening/
diff --git a/drivers/of/overlays/dwc3-flattening/Makefile b/drivers/of/overlays/dwc3-flattening/Makefile
new file mode 100644
index 000000000000..78ed59517887
--- /dev/null
+++ b/drivers/of/overlays/dwc3-flattening/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_OF_OVERLAYS_DWC3_FLATTENING) += dwc3-flattening-overlay.o
+dwc3-flattening-overlay-y += dwc3-flattening.o
diff --git a/drivers/of/overlays/dwc3-flattening/dwc3-flattening.c b/drivers/of/overlays/dwc3-flattening/dwc3-flattening.c
new file mode 100644
index 000000000000..fe8e42627fe3
--- /dev/null
+++ b/drivers/of/overlays/dwc3-flattening/dwc3-flattening.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#define pr_fmt(fmt) "dwc3-flattening: " fmt
+
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include "dwc3-flattening.h"
+
+struct dwc3_overlay_symbol {
+	const char *symbol;
+	const char *path;
+};
+
+struct dwc3_overlay_data {
+	const void *fdt;
+	const void *end;
+	const char *migrate_match;
+};
+
+static const struct of_device_id dwc3_flatten_of_match[] = {
+	{}
+};
+
+static int dwc3_flattening_copy_snps_properties(struct of_changeset *ocs,
+						struct device_node *np,
+						struct device_node *dwc3)
+{
+	struct property *prop;
+	int ret = 0;
+
+	for_each_property_of_node(dwc3, prop) {
+		if (strncmp(prop->name, "snps,", 5) &&
+		    strcmp(prop->name, "usb-role-switch") &&
+		    strcmp(prop->name, "dr_mode") &&
+		    strcmp(prop->name, "tx-fifo-resize") &&
+		    strcmp(prop->name, "maximum-speed"))
+			continue;
+
+		ret = of_changeset_add_prop_copy(ocs, np, prop);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+static int dwc3_flattening_copy_ports_tree(struct of_changeset *ocs,
+					   struct device_node *new_parent,
+					   struct device_node *old_node)
+{
+	struct device_node *new_node;
+	struct property *prop;
+	int ret;
+
+	new_node = of_changeset_create_node(ocs, new_parent, old_node->full_name);
+	if (!new_node)
+		return -ENOMEM;
+
+	for_each_property_of_node(old_node, prop) {
+		of_changeset_add_prop_copy(ocs, new_node, prop);
+	}
+
+	for_each_child_of_node_scoped(old_node, child) {
+		ret = dwc3_flattening_copy_ports_tree(ocs, new_node, child);
+		if (ret)
+			return ret;
+	}
+
+	return of_changeset_detach_node(ocs, old_node);
+}
+
+static int dwc3_flattening_migrate(struct of_changeset *ocs,
+				   struct device_node *np)
+{
+	struct device_node *ports;
+	struct device_node *dwc3;
+	int ret;
+
+	dwc3 = of_get_compatible_child(np, "snps,dwc3");
+	if (!dwc3)
+		return 0;
+
+	ret = dwc3_flattening_copy_snps_properties(ocs, np, dwc3);
+	if (ret) {
+		pr_err("failed to copy properties of %pOF", dwc3);
+		goto out;
+	}
+
+	ports = of_get_child_by_name(dwc3, "ports");
+	if (ports) {
+		ret = dwc3_flattening_copy_ports_tree(ocs, np, ports);
+		of_node_put(ports);
+		if (ret) {
+			pr_err("failed to clone ports child of %pOF", dwc3);
+			goto out;
+		}
+	}
+
+	ret = of_changeset_detach_node(ocs, dwc3);
+
+out:
+	of_node_put(dwc3);
+
+	return ret;
+}
+
+static int dwc3_flattening_init(void)
+{
+	const struct dwc3_overlay_data *data;
+	const struct of_device_id *match;
+	struct of_changeset migrate_ocs;
+	struct device_node *np;
+	int overlay_ovcs;
+	int ret;
+
+	/* TODO: Remove kill-switch as dwc3-qcom is migrated to qcom,snps-dwc */
+	return 0;
+
+	match = of_match_node(dwc3_flatten_of_match, of_root);
+	if (!match)
+		return 0;
+
+	data = match->data;
+
+	np = of_find_compatible_node(NULL, NULL, data->migrate_match);
+	if (!np) {
+		pr_debug("already applied\n");
+		return 0;
+	}
+	of_node_put(np);
+
+	of_changeset_init(&migrate_ocs);
+	for_each_compatible_node(np, NULL, data->migrate_match) {
+		ret = dwc3_flattening_migrate(&migrate_ocs, np);
+		if (ret < 0) {
+			of_node_put(np);
+			goto out_migrate_destroy;
+		}
+	}
+
+	ret = of_changeset_apply(&migrate_ocs);
+	if (ret < 0)
+		goto out_migrate_destroy;
+
+	ret = of_overlay_fdt_apply(data->fdt, data->end - data->fdt, &overlay_ovcs, NULL);
+	if (ret < 0) {
+		of_overlay_remove(&overlay_ovcs);
+		of_changeset_revert(&migrate_ocs);
+	}
+
+out_migrate_destroy:
+	of_changeset_destroy(&migrate_ocs);
+
+	return ret;
+}
+postcore_initcall(dwc3_flattening_init);
diff --git a/drivers/of/overlays/dwc3-flattening/dwc3-flattening.h b/drivers/of/overlays/dwc3-flattening/dwc3-flattening.h
new file mode 100644
index 000000000000..6147376d3c92
--- /dev/null
+++ b/drivers/of/overlays/dwc3-flattening/dwc3-flattening.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DWC3_FLATTENING_H__
+#define __DWC3_FLATTENING_H__
+
+#include <linux/kernel.h>
+
+#endif

-- 
2.45.2


  parent reply	other threads:[~2025-01-14  5:05 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-14  5:11 [PATCH v3 00/12] usb: dwc3: qcom: Flatten dwc3 structure Bjorn Andersson
2025-01-14  5:11 ` [PATCH v3 01/12] dt-bindings: usb: snps,dwc3: Split core description Bjorn Andersson
2025-01-14  5:11 ` [PATCH v3 02/12] dt-bindings: usb: Introduce qcom,snps-dwc3 Bjorn Andersson
2025-01-14  5:11 ` [PATCH v3 03/12] of: dynamic: Add of_changeset_add_prop_copy() Bjorn Andersson
2025-01-14  5:11 ` Bjorn Andersson [this message]
2025-01-14  5:11 ` [PATCH v3 05/12] of: overlays: dwc3-flattening: Add Qualcomm Arm32 overlays Bjorn Andersson
2025-01-14  5:11 ` [PATCH v3 06/12] of: overlays: dwc3-flattening: Add Qualcomm Arm64 board overlays Bjorn Andersson
2025-01-14 17:42   ` Rob Herring
2025-01-14 22:46     ` Bjorn Andersson
2025-01-14  5:11 ` [PATCH v3 07/12] of: overlays: dwc3-flattening: Provide overlay symbols Bjorn Andersson
2025-01-14  5:11 ` [PATCH v3 08/12] usb: dwc3: core: Expose core driver as library Bjorn Andersson
2025-01-14 19:43   ` Frank Li
2025-01-14 22:55     ` Bjorn Andersson
2025-01-15  1:56       ` Thinh Nguyen
2025-01-15  2:59         ` Thinh Nguyen
2025-01-14  5:11 ` [PATCH v3 09/12] usb: dwc3: core: Don't touch resets and clocks Bjorn Andersson
2025-01-14  5:11 ` [PATCH v3 10/12] usb: dwc3: qcom: Don't rely on drvdata during probe Bjorn Andersson
2025-01-14  5:11 ` [PATCH v3 11/12] usb: dwc3: qcom: Transition to flattened model Bjorn Andersson
2025-01-14  5:11 ` [PATCH v3 12/12] arm64: dts: qcom: sc8280x: Flatten the USB nodes Bjorn Andersson
2025-01-14 17:44 ` [PATCH v3 00/12] usb: dwc3: qcom: Flatten dwc3 structure Rob Herring
2025-01-14 23:04   ` Bjorn Andersson
2025-01-15 18:51     ` Rob Herring
2025-01-23  3:07       ` Bjorn Andersson
2025-01-23 21:22         ` Rob Herring
2025-01-27 17:57 ` Stephan Gerhold
2025-01-27 22:40   ` Bjorn Andersson
2025-01-28 10:42     ` Konrad Dybcio

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=20250113-dwc3-refactor-v3-4-d1722075df7b@oss.qualcomm.com \
    --to=bjorn.andersson@oss.qualcomm.com \
    --cc=Frank.li@nxp.com \
    --cc=Thinh.Nguyen@synopsys.com \
    --cc=andersson@kernel.org \
    --cc=balbi@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=konradybcio@kernel.org \
    --cc=krzk+dt@kernel.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=p.zabel@pengutronix.de \
    --cc=quic_wcheng@quicinc.com \
    --cc=robh@kernel.org \
    --cc=saravanak@google.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®