1 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <soc/addressmap.h>
5 #include <device/mmio.h>
7 #include <bdk-coreboot.h>
8 #include <console/console.h>
12 uint64_t cpu_get_available_core_mask(void)
14 return read64p(RST_PP_AVAILABLE
);
17 size_t cpu_get_num_available_cores(void)
19 return bdk_dpop(cpu_get_available_core_mask());
22 static void (*secondary_c_entry
)(size_t core_id
);
23 static size_t secondary_booted
;
25 void secondary_cpu_init(size_t core_id
)
27 write64(&secondary_booted
, 1);
30 if (secondary_c_entry
)
31 secondary_c_entry(core_id
);
36 size_t cpu_self_get_core_id(void)
39 asm("mrs %0, MPIDR_EL1\n\t" : "=r" (mpidr_el1
) :: "memory");
41 /* Core is 4 bits from AFF0 and rest from AFF1 */
43 core_num
= mpidr_el1
& 0xf;
44 core_num
|= (mpidr_el1
& 0xff00) >> 4;
49 uint64_t cpu_self_get_core_mask(void)
51 return 1ULL << cpu_self_get_core_id();
54 size_t start_cpu(size_t cpu
, void (*entry_64
)(size_t core_id
))
56 const uint64_t coremask
= 1ULL << cpu
;
60 printk(BIOS_DEBUG
, "CPU: Starting CPU%zu @ %p.\n", cpu
, entry_64
);
62 /* Core not available */
63 if (!(coremask
& cpu_get_available_core_mask()))
66 /* Only secondary CPUs are supported */
67 if (cpu
== cpu_self_get_core_id())
70 /* Check stack here, instead of in cpu_secondary.S */
71 if ((CONFIG_STACK_SIZE
* cpu
) > REGION_SIZE(stack_sec
))
74 /* Write the address of the main entry point */
75 write64p(MIO_BOOT_AP_JUMP
, (uintptr_t)secondary_init
);
77 /* Get coremask of cores in reset */
78 const uint64_t reset
= read64p(RST_PP_RESET
);
79 printk(BIOS_INFO
, "CPU: Cores currently in reset: 0x%llx\n", reset
);
81 /* Setup entry for secondary core */
82 write64(&secondary_c_entry
, (uintptr_t)entry_64
);
83 write64(&secondary_booted
, 0);
86 printk(BIOS_DEBUG
, "CPU: Taking core %zu out of reset.\n", cpu
);
88 /* Release core from reset */
89 write64p(RST_PP_RESET
, reset
& ~coremask
);
91 /* Wait for cores to finish coming out of reset */
94 stopwatch_init_usecs_expire(&sw
, 1000000);
96 pending
= read64p(RST_PP_PENDING
);
97 } while (!stopwatch_expired(&sw
) && (pending
& coremask
));
99 if (stopwatch_expired(&sw
)) {
100 printk(BIOS_ERR
, "Timeout waiting for reset "
101 "pending to clear.");
105 stopwatch_init_usecs_expire(&sw
, 1000000);
107 printk(BIOS_DEBUG
, "CPU: Wait up to 1s for the core to boot...\n");
108 while (!stopwatch_expired(&sw
) && !read64(&secondary_booted
))
112 write64(&secondary_c_entry
, 0);
115 if (!read64(&secondary_booted
)) {
116 printk(BIOS_ERR
, "Core %zu failed to start.\n", cpu
);
120 printk(BIOS_INFO
, "CPU: Core %zu booted\n", cpu
);