Merge patch series "Qualcomm: cleanup OF_LIVE fixup and fix RB1/2"
Caleb Connolly <caleb.connolly@linaro.org> says:
Introduce a new event to signal that the live tree has been built,
allowing boards to perform fixups on the tree before devices are bound.
Crucially this allows for devices to be enabled or disabled, but also
allows for properties that are parsed during the bind stage to be
modified (such as dr_mode for dwc3).
With this in place, mach-snapdragon is switched over to use the event
and some hacky U-Boot specific DT overrides (which had to be undone
prior to booting an image) are removed in favour of fixing up the
livetree (which is not passed on to further boot stages).
Finally, some minor fixes are made for the QCM2290 RB1 board, the sdcard
is enabled and it now uses USB host mode in U-Boot like it's bigger
sibling the RB2.
Link: https://lore.kernel.org/r/20250411-livetree-fixup-v2-0-1236823377bb@linaro.org
diff --git a/arch/arm/dts/qrb4210-rb2-u-boot.dtsi b/arch/arm/dts/qrb4210-rb2-u-boot.dtsi
deleted file mode 100644
index 7d1375f..0000000
--- a/arch/arm/dts/qrb4210-rb2-u-boot.dtsi
+++ /dev/null
@@ -1,6 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-/* This is usually OTG but U-Boot doesn't support that properly */
-&usb_dwc3 {
- dr_mode = "host";
-};
diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c
index deae4d3..3ab75f0 100644
--- a/arch/arm/mach-snapdragon/board.c
+++ b/arch/arm/mach-snapdragon/board.c
@@ -306,7 +306,6 @@
int board_init(void)
{
show_psci_version();
- qcom_of_fixup_nodes();
qcom_board_init();
return 0;
}
diff --git a/arch/arm/mach-snapdragon/of_fixup.c b/arch/arm/mach-snapdragon/of_fixup.c
index 1ea0c18..b398c6b 100644
--- a/arch/arm/mach-snapdragon/of_fixup.c
+++ b/arch/arm/mach-snapdragon/of_fixup.c
@@ -4,8 +4,7 @@
*
* This file implements runtime fixups for Qualcomm DT to improve
* compatibility with U-Boot. This includes adjusting the USB nodes
- * to only use USB high-speed, as well as remapping volume buttons
- * to behave as up/down for navigating U-Boot.
+ * to only use USB high-speed.
*
* We use OF_LIVE for this rather than early FDT fixup for a couple
* of reasons: it has a much nicer API, is most likely more efficient,
@@ -22,6 +21,7 @@
#include <dt-bindings/input/linux-event-codes.h>
#include <dm/of_access.h>
#include <dm/of.h>
+#include <event.h>
#include <fdt_support.h>
#include <linux/errno.h>
#include <stdlib.h>
@@ -32,7 +32,7 @@
* DT here. This improves compatibility with upstream DT and simplifies the
* porting process for new devices.
*/
-static int fixup_qcom_dwc3(struct device_node *glue_np)
+static int fixup_qcom_dwc3(struct device_node *root, struct device_node *glue_np)
{
struct device_node *dwc3;
int ret, len, hsphy_idx = 1;
@@ -72,11 +72,12 @@
return ret;
}
- if (!strncmp("usb3-phy", second_phy_name, strlen("usb3-phy"))) {
- log_debug("Second phy isn't superspeed (is '%s') assuming first phy is SS\n",
- second_phy_name);
+ /*
+ * Determine which phy is the superspeed phy by checking the name of the second phy
+ * since it is typically the superspeed one.
+ */
+ if (!strncmp("usb3-phy", second_phy_name, strlen("usb3-phy")))
hsphy_idx = 0;
- }
/* Overwrite the "phys" property to only contain the high-speed phy */
ret = of_write_prop(dwc3, "phys", sizeof(*phandles), phandles + hsphy_idx);
@@ -98,30 +99,45 @@
return ret;
}
+ /*
+ * The RB1/2 boards only have a single USB controller and it's muxed between the type-C port
+ * and a USB hub. Since we can't do OTG in U-Boot properly we prefer to put it into host mode.
+ */
+ if (of_device_is_compatible(root, "qcom,qrb4210-rb2", NULL, NULL) ||
+ of_device_is_compatible(root, "qcom,qrb2210-rb1", NULL, NULL)) {
+ ret = of_write_prop(dwc3, "dr_mode", sizeof("host"), "host");
+ if (ret) {
+ log_err("Failed to set 'dr_mode' property: %d\n", ret);
+ return ret;
+ }
+ }
+
return 0;
}
-static void fixup_usb_nodes(void)
+static void fixup_usb_nodes(struct device_node *root)
{
- struct device_node *glue_np = NULL;
+ struct device_node *glue_np = root;
int ret;
while ((glue_np = of_find_compatible_node(glue_np, NULL, "qcom,dwc3"))) {
- ret = fixup_qcom_dwc3(glue_np);
+ if (!of_device_is_available(glue_np))
+ continue;
+ ret = fixup_qcom_dwc3(root, glue_np);
if (ret)
log_warning("Failed to fixup node %s: %d\n", glue_np->name, ret);
}
}
/* Remove all references to the rpmhpd device */
-static void fixup_power_domains(void)
+static void fixup_power_domains(struct device_node *root)
{
struct device_node *pd = NULL, *np = NULL;
struct property *prop;
const __be32 *val;
/* All Qualcomm platforms name the rpm(h)pd "power-controller" */
- for_each_of_allnodes(pd) {
+ for_each_of_allnodes_from(root, pd) {
if (pd->name && !strcmp("power-controller", pd->name))
break;
}
@@ -133,7 +149,7 @@
}
/* Remove all references to the power domain controller */
- for_each_of_allnodes(np) {
+ for_each_of_allnodes_from(root, np) {
if (!(prop = of_find_property(np, "power-domains", NULL)))
continue;
@@ -150,26 +166,19 @@
debug(#func " took %lluus\n", timer_get_us() - start); \
} while (0)
-void qcom_of_fixup_nodes(void)
+static int qcom_of_fixup_nodes(void * __maybe_unused ctx, struct event *event)
{
- time_call(fixup_usb_nodes);
- time_call(fixup_power_domains);
-}
+ struct device_node *root = event->data.of_live_built.root;
-int ft_board_setup(void *blob, struct bd_info __maybe_unused *bd)
-{
- struct fdt_header *fdt = blob;
- int node;
+ time_call(fixup_usb_nodes, root);
+ time_call(fixup_power_domains, root);
- /* On RB1/2 we need to fix-up the dr_mode */
- if (!fdt_node_check_compatible(fdt, 0, "qcom,qrb4210-rb2") ||
- !fdt_node_check_compatible(fdt, 0, "qcom,qrb2210-rb1")) {
- fdt_for_each_node_by_compatible(node, blob, 0, "snps,dwc3") {
- log_debug("%s: Setting 'dr_mode' to OTG\n", fdt_get_name(blob, node, NULL));
- fdt_setprop_string(fdt, node, "dr_mode", "otg");
- break;
- }
- }
+ return 0;
+}
+
+EVENT_SPY_FULL(EVT_OF_LIVE_BUILT, qcom_of_fixup_nodes);
+int ft_board_setup(void __maybe_unused *blob, struct bd_info __maybe_unused *bd)
+{
return 0;
}
diff --git a/arch/arm/mach-snapdragon/qcom-priv.h b/arch/arm/mach-snapdragon/qcom-priv.h
index 74d3919..4f398e2 100644
--- a/arch/arm/mach-snapdragon/qcom-priv.h
+++ b/arch/arm/mach-snapdragon/qcom-priv.h
@@ -9,18 +9,4 @@
void qcom_configure_capsule_updates(void) {}
#endif /* EFI_HAVE_CAPSULE_SUPPORT */
-#if CONFIG_IS_ENABLED(OF_LIVE)
-/**
- * qcom_of_fixup_nodes() - Fixup Qualcomm DT nodes
- *
- * Adjusts nodes in the live tree to improve compatibility with U-Boot.
- */
-void qcom_of_fixup_nodes(void);
-#else
-static inline void qcom_of_fixup_nodes(void)
-{
- log_debug("Unable to dynamically fixup USB nodes, please enable CONFIG_OF_LIVE\n");
-}
-#endif /* OF_LIVE */
-
#endif /* __QCOM_PRIV_H__ */
diff --git a/common/event.c b/common/event.c
index dda569d..8d7513e 100644
--- a/common/event.c
+++ b/common/event.c
@@ -48,6 +48,9 @@
/* main loop events */
"main_loop",
+
+ /* livetree has been built */
+ "of_live_init",
};
_Static_assert(ARRAY_SIZE(type_name) == EVT_COUNT, "event type_name size");
diff --git a/drivers/clk/qcom/clock-qcm2290.c b/drivers/clk/qcom/clock-qcm2290.c
index 1326b77..fad104f 100644
--- a/drivers/clk/qcom/clock-qcm2290.c
+++ b/drivers/clk/qcom/clock-qcm2290.c
@@ -88,7 +88,7 @@
struct msm_clk_priv *priv = dev_get_priv(clk->dev);
const struct freq_tbl *freq;
- debug("%s: clk %s rate %lu\n", __func__, clk->dev->name, rate);
+ debug("%s: clk %s rate %lu\n", __func__, qcm2290_clks[clk->id].name, rate);
switch (clk->id) {
case GCC_QUPV3_WRAP0_S4_CLK: /*UART2*/
diff --git a/drivers/pinctrl/qcom/pinctrl-qcm2290.c b/drivers/pinctrl/qcom/pinctrl-qcm2290.c
index 0c2222c..84f76b6 100644
--- a/drivers/pinctrl/qcom/pinctrl-qcm2290.c
+++ b/drivers/pinctrl/qcom/pinctrl-qcm2290.c
@@ -45,7 +45,7 @@
struct msm_pinctrl_data qcm2290_data = {
.pin_data = {
- .pin_count = 133,
+ .pin_count = 134,
.special_pins_start = 127,
},
.functions_count = ARRAY_SIZE(msm_pinctrl_functions),
diff --git a/include/event.h b/include/event.h
index 75141a1..1d267f1 100644
--- a/include/event.h
+++ b/include/event.h
@@ -154,6 +154,15 @@
EVT_MAIN_LOOP,
/**
+ * @EVT_OF_LIVE_BUILT:
+ * This event is triggered immediately after the live device tree has been
+ * built. This allows for machine specific fixups to be done to the live tree
+ * (like disabling known-unsupported devices) before it is used. This
+ * event is only available if OF_LIVE is enabled and is only used after relocation.
+ */
+ EVT_OF_LIVE_BUILT,
+
+ /**
* @EVT_COUNT:
* This constants holds the maximum event number + 1 and is used when
* looping over all event classes.
@@ -203,6 +212,15 @@
oftree tree;
struct bootm_headers *images;
} ft_fixup;
+
+ /**
+ * struct event_of_live_built - livetree has been built
+ *
+ * @root: The root node of the live device tree
+ */
+ struct event_of_live_built {
+ struct device_node *root;
+ } of_live_built;
};
/**
diff --git a/lib/of_live.c b/lib/of_live.c
index 90b9459..c162061 100644
--- a/lib/of_live.c
+++ b/lib/of_live.c
@@ -11,6 +11,7 @@
#define LOG_CATEGORY LOGC_DT
#include <abuf.h>
+#include <event.h>
#include <log.h>
#include <linux/libfdt.h>
#include <of_live.h>
@@ -321,6 +322,7 @@
int of_live_build(const void *fdt_blob, struct device_node **rootp)
{
int ret;
+ union event_data evt;
debug("%s: start\n", __func__);
ret = unflatten_device_tree(fdt_blob, rootp);
@@ -335,6 +337,15 @@
}
debug("%s: stop\n", __func__);
+ if (CONFIG_IS_ENABLED(EVENT)) {
+ evt.of_live_built.root = *rootp;
+ ret = event_notify(EVT_OF_LIVE_BUILT, &evt, sizeof(evt));
+ if (ret) {
+ log_debug("Failed to notify livetree build event: err=%d\n", ret);
+ return ret;
+ }
+ }
+
return ret;
}