| From 839aeedc908eb729b9014e7d1d38e109778a52d2 Mon Sep 17 00:00:00 2001 |
| From: Robin Murphy <robin.murphy@arm.com> |
| Date: Tue, 2 Jul 2019 18:42:39 +0100 |
| Subject: [PATCH] of: Factor out #{addr,size}-cells parsing |
| |
| In some cases such as PCI host controllers, we may have a "parent bus" |
| which is an OF leaf node, but still need to correctly parse ranges from |
| the point of view of that bus. For that, factor out variants of the |
| "#addr-cells" and "#size-cells" parsers which do not assume they have a |
| device node and thus immediately traverse upwards before reading the |
| relevant property. |
| |
| Signed-off-by: Robin Murphy <robin.murphy@arm.com> |
| [robh: don't make of_bus_n_{addr,size}_cells() public] |
| Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> |
| Tested-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de> |
| Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de> |
| Signed-off-by: Rob Herring <robh@kernel.org> |
| |
| (cherry picked from commit b68ac8dc22ebbf003e26e44bf4dd3030c076df5a) |
| --- |
| drivers/of/address.c | 2 ++ |
| drivers/of/base.c | 32 ++++++++++++++++++++++---------- |
| drivers/of/of_private.h | 14 ++++++++++++++ |
| 3 files changed, 38 insertions(+), 10 deletions(-) |
| |
| --- a/drivers/of/address.c |
| +++ b/drivers/of/address.c |
| @@ -14,6 +14,8 @@ |
| #include <linux/slab.h> |
| #include <linux/string.h> |
| |
| +#include "of_private.h" |
| + |
| /* Max address size we deal with */ |
| #define OF_MAX_ADDR_CELLS 4 |
| #define OF_CHECK_ADDR_COUNT(na) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS) |
| --- a/drivers/of/base.c |
| +++ b/drivers/of/base.c |
| @@ -86,34 +86,46 @@ static bool __of_node_is_type(const stru |
| return np && match && type && !strcmp(match, type); |
| } |
| |
| -int of_n_addr_cells(struct device_node *np) |
| +int of_bus_n_addr_cells(struct device_node *np) |
| { |
| u32 cells; |
| |
| - do { |
| - if (np->parent) |
| - np = np->parent; |
| + for (; np; np = np->parent) |
| if (!of_property_read_u32(np, "#address-cells", &cells)) |
| return cells; |
| - } while (np->parent); |
| + |
| /* No #address-cells property for the root node */ |
| return OF_ROOT_NODE_ADDR_CELLS_DEFAULT; |
| } |
| + |
| +int of_n_addr_cells(struct device_node *np) |
| +{ |
| + if (np->parent) |
| + np = np->parent; |
| + |
| + return of_bus_n_addr_cells(np); |
| +} |
| EXPORT_SYMBOL(of_n_addr_cells); |
| |
| -int of_n_size_cells(struct device_node *np) |
| +int of_bus_n_size_cells(struct device_node *np) |
| { |
| u32 cells; |
| |
| - do { |
| - if (np->parent) |
| - np = np->parent; |
| + for (; np; np = np->parent) |
| if (!of_property_read_u32(np, "#size-cells", &cells)) |
| return cells; |
| - } while (np->parent); |
| + |
| /* No #size-cells property for the root node */ |
| return OF_ROOT_NODE_SIZE_CELLS_DEFAULT; |
| } |
| + |
| +int of_n_size_cells(struct device_node *np) |
| +{ |
| + if (np->parent) |
| + np = np->parent; |
| + |
| + return of_bus_n_size_cells(np); |
| +} |
| EXPORT_SYMBOL(of_n_size_cells); |
| |
| #ifdef CONFIG_NUMA |
| --- a/drivers/of/of_private.h |
| +++ b/drivers/of/of_private.h |
| @@ -158,4 +158,18 @@ extern void __of_sysfs_remove_bin_file(s |
| #define for_each_transaction_entry_reverse(_oft, _te) \ |
| list_for_each_entry_reverse(_te, &(_oft)->te_list, node) |
| |
| +extern int of_bus_n_addr_cells(struct device_node *np); |
| +extern int of_bus_n_size_cells(struct device_node *np); |
| + |
| +#ifdef CONFIG_OF_ADDRESS |
| +extern int of_dma_get_range(struct device_node *np, u64 *dma_addr, |
| + u64 *paddr, u64 *size); |
| +#else |
| +static inline int of_dma_get_range(struct device_node *np, u64 *dma_addr, |
| + u64 *paddr, u64 *size) |
| +{ |
| + return -ENODEV; |
| +} |
| +#endif |
| + |
| #endif /* _LINUX_OF_PRIVATE_H */ |