boot/efi: rework address-cells and size-cells handling
see Devicetree Specification, section 2.3.5 #address-cells and #size-cells The #address-cells and #size-cells properties may be used in any device node that has children in the devicetree hierarchy and describes how child device nodes should be addressed. The #address-cells and #size-cells properties are not inherited from ancestors in the devicetree. They shall be explicitly defined. If missing, a client program should assume a default value of 2 for #address-cells, and a value of 1 for #size-cells. Change-Id: Iafed49358540f8ac7aa673c3dc0191c9b580250b Reviewed-on: https://review.haiku-os.org/c/haiku/+/5144 Tested-by: Commit checker robot <[email protected]> Reviewed-by: Alex von Gluck IV <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
f5ea62c478
commit
9d65dbf1cb
@@ -9,7 +9,7 @@
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
void arch_handle_fdt(const void* fdt, int node, uint32 addressCells, uint32 sizeCells);
|
||||
void arch_handle_fdt(const void* fdt, int node);
|
||||
void arch_dtb_set_kernel_args(void);
|
||||
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ const struct supported_interrupt_controllers {
|
||||
|
||||
|
||||
void
|
||||
arch_handle_fdt(const void* fdt, int node, uint32 addressCells, uint32 sizeCells)
|
||||
arch_handle_fdt(const void* fdt, int node)
|
||||
{
|
||||
const char* deviceType = (const char*)fdt_getprop(fdt, node,
|
||||
"device_type", NULL);
|
||||
@@ -66,10 +66,8 @@ arch_handle_fdt(const void* fdt, int node, uint32 addressCells, uint32 sizeCells
|
||||
memcpy(interrupt_controller.kind, kSupportedInterruptControllers[i].kind,
|
||||
sizeof(interrupt_controller.kind));
|
||||
|
||||
dtb_get_reg(fdt, node, addressCells, sizeCells, 0,
|
||||
interrupt_controller.regs1);
|
||||
dtb_get_reg(fdt, node, addressCells, sizeCells, 1,
|
||||
interrupt_controller.regs2);
|
||||
dtb_get_reg(fdt, node, 0, interrupt_controller.regs1);
|
||||
dtb_get_reg(fdt, node, 1, interrupt_controller.regs2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ static addr_range sClint = {0};
|
||||
|
||||
|
||||
void
|
||||
arch_handle_fdt(const void* fdt, int node, uint32 addressCells, uint32 sizeCells)
|
||||
arch_handle_fdt(const void* fdt, int node)
|
||||
{
|
||||
const char* deviceType = (const char*)fdt_getprop(fdt, node,
|
||||
"device_type", NULL);
|
||||
@@ -73,13 +73,13 @@ arch_handle_fdt(const void* fdt, int node, uint32 addressCells, uint32 sizeCells
|
||||
return;
|
||||
|
||||
if (dtb_has_fdt_string(compatible, compatibleLen, "riscv,clint0")) {
|
||||
dtb_get_reg(fdt, node, addressCells, sizeCells, 0, sClint);
|
||||
dtb_get_reg(fdt, node, 0, sClint);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dtb_has_fdt_string(compatible, compatibleLen, "riscv,plic0")
|
||||
|| dtb_has_fdt_string(compatible, compatibleLen, "sifive,plic-1.0.0")) {
|
||||
dtb_get_reg(fdt, node, addressCells, sizeCells, 0, sPlic);
|
||||
dtb_get_reg(fdt, node, 0, sPlic);
|
||||
int propSize;
|
||||
if (uint32* prop = (uint32*)fdt_getprop(fdt, node, "interrupts-extended", &propSize)) {
|
||||
dprintf("PLIC contexts\n");
|
||||
|
||||
@@ -291,9 +291,48 @@ dtb_has_fdt_string(const char* prop, int size, const char* pattern)
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
dtb_get_reg(const void* fdt, int node, uint32 addressCells, uint32 sizeCells, size_t idx, addr_range& range)
|
||||
uint32
|
||||
dtb_get_address_cells(const void* fdt, int node)
|
||||
{
|
||||
uint32 res = 2;
|
||||
|
||||
int parent = fdt_parent_offset(fdt, node);
|
||||
if (parent < 0)
|
||||
return res;
|
||||
|
||||
uint32 *prop = (uint32*)fdt_getprop(sDtbTable, parent, "#address-cells", NULL);
|
||||
if (prop == NULL)
|
||||
return res;
|
||||
|
||||
res = fdt32_to_cpu(*prop);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
dtb_get_size_cells(const void* fdt, int node)
|
||||
{
|
||||
uint32 res = 1;
|
||||
|
||||
int parent = fdt_parent_offset(fdt, node);
|
||||
if (parent < 0)
|
||||
return res;
|
||||
|
||||
uint32 *prop = (uint32*)fdt_getprop(sDtbTable, parent, "#size-cells", NULL);
|
||||
if (prop == NULL)
|
||||
return res;
|
||||
|
||||
res = fdt32_to_cpu(*prop);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
dtb_get_reg(const void* fdt, int node, size_t idx, addr_range& range)
|
||||
{
|
||||
uint32 addressCells = dtb_get_address_cells(fdt, node);
|
||||
uint32 sizeCells = dtb_get_size_cells(fdt, node);
|
||||
|
||||
int propSize;
|
||||
const uint8* prop = (const uint8*)fdt_getprop(fdt, node, "reg", &propSize);
|
||||
if (prop == NULL)
|
||||
@@ -400,9 +439,9 @@ dtb_get_clock_frequency(const void* fdt, int node)
|
||||
|
||||
|
||||
static void
|
||||
dtb_handle_fdt(const void* fdt, int node, uint32 addressCells, uint32 sizeCells)
|
||||
dtb_handle_fdt(const void* fdt, int node)
|
||||
{
|
||||
arch_handle_fdt(fdt, node, addressCells, sizeCells);
|
||||
arch_handle_fdt(fdt, node);
|
||||
|
||||
int compatibleLen;
|
||||
const char* compatible = (const char*)fdt_getprop(fdt, node,
|
||||
@@ -423,7 +462,7 @@ dtb_handle_fdt(const void* fdt, int node, uint32 addressCells, uint32 sizeCells)
|
||||
memcpy(uart.kind, kSupportedUarts[i].kind,
|
||||
sizeof(uart.kind));
|
||||
|
||||
dtb_get_reg(fdt, node, addressCells, sizeCells, 0, uart.regs);
|
||||
dtb_get_reg(fdt, node, 0, uart.regs);
|
||||
uart.irq = dtb_get_interrupt(fdt, node);
|
||||
uart.clock = dtb_get_clock_frequency(fdt, node);
|
||||
|
||||
@@ -472,20 +511,8 @@ dtb_init()
|
||||
|
||||
int node = -1;
|
||||
int depth = -1;
|
||||
uint32 addressCells = 0;
|
||||
uint32 sizeCells = 0;
|
||||
while ((node = fdt_next_node(sDtbTable, node, &depth)) >= 0 && depth >= 0) {
|
||||
if (addressCells == 0) {
|
||||
uint32* prop = (uint32*)fdt_getprop(sDtbTable, node, "#address-cells", NULL);
|
||||
addressCells = fdt32_to_cpu(*prop);
|
||||
INFO("Address cells at %p: %u\n", prop, addressCells);
|
||||
}
|
||||
if (sizeCells == 0) {
|
||||
uint32* prop = (uint32*)fdt_getprop(sDtbTable, node, "#size-cells", NULL);
|
||||
sizeCells = fdt32_to_cpu(*prop);
|
||||
INFO("Size cells at %p: %u\n", prop, sizeCells);
|
||||
}
|
||||
dtb_handle_fdt(sDtbTable, node, addressCells, sizeCells);
|
||||
dtb_handle_fdt(sDtbTable, node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
extern void dtb_init();
|
||||
extern void dtb_set_kernel_args();
|
||||
|
||||
bool dtb_get_reg(const void* fdt, int node, uint32 addressCells, uint32 sizeCells, size_t idx, addr_range& range);
|
||||
bool dtb_get_reg(const void* fdt, int node, size_t idx, addr_range& range);
|
||||
bool dtb_has_fdt_string(const char* prop, int size, const char* pattern);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user