From mboxrd@z Thu Jan 1 00:00:00 1970 From: Bin Meng Date: Thu, 18 Feb 2021 23:57:31 +0800 Subject: [PATCH v2 03/38] common: fdt_support: Support special case of PCI address in fdt_read_prop() In-Reply-To: <1613663886-83811-1-git-send-email-bmeng.cn@gmail.com> References: <1613663886-83811-1-git-send-email-bmeng.cn@gmail.com> Message-ID: <1613663886-83811-4-git-send-email-bmeng.cn@gmail.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de 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 for a PCI bus node where the number of PCI address cell is 3. The property is an array of: { } When trying to read from a PCI bus node using fdt_read_prop(), as the codes below: /* Read */ 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 can be correctly read. This adds the special handling of such case. Signed-off-by: Bin Meng --- Changes in v2: - add more details in the commit message, and put some comments in the codes to explain why common/fdt_support.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/common/fdt_support.c b/common/fdt_support.c index 638eca9..17c54a3 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -1602,22 +1602,36 @@ u64 fdt_get_base_address(const void *fdt, int node) } /* - * Read a property of size . Currently only supports 1 or 2 cells. + * Read a property of size . 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 + * + * 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: -- 2.7.4