MIPS: smp-cps: Pull boot config retrieval out of mips_cps_boot_vpes
[cascardo/linux.git] / arch / mips / kernel / cps-vec.S
1 /*
2  * Copyright (C) 2013 Imagination Technologies
3  * Author: Paul Burton <paul.burton@imgtec.com>
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation;  either version 2 of the  License, or (at your
8  * option) any later version.
9  */
10
11 #include <asm/addrspace.h>
12 #include <asm/asm.h>
13 #include <asm/asm-offsets.h>
14 #include <asm/asmmacro.h>
15 #include <asm/cacheops.h>
16 #include <asm/eva.h>
17 #include <asm/mipsregs.h>
18 #include <asm/mipsmtregs.h>
19 #include <asm/pm.h>
20
21 #define GCR_CL_COHERENCE_OFS    0x2008
22 #define GCR_CL_ID_OFS           0x2028
23
24 .extern mips_cm_base
25
26 .set noreorder
27
28 #ifdef CONFIG_64BIT
29 # define STATUS_BITDEPS         ST0_KX
30 #else
31 # define STATUS_BITDEPS         0
32 #endif
33
34 #ifdef CONFIG_MIPS_CPS_NS16550
35
36 #define DUMP_EXCEP(name)                \
37         PTR_LA  a0, 8f;                 \
38         jal     mips_cps_bev_dump;      \
39          nop;                           \
40         TEXT(name)
41
42 #else /* !CONFIG_MIPS_CPS_NS16550 */
43
44 #define DUMP_EXCEP(name)
45
46 #endif /* !CONFIG_MIPS_CPS_NS16550 */
47
48         /*
49          * Set dest to non-zero if the core supports the MT ASE, else zero. If
50          * MT is not supported then branch to nomt.
51          */
52         .macro  has_mt  dest, nomt
53         mfc0    \dest, CP0_CONFIG, 1
54         bgez    \dest, \nomt
55          mfc0   \dest, CP0_CONFIG, 2
56         bgez    \dest, \nomt
57          mfc0   \dest, CP0_CONFIG, 3
58         andi    \dest, \dest, MIPS_CONF3_MT
59         beqz    \dest, \nomt
60          nop
61         .endm
62
63         /* Calculate an uncached address for the CM GCRs */
64         .macro  cmgcrb  dest
65         .set    push
66         .set    noat
67         MFC0    $1, CP0_CMGCRBASE
68         PTR_SLL $1, $1, 4
69         PTR_LI  \dest, UNCAC_BASE
70         PTR_ADDU \dest, \dest, $1
71         .set    pop
72         .endm
73
74 .section .text.cps-vec
75 .balign 0x1000
76
77 LEAF(mips_cps_core_entry)
78         /*
79          * These first 4 bytes will be patched by cps_smp_setup to load the
80          * CCA to use into register s0.
81          */
82         .word   0
83
84         /* Check whether we're here due to an NMI */
85         mfc0    k0, CP0_STATUS
86         and     k0, k0, ST0_NMI
87         beqz    k0, not_nmi
88          nop
89
90         /* This is an NMI */
91         PTR_LA  k0, nmi_handler
92         jr      k0
93          nop
94
95 not_nmi:
96         /* Setup Cause */
97         li      t0, CAUSEF_IV
98         mtc0    t0, CP0_CAUSE
99
100         /* Setup Status */
101         li      t0, ST0_CU1 | ST0_CU0 | ST0_BEV | STATUS_BITDEPS
102         mtc0    t0, CP0_STATUS
103
104         /* Initialize the L1 caches */
105         jal     mips_cps_cache_init
106          nop
107
108         /* Set Kseg0 CCA to that in s0 */
109         mfc0    t0, CP0_CONFIG
110         ori     t0, 0x7
111         xori    t0, 0x7
112         or      t0, t0, s0
113         mtc0    t0, CP0_CONFIG
114         ehb
115
116         /* Enter the coherent domain */
117         cmgcrb  v1
118         li      t0, 0xff
119         sw      t0, GCR_CL_COHERENCE_OFS(v1)
120         ehb
121
122         /* Jump to kseg0 */
123         PTR_LA  t0, 1f
124         jr      t0
125          nop
126
127         /*
128          * We're up, cached & coherent. Perform any further required core-level
129          * initialisation.
130          */
131 1:      jal     mips_cps_core_init
132          nop
133
134         /* Do any EVA initialization if necessary */
135         eva_init
136
137         /* Retrieve boot configuration pointers */
138         jal     mips_cps_get_bootcfg
139          nop
140
141         /*
142          * Boot any other VPEs within this core that should be online, and
143          * deactivate this VPE if it should be offline.
144          */
145         move    a1, t9
146         jal     mips_cps_boot_vpes
147          move   a0, v0
148
149         /* Off we go! */
150         PTR_L   t1, VPEBOOTCFG_PC(v1)
151         PTR_L   gp, VPEBOOTCFG_GP(v1)
152         PTR_L   sp, VPEBOOTCFG_SP(v1)
153         jr      t1
154          nop
155         END(mips_cps_core_entry)
156
157 .org 0x200
158 LEAF(excep_tlbfill)
159         DUMP_EXCEP("TLB Fill")
160         b       .
161          nop
162         END(excep_tlbfill)
163
164 .org 0x280
165 LEAF(excep_xtlbfill)
166         DUMP_EXCEP("XTLB Fill")
167         b       .
168          nop
169         END(excep_xtlbfill)
170
171 .org 0x300
172 LEAF(excep_cache)
173         DUMP_EXCEP("Cache")
174         b       .
175          nop
176         END(excep_cache)
177
178 .org 0x380
179 LEAF(excep_genex)
180         DUMP_EXCEP("General")
181         b       .
182          nop
183         END(excep_genex)
184
185 .org 0x400
186 LEAF(excep_intex)
187         DUMP_EXCEP("Interrupt")
188         b       .
189          nop
190         END(excep_intex)
191
192 .org 0x480
193 LEAF(excep_ejtag)
194         DUMP_EXCEP("EJTAG")
195         PTR_LA  k0, ejtag_debug_handler
196         jr      k0
197          nop
198         END(excep_ejtag)
199
200 LEAF(mips_cps_core_init)
201 #ifdef CONFIG_MIPS_MT_SMP
202         /* Check that the core implements the MT ASE */
203         has_mt  t0, 3f
204
205         .set    push
206         .set    mt
207
208         /* Only allow 1 TC per VPE to execute... */
209         dmt
210
211         /* ...and for the moment only 1 VPE */
212         dvpe
213         PTR_LA  t1, 1f
214         jr.hb   t1
215          nop
216
217         /* Enter VPE configuration state */
218 1:      mfc0    t0, CP0_MVPCONTROL
219         ori     t0, t0, MVPCONTROL_VPC
220         mtc0    t0, CP0_MVPCONTROL
221
222         /* Retrieve the number of VPEs within the core */
223         mfc0    t0, CP0_MVPCONF0
224         srl     t0, t0, MVPCONF0_PVPE_SHIFT
225         andi    t0, t0, (MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT)
226         addiu   ta3, t0, 1
227
228         /* If there's only 1, we're done */
229         beqz    t0, 2f
230          nop
231
232         /* Loop through each VPE within this core */
233         li      ta1, 1
234
235 1:      /* Operate on the appropriate TC */
236         mtc0    ta1, CP0_VPECONTROL
237         ehb
238
239         /* Bind TC to VPE (1:1 TC:VPE mapping) */
240         mttc0   ta1, CP0_TCBIND
241
242         /* Set exclusive TC, non-active, master */
243         li      t0, VPECONF0_MVP
244         sll     t1, ta1, VPECONF0_XTC_SHIFT
245         or      t0, t0, t1
246         mttc0   t0, CP0_VPECONF0
247
248         /* Set TC non-active, non-allocatable */
249         mttc0   zero, CP0_TCSTATUS
250
251         /* Set TC halted */
252         li      t0, TCHALT_H
253         mttc0   t0, CP0_TCHALT
254
255         /* Next VPE */
256         addiu   ta1, ta1, 1
257         slt     t0, ta1, ta3
258         bnez    t0, 1b
259          nop
260
261         /* Leave VPE configuration state */
262 2:      mfc0    t0, CP0_MVPCONTROL
263         xori    t0, t0, MVPCONTROL_VPC
264         mtc0    t0, CP0_MVPCONTROL
265
266 3:      .set    pop
267 #endif
268         jr      ra
269          nop
270         END(mips_cps_core_init)
271
272 /**
273  * mips_cps_get_bootcfg() - retrieve boot configuration pointers
274  *
275  * Returns: pointer to struct core_boot_config in v0, pointer to
276  *          struct vpe_boot_config in v1, VPE ID in t9
277  */
278 LEAF(mips_cps_get_bootcfg)
279         /* Calculate a pointer to this cores struct core_boot_config */
280         cmgcrb  t0
281         lw      t0, GCR_CL_ID_OFS(t0)
282         li      t1, COREBOOTCFG_SIZE
283         mul     t0, t0, t1
284         PTR_LA  t1, mips_cps_core_bootcfg
285         PTR_L   t1, 0(t1)
286         PTR_ADDU v0, t0, t1
287
288         /* Calculate this VPEs ID. If the core doesn't support MT use 0 */
289         li      t9, 0
290 #ifdef CONFIG_MIPS_MT_SMP
291         has_mt  ta2, 1f
292
293         /* Find the number of VPEs present in the core */
294         mfc0    t1, CP0_MVPCONF0
295         srl     t1, t1, MVPCONF0_PVPE_SHIFT
296         andi    t1, t1, MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT
297         addiu   t1, t1, 1
298
299         /* Calculate a mask for the VPE ID from EBase.CPUNum */
300         clz     t1, t1
301         li      t2, 31
302         subu    t1, t2, t1
303         li      t2, 1
304         sll     t1, t2, t1
305         addiu   t1, t1, -1
306
307         /* Retrieve the VPE ID from EBase.CPUNum */
308         mfc0    t9, $15, 1
309         and     t9, t9, t1
310 #endif
311
312 1:      /* Calculate a pointer to this VPEs struct vpe_boot_config */
313         li      t1, VPEBOOTCFG_SIZE
314         mul     v1, t9, t1
315         PTR_L   ta3, COREBOOTCFG_VPECONFIG(v0)
316         PTR_ADDU v1, v1, ta3
317
318         jr      ra
319          nop
320         END(mips_cps_get_bootcfg)
321
322 LEAF(mips_cps_boot_vpes)
323         PTR_L   ta2, COREBOOTCFG_VPEMASK(a0)
324         PTR_L   ta3, COREBOOTCFG_VPECONFIG(a0)
325
326 #ifdef CONFIG_MIPS_MT
327
328         .set    push
329         .set    mt
330
331         /* If the core doesn't support MT then return */
332         has_mt  t0, 5f
333
334         /* Enter VPE configuration state */
335         dvpe
336         PTR_LA  t1, 1f
337         jr.hb   t1
338          nop
339 1:      mfc0    t1, CP0_MVPCONTROL
340         ori     t1, t1, MVPCONTROL_VPC
341         mtc0    t1, CP0_MVPCONTROL
342         ehb
343
344         /* Loop through each VPE */
345         move    t8, ta2
346         li      ta1, 0
347
348         /* Check whether the VPE should be running. If not, skip it */
349 1:      andi    t0, ta2, 1
350         beqz    t0, 2f
351          nop
352
353         /* Operate on the appropriate TC */
354         mfc0    t0, CP0_VPECONTROL
355         ori     t0, t0, VPECONTROL_TARGTC
356         xori    t0, t0, VPECONTROL_TARGTC
357         or      t0, t0, ta1
358         mtc0    t0, CP0_VPECONTROL
359         ehb
360
361         /* Skip the VPE if its TC is not halted */
362         mftc0   t0, CP0_TCHALT
363         beqz    t0, 2f
364          nop
365
366         /* Calculate a pointer to the VPEs struct vpe_boot_config */
367         li      t0, VPEBOOTCFG_SIZE
368         mul     t0, t0, ta1
369         addu    t0, t0, ta3
370
371         /* Set the TC restart PC */
372         lw      t1, VPEBOOTCFG_PC(t0)
373         mttc0   t1, CP0_TCRESTART
374
375         /* Set the TC stack pointer */
376         lw      t1, VPEBOOTCFG_SP(t0)
377         mttgpr  t1, sp
378
379         /* Set the TC global pointer */
380         lw      t1, VPEBOOTCFG_GP(t0)
381         mttgpr  t1, gp
382
383         /* Copy config from this VPE */
384         mfc0    t0, CP0_CONFIG
385         mttc0   t0, CP0_CONFIG
386
387         /* Ensure no software interrupts are pending */
388         mttc0   zero, CP0_CAUSE
389         mttc0   zero, CP0_STATUS
390
391         /* Set TC active, not interrupt exempt */
392         mftc0   t0, CP0_TCSTATUS
393         li      t1, ~TCSTATUS_IXMT
394         and     t0, t0, t1
395         ori     t0, t0, TCSTATUS_A
396         mttc0   t0, CP0_TCSTATUS
397
398         /* Clear the TC halt bit */
399         mttc0   zero, CP0_TCHALT
400
401         /* Set VPE active */
402         mftc0   t0, CP0_VPECONF0
403         ori     t0, t0, VPECONF0_VPA
404         mttc0   t0, CP0_VPECONF0
405
406         /* Next VPE */
407 2:      srl     ta2, ta2, 1
408         addiu   ta1, ta1, 1
409         bnez    ta2, 1b
410          nop
411
412         /* Leave VPE configuration state */
413         mfc0    t1, CP0_MVPCONTROL
414         xori    t1, t1, MVPCONTROL_VPC
415         mtc0    t1, CP0_MVPCONTROL
416         ehb
417         evpe
418
419         /* Check whether this VPE is meant to be running */
420         li      t0, 1
421         sll     t0, t0, a1
422         and     t0, t0, t8
423         bnez    t0, 2f
424          nop
425
426         /* This VPE should be offline, halt the TC */
427         li      t0, TCHALT_H
428         mtc0    t0, CP0_TCHALT
429         PTR_LA  t0, 1f
430 1:      jr.hb   t0
431          nop
432
433 2:      .set    pop
434
435 #endif /* CONFIG_MIPS_MT_SMP */
436
437         /* Return */
438 5:      jr      ra
439          nop
440         END(mips_cps_boot_vpes)
441
442 LEAF(mips_cps_cache_init)
443         /*
444          * Clear the bits used to index the caches. Note that the architecture
445          * dictates that writing to any of TagLo or TagHi selects 0 or 2 should
446          * be valid for all MIPS32 CPUs, even those for which said writes are
447          * unnecessary.
448          */
449         mtc0    zero, CP0_TAGLO, 0
450         mtc0    zero, CP0_TAGHI, 0
451         mtc0    zero, CP0_TAGLO, 2
452         mtc0    zero, CP0_TAGHI, 2
453         ehb
454
455         /* Primary cache configuration is indicated by Config1 */
456         mfc0    v0, CP0_CONFIG, 1
457
458         /* Detect I-cache line size */
459         _EXT    t0, v0, MIPS_CONF1_IL_SHF, MIPS_CONF1_IL_SZ
460         beqz    t0, icache_done
461          li     t1, 2
462         sllv    t0, t1, t0
463
464         /* Detect I-cache size */
465         _EXT    t1, v0, MIPS_CONF1_IS_SHF, MIPS_CONF1_IS_SZ
466         xori    t2, t1, 0x7
467         beqz    t2, 1f
468          li     t3, 32
469         addiu   t1, t1, 1
470         sllv    t1, t3, t1
471 1:      /* At this point t1 == I-cache sets per way */
472         _EXT    t2, v0, MIPS_CONF1_IA_SHF, MIPS_CONF1_IA_SZ
473         addiu   t2, t2, 1
474         mul     t1, t1, t0
475         mul     t1, t1, t2
476
477         li      a0, CKSEG0
478         PTR_ADD a1, a0, t1
479 1:      cache   Index_Store_Tag_I, 0(a0)
480         PTR_ADD a0, a0, t0
481         bne     a0, a1, 1b
482          nop
483 icache_done:
484
485         /* Detect D-cache line size */
486         _EXT    t0, v0, MIPS_CONF1_DL_SHF, MIPS_CONF1_DL_SZ
487         beqz    t0, dcache_done
488          li     t1, 2
489         sllv    t0, t1, t0
490
491         /* Detect D-cache size */
492         _EXT    t1, v0, MIPS_CONF1_DS_SHF, MIPS_CONF1_DS_SZ
493         xori    t2, t1, 0x7
494         beqz    t2, 1f
495          li     t3, 32
496         addiu   t1, t1, 1
497         sllv    t1, t3, t1
498 1:      /* At this point t1 == D-cache sets per way */
499         _EXT    t2, v0, MIPS_CONF1_DA_SHF, MIPS_CONF1_DA_SZ
500         addiu   t2, t2, 1
501         mul     t1, t1, t0
502         mul     t1, t1, t2
503
504         li      a0, CKSEG0
505         PTR_ADDU a1, a0, t1
506         PTR_SUBU a1, a1, t0
507 1:      cache   Index_Store_Tag_D, 0(a0)
508         bne     a0, a1, 1b
509          PTR_ADD a0, a0, t0
510 dcache_done:
511
512         jr      ra
513          nop
514         END(mips_cps_cache_init)
515
516 #if defined(CONFIG_MIPS_CPS_PM) && defined(CONFIG_CPU_PM)
517
518         /* Calculate a pointer to this CPUs struct mips_static_suspend_state */
519         .macro  psstate dest
520         .set    push
521         .set    noat
522         lw      $1, TI_CPU(gp)
523         sll     $1, $1, LONGLOG
524         PTR_LA  \dest, __per_cpu_offset
525         addu    $1, $1, \dest
526         lw      $1, 0($1)
527         PTR_LA  \dest, cps_cpu_state
528         addu    \dest, \dest, $1
529         .set    pop
530         .endm
531
532 LEAF(mips_cps_pm_save)
533         /* Save CPU state */
534         SUSPEND_SAVE_REGS
535         psstate t1
536         SUSPEND_SAVE_STATIC
537         jr      v0
538          nop
539         END(mips_cps_pm_save)
540
541 LEAF(mips_cps_pm_restore)
542         /* Restore CPU state */
543         psstate t1
544         RESUME_RESTORE_STATIC
545         RESUME_RESTORE_REGS_RETURN
546         END(mips_cps_pm_restore)
547
548 #endif /* CONFIG_MIPS_CPS_PM && CONFIG_CPU_PM */