diff options
author | Kevin Cernekee <cernekee@gmail.com> | 2014-10-21 00:27:56 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-11-24 01:45:10 -0500 |
commit | 3677a283621446805044a73a36b3539a0b41bc12 (patch) | |
tree | c6d68cd283eba3fa6b8441d22819989dade134e6 /arch | |
parent | 230b6ff57552c23a03e1b8d3f4a401261ca981c7 (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.c | 29 |
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 | ||
50 | static 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 | */ |
230 | static void bmips_init_secondary(void) | 236 | static 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 | } |