mirror of
https://github.com/ipxe/ipxe
synced 2025-12-08 02:10:25 +03:00
[dt] Locate parent node at point of use in dt_ioremap()
We currently rely on the recursive nature of devicetree bus probing to obtain the region cell size specification from the parent device. This blocks the possibility of creating a standalone console device based on /chosen/stdout-path before probing the whole bus. Fix by using fdt_parent() to locate the parent device at the point of use within dt_ioremap(). Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -54,16 +54,25 @@ static void dt_remove_children ( struct dt_device *parent );
|
|||||||
*/
|
*/
|
||||||
void * dt_ioremap ( struct dt_device *dt, unsigned int offset,
|
void * dt_ioremap ( struct dt_device *dt, unsigned int offset,
|
||||||
unsigned int index, size_t len ) {
|
unsigned int index, size_t len ) {
|
||||||
struct dt_device *parent =
|
struct fdt_reg_cells regs;
|
||||||
container_of ( dt->dev.parent, struct dt_device, dev );
|
unsigned int parent;
|
||||||
struct fdt_reg_cells *regs = &parent->regs;
|
|
||||||
uint64_t address;
|
uint64_t address;
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
void *io_addr;
|
void *io_addr;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
/* Get parent node */
|
||||||
|
if ( ( rc = fdt_parent ( &sysfdt, offset, &parent ) ) != 0 ) {
|
||||||
|
DBGC ( dt, "DT %s could not locate parent: %s\n",
|
||||||
|
dt->path, strerror ( rc ) );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read #address-cells and #size-cells, if present */
|
||||||
|
fdt_reg_cells ( &sysfdt, parent, ®s );
|
||||||
|
|
||||||
/* Read address */
|
/* Read address */
|
||||||
if ( ( rc = fdt_reg_address ( &sysfdt, offset, regs, index,
|
if ( ( rc = fdt_reg_address ( &sysfdt, offset, ®s, index,
|
||||||
&address ) ) != 0 ) {
|
&address ) ) != 0 ) {
|
||||||
DBGC ( dt, "DT %s could not read region %d address: %s\n",
|
DBGC ( dt, "DT %s could not read region %d address: %s\n",
|
||||||
dt->path, index, strerror ( rc ) );
|
dt->path, index, strerror ( rc ) );
|
||||||
@@ -72,8 +81,8 @@ void * dt_ioremap ( struct dt_device *dt, unsigned int offset,
|
|||||||
|
|
||||||
/* Read size (or assume sufficient, if tree specifies no sizes) */
|
/* Read size (or assume sufficient, if tree specifies no sizes) */
|
||||||
size = len;
|
size = len;
|
||||||
if ( regs->size_cells &&
|
if ( regs.size_cells &&
|
||||||
( ( rc = fdt_reg_size ( &sysfdt, offset, regs, index,
|
( ( rc = fdt_reg_size ( &sysfdt, offset, ®s, index,
|
||||||
&size ) ) != 0 ) ) {
|
&size ) ) != 0 ) ) {
|
||||||
DBGC ( dt, "DT %s could not read region %d size: %s\n",
|
DBGC ( dt, "DT %s could not read region %d size: %s\n",
|
||||||
dt->path, index, strerror ( rc ) );
|
dt->path, index, strerror ( rc ) );
|
||||||
@@ -222,9 +231,6 @@ static int dt_probe_node ( struct dt_device *parent, unsigned int offset,
|
|||||||
INIT_LIST_HEAD ( &dt->dev.children );
|
INIT_LIST_HEAD ( &dt->dev.children );
|
||||||
list_add_tail ( &dt->dev.siblings, &dt->dev.parent->children );
|
list_add_tail ( &dt->dev.siblings, &dt->dev.parent->children );
|
||||||
|
|
||||||
/* Read #address-cells and #size-cells, if present */
|
|
||||||
fdt_reg_cells ( &sysfdt, offset, &dt->regs );
|
|
||||||
|
|
||||||
/* Probe device */
|
/* Probe device */
|
||||||
if ( ( rc = dt_probe ( dt, offset ) ) != 0 )
|
if ( ( rc = dt_probe ( dt, offset ) ) != 0 )
|
||||||
goto err_probe;
|
goto err_probe;
|
||||||
|
|||||||
@@ -25,9 +25,6 @@ struct dt_device {
|
|||||||
struct dt_driver *driver;
|
struct dt_driver *driver;
|
||||||
/** Driver-private data */
|
/** Driver-private data */
|
||||||
void *priv;
|
void *priv;
|
||||||
|
|
||||||
/** Register cell size specification */
|
|
||||||
struct fdt_reg_cells regs;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A devicetree driver */
|
/** A devicetree driver */
|
||||||
|
|||||||
Reference in New Issue
Block a user