diff --git a/headers/private/kernel/arch/arm/arch_kernel_args.h b/headers/private/kernel/arch/arm/arch_kernel_args.h index 081e7b9bcf..86ce4b7335 100644 --- a/headers/private/kernel/arch/arm/arch_kernel_args.h +++ b/headers/private/kernel/arch/arm/arch_kernel_args.h @@ -12,6 +12,7 @@ #include #include +#include #include @@ -42,8 +43,9 @@ typedef struct { FixedWidthPointer acpi_root; FixedWidthPointer fdt; - uart_info uart; - intc_info interrupt_controller; + uart_info uart; + intc_info interrupt_controller; + boot_timer_info timer; } _PACKED arch_kernel_args; #endif /* KERNEL_ARCH_ARM_KERNEL_ARGS_H */ diff --git a/headers/private/kernel/boot/timer.h b/headers/private/kernel/boot/timer.h new file mode 100644 index 0000000000..b98d36d6f2 --- /dev/null +++ b/headers/private/kernel/boot/timer.h @@ -0,0 +1,25 @@ +/* + * Copyright 2022 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef KERNEL_BOOT_TIMER_H +#define KERNEL_BOOT_TIMER_H + + +#include +#include + + +#define TIMER_KIND_ARMV7 "armv7" +#define TIMER_KIND_OMAP3 "omap3" +#define TIMER_KIND_PXA "pxa" + + +typedef struct { + char kind[32]; + addr_range regs; + uint32_t interrupt; +} __attribute__((packed)) boot_timer_info; + + +#endif /* KERNEL_BOOT_TIMER_H */ diff --git a/src/system/boot/platform/efi/arch/arm/arch_dtb.cpp b/src/system/boot/platform/efi/arch/arm/arch_dtb.cpp index 5dff8d61d1..e1f076fad5 100644 --- a/src/system/boot/platform/efi/arch/arm/arch_dtb.cpp +++ b/src/system/boot/platform/efi/arch/arm/arch_dtb.cpp @@ -32,6 +32,16 @@ const struct supported_interrupt_controllers { }; +const struct supported_timers { + const char* dtb_compat; + const char* kind; +} kSupportedTimers[] = { + { "arm,armv7-timer", TIMER_KIND_ARMV7 }, + { "ti,omap3430-timer", TIMER_KIND_OMAP3 }, + { "marvell,pxa-timers", TIMER_KIND_PXA }, +}; + + void arch_handle_fdt(const void* fdt, int node) { @@ -73,6 +83,21 @@ arch_handle_fdt(const void* fdt, int node) } } } + + boot_timer_info &timer = gKernelArgs.arch_args.timer; + if (timer.kind[0] == 0) { + for (uint32 i = 0; i < B_COUNT_OF(kSupportedTimers); i++) { + if (dtb_has_fdt_string(compatible, compatibleLen, + kSupportedTimers[i].dtb_compat)) { + + memcpy(timer.kind, kSupportedTimers[i].kind, + sizeof(timer.kind)); + + dtb_get_reg(fdt, node, 0, timer.regs); + timer.interrupt = dtb_get_interrupt(fdt, node); + } + } + } } @@ -92,4 +117,16 @@ arch_dtb_set_kernel_args(void) interrupt_controller.regs2.start, interrupt_controller.regs2.size); } + + boot_timer_info &timer = gKernelArgs.arch_args.timer; + dprintf("Chosen timer:\n"); + if (timer.kind[0] == 0) { + dprintf("kind: None!\n"); + } else { + dprintf(" kind: %s\n", timer.kind); + dprintf(" regs: %#" B_PRIx64 ", %#" B_PRIx64 "\n", + timer.regs.start, + timer.regs.size); + dprintf(" irq: %" B_PRIu32 "\n", timer.interrupt); + } } diff --git a/src/system/boot/platform/efi/dtb.cpp b/src/system/boot/platform/efi/dtb.cpp index b1a43d483e..2451818046 100644 --- a/src/system/boot/platform/efi/dtb.cpp +++ b/src/system/boot/platform/efi/dtb.cpp @@ -482,7 +482,7 @@ dtb_get_interrupt_cells(const void* fdt, int node) } -static uint32 +uint32 dtb_get_interrupt(const void* fdt, int node) { uint32 interruptCells = dtb_get_interrupt_cells(fdt, node); diff --git a/src/system/boot/platform/efi/dtb.h b/src/system/boot/platform/efi/dtb.h index b79e265bba..e9c87c33fd 100644 --- a/src/system/boot/platform/efi/dtb.h +++ b/src/system/boot/platform/efi/dtb.h @@ -16,6 +16,7 @@ extern void dtb_init(); extern void dtb_set_kernel_args(); bool dtb_get_reg(const void* fdt, int node, size_t idx, addr_range& range); +uint32 dtb_get_interrupt(const void* fdt, int node); bool dtb_has_fdt_string(const char* prop, int size, const char* pattern); diff --git a/src/system/kernel/arch/arm/arch_timer.cpp b/src/system/kernel/arch/arm/arch_timer.cpp index b98302bc78..f0fabbd963 100644 --- a/src/system/kernel/arch/arm/arch_timer.cpp +++ b/src/system/kernel/arch/arm/arch_timer.cpp @@ -34,20 +34,6 @@ #endif -#if 0 -static struct fdt_device_info intc_table[] = { - { - .compatible = "marvell,pxa-timers", // XXX not in FDT (also not in upstream!) - .init = PXATimer::Init, - }, { - .compatible = "ti,omap3430-timer", - .init = OMAP3Timer::Init, - } -}; -static int intc_count = sizeof(intc_table) / sizeof(struct fdt_device_info); -#endif - - void arch_timer_set_hardware_timer(bigtime_t timeout) { @@ -73,20 +59,16 @@ arch_init_timer(kernel_args *args) if (ARMGenericTimer::IsAvailable()) { TRACE("init ARMv7 generic timer\n"); ARMGenericTimer::Init(); - } - - //TODO: use SoC-specific timer as a fallback - //if the generic timer is not available - -#if 0 - status_t rc = get_module(B_FDT_MODULE_NAME, (module_info**)&sFdtModule); - if (rc != B_OK) - panic("Unable to get FDT module: %08lx!\n", rc); - - rc = sFdtModule->setup_devices(intc_table, intc_count, NULL); - if (rc != B_OK) + } else if (strncmp(args->arch_args.timer.kind, TIMER_KIND_OMAP3, + sizeof(args->arch_args.timer.kind)) == 0) { + OMAP3Timer::Init(args->arch_args.timer.regs.start, + args->arch_args.timer.interrupt); + } else if (strncmp(args->arch_args.timer.kind, TIMER_KIND_PXA, + sizeof(args->arch_args.timer.kind)) == 0) { + PXATimer::Init(args->arch_args.timer.regs.start); + } else { panic("No hardware timer found!\n"); -#endif + } return B_OK; } diff --git a/src/system/kernel/arch/arm/soc_omap3.cpp b/src/system/kernel/arch/arm/soc_omap3.cpp index 24ad86c2a6..bac68da735 100644 --- a/src/system/kernel/arch/arm/soc_omap3.cpp +++ b/src/system/kernel/arch/arm/soc_omap3.cpp @@ -79,7 +79,7 @@ OMAP3InterruptController::SoftReset() { uint32 tmp = fRegBase[INTCPS_REVISION] & 0xff; - dprintf("OMAP: INTC found at 0x%p (rev %ld.%ld)\n", + dprintf("OMAP: INTC found at 0x%p (rev %" B_PRIu32 ".%" B_PRIu32 ")\n", fRegBase, tmp >> 4, tmp & 0xf); tmp = fRegBase[INTCPS_SYSCONFIG]; @@ -184,21 +184,22 @@ OMAP3Timer::Clear() } -#if 0 -OMAP3Timer::OMAP3Timer(fdt_module_info *fdtModule, fdt_device_node node) - : HardwareTimer(fdtModule, node), - fSystemTime(0) +OMAP3Timer::OMAP3Timer(uint32_t reg_base, uint32_t interrupt) + : fSystemTime(0) { - fRegArea = fFDT->map_reg_range(node, 0, (void**)&fRegBase); + fRegArea = vm_map_physical_memory(B_SYSTEM_TEAM, "timer-omap3", (void**)&fRegBase, + B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, + reg_base, false); if (fRegArea < 0) panic("Cannot map OMAP3Timer registers!"); - fInterrupt = fFDT->get_interrupt(node, 0); + fInterrupt = interrupt; if (fInterrupt < 0) panic("Cannot get OMAP3Timer interrupt!"); uint32 rev = fRegBase[TIDR]; - dprintf("OMAP: Found timer @ 0x%p, IRQ %d (rev %ld.%ld)\n", fRegBase, fInterrupt, (rev >> 4) & 0xf, rev & 0xf); + dprintf("OMAP: Found timer @ 0x%p, IRQ %d (rev %" B_PRIu32 ".%" B_PRIu32 ")\n", + fRegBase, fInterrupt, (rev >> 4) & 0xf, rev & 0xf); // Let the timer run (so we can use it as clocksource) fRegBase[TCLR] |= 1; @@ -206,4 +207,3 @@ OMAP3Timer::OMAP3Timer(fdt_module_info *fdtModule, fdt_device_node node) install_io_interrupt_handler(fInterrupt, &OMAP3Timer::_InterruptWrapper, this, 0); } -#endif diff --git a/src/system/kernel/arch/arm/soc_omap3.h b/src/system/kernel/arch/arm/soc_omap3.h index 14e43dafd7..5c55ecfd32 100644 --- a/src/system/kernel/arch/arm/soc_omap3.h +++ b/src/system/kernel/arch/arm/soc_omap3.h @@ -29,10 +29,9 @@ public: bigtime_t Time(); void Clear(); -#if 0 - static status_t Init(fdt_module_info *fdt, fdt_device_node node, void *cookie) { + static status_t Init(uint32_t reg_base, uint32_t interrupt) { if (sInstance == NULL) { - OMAP3Timer *timer = new(std::nothrow) OMAP3Timer(fdt, node); + OMAP3Timer *timer = new(std::nothrow) OMAP3Timer(reg_base, interrupt); // XXX implement InitCheck() functionality return timer != NULL ? B_OK : B_NO_MEMORY; } else { @@ -41,10 +40,9 @@ public: return B_OK; } } -#endif private: - //OMAP3Timer(fdt_module_info *fdtModule, fdt_device_node node); + OMAP3Timer(uint32_t reg_base, uint32_t interrupt); static int32 _InterruptWrapper(void *data); int32 HandleInterrupt(); diff --git a/src/system/kernel/arch/arm/soc_pxa.cpp b/src/system/kernel/arch/arm/soc_pxa.cpp index 299196fec6..657ff56797 100644 --- a/src/system/kernel/arch/arm/soc_pxa.cpp +++ b/src/system/kernel/arch/arm/soc_pxa.cpp @@ -92,7 +92,7 @@ PXATimer::SetTimeout(bigtime_t timeout) } } - dprintf("arch_timer_set_hardware_timer(val=%lu, res=%lu)\n", val, res); + dprintf("arch_timer_set_hardware_timer(val=%" B_PRIu32 ", res=%" B_PRIu32 ")\n", val, res); fRegBase[PXA_OIER] |= (1 << 4); fRegBase[PXA_OMCR4] = res; fRegBase[PXA_OSMR4] = val; @@ -143,11 +143,11 @@ PXATimer::HandleInterrupt() } -#if 0 -PXATimer::PXATimer(fdt_module_info *fdt, fdt_device_node node) - : HardwareTimer(fdt, node) +PXATimer::PXATimer(uint32_t reg_base) { - fRegArea = fFDT->map_reg_range(node, 0, (void**)&fRegBase); + fRegArea = vm_map_physical_memory(B_SYSTEM_TEAM, "pxa-timer", (void**)&fRegBase, + B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, + reg_base, false); if (fRegArea < 0) panic("Cannot map PXATimer registers!"); @@ -158,4 +158,3 @@ PXATimer::PXATimer(fdt_module_info *fdt, fdt_device_node node) install_io_interrupt_handler(PXA_TIMERS_INTERRUPT, &PXATimer::_InterruptWrapper, NULL, 0); } -#endif diff --git a/src/system/kernel/arch/arm/soc_pxa.h b/src/system/kernel/arch/arm/soc_pxa.h index 6226aa469f..375d4c173a 100644 --- a/src/system/kernel/arch/arm/soc_pxa.h +++ b/src/system/kernel/arch/arm/soc_pxa.h @@ -27,16 +27,14 @@ public: void Clear(); bigtime_t Time(); -#if 0 - static status_t Init(fdt_module_info *fdt, fdt_device_node node, void *cookie) { - PXATimer *timer = new(std::nothrow) PXATimer(fdt, node); + static status_t Init(uint32_t reg_base) { + PXATimer *timer = new(std::nothrow) PXATimer(reg_base); // XXX implement InitCheck() functionality return timer != NULL ? B_OK : B_NO_MEMORY; } -#endif protected: - //PXATimer(fdt_module_info *fdt, fdt_device_node node); + PXATimer(uint32_t reg_base); area_id fRegArea; uint32 *fRegBase;