diff mbox series

[v3,03/38] common: fdt_support: Support special case of PCI address in fdt_read_prop()

Message ID 1614244979-48216-4-git-send-email-bmeng.cn@gmail.com
State Accepted
Commit a932aa3c692606d6ada803de966b1aee09257993
Delegated to: Priyanka Jain
Headers show
Series ppc: qemu: Convert qemu-ppce500 to driver model and enable additional driver support | expand

Commit Message

Bin Meng Feb. 25, 2021, 9:22 a.m. UTC
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>

---

(no changes since v2)

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 mbox series

Patch

diff --git a/common/fdt_support.c b/common/fdt_support.c
index 08d540b..e624bbd 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: