boot/efi: introduce arch_dtb
Change-Id: Iff9e4198aca706097889faf51e9559fe551126ad Reviewed-on: https://review.haiku-os.org/c/haiku/+/4782 Tested-by: Commit checker robot <[email protected]> Reviewed-by: Alex von Gluck IV <[email protected]>
This commit is contained in:
committed by
Alex von Gluck IV
parent
f4df72a061
commit
023a36024d
@@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef KERNEL_BOOT_PLATFORM_EFI_ARCH_DTB_H
|
||||||
|
#define KERNEL_BOOT_PLATFORM_EFI_ARCH_DTB_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
void arch_handle_fdt(const void* fdt, int node, uint32 addressCells, uint32 sizeCells);
|
||||||
|
void arch_dtb_set_kernel_args(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* KERNEL_BOOT_PLATFORM_EFI_ARCH_DTB_H */
|
||||||
@@ -2,6 +2,8 @@ SubDir HAIKU_TOP src system boot platform efi arch arm ;
|
|||||||
|
|
||||||
SubDirHdrs $(HAIKU_TOP) src system boot platform efi ;
|
SubDirHdrs $(HAIKU_TOP) src system boot platform efi ;
|
||||||
|
|
||||||
|
UseLibraryHeaders [ FDirName libfdt ] ;
|
||||||
|
|
||||||
UsePrivateHeaders [ FDirName kernel platform ] ;
|
UsePrivateHeaders [ FDirName kernel platform ] ;
|
||||||
UsePrivateHeaders [ FDirName kernel boot platform efi ] ;
|
UsePrivateHeaders [ FDirName kernel boot platform efi ] ;
|
||||||
|
|
||||||
@@ -19,6 +21,7 @@ for platform in [ MultiBootSubDirSetup efi ] {
|
|||||||
crt0-efi-$(TARGET_ARCH).S
|
crt0-efi-$(TARGET_ARCH).S
|
||||||
entry.S
|
entry.S
|
||||||
relocation_func.cpp
|
relocation_func.cpp
|
||||||
|
arch_dtb.cpp
|
||||||
arch_mmu.cpp
|
arch_mmu.cpp
|
||||||
arch_smp.cpp
|
arch_smp.cpp
|
||||||
arch_start.cpp
|
arch_start.cpp
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2021 Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Alexander von Gluck IV <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <arch_cpu_defs.h>
|
||||||
|
#include <arch_dtb.h>
|
||||||
|
#include <arch_smp.h>
|
||||||
|
#include <boot/platform.h>
|
||||||
|
#include <boot/stage2.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <libfdt.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "dtb.h"
|
||||||
|
|
||||||
|
|
||||||
|
const struct supported_interrupt_controllers {
|
||||||
|
const char* dtb_compat;
|
||||||
|
const char* kind;
|
||||||
|
} kSupportedInterruptControllers[] = {
|
||||||
|
{ "arm,cortex-a9-gic", INTC_KIND_GICV1 },
|
||||||
|
{ "arm,cortex-a15-gic", INTC_KIND_GICV2 },
|
||||||
|
{ "ti,omap3-intc", INTC_KIND_OMAP3 },
|
||||||
|
{ "marvell,pxa-intc", INTC_KIND_PXA },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
arch_handle_fdt(const void* fdt, int node, uint32 addressCells, uint32 sizeCells)
|
||||||
|
{
|
||||||
|
const char* deviceType = (const char*)fdt_getprop(fdt, node,
|
||||||
|
"device_type", NULL);
|
||||||
|
|
||||||
|
if (deviceType != NULL) {
|
||||||
|
if (strcmp(deviceType, "cpu") == 0) {
|
||||||
|
platform_cpu_info* info;
|
||||||
|
arch_smp_register_cpu(&info);
|
||||||
|
if (info == NULL)
|
||||||
|
return;
|
||||||
|
info->id = fdt32_to_cpu(*(uint32*)fdt_getprop(fdt, node,
|
||||||
|
"reg", NULL));
|
||||||
|
dprintf("cpu\n");
|
||||||
|
dprintf(" id: %" B_PRIu32 "\n", info->id);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int compatibleLen;
|
||||||
|
const char* compatible = (const char*)fdt_getprop(fdt, node,
|
||||||
|
"compatible", &compatibleLen);
|
||||||
|
|
||||||
|
if (compatible == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
intc_info &interrupt_controller = gKernelArgs.arch_args.interrupt_controller;
|
||||||
|
if (interrupt_controller.kind[0] == 0) {
|
||||||
|
for (uint32 i = 0; i < B_COUNT_OF(kSupportedInterruptControllers); i++) {
|
||||||
|
if (dtb_has_fdt_string(compatible, compatibleLen,
|
||||||
|
kSupportedInterruptControllers[i].dtb_compat)) {
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
arch_dtb_set_kernel_args(void)
|
||||||
|
{
|
||||||
|
intc_info &interrupt_controller = gKernelArgs.arch_args.interrupt_controller;
|
||||||
|
dprintf("Chosen interrupt controller:\n");
|
||||||
|
if (interrupt_controller.kind[0] == 0) {
|
||||||
|
dprintf("kind: None!\n");
|
||||||
|
} else {
|
||||||
|
dprintf(" kind: %s\n", interrupt_controller.kind);
|
||||||
|
dprintf(" regs: %#" B_PRIx64 ", %#" B_PRIx64 "\n",
|
||||||
|
interrupt_controller.regs1.start,
|
||||||
|
interrupt_controller.regs1.size);
|
||||||
|
dprintf(" %#" B_PRIx64 ", %#" B_PRIx64 "\n",
|
||||||
|
interrupt_controller.regs2.start,
|
||||||
|
interrupt_controller.regs2.size);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ SubDir HAIKU_TOP src system boot platform efi arch riscv64 ;
|
|||||||
|
|
||||||
SubDirHdrs $(HAIKU_TOP) src system boot platform efi ;
|
SubDirHdrs $(HAIKU_TOP) src system boot platform efi ;
|
||||||
|
|
||||||
|
UseLibraryHeaders [ FDirName libfdt ] ;
|
||||||
|
|
||||||
UsePrivateHeaders [ FDirName kernel platform ] ;
|
UsePrivateHeaders [ FDirName kernel platform ] ;
|
||||||
UsePrivateHeaders [ FDirName kernel boot platform efi ] ;
|
UsePrivateHeaders [ FDirName kernel boot platform efi ] ;
|
||||||
|
|
||||||
@@ -13,9 +15,10 @@ for platform in [ MultiBootSubDirSetup efi ] {
|
|||||||
crt0-efi-$(TARGET_ARCH).S
|
crt0-efi-$(TARGET_ARCH).S
|
||||||
entry.S
|
entry.S
|
||||||
relocation_func.cpp
|
relocation_func.cpp
|
||||||
arch_start.cpp
|
arch_dtb.cpp
|
||||||
arch_smp.cpp
|
|
||||||
arch_mmu.cpp
|
arch_mmu.cpp
|
||||||
|
arch_smp.cpp
|
||||||
|
arch_start.cpp
|
||||||
arch_timer.cpp
|
arch_timer.cpp
|
||||||
arch_traps.cpp
|
arch_traps.cpp
|
||||||
arch_traps_asm.S
|
arch_traps_asm.S
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2021 Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Alexander von Gluck IV <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <arch_cpu_defs.h>
|
||||||
|
#include <arch_dtb.h>
|
||||||
|
#include <arch_smp.h>
|
||||||
|
#include <boot/platform.h>
|
||||||
|
#include <boot/stage2.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <libfdt.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "dtb.h"
|
||||||
|
|
||||||
|
|
||||||
|
uint32 gBootHart = 0;
|
||||||
|
static uint64 sTimerFrequency = 10000000;
|
||||||
|
|
||||||
|
static addr_range sPlic = {0};
|
||||||
|
static addr_range sClint = {0};
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
arch_handle_fdt(const void* fdt, int node, uint32 addressCells, uint32 sizeCells)
|
||||||
|
{
|
||||||
|
const char* deviceType = (const char*)fdt_getprop(fdt, node,
|
||||||
|
"device_type", NULL);
|
||||||
|
|
||||||
|
const char* name = fdt_get_name(fdt, node, NULL);
|
||||||
|
if (strcmp(name, "chosen") == 0) {
|
||||||
|
if (uint32* prop = (uint32*)fdt_getprop(fdt, node, "boot-hartid", NULL))
|
||||||
|
gBootHart = fdt32_to_cpu(*prop);
|
||||||
|
} else if (strcmp(name, "cpus") == 0) {
|
||||||
|
if (uint32* prop = (uint32*)fdt_getprop(fdt, node, "timebase-frequency", NULL))
|
||||||
|
sTimerFrequency = fdt32_to_cpu(*prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deviceType != NULL) {
|
||||||
|
if (strcmp(deviceType, "cpu") == 0) {
|
||||||
|
// TODO: improve incompatible CPU detection
|
||||||
|
if (!(fdt_getprop(fdt, node, "mmu-type", NULL) != NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
platform_cpu_info* info;
|
||||||
|
arch_smp_register_cpu(&info);
|
||||||
|
if (info == NULL)
|
||||||
|
return;
|
||||||
|
info->id = fdt32_to_cpu(*(uint32*)fdt_getprop(fdt, node,
|
||||||
|
"reg", NULL));
|
||||||
|
dprintf("cpu\n");
|
||||||
|
dprintf(" id: %" B_PRIu32 "\n", info->id);
|
||||||
|
|
||||||
|
int subNode = fdt_subnode_offset(fdt, node, "interrupt-controller");
|
||||||
|
if (subNode < 0) {
|
||||||
|
dprintf(" [!] no interrupt controller\n");
|
||||||
|
} else {
|
||||||
|
info->phandle = fdt_get_phandle(fdt, subNode);
|
||||||
|
dprintf(" phandle: %" B_PRIu32 "\n", info->phandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int compatibleLen;
|
||||||
|
const char* compatible = (const char*)fdt_getprop(fdt, node,
|
||||||
|
"compatible", &compatibleLen);
|
||||||
|
|
||||||
|
if (compatible == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (dtb_has_fdt_string(compatible, compatibleLen, "riscv,clint0")) {
|
||||||
|
dtb_get_reg(fdt, node, addressCells, sizeCells, 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);
|
||||||
|
int propSize;
|
||||||
|
if (uint32* prop = (uint32*)fdt_getprop(fdt, node, "interrupts-extended", &propSize)) {
|
||||||
|
dprintf("PLIC contexts\n");
|
||||||
|
uint32 contextId = 0;
|
||||||
|
for (uint32 *it = prop; (uint8_t*)it - (uint8_t*)prop < propSize; it += 2) {
|
||||||
|
uint32 phandle = fdt32_to_cpu(*it);
|
||||||
|
uint32 interrupt = fdt32_to_cpu(*(it + 1));
|
||||||
|
if (interrupt == sExternInt) {
|
||||||
|
platform_cpu_info* cpuInfo = arch_smp_find_cpu(phandle);
|
||||||
|
dprintf(" context %" B_PRIu32 ": %" B_PRIu32 "\n", contextId, phandle);
|
||||||
|
if (cpuInfo != NULL) {
|
||||||
|
cpuInfo->plicContext = contextId;
|
||||||
|
dprintf(" cpu id: %" B_PRIu32 "\n", cpuInfo->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contextId++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
arch_dtb_set_kernel_args(void)
|
||||||
|
{
|
||||||
|
dprintf("bootHart: %" B_PRIu32 "\n", gBootHart);
|
||||||
|
dprintf("timerFrequency: %" B_PRIu64 "\n", sTimerFrequency);
|
||||||
|
gKernelArgs.arch_args.timerFrequency = sTimerFrequency;
|
||||||
|
|
||||||
|
// gKernelArgs.arch_args.htif = {.start = 0x40008000, .size = 0x10};
|
||||||
|
gKernelArgs.arch_args.htif = {.start = 0, .size = 0};
|
||||||
|
gKernelArgs.arch_args.plic = sPlic;
|
||||||
|
gKernelArgs.arch_args.clint = sClint;
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
// TODO: split arch-depending code to per-arch source
|
// TODO: split arch-depending code to per-arch source
|
||||||
|
|
||||||
#include <arch_cpu_defs.h>
|
#include <arch_cpu_defs.h>
|
||||||
|
#include <arch_dtb.h>
|
||||||
#include <arch_smp.h>
|
#include <arch_smp.h>
|
||||||
#include <arch/generic/debug_uart_8250.h>
|
#include <arch/generic/debug_uart_8250.h>
|
||||||
#if defined(__riscv)
|
#if defined(__riscv)
|
||||||
@@ -41,14 +42,6 @@ extern "C" {
|
|||||||
static void* sDtbTable = NULL;
|
static void* sDtbTable = NULL;
|
||||||
static uint32 sDtbSize = 0;
|
static uint32 sDtbSize = 0;
|
||||||
|
|
||||||
// TODO: gBootHart is riscy, move
|
|
||||||
uint32 gBootHart = 0;
|
|
||||||
static uint64 sTimerFrequency = 10000000;
|
|
||||||
|
|
||||||
static addr_range sPlic = {0};
|
|
||||||
static addr_range sClint = {0};
|
|
||||||
|
|
||||||
|
|
||||||
static void WriteString(const char *str) {dprintf("%s", str);}
|
static void WriteString(const char *str) {dprintf("%s", str);}
|
||||||
static void WriteLn() {dprintf("\n");}
|
static void WriteLn() {dprintf("\n");}
|
||||||
static void WriteHex(uint64_t val, int n) {dprintf("%08" B_PRIx64, val);}
|
static void WriteHex(uint64_t val, int n) {dprintf("%08" B_PRIx64, val);}
|
||||||
@@ -77,19 +70,6 @@ const struct supported_uarts {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifdef __ARM__
|
|
||||||
const struct supported_interrupt_controllers {
|
|
||||||
const char* dtb_compat;
|
|
||||||
const char* kind;
|
|
||||||
} kSupportedInterruptControllers[] = {
|
|
||||||
{ "arm,cortex-a9-gic", INTC_KIND_GICV1 },
|
|
||||||
{ "arm,cortex-a15-gic", INTC_KIND_GICV2 },
|
|
||||||
{ "ti,omap3-intc", INTC_KIND_OMAP3 },
|
|
||||||
{ "marvell,pxa-intc", INTC_KIND_PXA },
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static void WriteStringList(const char* prop, size_t size)
|
static void WriteStringList(const char* prop, size_t size)
|
||||||
{
|
{
|
||||||
bool first = true;
|
bool first = true;
|
||||||
@@ -295,8 +275,8 @@ static void DumpFdt(const void *fdt)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
HasFdtString(const char* prop, int size, const char* pattern)
|
dtb_has_fdt_string(const char* prop, int size, const char* pattern)
|
||||||
{
|
{
|
||||||
int patternLen = strlen(pattern);
|
int patternLen = strlen(pattern);
|
||||||
const char* propEnd = prop + size;
|
const char* propEnd = prop + size;
|
||||||
@@ -310,8 +290,8 @@ HasFdtString(const char* prop, int size, const char* pattern)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
GetReg(const void* fdt, int node, uint32 addressCells, uint32 sizeCells, size_t idx, addr_range& range)
|
dtb_get_reg(const void* fdt, int node, uint32 addressCells, uint32 sizeCells, size_t idx, addr_range& range)
|
||||||
{
|
{
|
||||||
int propSize;
|
int propSize;
|
||||||
const uint8* prop = (const uint8*)fdt_getprop(fdt, node, "reg", &propSize);
|
const uint8* prop = (const uint8*)fdt_getprop(fdt, node, "reg", &propSize);
|
||||||
@@ -339,7 +319,7 @@ GetReg(const void* fdt, int node, uint32 addressCells, uint32 sizeCells, size_t
|
|||||||
|
|
||||||
|
|
||||||
static uint32
|
static uint32
|
||||||
GetInterruptParent(const void* fdt, int node)
|
dtb_get_interrupt_parent(const void* fdt, int node)
|
||||||
{
|
{
|
||||||
while (node >= 0) {
|
while (node >= 0) {
|
||||||
uint32* prop;
|
uint32* prop;
|
||||||
@@ -357,9 +337,9 @@ GetInterruptParent(const void* fdt, int node)
|
|||||||
|
|
||||||
|
|
||||||
static uint32
|
static uint32
|
||||||
GetInterruptCells(const void* fdt, int node)
|
dtb_get_interrupt_cells(const void* fdt, int node)
|
||||||
{
|
{
|
||||||
uint32 intc_node = GetInterruptParent(fdt, node);
|
uint32 intc_node = dtb_get_interrupt_parent(fdt, node);
|
||||||
if (intc_node > 0) {
|
if (intc_node > 0) {
|
||||||
uint32* prop = (uint32*)fdt_getprop(fdt, intc_node, "#interrupt-cells", NULL);
|
uint32* prop = (uint32*)fdt_getprop(fdt, intc_node, "#interrupt-cells", NULL);
|
||||||
if (prop != NULL) {
|
if (prop != NULL) {
|
||||||
@@ -372,9 +352,9 @@ GetInterruptCells(const void* fdt, int node)
|
|||||||
|
|
||||||
|
|
||||||
static uint32
|
static uint32
|
||||||
GetInterrupt(const void* fdt, int node)
|
dtb_get_interrupt(const void* fdt, int node)
|
||||||
{
|
{
|
||||||
uint32 interruptCells = GetInterruptCells(fdt, node);
|
uint32 interruptCells = dtb_get_interrupt_cells(fdt, node);
|
||||||
|
|
||||||
if (uint32* prop = (uint32*)fdt_getprop(fdt, node, "interrupts-extended", NULL)) {
|
if (uint32* prop = (uint32*)fdt_getprop(fdt, node, "interrupts-extended", NULL)) {
|
||||||
return fdt32_to_cpu(*(prop + 1));
|
return fdt32_to_cpu(*(prop + 1));
|
||||||
@@ -392,7 +372,7 @@ GetInterrupt(const void* fdt, int node)
|
|||||||
|
|
||||||
|
|
||||||
static int64
|
static int64
|
||||||
GetClockFrequency(const void* fdt, int node)
|
dtb_get_clock_frequency(const void* fdt, int node)
|
||||||
{
|
{
|
||||||
uint32* prop;
|
uint32* prop;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@@ -419,43 +399,9 @@ GetClockFrequency(const void* fdt, int node)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
HandleFdt(const void* fdt, int node, uint32 addressCells, uint32 sizeCells)
|
dtb_handle_fdt(const void* fdt, int node, uint32 addressCells, uint32 sizeCells)
|
||||||
{
|
{
|
||||||
const char* name = fdt_get_name(fdt, node, NULL);
|
arch_handle_fdt(fdt, node, addressCells, sizeCells);
|
||||||
if (strcmp(name, "chosen") == 0) {
|
|
||||||
if (uint32* prop = (uint32*)fdt_getprop(fdt, node, "boot-hartid", NULL))
|
|
||||||
gBootHart = fdt32_to_cpu(*prop);
|
|
||||||
} else if (strcmp(name, "cpus") == 0) {
|
|
||||||
if (uint32* prop = (uint32*)fdt_getprop(fdt, node, "timebase-frequency", NULL))
|
|
||||||
sTimerFrequency = fdt32_to_cpu(*prop);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* deviceType = (const char*)fdt_getprop(fdt, node,
|
|
||||||
"device_type", NULL);
|
|
||||||
|
|
||||||
if (deviceType != NULL) {
|
|
||||||
if (strcmp(deviceType, "cpu") == 0) {
|
|
||||||
// TODO: improve incompatible CPU detection
|
|
||||||
if (!(fdt_getprop(fdt, node, "mmu-type", NULL) != NULL))
|
|
||||||
return;
|
|
||||||
platform_cpu_info* info;
|
|
||||||
arch_smp_register_cpu(&info);
|
|
||||||
if (info == NULL)
|
|
||||||
return;
|
|
||||||
info->id = fdt32_to_cpu(*(uint32*)fdt_getprop(fdt, node,
|
|
||||||
"reg", NULL));
|
|
||||||
dprintf("cpu\n");
|
|
||||||
dprintf(" id: %" B_PRIu32 "\n", info->id);
|
|
||||||
|
|
||||||
int subNode = fdt_subnode_offset(fdt, node, "interrupt-controller");
|
|
||||||
if (subNode < 0) {
|
|
||||||
dprintf(" [!] no interrupt controller\n");
|
|
||||||
} else {
|
|
||||||
info->phandle = fdt_get_phandle(fdt, subNode);
|
|
||||||
dprintf(" phandle: %" B_PRIu32 "\n", info->phandle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int compatibleLen;
|
int compatibleLen;
|
||||||
const char* compatible = (const char*)fdt_getprop(fdt, node,
|
const char* compatible = (const char*)fdt_getprop(fdt, node,
|
||||||
@@ -464,50 +410,21 @@ HandleFdt(const void* fdt, int node, uint32 addressCells, uint32 sizeCells)
|
|||||||
if (compatible == NULL)
|
if (compatible == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (HasFdtString(compatible, compatibleLen, "riscv,clint0")) {
|
|
||||||
GetReg(fdt, node, addressCells, sizeCells, 0, sClint);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HasFdtString(compatible, compatibleLen, "riscv,plic0")
|
|
||||||
|| HasFdtString(compatible, compatibleLen, "sifive,plic-1.0.0")) {
|
|
||||||
GetReg(fdt, node, addressCells, sizeCells, 0, sPlic);
|
|
||||||
int propSize;
|
|
||||||
if (uint32* prop = (uint32*)fdt_getprop(fdt, node, "interrupts-extended", &propSize)) {
|
|
||||||
dprintf("PLIC contexts\n");
|
|
||||||
uint32 contextId = 0;
|
|
||||||
for (uint32 *it = prop; (uint8_t*)it - (uint8_t*)prop < propSize; it += 2) {
|
|
||||||
uint32 phandle = fdt32_to_cpu(*it);
|
|
||||||
uint32 interrupt = fdt32_to_cpu(*(it + 1));
|
|
||||||
if (interrupt == sExternInt) {
|
|
||||||
platform_cpu_info* cpuInfo = arch_smp_find_cpu(phandle);
|
|
||||||
dprintf(" context %" B_PRIu32 ": %" B_PRIu32 "\n", contextId, phandle);
|
|
||||||
if (cpuInfo != NULL) {
|
|
||||||
cpuInfo->plicContext = contextId;
|
|
||||||
dprintf(" cpu id: %" B_PRIu32 "\n", cpuInfo->id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
contextId++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: We should check for the "chosen" uart and prioritize that one
|
// TODO: We should check for the "chosen" uart and prioritize that one
|
||||||
|
|
||||||
// check for a uart if we don't have one
|
// check for a uart if we don't have one
|
||||||
uart_info &uart = gKernelArgs.arch_args.uart;
|
uart_info &uart = gKernelArgs.arch_args.uart;
|
||||||
if (uart.kind[0] == 0) {
|
if (uart.kind[0] == 0) {
|
||||||
for (uint32 i = 0; i < B_COUNT_OF(kSupportedUarts); i++) {
|
for (uint32 i = 0; i < B_COUNT_OF(kSupportedUarts); i++) {
|
||||||
if (HasFdtString(compatible, compatibleLen,
|
if (dtb_has_fdt_string(compatible, compatibleLen,
|
||||||
kSupportedUarts[i].dtb_compat)) {
|
kSupportedUarts[i].dtb_compat)) {
|
||||||
|
|
||||||
memcpy(uart.kind, kSupportedUarts[i].kind,
|
memcpy(uart.kind, kSupportedUarts[i].kind,
|
||||||
sizeof(uart.kind));
|
sizeof(uart.kind));
|
||||||
|
|
||||||
GetReg(fdt, node, addressCells, sizeCells, 0, uart.regs);
|
dtb_get_reg(fdt, node, addressCells, sizeCells, 0, uart.regs);
|
||||||
uart.irq = GetInterrupt(fdt, node);
|
uart.irq = dtb_get_interrupt(fdt, node);
|
||||||
uart.clock = GetClockFrequency(fdt, node);
|
uart.clock = dtb_get_clock_frequency(fdt, node);
|
||||||
|
|
||||||
gUART = kSupportedUarts[i].uart_driver_init(uart.regs.start,
|
gUART = kSupportedUarts[i].uart_driver_init(uart.regs.start,
|
||||||
uart.clock);
|
uart.clock);
|
||||||
@@ -517,25 +434,6 @@ HandleFdt(const void* fdt, int node, uint32 addressCells, uint32 sizeCells)
|
|||||||
if (gUART != NULL)
|
if (gUART != NULL)
|
||||||
gUART->InitEarly();
|
gUART->InitEarly();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__ARM__)
|
|
||||||
intc_info &interrupt_controller = gKernelArgs.arch_args.interrupt_controller;
|
|
||||||
if (interrupt_controller.kind[0] == 0) {
|
|
||||||
for (uint32 i = 0; i < B_COUNT_OF(kSupportedInterruptControllers); i++) {
|
|
||||||
if (HasFdtString(compatible, compatibleLen,
|
|
||||||
kSupportedInterruptControllers[i].dtb_compat)) {
|
|
||||||
|
|
||||||
memcpy(interrupt_controller.kind, kSupportedInterruptControllers[i].kind,
|
|
||||||
sizeof(interrupt_controller.kind));
|
|
||||||
|
|
||||||
GetReg(fdt, node, addressCells, sizeCells, 0,
|
|
||||||
interrupt_controller.regs1);
|
|
||||||
GetReg(fdt, node, addressCells, sizeCells, 1,
|
|
||||||
interrupt_controller.regs2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -574,7 +472,7 @@ dtb_init()
|
|||||||
int node = -1;
|
int node = -1;
|
||||||
int depth = -1;
|
int depth = -1;
|
||||||
while ((node = fdt_next_node(sDtbTable, node, &depth)) >= 0 && depth >= 0) {
|
while ((node = fdt_next_node(sDtbTable, node, &depth)) >= 0 && depth >= 0) {
|
||||||
HandleFdt(sDtbTable, node, 2, 2);
|
dtb_handle_fdt(sDtbTable, node, 2, 2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -586,7 +484,6 @@ dtb_set_kernel_args()
|
|||||||
{
|
{
|
||||||
// pack into proper location if the architecture cares
|
// pack into proper location if the architecture cares
|
||||||
if (sDtbTable != NULL) {
|
if (sDtbTable != NULL) {
|
||||||
#if defined(__ARM__) || defined(__riscv)
|
|
||||||
// libfdt requires 8-byte alignment
|
// libfdt requires 8-byte alignment
|
||||||
gKernelArgs.arch_args.fdt = (void*)(addr_t)kernel_args_malloc(sDtbSize, 8);
|
gKernelArgs.arch_args.fdt = (void*)(addr_t)kernel_args_malloc(sDtbSize, 8);
|
||||||
|
|
||||||
@@ -594,20 +491,8 @@ dtb_set_kernel_args()
|
|||||||
memcpy(gKernelArgs.arch_args.fdt, sDtbTable, sDtbSize);
|
memcpy(gKernelArgs.arch_args.fdt, sDtbTable, sDtbSize);
|
||||||
else
|
else
|
||||||
ERROR("unable to malloc for fdt!\n");
|
ERROR("unable to malloc for fdt!\n");
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __riscv
|
|
||||||
dprintf("bootHart: %" B_PRIu32 "\n", gBootHart);
|
|
||||||
dprintf("timerFrequency: %" B_PRIu64 "\n", sTimerFrequency);
|
|
||||||
gKernelArgs.arch_args.timerFrequency = sTimerFrequency;
|
|
||||||
|
|
||||||
// gKernelArgs.arch_args.htif = {.start = 0x40008000, .size = 0x10};
|
|
||||||
gKernelArgs.arch_args.htif = {.start = 0, .size = 0};
|
|
||||||
gKernelArgs.arch_args.plic = sPlic;
|
|
||||||
gKernelArgs.arch_args.clint = sClint;
|
|
||||||
#endif
|
|
||||||
#if defined(__ARM__) || defined(__riscv)
|
|
||||||
uart_info &uart = gKernelArgs.arch_args.uart;
|
uart_info &uart = gKernelArgs.arch_args.uart;
|
||||||
dprintf("Chosen UART:\n");
|
dprintf("Chosen UART:\n");
|
||||||
if (uart.kind[0] == 0) {
|
if (uart.kind[0] == 0) {
|
||||||
@@ -619,20 +504,6 @@ dtb_set_kernel_args()
|
|||||||
dprintf(" irq: %" B_PRIu32 "\n", uart.irq);
|
dprintf(" irq: %" B_PRIu32 "\n", uart.irq);
|
||||||
dprintf(" clock: %" B_PRIu64 "\n", uart.clock);
|
dprintf(" clock: %" B_PRIu64 "\n", uart.clock);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#if defined(__ARM__)
|
arch_dtb_set_kernel_args();
|
||||||
intc_info &interrupt_controller = gKernelArgs.arch_args.interrupt_controller;
|
|
||||||
dprintf("Chosen interrupt controller:\n");
|
|
||||||
if (interrupt_controller.kind[0] == 0) {
|
|
||||||
dprintf("kind: None!\n");
|
|
||||||
} else {
|
|
||||||
dprintf(" kind: %s\n", interrupt_controller.kind);
|
|
||||||
dprintf(" regs: %#" B_PRIx64 ", %#" B_PRIx64 "\n",
|
|
||||||
interrupt_controller.regs1.start,
|
|
||||||
interrupt_controller.regs1.size);
|
|
||||||
dprintf(" %#" B_PRIx64 ", %#" B_PRIx64 "\n",
|
|
||||||
interrupt_controller.regs2.start,
|
|
||||||
interrupt_controller.regs2.size);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,9 @@
|
|||||||
extern void dtb_init();
|
extern void dtb_init();
|
||||||
extern void dtb_set_kernel_args();
|
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_has_fdt_string(const char* prop, int size, const char* pattern);
|
||||||
|
|
||||||
|
|
||||||
#endif /* !_ASSEMBLER */
|
#endif /* !_ASSEMBLER */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user