From: Michael Brown Date: Thu, 7 Aug 2025 14:41:42 +0000 (+0100) Subject: [fdt] Provide fdt_reg() for unsized single-entry regions X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=88ba0117649bd8ec711ec0d799acb649284dc492;p=thirdparty%2Fipxe.git [fdt] Provide fdt_reg() for unsized single-entry regions Many region types (e.g. I2C bus addresses) can only ever contain a single region with no size cells specified. Provide fdt_reg() to reduce boilerplate in this common use case. Signed-off-by: Michael Brown --- diff --git a/src/core/fdt.c b/src/core/fdt.c index ae723213b..08adb166e 100644 --- a/src/core/fdt.c +++ b/src/core/fdt.c @@ -732,6 +732,29 @@ void fdt_reg_cells ( struct fdt *fdt, unsigned int offset, regs->stride = ( regs->address_cells + regs->size_cells ); } +/** + * Get parent region cell size specification + * + * @v fdt Device tree + * @v offset Starting node offset + * @v regs Region cell size specification to fill in + * @ret rc Return status code + */ +int fdt_parent_reg_cells ( struct fdt *fdt, unsigned int offset, + struct fdt_reg_cells *regs ) { + unsigned int parent; + int rc; + + /* Get parent node */ + if ( ( rc = fdt_parent ( fdt, offset, &parent ) ) != 0 ) + return rc; + + /* Read #address-cells and #size-cells, if present */ + fdt_reg_cells ( fdt, parent, regs ); + + return 0; +} + /** * Get number of regions * @@ -806,6 +829,32 @@ int fdt_reg_size ( struct fdt *fdt, unsigned int offset, return 0; } +/** + * Get unsized single-entry region address + * + * @v fdt Device tree + * @v offset Starting node offset + * @v address Region address to fill in + * @ret rc Return status code + * + * Many region types (e.g. I2C bus addresses) can only ever contain a + * single region with no size cells specified. + */ +int fdt_reg ( struct fdt *fdt, unsigned int offset, uint64_t *region ) { + struct fdt_reg_cells regs; + int rc; + + /* Get parent region cell size specification */ + if ( ( rc = fdt_parent_reg_cells ( fdt, offset, ®s ) ) != 0 ) + return rc; + + /* Get first region address */ + if ( ( rc = fdt_reg_address ( fdt, offset, ®s, 0, region ) ) != 0 ) + return rc; + + return 0; +} + /** * Get MAC address from property * diff --git a/src/drivers/bus/devtree.c b/src/drivers/bus/devtree.c index 32ab1c2cb..f71ad1ea4 100644 --- a/src/drivers/bus/devtree.c +++ b/src/drivers/bus/devtree.c @@ -52,22 +52,18 @@ static struct dt_driver dt_node_driver __dt_driver; void * dt_ioremap ( struct dt_device *dt, unsigned int offset, unsigned int index, size_t len ) { struct fdt_reg_cells regs; - unsigned int parent; uint64_t address; uint64_t size; void *io_addr; int rc; - /* Get parent node */ - if ( ( rc = fdt_parent ( &sysfdt, offset, &parent ) ) != 0 ) { - DBGC ( dt, "DT %s could not locate parent: %s\n", + /* Get parent region cell size specification */ + if ( ( rc = fdt_parent_reg_cells ( &sysfdt, offset, ®s ) ) != 0 ) { + DBGC ( dt, "DT %s could not get region cell sizes: %s\n", dt->name, strerror ( rc ) ); return NULL; } - /* Read #address-cells and #size-cells, if present */ - fdt_reg_cells ( &sysfdt, parent, ®s ); - /* Read address */ if ( ( rc = fdt_reg_address ( &sysfdt, offset, ®s, index, &address ) ) != 0 ) { diff --git a/src/include/ipxe/fdt.h b/src/include/ipxe/fdt.h index eec02c5b3..e951aea59 100644 --- a/src/include/ipxe/fdt.h +++ b/src/include/ipxe/fdt.h @@ -190,6 +190,8 @@ extern int fdt_u32 ( struct fdt *fdt, unsigned int offset, const char *name, 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_parent_reg_cells ( struct fdt *fdt, unsigned int offset, + struct fdt_reg_cells *regs ); extern int fdt_reg_count ( struct fdt *fdt, unsigned int offset, struct fdt_reg_cells *regs ); extern int fdt_reg_address ( struct fdt *fdt, unsigned int offset, @@ -198,6 +200,7 @@ extern int fdt_reg_address ( struct fdt *fdt, unsigned int offset, extern int fdt_reg_size ( struct fdt *fdt, unsigned int offset, struct fdt_reg_cells *regs, unsigned int index, uint64_t *size ); +extern int fdt_reg ( struct fdt *fdt, unsigned int offset, uint64_t *region ); extern int fdt_mac ( struct fdt *fdt, unsigned int offset, struct net_device *netdev ); extern int fdt_parse ( struct fdt *fdt, struct fdt_header *hdr,