]>
Commit | Line | Data |
---|---|---|
1a59d1b8 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
f137e463 AI |
2 | /* |
3 | * Copyright (C) 2001,2002,2004 Broadcom Corporation | |
f137e463 AI |
4 | */ |
5 | ||
6 | #include <linux/init.h> | |
7 | #include <linux/delay.h> | |
8 | #include <linux/smp.h> | |
9 | #include <linux/kernel_stat.h> | |
184748cc | 10 | #include <linux/sched.h> |
68db0cf1 | 11 | #include <linux/sched/task_stack.h> |
f137e463 AI |
12 | |
13 | #include <asm/mmu_context.h> | |
14 | #include <asm/io.h> | |
87353d8a | 15 | #include <asm/fw/cfe/cfe_api.h> |
f137e463 AI |
16 | #include <asm/sibyte/sb1250.h> |
17 | #include <asm/sibyte/bcm1480_regs.h> | |
18 | #include <asm/sibyte/bcm1480_int.h> | |
19 | ||
f137e463 AI |
20 | /* |
21 | * These are routines for dealing with the bcm1480 smp capabilities | |
22 | * independent of board/firmware | |
23 | */ | |
24 | ||
8fb303c7 | 25 | static void *mailbox_0_set_regs[] = { |
f137e463 AI |
26 | IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU), |
27 | IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU), | |
28 | IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU), | |
29 | IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU), | |
30 | }; | |
31 | ||
8fb303c7 | 32 | static void *mailbox_0_clear_regs[] = { |
f137e463 AI |
33 | IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU), |
34 | IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU), | |
35 | IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU), | |
36 | IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU), | |
37 | }; | |
38 | ||
8fb303c7 | 39 | static void *mailbox_0_regs[] = { |
f137e463 AI |
40 | IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_CPU), |
41 | IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_CPU), | |
42 | IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_CPU), | |
43 | IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_CPU), | |
44 | }; | |
45 | ||
46 | /* | |
47 | * SMP init and finish on secondary CPUs | |
48 | */ | |
078a55fc | 49 | void bcm1480_smp_init(void) |
f137e463 AI |
50 | { |
51 | unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 | | |
52 | STATUSF_IP1 | STATUSF_IP0; | |
53 | ||
54 | /* Set interrupt mask, but don't enable */ | |
55 | change_c0_status(ST0_IM, imask); | |
56 | } | |
57 | ||
87353d8a RB |
58 | /* |
59 | * These are routines for dealing with the sb1250 smp capabilities | |
60 | * independent of board/firmware | |
61 | */ | |
62 | ||
63 | /* | |
64 | * Simple enough; everything is set up, so just poke the appropriate mailbox | |
65 | * register, and we should be set | |
66 | */ | |
67 | static void bcm1480_send_ipi_single(int cpu, unsigned int action) | |
68 | { | |
69 | __raw_writeq((((u64)action)<< 48), mailbox_0_set_regs[cpu]); | |
70 | } | |
71 | ||
48a048fe RR |
72 | static void bcm1480_send_ipi_mask(const struct cpumask *mask, |
73 | unsigned int action) | |
87353d8a RB |
74 | { |
75 | unsigned int i; | |
76 | ||
48a048fe | 77 | for_each_cpu(i, mask) |
87353d8a RB |
78 | bcm1480_send_ipi_single(i, action); |
79 | } | |
80 | ||
81 | /* | |
82 | * Code to run on secondary just after probing the CPU | |
83 | */ | |
078a55fc | 84 | static void bcm1480_init_secondary(void) |
87353d8a RB |
85 | { |
86 | extern void bcm1480_smp_init(void); | |
87 | ||
88 | bcm1480_smp_init(); | |
89 | } | |
90 | ||
91 | /* | |
92 | * Do any tidying up before marking online and running the idle | |
93 | * loop | |
94 | */ | |
078a55fc | 95 | static void bcm1480_smp_finish(void) |
f137e463 | 96 | { |
d527eef5 RB |
97 | extern void sb1480_clockevent_init(void); |
98 | ||
99 | sb1480_clockevent_init(); | |
f137e463 AI |
100 | local_irq_enable(); |
101 | } | |
102 | ||
f137e463 | 103 | /* |
87353d8a RB |
104 | * Setup the PC, SP, and GP of a secondary processor and start it |
105 | * running! | |
f137e463 | 106 | */ |
d595d423 | 107 | static int bcm1480_boot_secondary(int cpu, struct task_struct *idle) |
f137e463 | 108 | { |
87353d8a RB |
109 | int retval; |
110 | ||
111 | retval = cfe_cpu_start(cpu_logical_map(cpu), &smp_bootstrap, | |
112 | __KSTK_TOS(idle), | |
113 | (unsigned long)task_thread_info(idle), 0); | |
114 | if (retval != 0) | |
115 | printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval); | |
d595d423 | 116 | return retval; |
f137e463 AI |
117 | } |
118 | ||
87353d8a RB |
119 | /* |
120 | * Use CFE to find out how many CPUs are available, setting up | |
5f054e31 | 121 | * cpu_possible_mask and the logical/physical mappings. |
87353d8a RB |
122 | * XXXKW will the boot CPU ever not be physical 0? |
123 | * | |
124 | * Common setup before any secondaries are started | |
125 | */ | |
126 | static void __init bcm1480_smp_setup(void) | |
127 | { | |
128 | int i, num; | |
129 | ||
0b5f9c00 | 130 | init_cpu_possible(cpumask_of(0)); |
87353d8a RB |
131 | __cpu_number_map[0] = 0; |
132 | __cpu_logical_map[0] = 0; | |
133 | ||
134 | for (i = 1, num = 0; i < NR_CPUS; i++) { | |
135 | if (cfe_cpu_stop(i) == 0) { | |
0b5f9c00 | 136 | set_cpu_possible(i, true); |
87353d8a RB |
137 | __cpu_number_map[i] = ++num; |
138 | __cpu_logical_map[num] = i; | |
139 | } | |
140 | } | |
141 | printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num); | |
142 | } | |
143 | ||
144 | static void __init bcm1480_prepare_cpus(unsigned int max_cpus) | |
145 | { | |
146 | } | |
147 | ||
ff2c8252 | 148 | const struct plat_smp_ops bcm1480_smp_ops = { |
87353d8a RB |
149 | .send_ipi_single = bcm1480_send_ipi_single, |
150 | .send_ipi_mask = bcm1480_send_ipi_mask, | |
151 | .init_secondary = bcm1480_init_secondary, | |
152 | .smp_finish = bcm1480_smp_finish, | |
87353d8a RB |
153 | .boot_secondary = bcm1480_boot_secondary, |
154 | .smp_setup = bcm1480_smp_setup, | |
155 | .prepare_cpus = bcm1480_prepare_cpus, | |
156 | }; | |
157 | ||
937a8015 | 158 | void bcm1480_mailbox_interrupt(void) |
f137e463 AI |
159 | { |
160 | int cpu = smp_processor_id(); | |
d2287f5e | 161 | int irq = K_BCM1480_INT_MBOX_0_0; |
f137e463 AI |
162 | unsigned int action; |
163 | ||
310ff2c8 | 164 | kstat_incr_irq_this_cpu(irq); |
f137e463 AI |
165 | /* Load the mailbox register to figure out what we're supposed to do */ |
166 | action = (__raw_readq(mailbox_0_regs[cpu]) >> 48) & 0xffff; | |
167 | ||
168 | /* Clear the mailbox to clear the interrupt */ | |
169 | __raw_writeq(((u64)action)<<48, mailbox_0_clear_regs[cpu]); | |
170 | ||
184748cc PZ |
171 | if (action & SMP_RESCHEDULE_YOURSELF) |
172 | scheduler_ipi(); | |
f137e463 | 173 | |
4ace6139 AS |
174 | if (action & SMP_CALL_FUNCTION) { |
175 | irq_enter(); | |
176 | generic_smp_call_function_interrupt(); | |
177 | irq_exit(); | |
178 | } | |
f137e463 | 179 | } |