]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[fdt] Provide fdt_reg() for unsized single-entry regions
authorMichael Brown <mcb30@ipxe.org>
Thu, 7 Aug 2025 14:41:42 +0000 (15:41 +0100)
committerMichael Brown <mcb30@ipxe.org>
Thu, 7 Aug 2025 14:49:09 +0000 (15:49 +0100)
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>
src/core/fdt.c
src/drivers/bus/devtree.c
src/include/ipxe/fdt.h

index ae723213bedf979c1b1094c8680ac16506548549..08adb166e2713e1381726f65c28e1b2c6f6d29c7 100644 (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
  *
index 32ab1c2cb99656843d52276f23c51b2ccb25802b..f71ad1ea410212e2f34cfa6af80eb18159a829a4 100644 (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 ) {
index eec02c5b36f4f82399128753e3b3238ab1d422ee..e951aea59eaa01f71e10bb5489624114072e28d5 100644 (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,