diff options
author | Patrick Rudolph <patrick.rudolph@9elements.com> | 2018-04-11 11:40:55 +0200 |
---|---|---|
committer | Patrick Rudolph <siro@das-labor.org> | 2018-07-10 07:07:09 +0000 |
commit | 88f81af1ef0d74ca2be865454cc801efe32a88af (patch) | |
tree | 997d9a0b703bbb82f9e7666dd06984bf215c928d /src/soc/cavium/cn81xx/cpu.c | |
parent | ae15fec0b8ca7578ee56e2d1d9579922bb1ec0b6 (diff) | |
download | coreboot-88f81af1ef0d74ca2be865454cc801efe32a88af.tar.xz |
soc/cavium: Add secondary CPU support
Change-Id: I07428161615bcd3d03a3eea0df2dd813e08c8f66
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Reviewed-on: https://review.coreboot.org/25752
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: David Hendricks <david.hendricks@gmail.com>
Diffstat (limited to 'src/soc/cavium/cn81xx/cpu.c')
-rw-r--r-- | src/soc/cavium/cn81xx/cpu.c | 117 |
1 files changed, 113 insertions, 4 deletions
diff --git a/src/soc/cavium/cn81xx/cpu.c b/src/soc/cavium/cn81xx/cpu.c index c054aa8987..9504868dff 100644 --- a/src/soc/cavium/cn81xx/cpu.c +++ b/src/soc/cavium/cn81xx/cpu.c @@ -14,13 +14,122 @@ */ #include <types.h> +#include <soc/addressmap.h> #include <arch/io.h> #include <soc/cpu.h> #include <bdk-coreboot.h> +#include <console/console.h> +#include <timer.h> +#include <delay.h> -/* Return the number of cores available in the chip */ -size_t cpu_get_num_cores(void) +uint64_t cpu_get_available_core_mask(void) { - uint64_t available = read64((void *)0x87e006001738ll); - return bdk_dpop(available); + return read64((void *)RST_PP_AVAILABLE); +} + +size_t cpu_get_num_available_cores(void) +{ + return bdk_dpop(cpu_get_available_core_mask()); +} + +static void (*secondary_c_entry)(size_t core_id); +static size_t secondary_booted; + +void secondary_cpu_init(size_t core_id) +{ + write64(&secondary_booted, 1); + dmb(); + + if (secondary_c_entry) + secondary_c_entry(core_id); + else + asm("wfi"); +} + +size_t cpu_self_get_core_id(void) +{ + u32 mpidr_el1; + asm("mrs %0, MPIDR_EL1\n\t" : "=r" (mpidr_el1) :: "memory"); + + /* Core is 4 bits from AFF0 and rest from AFF1 */ + size_t core_num; + core_num = mpidr_el1 & 0xf; + core_num |= (mpidr_el1 & 0xff00) >> 4; + + return core_num; +} + +uint64_t cpu_self_get_core_mask(void) +{ + return 1ULL << cpu_self_get_core_id(); +} + +size_t start_cpu(size_t cpu, void (*entry_64)(size_t core_id)) +{ + const uint64_t coremask = 1ULL << cpu; + struct stopwatch sw; + uint64_t pending; + + printk(BIOS_DEBUG, "CPU: Starting CPU%zu @ %p.\n", cpu, entry_64); + + /* Core not available */ + if (!(coremask & cpu_get_available_core_mask())) + return 1; + + /* Only secondary CPUs are supported */ + if (cpu == cpu_self_get_core_id()) + return 1; + + /* Check stack here, instead of in cpu_secondary.S */ + if ((CONFIG_STACK_SIZE * cpu) > _stack_sec_size) + return 1; + + /* Write the address of the main entry point */ + write64((void *)MIO_BOOT_AP_JUMP, (uintptr_t)secondary_init); + + /* Get coremask of cores in reset */ + const uint64_t reset = read64((void *)RST_PP_RESET); + printk(BIOS_INFO, "CPU: Cores currently in reset: 0x%llx\n", reset); + + /* Setup entry for secondary core */ + write64(&secondary_c_entry, (uintptr_t)entry_64); + write64(&secondary_booted, 0); + dmb(); + + printk(BIOS_DEBUG, "CPU: Taking core %zu out of reset.\n", cpu); + + /* Release core from reset */ + write64((void *)RST_PP_RESET, reset & ~coremask); + + /* Wait for cores to finish coming out of reset */ + udelay(1); + + stopwatch_init_usecs_expire(&sw, 1000000); + do { + pending = read64((void *)RST_PP_PENDING); + } while (!stopwatch_expired(&sw) && (pending & coremask)); + + if (stopwatch_expired(&sw)) { + printk(BIOS_ERR, "ERROR: Timeout waiting for reset " + "pending to clear."); + return 1; + } + + stopwatch_init_usecs_expire(&sw, 1000000); + + printk(BIOS_DEBUG, "CPU: Wait up to 1s for the core to boot...\n"); + while (!stopwatch_expired(&sw) && !read64(&secondary_booted)) + ; + + /* Cleanup */ + write64(&secondary_c_entry, 0); + dmb(); + + if (!read64(&secondary_booted)) { + printk(BIOS_ERR, "ERROR: Core %zu failed to start.\n", cpu); + return 1; + } + + printk(BIOS_INFO, "CPU: Core %zu booted\n", cpu); + return 0; } |