diff options
author | Scott Wood <scottwood@freescale.com> | 2010-08-12 18:37:39 -0500 |
---|---|---|
committer | Kumar Gala <galak@kernel.crashing.org> | 2010-08-19 21:21:41 -0500 |
commit | 6395f318e9ddf26817a01f0b3877af0e3e47d056 (patch) | |
tree | 5922044bd8856098212ff01d68763273b04d18b8 /common | |
parent | b80d30546e88c70985094d81297d449b2bc59033 (diff) |
fdt: call fdt_parent_offset fewer times while translating addresses
fdt_parent_offset() is an expensive operation, so we'd like to reduce
unnecessary calls to it.
Further, the practice of iterating up to the root if address/size cells
aren't found was apparently done for Linux for compatibility with certain
buggy Open Firmware implementations, and U-Boot inherited the code. The
compliant behavior is to treat a missing #address-cells as 2, and a missing
#size-cells as 1 -- never looking anywhere but the immediate parent of the
node of interest.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'common')
-rw-r--r-- | common/fdt_support.c | 58 |
1 files changed, 21 insertions, 37 deletions
diff --git a/common/fdt_support.c b/common/fdt_support.c index 33336be062e..aef4fe23e05 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -874,35 +874,6 @@ static inline u64 of_read_number(const __be32 *cell, int size) return r; } -static int of_n_cells(const void *blob, int nodeoffset, const char *name) -{ - int np; - const int *ip; - - do { - np = fdt_parent_offset(blob, nodeoffset); - - if (np >= 0) - nodeoffset = np; - ip = (int *)fdt_getprop(blob, nodeoffset, name, NULL); - if (ip) - return be32_to_cpup(ip); - } while (np >= 0); - - /* No #<NAME>-cells property for the root node */ - return 1; -} - -int of_n_addr_cells(const void *blob, int nodeoffset) -{ - return of_n_cells(blob, nodeoffset, "#address-cells"); -} - -int of_n_size_cells(const void *blob, int nodeoffset) -{ - return of_n_cells(blob, nodeoffset, "#size-cells"); -} - #define PRu64 "%llx" /* Max address size we deal with */ @@ -928,7 +899,7 @@ static void of_dump_addr(const char *s, const u32 *addr, int na) { } struct of_bus { const char *name; const char *addresses; - void (*count_cells)(void *blob, int offset, + void (*count_cells)(void *blob, int parentoffset, int *addrc, int *sizec); u64 (*map)(u32 *addr, const u32 *range, int na, int ns, int pna); @@ -936,13 +907,26 @@ struct of_bus { }; /* Default translator (generic bus) */ -static void of_bus_default_count_cells(void *blob, int offset, +static void of_bus_default_count_cells(void *blob, int parentoffset, int *addrc, int *sizec) { - if (addrc) - *addrc = of_n_addr_cells(blob, offset); - if (sizec) - *sizec = of_n_size_cells(blob, offset); + const u32 *prop; + + if (addrc) { + prop = fdt_getprop(blob, parentoffset, "#address-cells", NULL); + if (prop) + *addrc = be32_to_cpup(prop); + else + *addrc = 2; + } + + if (sizec) { + prop = fdt_getprop(blob, parentoffset, "#size-cells", NULL); + if (prop) + *sizec = be32_to_cpup(prop); + else + *sizec = 1; + } } static u64 of_bus_default_map(u32 *addr, const u32 *range, @@ -1068,7 +1052,7 @@ u64 __of_translate_address(void *blob, int node_offset, const u32 *in_addr, bus = &of_busses[0]; /* Cound address cells & copy address locally */ - bus->count_cells(blob, node_offset, &na, &ns); + bus->count_cells(blob, parent, &na, &ns); if (!OF_CHECK_COUNTS(na, ns)) { printf("%s: Bad cell count for %s\n", __FUNCTION__, fdt_get_name(blob, node_offset, NULL)); @@ -1095,7 +1079,7 @@ u64 __of_translate_address(void *blob, int node_offset, const u32 *in_addr, /* Get new parent bus and counts */ pbus = &of_busses[0]; - pbus->count_cells(blob, node_offset, &pna, &pns); + pbus->count_cells(blob, parent, &pna, &pns); if (!OF_CHECK_COUNTS(pna, pns)) { printf("%s: Bad cell count for %s\n", __FUNCTION__, fdt_get_name(blob, node_offset, NULL)); |