boot/mmu: Consolidate some fdt mapping functions
* Realized we already had a function which iterates over an fdt node and maps it's memory regs. Make it work for physical mappings or identity mappings. Change-Id: I0e3e323798bc2dfcead1accc1d403b30a8ab188f
This commit is contained in:
@@ -352,38 +352,71 @@ map_pages_loader()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TODO:move this to generic/ ?
|
||||||
static status_t
|
static status_t
|
||||||
map_pages_peripherals()
|
fdt_map_memory_ranges(const char* path, bool physical = false)
|
||||||
{
|
{
|
||||||
int node;
|
int node;
|
||||||
phys_addr_t regs_start;
|
const void *prop;
|
||||||
phys_addr_t regs_end;
|
int len;
|
||||||
const char* name = "/axi";
|
uint64 total;
|
||||||
|
|
||||||
node = fdt_path_offset(gFDT, name);
|
dprintf("checking FDT for %s...\n", path);
|
||||||
if (node < 0) {
|
node = fdt_path_offset(gFDT, path);
|
||||||
TRACE(("Unable to locate path offset for simple-bus!"));
|
|
||||||
|
total = 0;
|
||||||
|
|
||||||
|
int32 regAddressCells = 1;
|
||||||
|
int32 regSizeCells = 1;
|
||||||
|
fdt_get_cell_count(gFDT, node, regAddressCells, regSizeCells);
|
||||||
|
|
||||||
|
prop = fdt_getprop(gFDT, node, "reg", &len);
|
||||||
|
if (prop == NULL) {
|
||||||
|
dprintf("Unable to locate %s in FDT!\n", path);
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine the MMIO address
|
const uint32 *p = (const uint32 *)prop;
|
||||||
regs_start = fdt_get_device_reg(gFDT, node, false);
|
for (int32 i = 0; len; i++) {
|
||||||
|
uint64 base;
|
||||||
|
uint64 size;
|
||||||
|
if (regAddressCells == 2)
|
||||||
|
base = fdt64_to_cpu(*(uint64_t *)p);
|
||||||
|
else
|
||||||
|
base = fdt32_to_cpu(*(uint32_t *)p);
|
||||||
|
p += regAddressCells;
|
||||||
|
if (regSizeCells == 2)
|
||||||
|
size = fdt64_to_cpu(*(uint64_t *)p);
|
||||||
|
else
|
||||||
|
size = fdt32_to_cpu(*(uint32_t *)p);
|
||||||
|
p += regSizeCells;
|
||||||
|
len -= sizeof(uint32) * (regAddressCells + regSizeCells);
|
||||||
|
|
||||||
#warning TODO: This MMU code is overly simplistic.
|
if (size <= 0) {
|
||||||
if (regs_start == 0) {
|
dprintf("%ld: empty region\n", i);
|
||||||
// TODO: FDT's like am335x have peripherals at various
|
continue;
|
||||||
// locations. We should map *each* item within simple-bus.
|
}
|
||||||
panic("No reg for simple-bus. See TODO");
|
dprintf("%" B_PRIu32 ": base = %" B_PRIu64 ","
|
||||||
return B_ERROR;
|
"size = %" B_PRIu64 "\n", i, base, size);
|
||||||
|
|
||||||
|
total += size;
|
||||||
|
|
||||||
|
if (physical) {
|
||||||
|
if (insert_physical_memory_range(base, size) != B_OK) {
|
||||||
|
dprintf("cannot map physical memory range "
|
||||||
|
"(num ranges = %" B_PRIu32 ")!\n",
|
||||||
|
gKernelArgs.num_physical_memory_ranges);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (mmu_map_identity(base, base + size, ARM_MMU_L2_FLAG_B)) {
|
||||||
|
dprintf("cannot identity map memory range!");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Obvious hack is obvious
|
dprintf("total '%s' physical memory = %" B_PRId64 "MB\n", path,
|
||||||
regs_end = regs_start + 0x01000000;
|
total / (1024 * 1024));
|
||||||
|
|
||||||
TRACE(("BLOCK: %s START: %lx END %lx\n", name, regs_start, regs_end));
|
|
||||||
ASSERT((regs_start & ~ARM_PTE_ADDRESS_MASK) == 0);
|
|
||||||
|
|
||||||
mmu_map_identity(regs_start, regs_end, ARM_MMU_L2_FLAG_B);
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -410,11 +443,10 @@ init_page_directory()
|
|||||||
// map our well known / static pages
|
// map our well known / static pages
|
||||||
map_pages_loader();
|
map_pages_loader();
|
||||||
|
|
||||||
// map peripheral devices from fdt
|
// map peripheral devices (such as uart) from fdt
|
||||||
if (map_pages_peripherals() != B_OK) {
|
// TODO: Iterate over for "simple-bus" compatible devices!
|
||||||
// This is a panic since we still have serial access.
|
// this assumes /axi which is broadcom!
|
||||||
panic("%s: unable to map peripherals! Check FDT.\n", __func__);
|
fdt_map_memory_ranges("/axi");
|
||||||
}
|
|
||||||
|
|
||||||
mmu_flush_TLB();
|
mmu_flush_TLB();
|
||||||
|
|
||||||
@@ -662,69 +694,6 @@ mmu_init_for_kernel(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//TODO:move this to generic/ ?
|
|
||||||
static status_t
|
|
||||||
find_physical_memory_ranges(uint64 &total)
|
|
||||||
{
|
|
||||||
int node;
|
|
||||||
const void *prop;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
dprintf("checking for memory...\n");
|
|
||||||
// let's just skip the OF way (prop memory on /chosen)
|
|
||||||
//node = fdt_path_offset(gFDT, "/chosen");
|
|
||||||
node = fdt_path_offset(gFDT, "/memory");
|
|
||||||
// TODO: check devicetype=="memory" ?
|
|
||||||
|
|
||||||
total = 0;
|
|
||||||
|
|
||||||
int32 regAddressCells = 1;
|
|
||||||
int32 regSizeCells = 1;
|
|
||||||
fdt_get_cell_count(gFDT, node, regAddressCells, regSizeCells);
|
|
||||||
|
|
||||||
prop = fdt_getprop(gFDT, node, "reg", &len);
|
|
||||||
if (prop == NULL) {
|
|
||||||
panic("FDT /memory reg property not set");
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint32 *p = (const uint32 *)prop;
|
|
||||||
for (int32 i = 0; len; i++) {
|
|
||||||
uint64 base;
|
|
||||||
uint64 size;
|
|
||||||
if (regAddressCells == 2)
|
|
||||||
base = fdt64_to_cpu(*(uint64_t *)p);
|
|
||||||
else
|
|
||||||
base = fdt32_to_cpu(*(uint32_t *)p);
|
|
||||||
p += regAddressCells;
|
|
||||||
if (regSizeCells == 2)
|
|
||||||
size = fdt64_to_cpu(*(uint64_t *)p);
|
|
||||||
else
|
|
||||||
size = fdt32_to_cpu(*(uint32_t *)p);
|
|
||||||
p += regSizeCells;
|
|
||||||
len -= sizeof(uint32) * (regAddressCells + regSizeCells);
|
|
||||||
|
|
||||||
if (size <= 0) {
|
|
||||||
dprintf("%ld: empty region\n", i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
dprintf("%" B_PRIu32 ": base = %" B_PRIu64 ","
|
|
||||||
"size = %" B_PRIu64 "\n", i, base, size);
|
|
||||||
|
|
||||||
total += size;
|
|
||||||
|
|
||||||
if (insert_physical_memory_range(base, size) != B_OK) {
|
|
||||||
dprintf("cannot map physical memory range "
|
|
||||||
"(num ranges = %" B_PRIu32 ")!\n",
|
|
||||||
gKernelArgs.num_physical_memory_ranges);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
mmu_init(void)
|
mmu_init(void)
|
||||||
{
|
{
|
||||||
@@ -734,22 +703,19 @@ mmu_init(void)
|
|||||||
if (gKernelArgs.num_physical_memory_ranges == 0) {
|
if (gKernelArgs.num_physical_memory_ranges == 0) {
|
||||||
// get map of physical memory (fill in kernel_args structure)
|
// get map of physical memory (fill in kernel_args structure)
|
||||||
|
|
||||||
uint64 total;
|
if (fdt_map_memory_ranges("/memory", true) != B_OK) {
|
||||||
if (find_physical_memory_ranges(total) != B_OK) {
|
panic("Error: could not find physical memory ranges from FDT!\n");
|
||||||
dprintf("Error: could not find physical memory ranges!\n");
|
|
||||||
|
|
||||||
#ifdef SDRAM_BASE
|
#ifdef SDRAM_BASE
|
||||||
dprintf("Defaulting to 32MB at %" B_PRIx64 "\n", (uint64)SDRAM_BASE);
|
dprintf("Defaulting to 32MB at %" B_PRIx64 "\n", (uint64)SDRAM_BASE);
|
||||||
// specify available physical memory, using 32MB for now, since our
|
// specify available physical memory, using 32MB for now, since our
|
||||||
// ARMv5 targets have very little by default.
|
// ARMv5 targets have very little by default.
|
||||||
total = 32 * 1024 * 1024;
|
uint64 total = 32 * 1024 * 1024;
|
||||||
insert_physical_memory_range(SDRAM_BASE, total);
|
insert_physical_memory_range(SDRAM_BASE, total);
|
||||||
#else
|
#else
|
||||||
return /*B_ERROR*/;
|
return /*B_ERROR*/;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
dprintf("total physical memory = %" B_PRId64 "MB\n",
|
|
||||||
total / (1024 * 1024));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// see if subpages are disabled
|
// see if subpages are disabled
|
||||||
|
|||||||
Reference in New Issue
Block a user