1 /*
2  * Copyright (c) 2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/init.h>
8 #include <zephyr/kernel.h>
9 #include <ksched.h>
10 #include <zephyr/irq.h>
11 #include <zephyr/sys/atomic.h>
12 #include <zephyr/arch/riscv/irq.h>
13 #include <zephyr/drivers/pm_cpu_ops.h>
14 #include <zephyr/platform/hooks.h>
15 
16 volatile struct {
17 	arch_cpustart_t fn;
18 	void *arg;
19 } riscv_cpu_init[CONFIG_MP_MAX_NUM_CPUS];
20 
21 volatile uintptr_t __noinit riscv_cpu_wake_flag;
22 volatile uintptr_t riscv_cpu_boot_flag;
23 volatile void *riscv_cpu_sp;
24 
25 extern void __start(void);
26 
27 #if defined(CONFIG_RISCV_SOC_INTERRUPT_INIT)
28 void soc_interrupt_init(void);
29 #endif
30 
arch_cpu_start(int cpu_num,k_thread_stack_t * stack,int sz,arch_cpustart_t fn,void * arg)31 void arch_cpu_start(int cpu_num, k_thread_stack_t *stack, int sz,
32 		    arch_cpustart_t fn, void *arg)
33 {
34 	riscv_cpu_init[cpu_num].fn = fn;
35 	riscv_cpu_init[cpu_num].arg = arg;
36 
37 	riscv_cpu_sp = K_KERNEL_STACK_BUFFER(stack) + sz;
38 	riscv_cpu_boot_flag = 0U;
39 
40 #ifdef CONFIG_PM_CPU_OPS
41 	if (pm_cpu_on(cpu_num, (uintptr_t)&__start)) {
42 		printk("Failed to boot secondary CPU %d\n", cpu_num);
43 		return;
44 	}
45 #endif
46 
47 	while (riscv_cpu_boot_flag == 0U) {
48 		riscv_cpu_wake_flag = _kernel.cpus[cpu_num].arch.hartid;
49 	}
50 }
51 
arch_secondary_cpu_init(int hartid)52 void arch_secondary_cpu_init(int hartid)
53 {
54 	unsigned int i;
55 	unsigned int cpu_num = 0;
56 
57 	for (i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) {
58 		if (_kernel.cpus[i].arch.hartid == hartid) {
59 			cpu_num = i;
60 		}
61 	}
62 	csr_write(mscratch, &_kernel.cpus[cpu_num]);
63 #ifdef CONFIG_SMP
64 	_kernel.cpus[cpu_num].arch.online = true;
65 #endif
66 #if defined(CONFIG_MULTITHREADING) && defined(CONFIG_THREAD_LOCAL_STORAGE)
67 	__asm__("mv tp, %0" : : "r" (z_idle_threads[cpu_num].tls));
68 #endif
69 #if defined(CONFIG_RISCV_SOC_INTERRUPT_INIT)
70 	soc_interrupt_init();
71 #endif
72 #ifdef CONFIG_RISCV_PMP
73 	z_riscv_pmp_init();
74 #endif
75 #ifdef CONFIG_SMP
76 	irq_enable(RISCV_IRQ_MSOFT);
77 #endif /* CONFIG_SMP */
78 #ifdef CONFIG_PLIC_IRQ_AFFINITY
79 	/* Enable on secondary cores so that they can respond to PLIC */
80 	irq_enable(RISCV_IRQ_MEXT);
81 #endif /* CONFIG_PLIC_IRQ_AFFINITY */
82 #ifdef CONFIG_SOC_PER_CORE_INIT_HOOK
83 	soc_per_core_init_hook();
84 #endif /* CONFIG_SOC_PER_CORE_INIT_HOOK */
85 	riscv_cpu_init[cpu_num].fn(riscv_cpu_init[cpu_num].arg);
86 }
87