From 247970978d3de3e46537550e83137df586d9dee9 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:37 -0600 Subject: dm: core: Reverse the argument order in ofnode_copy_props() Follow the order used by memcpy() as it may be less confusing. Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/core/ofnode.c') diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 2cafa7bca5b..515396c62f4 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -1731,7 +1731,7 @@ int ofnode_add_subnode(ofnode node, const char *name, ofnode *subnodep) return ret; /* 0 or -EEXIST */ } -int ofnode_copy_props(ofnode src, ofnode dst) +int ofnode_copy_props(ofnode dst, ofnode src) { struct ofprop prop; -- cgit v1.2.3 From e0c3c21d8ba1a0abbb7effee6c5a952f3e65a03d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:40 -0600 Subject: dm: core: Add a function to create an empty tree Provide a function to create a new, empty tree. Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 4 deletions(-) (limited to 'drivers/core/ofnode.c') diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 515396c62f4..d2bdb8b9af1 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -47,6 +47,17 @@ static int oftree_find(const void *fdt) return -1; } +static int check_tree_count(void) +{ + if (oftree_count == CONFIG_OFNODE_MULTI_TREE_MAX) { + log_warning("Too many registered device trees (max %d)\n", + CONFIG_OFNODE_MULTI_TREE_MAX); + return -E2BIG; + } + + return 0; +} + static oftree oftree_ensure(void *fdt) { oftree tree; @@ -69,11 +80,8 @@ static oftree oftree_ensure(void *fdt) if (gd->flags & GD_FLG_RELOC) { i = oftree_find(fdt); if (i == -1) { - if (oftree_count == CONFIG_OFNODE_MULTI_TREE_MAX) { - log_warning("Too many registered device trees (max %d)\n", - CONFIG_OFNODE_MULTI_TREE_MAX); + if (check_tree_count()) return oftree_null(); - } /* register the new tree */ i = oftree_count++; @@ -92,6 +100,41 @@ static oftree oftree_ensure(void *fdt) return tree; } +int oftree_new(oftree *treep) +{ + oftree tree = oftree_null(); + int ret; + + if (of_live_active()) { + struct device_node *root; + + ret = of_live_create_empty(&root); + if (ret) + return log_msg_ret("liv", ret); + tree = oftree_from_np(root); + } else { + const int size = 1024; + void *fdt; + + ret = check_tree_count(); + if (ret) + return log_msg_ret("fla", ret); + + /* register the new tree with a small size */ + fdt = malloc(size); + if (!fdt) + return log_msg_ret("fla", -ENOMEM); + ret = fdt_create_empty_tree(fdt, size); + if (ret) + return log_msg_ret("fla", -EINVAL); + oftree_list[oftree_count++] = fdt; + tree.fdt = fdt; + } + *treep = tree; + + return 0; +} + void oftree_dispose(oftree tree) { if (of_live_active()) @@ -193,6 +236,11 @@ static inline int oftree_find(const void *fdt) return 0; } +int oftree_new(oftree *treep) +{ + return -ENOSYS; +} + #endif /* OFNODE_MULTI_TREE */ /** -- cgit v1.2.3 From c15862ffdd5f7797338808cf7645786109bcddc3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:41 -0600 Subject: dm: core: Add a way to copy a node Add a function to copy a node to another place under a new name. This is useful at least for testing, since copying a test node with existing properties is easier than writing the code to generate it all afresh. Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/core/ofnode.c') diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index d2bdb8b9af1..403ee06ad94 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -1802,3 +1802,23 @@ int ofnode_copy_props(ofnode dst, ofnode src) return 0; } + +int ofnode_copy_node(ofnode dst_parent, const char *name, ofnode src, + ofnode *nodep) +{ + ofnode node; + int ret; + + ret = ofnode_add_subnode(dst_parent, name, &node); + if (ret) { + if (ret == -EEXIST) + *nodep = node; + return log_msg_ret("add", ret); + } + ret = ofnode_copy_props(node, src); + if (ret) + return log_msg_ret("cpy", ret); + *nodep = node; + + return 0; +} -- cgit v1.2.3 From 67fb2159fb3438359fa0fc3f8cb491ffe8d57c0f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:42 -0600 Subject: dm: core: Add a way to delete a node Add a function to delete a node in an existing tree. Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers/core/ofnode.c') diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 403ee06ad94..a5efedf6af3 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -1779,6 +1779,29 @@ int ofnode_add_subnode(ofnode node, const char *name, ofnode *subnodep) return ret; /* 0 or -EEXIST */ } +int ofnode_delete(ofnode *nodep) +{ + ofnode node = *nodep; + int ret; + + assert(ofnode_valid(node)); + if (ofnode_is_np(node)) { + ret = of_remove_node(ofnode_to_np(node)); + } else { + void *fdt = ofnode_to_fdt(node); + int offset = ofnode_to_offset(node); + + ret = fdt_del_node(fdt, offset); + if (ret) + ret = -EFAULT; + } + if (ret) + return ret; + *nodep = ofnode_null(); + + return 0; +} + int ofnode_copy_props(ofnode dst, ofnode src) { struct ofprop prop; -- cgit v1.2.3 From 62b1db33778611a3023d1e3a98e869b495edc9ca Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:43 -0600 Subject: dm: core: Add a way to convert a devicetree to a dtb Add a way to flatten a devicetree into binary form. For livetree this involves generating the devicetree using fdt_property() and other calls. For flattree it simply involves providing the buffer containing the tree. Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/core/ofnode.c') diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index a5efedf6af3..39ba480c8f8 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -243,6 +243,24 @@ int oftree_new(oftree *treep) #endif /* OFNODE_MULTI_TREE */ +int oftree_to_fdt(oftree tree, struct abuf *buf) +{ + int ret; + + if (of_live_active()) { + ret = of_live_flatten(ofnode_to_np(oftree_root(tree)), buf); + if (ret) + return log_msg_ret("flt", ret); + } else { + void *fdt = oftree_lookup_fdt(tree); + + abuf_init(buf); + abuf_set(buf, fdt, fdt_totalsize(fdt)); + } + + return 0; +} + /** * ofnode_from_tree_offset() - get an ofnode from a tree offset (flat tree) * -- cgit v1.2.3 From d9216c8683fced4cbf6d437b4357c9368bf1bf86 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:44 -0600 Subject: dm: core: Support writing a boolean Add functions to write a boolean property. This involves deleting it if the value is false. Add a new ofnode_has_property() as well. Add a comment about the behaviour of of_read_property() when the property value is empty. Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) (limited to 'drivers/core/ofnode.c') diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 39ba480c8f8..4dcb3dd1c03 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -491,12 +491,12 @@ u64 ofnode_read_u64_default(ofnode node, const char *propname, u64 def) bool ofnode_read_bool(ofnode node, const char *propname) { - const void *prop; + bool prop; assert(ofnode_valid(node)); debug("%s: %s: ", __func__, propname); - prop = ofnode_get_property(node, propname, NULL); + prop = ofnode_has_property(node, propname); debug("%s\n", prop ? "true" : "false"); @@ -1168,6 +1168,14 @@ const void *ofnode_get_property(ofnode node, const char *propname, int *lenp) propname, lenp); } +bool ofnode_has_property(ofnode node, const char *propname) +{ + if (ofnode_is_np(node)) + return of_find_property(ofnode_to_np(node), propname, NULL); + else + return ofnode_get_property(node, propname, NULL); +} + int ofnode_first_property(ofnode node, struct ofprop *prop) { prop->node = node; @@ -1616,6 +1624,30 @@ int ofnode_write_u32(ofnode node, const char *propname, u32 value) return ofnode_write_prop(node, propname, val, sizeof(value), false); } +int ofnode_write_bool(ofnode node, const char *propname, bool value) +{ + if (value) + return ofnode_write_prop(node, propname, NULL, 0, false); + else + return ofnode_delete_prop(node, propname); +} + +int ofnode_delete_prop(ofnode node, const char *propname) +{ + if (ofnode_is_np(node)) { + struct property *prop; + int len; + + prop = of_find_property(ofnode_to_np(node), propname, &len); + if (prop) + return of_remove_property(ofnode_to_np(node), prop); + return 0; + } else { + return fdt_delprop(ofnode_to_fdt(node), ofnode_to_offset(node), + propname); + } +} + int ofnode_set_enabled(ofnode node, bool value) { assert(ofnode_valid(node)); -- cgit v1.2.3 From 7071c82bdc55ed5d7955d8e1682b7c80af5659b5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:45 -0600 Subject: dm: core: Support writing a 64-bit value Add support for writing a single 64-bit value into a property. Repurpose the existing tests to handle this case too. Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers/core/ofnode.c') diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 4dcb3dd1c03..18d2eb0f118 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -1621,7 +1621,22 @@ int ofnode_write_u32(ofnode node, const char *propname, u32 value) return -ENOMEM; *val = cpu_to_fdt32(value); - return ofnode_write_prop(node, propname, val, sizeof(value), false); + return ofnode_write_prop(node, propname, val, sizeof(value), true); +} + +int ofnode_write_u64(ofnode node, const char *propname, u64 value) +{ + fdt64_t *val; + + assert(ofnode_valid(node)); + + log_debug("%s = %llx", propname, (unsigned long long)value); + val = malloc(sizeof(*val)); + if (!val) + return -ENOMEM; + *val = cpu_to_fdt64(value); + + return ofnode_write_prop(node, propname, val, sizeof(value), true); } int ofnode_write_bool(ofnode node, const char *propname, bool value) -- cgit v1.2.3 From f69d3d6d10b15872a279aeb10b7c522627aff6c2 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 26 Sep 2023 08:14:58 -0600 Subject: pci: serial: Support reading PCI-register size with base The PCI helpers read only the base address for a PCI region. In some cases the size is needed as well, e.g. to pass along to a driver which needs to know the size of its register area. Update the functions to allow the size to be returned. For serial, record the information and provided it with the serial_info() call. A limitation still exists in that the size is not available when OF_LIVE is enabled, so take account of that in the tests. Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/core/ofnode.c') diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 18d2eb0f118..29a42945102 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -1270,7 +1270,8 @@ const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname, } int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type, - const char *propname, struct fdt_pci_addr *addr) + const char *propname, struct fdt_pci_addr *addr, + fdt_size_t *size) { const fdt32_t *cell; int len; @@ -1298,14 +1299,18 @@ int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type, (ulong)fdt32_to_cpu(cell[1]), (ulong)fdt32_to_cpu(cell[2])); if ((fdt32_to_cpu(*cell) & type) == type) { + const unaligned_fdt64_t *ptr; + addr->phys_hi = fdt32_to_cpu(cell[0]); addr->phys_mid = fdt32_to_cpu(cell[1]); addr->phys_lo = fdt32_to_cpu(cell[2]); + ptr = (const unaligned_fdt64_t *)(cell + 3); + if (size) + *size = fdt64_to_cpu(*ptr); break; } - cell += (FDT_PCI_ADDR_CELLS + - FDT_PCI_SIZE_CELLS); + cell += FDT_PCI_ADDR_CELLS + FDT_PCI_SIZE_CELLS; } if (i == num) { -- cgit v1.2.3