[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 <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2025-08-07 15:41:42 +01:00
parent 9d4a2ee353
commit 88ba011764
3 changed files with 55 additions and 7 deletions

View File

@@ -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, &regs ) ) != 0 )
return rc;
/* Get first region address */
if ( ( rc = fdt_reg_address ( fdt, offset, &regs, 0, region ) ) != 0 )
return rc;
return 0;
}
/**
* Get MAC address from property
*

View File

@@ -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, &regs ) ) != 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, &regs );
/* Read address */
if ( ( rc = fdt_reg_address ( &sysfdt, offset, &regs, index,
&address ) ) != 0 ) {

View File

@@ -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,