From 1614347036716dd8fe55ed530cb7c0d7dc5994ed Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Sun, 10 Nov 2024 12:50:20 +0100 Subject: dm: core: implement oftree variant of parse_phandle OPs Implement oftree variant of parse_phandle OPs. There is currently a very hidden and laten BUG with parse_phandle OPs that doesn't permit the support of multiple DTS in a system. One usage example if sandbox with the usage of other.dts The BUG is only present on live scenario where of_... OPs are used and it's not present when fdt... OPs are used. This is caused by an assumption made in __of_parse_phandle_with_args, with the of_find_node_by_phandle call that pass the first arg as NULL. This makes of_find_node_by_phandle use the default root node of the system and doesn't permit the usage of alternative tree. This is correct for normal system and also for the linux kernel where it's assumed a single device tree. It's problematic if other device tree needs to be used. To fix this, introduce __of_root_parse_phandle_with_args to define a root device tree for of_find_node_by_phandle. Introduce all the variant OPs for this and in ofnode, the oftree OPs following how it's done for other OPs with similar task. For FDT scenario, ofnode_from_fdtdec_phandle_args is reworked to accept a new variable, node and noffset_to_ofnode is used instead of offset_to_ofnode. This is required to support multiple FDB blob to calculate the correct of_offset of the ofnode. Signed-off-by: Christian Marangi Reviewed-by: Simon Glass --- drivers/core/ofnode.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) (limited to 'drivers/core/ofnode.c') diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 950895e72a9..b9cc9419407 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -879,11 +879,11 @@ int ofnode_read_string_list(ofnode node, const char *property, return count; } -static void ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args *in, +static void ofnode_from_fdtdec_phandle_args(ofnode node, struct fdtdec_phandle_args *in, struct ofnode_phandle_args *out) { assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS); - out->node = offset_to_ofnode(in->node); + out->node = noffset_to_ofnode(node, in->node); out->args_count = in->args_count; memcpy(out->args, in->args, sizeof(out->args)); } @@ -923,7 +923,40 @@ int ofnode_parse_phandle_with_args(ofnode node, const char *list_name, cell_count, index, &args); if (ret) return ret; - ofnode_from_fdtdec_phandle_args(&args, out_args); + ofnode_from_fdtdec_phandle_args(node, &args, out_args); + } + + return 0; +} + +int oftree_parse_phandle_with_args(oftree tree, ofnode node, const char *list_name, + const char *cells_name, int cell_count, + int index, + struct ofnode_phandle_args *out_args) +{ + if (ofnode_is_np(node)) { + struct of_phandle_args args; + int ret; + + ret = of_root_parse_phandle_with_args(tree.np, + ofnode_to_np(node), + list_name, cells_name, + cell_count, index, + &args); + if (ret) + return ret; + ofnode_from_of_phandle_args(&args, out_args); + } else { + struct fdtdec_phandle_args args; + int ret; + + ret = fdtdec_parse_phandle_with_args(tree.fdt, + ofnode_to_offset(node), + list_name, cells_name, + cell_count, index, &args); + if (ret) + return ret; + ofnode_from_fdtdec_phandle_args(node, &args, out_args); } return 0; @@ -941,6 +974,18 @@ int ofnode_count_phandle_with_args(ofnode node, const char *list_name, cell_count, -1, NULL); } +int oftree_count_phandle_with_args(oftree tree, ofnode node, const char *list_name, + const char *cells_name, int cell_count) +{ + if (ofnode_is_np(node)) + return of_root_count_phandle_with_args(tree.np, ofnode_to_np(node), + list_name, cells_name, cell_count); + else + return fdtdec_parse_phandle_with_args(tree.fdt, + ofnode_to_offset(node), list_name, cells_name, + cell_count, -1, NULL); +} + ofnode ofnode_path(const char *path) { if (of_live_active()) -- cgit v1.2.3 From 2d31a2797a359e8eda95ca9e742982e67ce57ba7 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Sun, 10 Nov 2024 12:50:22 +0100 Subject: dm: core: implement ofnode/tree_parse_phandle() helper Implement ofnode/tree_parse_phandle() helper as an equivalent of of_parse_phandle to handle simple single value phandle. Signed-off-by: Christian Marangi Reviewed-by: Simon Glass --- drivers/core/ofnode.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'drivers/core/ofnode.c') diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index b9cc9419407..dc6ac069311 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -879,6 +879,64 @@ int ofnode_read_string_list(ofnode node, const char *property, return count; } +ofnode ofnode_parse_phandle(ofnode node, const char *phandle_name, + int index) +{ + ofnode phandle; + + if (ofnode_is_np(node)) { + struct device_node *np; + + np = of_parse_phandle(ofnode_to_np(node), phandle_name, + index); + if (!np) + return ofnode_null(); + + phandle = np_to_ofnode(np); + } else { + struct fdtdec_phandle_args args; + + if (fdtdec_parse_phandle_with_args(ofnode_to_fdt(node), + ofnode_to_offset(node), + phandle_name, NULL, + 0, index, &args)) + return ofnode_null(); + + phandle = offset_to_ofnode(args.node); + } + + return phandle; +} + +ofnode oftree_parse_phandle(oftree tree, ofnode node, const char *phandle_name, + int index) +{ + ofnode phandle; + + if (ofnode_is_np(node)) { + struct device_node *np; + + np = of_root_parse_phandle(tree.np, ofnode_to_np(node), + phandle_name, index); + if (!np) + return ofnode_null(); + + phandle = np_to_ofnode(np); + } else { + struct fdtdec_phandle_args args; + + if (fdtdec_parse_phandle_with_args(tree.fdt, + ofnode_to_offset(node), + phandle_name, NULL, + 0, index, &args)) + return ofnode_null(); + + phandle = noffset_to_ofnode(node, args.node); + } + + return phandle; +} + static void ofnode_from_fdtdec_phandle_args(ofnode node, struct fdtdec_phandle_args *in, struct ofnode_phandle_args *out) { -- cgit v1.2.3 From cab275c446d3a332890b2751e50636ecf38c1098 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Sun, 10 Nov 2024 12:50:24 +0100 Subject: dm: core: implement phandle ofnode_options helper Implement ofnode_options phandle helper to get an ofnode from a phandle option in /options/u-boot. This helper can be useful since new DT yaml usually require to link a phandle of a node instead of referencing it by name or other indirect way. Signed-off-by: Christian Marangi Reviewed-by: Simon Glass --- drivers/core/ofnode.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/core/ofnode.c') diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index dc6ac069311..c8161827d1c 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -1871,6 +1871,21 @@ const char *ofnode_options_read_str(const char *prop_name) return ofnode_read_string(uboot, prop_name); } +int ofnode_options_get_by_phandle(const char *prop_name, ofnode *nodep) +{ + ofnode uboot; + + uboot = ofnode_path("/options/u-boot"); + if (!ofnode_valid(uboot)) + return -EINVAL; + + *nodep = ofnode_parse_phandle(uboot, prop_name, 0); + if (!ofnode_valid(*nodep)) + return -EINVAL; + + return 0; +} + int ofnode_read_bootscript_address(u64 *bootscr_address, u64 *bootscr_offset) { int ret; -- cgit v1.2.3