diff options
author | Bin Meng | 2021-02-25 17:22:24 +0800 |
---|---|---|
committer | Priyanka Jain | 2021-03-05 10:25:42 +0530 |
commit | a932aa3c692606d6ada803de966b1aee09257993 (patch) | |
tree | fa7b835d7d4083115886622ad7ce30aa8f0d3735 /common | |
parent | 5cd1ecb994904365018f64132a85144625017fb9 (diff) |
common: fdt_support: Support special case of PCI address in fdt_read_prop()
At present fdt_read_prop() can only handle 1 or 2 cells. It is
called by fdt_read_range() which may be used to read PCI address
from <ranges> for a PCI bus node where the number of PCI address
cell is 3. The <ranges> property is an array of:
{ <child address> <parent address> <size in child address space> }
When trying to read <child address> from a PCI bus node using
fdt_read_prop(), as the codes below:
/* Read <child address> */
if (child_addr) {
r = fdt_read_prop(ranges, ranges_len, cell, child_addr,
acells);
if (r)
return r;
}
it will fail, because the PCI child address is made up of 3 cells
but fdt_read_prop() cannot handle it. We advance the cell offset
by 1 so that the <child address> can be correctly read.
This adds the special handling of such case.
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Priyanka Jain <priyanka.jain@nxp.com>
Diffstat (limited to 'common')
-rw-r--r-- | common/fdt_support.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/common/fdt_support.c b/common/fdt_support.c index 08d540bfc85..e624bbdf404 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -1668,22 +1668,36 @@ u64 fdt_get_base_address(const void *fdt, int node) } /* - * Read a property of size <prop_len>. Currently only supports 1 or 2 cells. + * Read a property of size <prop_len>. Currently only supports 1 or 2 cells, + * or 3 cells specially for a PCI address. */ static int fdt_read_prop(const fdt32_t *prop, int prop_len, int cell_off, uint64_t *val, int cells) { - const fdt32_t *prop32 = &prop[cell_off]; - const unaligned_fdt64_t *prop64 = (const fdt64_t *)&prop[cell_off]; + const fdt32_t *prop32; + const unaligned_fdt64_t *prop64; if ((cell_off + cells) > prop_len) return -FDT_ERR_NOSPACE; + prop32 = &prop[cell_off]; + + /* + * Special handling for PCI address in PCI bus <ranges> + * + * PCI child address is made up of 3 cells. Advance the cell offset + * by 1 so that the PCI child address can be correctly read. + */ + if (cells == 3) + cell_off += 1; + prop64 = (const fdt64_t *)&prop[cell_off]; + switch (cells) { case 1: *val = fdt32_to_cpu(*prop32); break; case 2: + case 3: *val = fdt64_to_cpu(*prop64); break; default: |