added 1 changeset to branch 'refs/remotes/mmu_man-github/sam460ex' old head: 4c50a9bcfd5f92310d3a3493381c9042f6ef5df8 new head: 0255210b042a1beeb3dbc72ae118c325031328b1 overview: https://github.com/mmuman/haiku/compare/4c50a9b...0255210 ---------------------------------------------------------------------------- 0255210: U-Boot: PPC: properly enumerate CPUs * Code comes almost verbatim from OF platform. * Only bus frequency needs to be read from the /plb node instead. [ François Revol <revol@xxxxxxx> ] ---------------------------------------------------------------------------- Commit: 0255210b042a1beeb3dbc72ae118c325031328b1 Author: François Revol <revol@xxxxxxx> Date: Mon Feb 18 01:47:34 2013 UTC ---------------------------------------------------------------------------- 1 file changed, 111 insertions(+), 10 deletions(-) .../boot/platform/u-boot/arch/ppc/arch_cpu.cpp | 121 +++++++++++++++++-- ---------------------------------------------------------------------------- diff --git a/src/system/boot/platform/u-boot/arch/ppc/arch_cpu.cpp b/src/system/boot/platform/u-boot/arch/ppc/arch_cpu.cpp index ac3a0a6..3bb9bfe 100644 --- a/src/system/boot/platform/u-boot/arch/ppc/arch_cpu.cpp +++ b/src/system/boot/platform/u-boot/arch/ppc/arch_cpu.cpp @@ -19,9 +19,12 @@ #include <arch/ppc/arch_cpu.h> #include <arch_kernel.h> #include <arch_system_info.h> +#include <platform/openfirmware/devices.h> +#include <platform/openfirmware/openfirmware.h> #include <string.h> +// TODO: try to move remaining FDT code to OF calls extern "C" { #include <fdt.h> #include <libfdt.h> @@ -38,13 +41,112 @@ extern void *gFDT; # define TRACE(x) ; #endif -//uint32 gTimeConversionFactor; - -static void -calculate_cpu_conversion_factor() +static status_t +enumerate_cpus(void) { - #warning U-Boot:TODO! + // iterate through the "/cpus" node to find all CPUs + int cpus = of_finddevice("/cpus"); + if (cpus == OF_FAILED) { + printf("enumerate_cpus(): Failed to open \"/cpus\"!\n"); + return B_ERROR; + } + + char cpuPath[256]; + int cookie = 0; + int cpuCount = 0; + while (of_get_next_device(&cookie, cpus, "cpu", cpuPath, + sizeof(cpuPath)) == B_OK) { + TRACE(("found CPU: %s\n", cpuPath)); + + // For the first CPU get the frequencies of CPU, bus, and time base. + // We assume they are the same for all CPUs. + if (cpuCount == 0) { + int cpu = of_finddevice(cpuPath); + if (cpu == OF_FAILED) { + printf("enumerate_cpus: Failed get CPU device node!\n"); + return B_ERROR; + } + + // TODO: Does encode-int really encode quadlet (32 bit numbers) + // only? + int32 clockFrequency; + if (of_getprop(cpu, "clock-frequency", &clockFrequency, 4) + == OF_FAILED) { + printf("enumerate_cpus: Failed to get CPU clock " + "frequency!\n"); + return B_ERROR; + } + int32 busFrequency = 0; + if (of_getprop(cpu, "bus-frequency", &busFrequency, 4) + == OF_FAILED) { + //printf("enumerate_cpus: Failed to get bus clock " + // "frequency!\n"); + //return B_ERROR; + } + int32 timeBaseFrequency; + if (of_getprop(cpu, "timebase-frequency", &timeBaseFrequency, 4) + == OF_FAILED) { + printf("enumerate_cpus: Failed to get time base " + "frequency!\n"); + return B_ERROR; + } + + gKernelArgs.arch_args.cpu_frequency = clockFrequency; + gKernelArgs.arch_args.bus_frequency = busFrequency; + gKernelArgs.arch_args.time_base_frequency = timeBaseFrequency; + + TRACE((" CPU clock frequency: %ld\n", clockFrequency)); + //TRACE((" bus clock frequency: %ld\n", busFrequency)); + TRACE((" time base frequency: %ld\n", timeBaseFrequency)); + } + + cpuCount++; + } + + if (cpuCount == 0) { + printf("enumerate_cpus(): Found no CPUs!\n"); + return B_ERROR; + } + + gKernelArgs.num_cpus = cpuCount; + + // FDT doesn't list bus frequency on the cpu node but on the plb node + if (gKernelArgs.arch_args.bus_frequency == 0) { + int plb = of_finddevice("/plb"); + + int32 busFrequency = 0; + if (of_getprop(plb, "clock-frequency", &busFrequency, 4) + == OF_FAILED) { + printf("enumerate_cpus: Failed to get bus clock " + "frequency!\n"); + return B_ERROR; + } + gKernelArgs.arch_args.bus_frequency = busFrequency; + } + TRACE((" bus clock frequency: %ld\n", gKernelArgs.arch_args.bus_frequency)); + +#if 0 +//XXX:Classic + // allocate the kernel stacks (the memory stuff is already initialized + // at this point) + addr_t stack = (addr_t)arch_mmu_allocate((void*)0x80000000, + cpuCount * (KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE), + B_READ_AREA | B_WRITE_AREA, false); + if (!stack) { + printf("enumerate_cpus(): Failed to allocate kernel stack(s)!\n"); + return B_NO_MEMORY; + } + + for (int i = 0; i < cpuCount; i++) { + gKernelArgs.cpu_kstack[i].start = stack; + gKernelArgs.cpu_kstack[i].size = KERNEL_STACK_SIZE + + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE; + stack += KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE; + } +#endif + + return B_OK; } @@ -155,6 +257,8 @@ arch_spin(bigtime_t microseconds) extern "C" status_t boot_arch_cpu_init(void) { + // first check some features + // including some necessary for dprintf()... status_t err = check_cpu_features(); if (err != B_OK) { @@ -162,11 +266,8 @@ boot_arch_cpu_init(void) return err; } - calculate_cpu_conversion_factor(); - - gKernelArgs.num_cpus = 1; - // this will eventually be corrected later on - // TODO:iterate on /cpus/* + // now enumerate correctly all CPUs and get system frequencies + enumerate_cpus(); return B_OK; }