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