mirror of
https://github.com/ipxe/ipxe
synced 2025-12-12 23:15:10 +03:00
[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 <mcb30@ipxe.org>
This commit is contained in:
@@ -482,57 +482,6 @@ int fdt_alias ( struct fdt *fdt, const char *name, unsigned int *offset ) {
|
|||||||
return 0;
|
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
|
* Find property
|
||||||
*
|
*
|
||||||
@@ -730,6 +679,28 @@ int fdt_u32 ( struct fdt *fdt, unsigned int offset, const char *name,
|
|||||||
return 0;
|
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
|
* Get region cell size specification
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -219,6 +219,7 @@ int dt_probe_node ( struct device *parent, unsigned int offset ) {
|
|||||||
dt->name = dt->dev.name;
|
dt->name = dt->dev.name;
|
||||||
snprintf ( dt->dev.name, sizeof ( dt->dev.name ), "%s", name );
|
snprintf ( dt->dev.name, sizeof ( dt->dev.name ), "%s", name );
|
||||||
dt->dev.desc.bus_type = BUS_TYPE_DT;
|
dt->dev.desc.bus_type = BUS_TYPE_DT;
|
||||||
|
dt->dev.desc.location = fdt_phandle ( &sysfdt, offset );
|
||||||
dt->dev.parent = parent;
|
dt->dev.parent = parent;
|
||||||
INIT_LIST_HEAD ( &dt->dev.children );
|
INIT_LIST_HEAD ( &dt->dev.children );
|
||||||
list_add_tail ( &dt->dev.siblings, &parent->children );
|
list_add_tail ( &dt->dev.siblings, &parent->children );
|
||||||
|
|||||||
@@ -176,8 +176,6 @@ extern int fdt_path ( struct fdt *fdt, const char *path,
|
|||||||
unsigned int *offset );
|
unsigned int *offset );
|
||||||
extern int fdt_alias ( struct fdt *fdt, const char *name,
|
extern int fdt_alias ( struct fdt *fdt, const char *name,
|
||||||
unsigned int *offset );
|
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,
|
extern const char * fdt_strings ( struct fdt *fdt, unsigned int offset,
|
||||||
const char *name, unsigned int *count );
|
const char *name, unsigned int *count );
|
||||||
extern const char * fdt_string ( struct fdt *fdt, unsigned int offset,
|
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 );
|
uint64_t *value );
|
||||||
extern int fdt_u32 ( struct fdt *fdt, unsigned int offset, const char *name,
|
extern int fdt_u32 ( struct fdt *fdt, unsigned int offset, const char *name,
|
||||||
uint32_t *value );
|
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,
|
extern void fdt_reg_cells ( struct fdt *fdt, unsigned int offset,
|
||||||
struct fdt_reg_cells *regs );
|
struct fdt_reg_cells *regs );
|
||||||
extern int fdt_reg_count ( struct fdt *fdt, unsigned int offset,
|
extern int fdt_reg_count ( struct fdt *fdt, unsigned int offset,
|
||||||
|
|||||||
@@ -237,6 +237,16 @@ static void fdt_test_exec ( void ) {
|
|||||||
ok ( fdt_path ( &fdt, "/soc/ethernet@10090000", &offset ) == 0 );
|
ok ( fdt_path ( &fdt, "/soc/ethernet@10090000", &offset ) == 0 );
|
||||||
ok ( fdt_u32 ( &fdt, offset, "max-speed", &u32 ) != 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 */
|
/* Verify cell properties */
|
||||||
ok ( fdt_path ( &fdt, "/soc/ethernet@10090000", &offset ) == 0 );
|
ok ( fdt_path ( &fdt, "/soc/ethernet@10090000", &offset ) == 0 );
|
||||||
ok ( fdt_cells ( &fdt, offset, "reg", 4, 2, &u64 ) == 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 ( ( string = fdt_string ( &fdt, offset, "phy-mode" ) ) != NULL );
|
||||||
ok ( strcmp ( string, "gmii" ) == 0 );
|
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 */
|
/* Verify node description */
|
||||||
ok ( fdt_path ( &fdt, "/memory@80000000", &offset ) == 0 );
|
ok ( fdt_path ( &fdt, "/memory@80000000", &offset ) == 0 );
|
||||||
ok ( fdt_describe ( &fdt, offset, &desc ) == 0 );
|
ok ( fdt_describe ( &fdt, offset, &desc ) == 0 );
|
||||||
|
|||||||
Reference in New Issue
Block a user