aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/cps-vec.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/cps-vec.S')
-rw-r--r--arch/mips/kernel/cps-vec.S328
1 files changed, 312 insertions, 16 deletions
diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S
index f7a46db4b161..6f4f739dad96 100644
--- a/arch/mips/kernel/cps-vec.S
+++ b/arch/mips/kernel/cps-vec.S
@@ -14,19 +14,43 @@
14#include <asm/asmmacro.h> 14#include <asm/asmmacro.h>
15#include <asm/cacheops.h> 15#include <asm/cacheops.h>
16#include <asm/mipsregs.h> 16#include <asm/mipsregs.h>
17#include <asm/mipsmtregs.h>
18#include <asm/pm.h>
17 19
18#define GCR_CL_COHERENCE_OFS 0x2008 20#define GCR_CL_COHERENCE_OFS 0x2008
21#define GCR_CL_ID_OFS 0x2028
22
23.extern mips_cm_base
24
25.set noreorder
26
27 /*
28 * Set dest to non-zero if the core supports the MT ASE, else zero. If
29 * MT is not supported then branch to nomt.
30 */
31 .macro has_mt dest, nomt
32 mfc0 \dest, CP0_CONFIG
33 bgez \dest, \nomt
34 mfc0 \dest, CP0_CONFIG, 1
35 bgez \dest, \nomt
36 mfc0 \dest, CP0_CONFIG, 2
37 bgez \dest, \nomt
38 mfc0 \dest, CP0_CONFIG, 3
39 andi \dest, \dest, MIPS_CONF3_MT
40 beqz \dest, \nomt
41 .endm
19 42
20.section .text.cps-vec 43.section .text.cps-vec
21.balign 0x1000 44.balign 0x1000
22.set noreorder
23 45
24LEAF(mips_cps_core_entry) 46LEAF(mips_cps_core_entry)
25 /* 47 /*
26 * These first 8 bytes will be patched by cps_smp_setup to load the 48 * These first 12 bytes will be patched by cps_smp_setup to load the
27 * base address of the CM GCRs into register v1. 49 * base address of the CM GCRs into register v1 and the CCA to use into
50 * register s0.
28 */ 51 */
29 .quad 0 52 .quad 0
53 .word 0
30 54
31 /* Check whether we're here due to an NMI */ 55 /* Check whether we're here due to an NMI */
32 mfc0 k0, CP0_STATUS 56 mfc0 k0, CP0_STATUS
@@ -117,10 +141,11 @@ icache_done:
117 add a0, a0, t0 141 add a0, a0, t0
118dcache_done: 142dcache_done:
119 143
120 /* Set Kseg0 cacheable, coherent, write-back, write-allocate */ 144 /* Set Kseg0 CCA to that in s0 */
121 mfc0 t0, CP0_CONFIG 145 mfc0 t0, CP0_CONFIG
122 ori t0, 0x7 146 ori t0, 0x7
123 xori t0, 0x2 147 xori t0, 0x7
148 or t0, t0, s0
124 mtc0 t0, CP0_CONFIG 149 mtc0 t0, CP0_CONFIG
125 ehb 150 ehb
126 151
@@ -134,21 +159,24 @@ dcache_done:
134 jr t0 159 jr t0
135 nop 160 nop
136 161
1371: /* We're up, cached & coherent */ 162 /*
163 * We're up, cached & coherent. Perform any further required core-level
164 * initialisation.
165 */
1661: jal mips_cps_core_init
167 nop
138 168
139 /* 169 /*
140 * TODO: We should check the VPE number we intended to boot here, and 170 * Boot any other VPEs within this core that should be online, and
141 * if non-zero we should start that VPE and stop this one. For 171 * deactivate this VPE if it should be offline.
142 * the moment this doesn't matter since CPUs are brought up
143 * sequentially and in order, but once hotplug is implemented
144 * this will need revisiting.
145 */ 172 */
173 jal mips_cps_boot_vpes
174 nop
146 175
147 /* Off we go! */ 176 /* Off we go! */
148 la t0, mips_cps_bootcfg 177 lw t1, VPEBOOTCFG_PC(v0)
149 lw t1, BOOTCFG_PC(t0) 178 lw gp, VPEBOOTCFG_GP(v0)
150 lw gp, BOOTCFG_GP(t0) 179 lw sp, VPEBOOTCFG_SP(v0)
151 lw sp, BOOTCFG_SP(t0)
152 jr t1 180 jr t1
153 nop 181 nop
154 END(mips_cps_core_entry) 182 END(mips_cps_core_entry)
@@ -189,3 +217,271 @@ LEAF(excep_ejtag)
189 jr k0 217 jr k0
190 nop 218 nop
191 END(excep_ejtag) 219 END(excep_ejtag)
220
221LEAF(mips_cps_core_init)
222#ifdef CONFIG_MIPS_MT
223 /* Check that the core implements the MT ASE */
224 has_mt t0, 3f
225 nop
226
227 .set push
228 .set mt
229
230 /* Only allow 1 TC per VPE to execute... */
231 dmt
232
233 /* ...and for the moment only 1 VPE */
234 dvpe
235 la t1, 1f
236 jr.hb t1
237 nop
238
239 /* Enter VPE configuration state */
2401: mfc0 t0, CP0_MVPCONTROL
241 ori t0, t0, MVPCONTROL_VPC
242 mtc0 t0, CP0_MVPCONTROL
243
244 /* Retrieve the number of VPEs within the core */
245 mfc0 t0, CP0_MVPCONF0
246 srl t0, t0, MVPCONF0_PVPE_SHIFT
247 andi t0, t0, (MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT)
248 addi t7, t0, 1
249
250 /* If there's only 1, we're done */
251 beqz t0, 2f
252 nop
253
254 /* Loop through each VPE within this core */
255 li t5, 1
256
2571: /* Operate on the appropriate TC */
258 mtc0 t5, CP0_VPECONTROL
259 ehb
260
261 /* Bind TC to VPE (1:1 TC:VPE mapping) */
262 mttc0 t5, CP0_TCBIND
263
264 /* Set exclusive TC, non-active, master */
265 li t0, VPECONF0_MVP
266 sll t1, t5, VPECONF0_XTC_SHIFT
267 or t0, t0, t1
268 mttc0 t0, CP0_VPECONF0
269
270 /* Set TC non-active, non-allocatable */
271 mttc0 zero, CP0_TCSTATUS
272
273 /* Set TC halted */
274 li t0, TCHALT_H
275 mttc0 t0, CP0_TCHALT
276
277 /* Next VPE */
278 addi t5, t5, 1
279 slt t0, t5, t7
280 bnez t0, 1b
281 nop
282
283 /* Leave VPE configuration state */
2842: mfc0 t0, CP0_MVPCONTROL
285 xori t0, t0, MVPCONTROL_VPC
286 mtc0 t0, CP0_MVPCONTROL
287
2883: .set pop
289#endif
290 jr ra
291 nop
292 END(mips_cps_core_init)
293
294LEAF(mips_cps_boot_vpes)
295 /* Retrieve CM base address */
296 la t0, mips_cm_base
297 lw t0, 0(t0)
298
299 /* Calculate a pointer to this cores struct core_boot_config */
300 lw t0, GCR_CL_ID_OFS(t0)
301 li t1, COREBOOTCFG_SIZE
302 mul t0, t0, t1
303 la t1, mips_cps_core_bootcfg
304 lw t1, 0(t1)
305 addu t0, t0, t1
306
307 /* Calculate this VPEs ID. If the core doesn't support MT use 0 */
308 has_mt t6, 1f
309 li t9, 0
310
311 /* Find the number of VPEs present in the core */
312 mfc0 t1, CP0_MVPCONF0
313 srl t1, t1, MVPCONF0_PVPE_SHIFT
314 andi t1, t1, MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT
315 addi t1, t1, 1
316
317 /* Calculate a mask for the VPE ID from EBase.CPUNum */
318 clz t1, t1
319 li t2, 31
320 subu t1, t2, t1
321 li t2, 1
322 sll t1, t2, t1
323 addiu t1, t1, -1
324
325 /* Retrieve the VPE ID from EBase.CPUNum */
326 mfc0 t9, $15, 1
327 and t9, t9, t1
328
3291: /* Calculate a pointer to this VPEs struct vpe_boot_config */
330 li t1, VPEBOOTCFG_SIZE
331 mul v0, t9, t1
332 lw t7, COREBOOTCFG_VPECONFIG(t0)
333 addu v0, v0, t7
334
335#ifdef CONFIG_MIPS_MT
336
337 /* If the core doesn't support MT then return */
338 bnez t6, 1f
339 nop
340 jr ra
341 nop
342
343 .set push
344 .set mt
345
3461: /* Enter VPE configuration state */
347 dvpe
348 la t1, 1f
349 jr.hb t1
350 nop
3511: mfc0 t1, CP0_MVPCONTROL
352 ori t1, t1, MVPCONTROL_VPC
353 mtc0 t1, CP0_MVPCONTROL
354 ehb
355
356 /* Loop through each VPE */
357 lw t6, COREBOOTCFG_VPEMASK(t0)
358 move t8, t6
359 li t5, 0
360
361 /* Check whether the VPE should be running. If not, skip it */
3621: andi t0, t6, 1
363 beqz t0, 2f
364 nop
365
366 /* Operate on the appropriate TC */
367 mfc0 t0, CP0_VPECONTROL
368 ori t0, t0, VPECONTROL_TARGTC
369 xori t0, t0, VPECONTROL_TARGTC
370 or t0, t0, t5
371 mtc0 t0, CP0_VPECONTROL
372 ehb
373
374 /* Skip the VPE if its TC is not halted */
375 mftc0 t0, CP0_TCHALT
376 beqz t0, 2f
377 nop
378
379 /* Calculate a pointer to the VPEs struct vpe_boot_config */
380 li t0, VPEBOOTCFG_SIZE
381 mul t0, t0, t5
382 addu t0, t0, t7
383
384 /* Set the TC restart PC */
385 lw t1, VPEBOOTCFG_PC(t0)
386 mttc0 t1, CP0_TCRESTART
387
388 /* Set the TC stack pointer */
389 lw t1, VPEBOOTCFG_SP(t0)
390 mttgpr t1, sp
391
392 /* Set the TC global pointer */
393 lw t1, VPEBOOTCFG_GP(t0)
394 mttgpr t1, gp
395
396 /* Copy config from this VPE */
397 mfc0 t0, CP0_CONFIG
398 mttc0 t0, CP0_CONFIG
399
400 /* Ensure no software interrupts are pending */
401 mttc0 zero, CP0_CAUSE
402 mttc0 zero, CP0_STATUS
403
404 /* Set TC active, not interrupt exempt */
405 mftc0 t0, CP0_TCSTATUS
406 li t1, ~TCSTATUS_IXMT
407 and t0, t0, t1
408 ori t0, t0, TCSTATUS_A
409 mttc0 t0, CP0_TCSTATUS
410
411 /* Clear the TC halt bit */
412 mttc0 zero, CP0_TCHALT
413
414 /* Set VPE active */
415 mftc0 t0, CP0_VPECONF0
416 ori t0, t0, VPECONF0_VPA
417 mttc0 t0, CP0_VPECONF0
418
419 /* Next VPE */
4202: srl t6, t6, 1
421 addi t5, t5, 1
422 bnez t6, 1b
423 nop
424
425 /* Leave VPE configuration state */
426 mfc0 t1, CP0_MVPCONTROL
427 xori t1, t1, MVPCONTROL_VPC
428 mtc0 t1, CP0_MVPCONTROL
429 ehb
430 evpe
431
432 /* Check whether this VPE is meant to be running */
433 li t0, 1
434 sll t0, t0, t9
435 and t0, t0, t8
436 bnez t0, 2f
437 nop
438
439 /* This VPE should be offline, halt the TC */
440 li t0, TCHALT_H
441 mtc0 t0, CP0_TCHALT
442 la t0, 1f
4431: jr.hb t0
444 nop
445
4462: .set pop
447
448#endif /* CONFIG_MIPS_MT */
449
450 /* Return */
451 jr ra
452 nop
453 END(mips_cps_boot_vpes)
454
455#if defined(CONFIG_MIPS_CPS_PM) && defined(CONFIG_CPU_PM)
456
457 /* Calculate a pointer to this CPUs struct mips_static_suspend_state */
458 .macro psstate dest
459 .set push
460 .set noat
461 lw $1, TI_CPU(gp)
462 sll $1, $1, LONGLOG
463 la \dest, __per_cpu_offset
464 addu $1, $1, \dest
465 lw $1, 0($1)
466 la \dest, cps_cpu_state
467 addu \dest, \dest, $1
468 .set pop
469 .endm
470
471LEAF(mips_cps_pm_save)
472 /* Save CPU state */
473 SUSPEND_SAVE_REGS
474 psstate t1
475 SUSPEND_SAVE_STATIC
476 jr v0
477 nop
478 END(mips_cps_pm_save)
479
480LEAF(mips_cps_pm_restore)
481 /* Restore CPU state */
482 psstate t1
483 RESUME_RESTORE_STATIC
484 RESUME_RESTORE_REGS_RETURN
485 END(mips_cps_pm_restore)
486
487#endif /* CONFIG_MIPS_CPS_PM && CONFIG_CPU_PM */