1 /*
2 * Copyright (c) 2014 Travis Geiselbrecht
3 *
4 * Use of this source code is governed by a MIT-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/MIT
7 */
8 #include <arch/mp.h>
9
10 #include <assert.h>
11 #include <lk/trace.h>
12 #include <lk/err.h>
13 #include <platform/interrupts.h>
14 #include <arch/ops.h>
15
16 #if WITH_DEV_INTERRUPT_ARM_GIC
17 #include <dev/interrupt/arm_gic.h>
18 #elif PLATFORM_BCM28XX
19 /* bcm28xx has a weird custom interrupt controller for MP */
20 extern void bcm28xx_send_ipi(uint irq, uint cpu_mask);
21 #else
22 #error need other implementation of interrupt controller that can ipi
23 #endif
24
25 #define LOCAL_TRACE 0
26
27 #define GIC_IPI_BASE (14)
28
arch_mp_send_ipi(mp_cpu_mask_t target,mp_ipi_t ipi)29 status_t arch_mp_send_ipi(mp_cpu_mask_t target, mp_ipi_t ipi) {
30 LTRACEF("target 0x%x, ipi %u\n", target, ipi);
31
32 #if WITH_DEV_INTERRUPT_ARM_GIC
33 uint gic_ipi_num = ipi + GIC_IPI_BASE;
34
35 /* filter out targets outside of the range of cpus we care about */
36 target &= ((1UL << SMP_MAX_CPUS) - 1);
37 if (target != 0) {
38 LTRACEF("target 0x%x, gic_ipi %u\n", target, gic_ipi_num);
39 arm_gic_sgi(gic_ipi_num, ARM_GIC_SGI_FLAG_NS, target);
40 }
41 #elif PLATFORM_BCM28XX
42 /* filter out targets outside of the range of cpus we care about */
43 target &= ((1UL << SMP_MAX_CPUS) - 1);
44 if (target != 0) {
45 bcm28xx_send_ipi(ipi, target);
46 }
47 #endif
48
49 return NO_ERROR;
50 }
51
arm_ipi_generic_handler(void * arg)52 static enum handler_return arm_ipi_generic_handler(void *arg) {
53 LTRACEF("cpu %u, arg %p\n", arch_curr_cpu_num(), arg);
54
55 return INT_NO_RESCHEDULE;
56 }
57
arm_ipi_reschedule_handler(void * arg)58 static enum handler_return arm_ipi_reschedule_handler(void *arg) {
59 LTRACEF("cpu %u, arg %p\n", arch_curr_cpu_num(), arg);
60
61 return mp_mbx_reschedule_irq();
62 }
63
arch_mp_init_percpu(void)64 void arch_mp_init_percpu(void) {
65 register_int_handler(MP_IPI_GENERIC + GIC_IPI_BASE, &arm_ipi_generic_handler, 0);
66 register_int_handler(MP_IPI_RESCHEDULE + GIC_IPI_BASE, &arm_ipi_reschedule_handler, 0);
67
68 //unmask_interrupt(MP_IPI_GENERIC + GIC_IPI_BASE);
69 //unmask_interrupt(MP_IPI_RESCHEDULE + GIC_IPI_BASE);
70 }
71
72