From: Michael Brown Date: Mon, 4 Aug 2025 13:52:00 +0000 (+0100) Subject: [fdt] Use phandle as device location X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=5f10b7455547fc563caab58f8941111346346433;p=thirdparty%2Fipxe.git [fdt] Use phandle as device location Consumption of phandles will be in the form of locating a functional device (e.g. a GPIO device, or an I2C device, or a reset controller) by phandle, rather than locating the device tree node to which the phandle refers. Repurpose fdt_phandle() to obtain the phandle value (instead of searching by phandle), and record this value as the bus location within the generic device structure. Signed-off-by: Michael Brown --- diff --git a/src/core/fdt.c b/src/core/fdt.c index 6989690bf..ae723213b 100644 --- a/src/core/fdt.c +++ b/src/core/fdt.c @@ -482,57 +482,6 @@ int fdt_alias ( struct fdt *fdt, const char *name, unsigned int *offset ) { return 0; } -/** - * Find node by package handle (phandle) - * - * @v fdt Device tree - * @v phandle Package handle - * @v offset Offset to fill in - * @ret rc Return status code - */ -int fdt_phandle ( struct fdt *fdt, uint32_t phandle, unsigned int *offset ) { - struct fdt_descriptor desc; - uint32_t value; - int depth; - int rc; - - /* Initialise offset */ - *offset = 0; - - /* Find node with matching phandle */ - for ( depth = -1 ; ; depth += desc.depth, *offset = desc.next ) { - - /* Describe token */ - if ( ( rc = fdt_describe ( fdt, *offset, &desc ) ) != 0 ) { - DBGC ( fdt, "FDT +%#04x has malformed node: %s\n", - *offset, strerror ( rc ) ); - return rc; - } - - /* Terminate when we exit the root node */ - if ( ( depth == 0 ) && ( desc.depth < 0 ) ) - break; - - /* Ignore non-nodes */ - if ( ( ! desc.name ) || desc.data ) - continue; - - /* Check for matching "phandle" or "linux-phandle" property */ - if ( ( ( ( rc = fdt_u32 ( fdt, *offset, "phandle", - &value ) ) == 0 ) || - ( ( rc = fdt_u32 ( fdt, *offset, "linux,phandle", - &value ) ) == 0 ) ) && - ( value == phandle ) ) { - DBGC2 ( fdt, "FDT +%#04x has phandle %#02x\n", - *offset, phandle ); - return 0; - } - } - - DBGC ( fdt, "FDT has no phandle %#02x\n", phandle ); - return -ENOENT; -} - /** * Find property * @@ -730,6 +679,28 @@ int fdt_u32 ( struct fdt *fdt, unsigned int offset, const char *name, return 0; } +/** + * Get package handle (phandle) property + * + * @v fdt Device tree + * @v offset Starting node offset + * @ret phandle Package handle, or 0 on error + */ +uint32_t fdt_phandle ( struct fdt *fdt, unsigned int offset ) { + uint32_t phandle; + int rc; + + /* Get "phandle" or "linux,phandle" property */ + if ( ( ( rc = fdt_u32 ( fdt, offset, "phandle", &phandle ) ) == 0 ) || + ( ( rc = fdt_u32 ( fdt, offset, "linux,phandle", + &phandle ) ) == 0 ) ) { + assert ( phandle != 0 ); + return phandle; + } + + return 0; +} + /** * Get region cell size specification * diff --git a/src/drivers/bus/devtree.c b/src/drivers/bus/devtree.c index 59bbc9bf7..cd5bb09a0 100644 --- a/src/drivers/bus/devtree.c +++ b/src/drivers/bus/devtree.c @@ -219,6 +219,7 @@ int dt_probe_node ( struct device *parent, unsigned int offset ) { dt->name = dt->dev.name; snprintf ( dt->dev.name, sizeof ( dt->dev.name ), "%s", name ); dt->dev.desc.bus_type = BUS_TYPE_DT; + dt->dev.desc.location = fdt_phandle ( &sysfdt, offset ); dt->dev.parent = parent; INIT_LIST_HEAD ( &dt->dev.children ); list_add_tail ( &dt->dev.siblings, &parent->children ); diff --git a/src/include/ipxe/fdt.h b/src/include/ipxe/fdt.h index c73389ad7..eec02c5b3 100644 --- a/src/include/ipxe/fdt.h +++ b/src/include/ipxe/fdt.h @@ -176,8 +176,6 @@ extern int fdt_path ( struct fdt *fdt, const char *path, unsigned int *offset ); extern int fdt_alias ( struct fdt *fdt, const char *name, unsigned int *offset ); -extern int fdt_phandle ( struct fdt *fdt, uint32_t phandle, - unsigned int *offset ); extern const char * fdt_strings ( struct fdt *fdt, unsigned int offset, const char *name, unsigned int *count ); extern const char * fdt_string ( struct fdt *fdt, unsigned int offset, @@ -189,6 +187,7 @@ extern int fdt_u64 ( struct fdt *fdt, unsigned int offset, const char *name, uint64_t *value ); extern int fdt_u32 ( struct fdt *fdt, unsigned int offset, const char *name, uint32_t *value ); +extern uint32_t fdt_phandle ( struct fdt *fdt, unsigned int offset ); extern void fdt_reg_cells ( struct fdt *fdt, unsigned int offset, struct fdt_reg_cells *regs ); extern int fdt_reg_count ( struct fdt *fdt, unsigned int offset, diff --git a/src/tests/fdt_test.c b/src/tests/fdt_test.c index 099a093b4..07f7e8911 100644 --- a/src/tests/fdt_test.c +++ b/src/tests/fdt_test.c @@ -237,6 +237,16 @@ static void fdt_test_exec ( void ) { ok ( fdt_path ( &fdt, "/soc/ethernet@10090000", &offset ) == 0 ); ok ( fdt_u32 ( &fdt, offset, "max-speed", &u32 ) != 0 ); + /* Verify phandle properties */ + ok ( fdt_path ( &fdt, "/cpus/cpu@0/interrupt-controller", + &offset ) == 0 ); + ok ( fdt_phandle ( &fdt, offset ) == 0x03 ); + ok ( fdt_path ( &fdt, "/soc/ethernet@10090000/ethernet-phy@0", + &offset ) == 0 ); + ok ( fdt_phandle ( &fdt, offset ) == 0x08 ); + ok ( fdt_path ( &fdt, "/soc/serial@10010000", &offset ) == 0 ); + ok ( fdt_phandle ( &fdt, offset ) == 0 ); + /* Verify cell properties */ ok ( fdt_path ( &fdt, "/soc/ethernet@10090000", &offset ) == 0 ); ok ( fdt_cells ( &fdt, offset, "reg", 4, 2, &u64 ) == 0 ); @@ -261,15 +271,6 @@ static void fdt_test_exec ( void ) { ok ( ( string = fdt_string ( &fdt, offset, "phy-mode" ) ) != NULL ); ok ( strcmp ( string, "gmii" ) == 0 ); - /* Verify phandle lookup */ - ok ( fdt_phandle ( &fdt, 0x03, &offset ) == 0 ); - ok ( fdt_describe ( &fdt, offset, &desc ) == 0 ); - ok ( strcmp ( desc.name, "interrupt-controller" ) == 0 ); - ok ( fdt_phandle ( &fdt, 0x08, &offset ) == 0 ); - ok ( fdt_describe ( &fdt, offset, &desc ) == 0 ); - ok ( strcmp ( desc.name, "ethernet-phy@0" ) == 0 ); - ok ( fdt_phandle ( &fdt, 0x2a, &offset ) != 0 ); - /* Verify node description */ ok ( fdt_path ( &fdt, "/memory@80000000", &offset ) == 0 ); ok ( fdt_describe ( &fdt, offset, &desc ) == 0 );