aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorKevin Cernekee <cernekee@gmail.com>2014-10-21 00:27:56 -0400
committerRalf Baechle <ralf@linux-mips.org>2014-11-24 01:45:10 -0500
commit3677a283621446805044a73a36b3539a0b41bc12 (patch)
treec6d68cd283eba3fa6b8441d22819989dade134e6 /arch
parent230b6ff57552c23a03e1b8d3f4a401261ca981c7 (diff)
MIPS: BMIPS: Explicitly configure reset vectors prior to secondary boot
The secondary CPU's reset vector needs to be set to KSEG1 for a cold boot (release from reset), or KSEG0 for a warm restart. On a cold boot KSEG0 may be unavailable (BMIPS4380), and on a warm restart KSEG1 may be unavailable (XKS01 mode on 4380 or 5000). Signed-off-by: Kevin Cernekee <cernekee@gmail.com> Cc: f.fainelli@gmail.com Cc: mbizon@freebox.fr Cc: jogo@openwrt.org Cc: jfraser@broadcom.com Cc: linux-mips@linux-mips.org Cc: devicetree@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/8161/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/kernel/smp-bmips.c29
1 files changed, 8 insertions, 21 deletions
diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c
index f7b1beef7790..162391d548b5 100644
--- a/arch/mips/kernel/smp-bmips.c
+++ b/arch/mips/kernel/smp-bmips.c
@@ -47,6 +47,8 @@ cpumask_t bmips_booted_mask;
47#define RESET_FROM_KSEG0 0x80080800 47#define RESET_FROM_KSEG0 0x80080800
48#define RESET_FROM_KSEG1 0xa0080800 48#define RESET_FROM_KSEG1 0xa0080800
49 49
50static void bmips_set_reset_vec(int cpu, u32 val);
51
50#ifdef CONFIG_SMP 52#ifdef CONFIG_SMP
51 53
52/* initial $sp, $gp - used by arch/mips/kernel/bmips_vec.S */ 54/* initial $sp, $gp - used by arch/mips/kernel/bmips_vec.S */
@@ -198,6 +200,9 @@ static void bmips_boot_secondary(int cpu, struct task_struct *idle)
198 pr_info("SMP: Booting CPU%d...\n", cpu); 200 pr_info("SMP: Booting CPU%d...\n", cpu);
199 201
200 if (cpumask_test_cpu(cpu, &bmips_booted_mask)) { 202 if (cpumask_test_cpu(cpu, &bmips_booted_mask)) {
203 /* kseg1 might not exist if this CPU enabled XKS01 */
204 bmips_set_reset_vec(cpu, RESET_FROM_KSEG0);
205
201 switch (current_cpu_type()) { 206 switch (current_cpu_type()) {
202 case CPU_BMIPS4350: 207 case CPU_BMIPS4350:
203 case CPU_BMIPS4380: 208 case CPU_BMIPS4380:
@@ -207,8 +212,9 @@ static void bmips_boot_secondary(int cpu, struct task_struct *idle)
207 bmips5000_send_ipi_single(cpu, 0); 212 bmips5000_send_ipi_single(cpu, 0);
208 break; 213 break;
209 } 214 }
210 } 215 } else {
211 else { 216 bmips_set_reset_vec(cpu, RESET_FROM_KSEG1);
217
212 switch (current_cpu_type()) { 218 switch (current_cpu_type()) {
213 case CPU_BMIPS4350: 219 case CPU_BMIPS4350:
214 case CPU_BMIPS4380: 220 case CPU_BMIPS4380:
@@ -229,31 +235,12 @@ static void bmips_boot_secondary(int cpu, struct task_struct *idle)
229 */ 235 */
230static void bmips_init_secondary(void) 236static void bmips_init_secondary(void)
231{ 237{
232 /* move NMI vector to kseg0, in case XKS01 is enabled */
233
234 void __iomem *cbr;
235 unsigned long old_vec;
236 unsigned long relo_vector;
237 int boot_cpu;
238
239 switch (current_cpu_type()) { 238 switch (current_cpu_type()) {
240 case CPU_BMIPS4350: 239 case CPU_BMIPS4350:
241 case CPU_BMIPS4380: 240 case CPU_BMIPS4380:
242 cbr = BMIPS_GET_CBR();
243
244 boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
245 relo_vector = boot_cpu ? BMIPS_RELO_VECTOR_CONTROL_0 :
246 BMIPS_RELO_VECTOR_CONTROL_1;
247
248 old_vec = __raw_readl(cbr + relo_vector);
249 __raw_writel(old_vec & ~0x20000000, cbr + relo_vector);
250
251 clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0); 241 clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0);
252 break; 242 break;
253 case CPU_BMIPS5000: 243 case CPU_BMIPS5000:
254 write_c0_brcm_bootvec(read_c0_brcm_bootvec() &
255 (smp_processor_id() & 0x01 ? ~0x20000000 : ~0x2000));
256
257 write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0)); 244 write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0));
258 break; 245 break;
259 } 246 }