diff --git a/headers/private/kernel/arch/arm/arch_kernel_args.h b/headers/private/kernel/arch/arm/arch_kernel_args.h index 513848004b..f2a9881db3 100644 --- a/headers/private/kernel/arch/arm/arch_kernel_args.h +++ b/headers/private/kernel/arch/arm/arch_kernel_args.h @@ -11,6 +11,7 @@ #include +#include #include @@ -41,6 +42,7 @@ typedef struct { FixedWidthPointer fdt; uart_info uart; + intc_info interrupt_controller; } _PACKED arch_kernel_args; #endif /* KERNEL_ARCH_ARM_KERNEL_ARGS_H */ diff --git a/headers/private/kernel/boot/interrupt_controller.h b/headers/private/kernel/boot/interrupt_controller.h new file mode 100644 index 0000000000..61f91da4d4 --- /dev/null +++ b/headers/private/kernel/boot/interrupt_controller.h @@ -0,0 +1,26 @@ +/* + * Copyright 2021 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef KERNEL_BOOT_INTERRUPT_CONTROLLER_H +#define KERNEL_BOOT_INTERRUPT_CONTROLLER_H + + +#include +#include + + +#define INTC_KIND_GICV1 "gicv1" +#define INTC_KIND_GICV2 "gicv2" +#define INTC_KIND_OMAP3 "omap3" +#define INTC_KIND_PXA "pxa" + + +typedef struct { + char kind[32]; + addr_range regs1; + addr_range regs2; +} __attribute__((packed)) intc_info; + + +#endif /* KERNEL_BOOT_INTERRUPT_CONTROLLER_H */ diff --git a/src/system/boot/platform/efi/dtb.cpp b/src/system/boot/platform/efi/dtb.cpp index 1717fda71e..4f64595901 100644 --- a/src/system/boot/platform/efi/dtb.cpp +++ b/src/system/boot/platform/efi/dtb.cpp @@ -73,6 +73,19 @@ const struct supported_uarts { }; +const struct supported_interrupt_controllers { + const char* dtb_compat; + const char* kind; +} kSupportedInterruptControllers[] = { +#ifdef __ARM__ + { "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) { bool first = true; @@ -449,29 +462,45 @@ HandleFdt(const void* fdt, int node, uint32 addressCells, uint32 sizeCells) // TODO: We should check for the "chosen" uart and prioritize that one - uart_info &uart = gKernelArgs.arch_args.uart; - if (uart.kind[0] != 0) - return; - // check for a uart if we don't have one - for (uint32 i = 0; i < B_COUNT_OF(kSupportedUarts); i++) { - if (HasFdtString(compatible, compatibleLen, - kSupportedUarts[i].dtb_compat)) { + uart_info &uart = gKernelArgs.arch_args.uart; + if (uart.kind[0] == 0) { + for (uint32 i = 0; i < B_COUNT_OF(kSupportedUarts); i++) { + if (HasFdtString(compatible, compatibleLen, + kSupportedUarts[i].dtb_compat)) { - memcpy(uart.kind, kSupportedUarts[i].kind, - sizeof(uart.kind)); + memcpy(uart.kind, kSupportedUarts[i].kind, + sizeof(uart.kind)); - GetReg(fdt, node, addressCells, sizeCells, 0, uart.regs); - uart.irq = GetInterrupt(fdt, node); - uart.clock = GetClockFrequency(fdt, node); + GetReg(fdt, node, addressCells, sizeCells, 0, uart.regs); + uart.irq = GetInterrupt(fdt, node); + uart.clock = GetClockFrequency(fdt, node); - gUART = kSupportedUarts[i].uart_driver_init(uart.regs.start, - uart.clock); + gUART = kSupportedUarts[i].uart_driver_init(uart.regs.start, + uart.clock); + } } + + if (gUART != NULL) + gUART->InitEarly(); } - if (gUART != NULL) - gUART->InitEarly(); + 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); + } + } + } } @@ -558,4 +587,17 @@ dtb_set_kernel_args() dprintf(" clock: %" B_PRIu64 "\n", uart.clock); } #endif + 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); + } }