xref: /openbmc/linux/arch/mips/kernel/cps-vec.S (revision aa45787c)
12874c5fdSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-or-later */
20ee958e1SPaul Burton/*
30ee958e1SPaul Burton * Copyright (C) 2013 Imagination Technologies
4fb615d61SPaul Burton * Author: Paul Burton <paul.burton@mips.com>
50ee958e1SPaul Burton */
60ee958e1SPaul Burton
70ee958e1SPaul Burton#include <asm/addrspace.h>
80ee958e1SPaul Burton#include <asm/asm.h>
90ee958e1SPaul Burton#include <asm/asm-offsets.h>
100ee958e1SPaul Burton#include <asm/asmmacro.h>
110ee958e1SPaul Burton#include <asm/cacheops.h>
126521d9a4SMarkos Chandras#include <asm/eva.h>
130ee958e1SPaul Burton#include <asm/mipsregs.h>
14245a7868SPaul Burton#include <asm/mipsmtregs.h>
153179d37eSPaul Burton#include <asm/pm.h>
16fea8826dSJiaxun Yang#include <asm/smp-cps.h>
170ee958e1SPaul Burton
185a3e7c02SPaul Burton#define GCR_CPC_BASE_OFS	0x0088
190ee958e1SPaul Burton#define GCR_CL_COHERENCE_OFS	0x2008
20245a7868SPaul Burton#define GCR_CL_ID_OFS		0x2028
21245a7868SPaul Burton
22fa7a3b4aSPaul Burton#define CPC_CL_VC_STOP_OFS	0x2020
235a3e7c02SPaul Burton#define CPC_CL_VC_RUN_OFS	0x2028
245a3e7c02SPaul Burton
25245a7868SPaul Burton.extern mips_cm_base
26245a7868SPaul Burton
27245a7868SPaul Burton.set noreorder
28245a7868SPaul Burton
298fe2c547SPaul Burton#ifdef CONFIG_64BIT
308fe2c547SPaul Burton# define STATUS_BITDEPS		ST0_KX
318fe2c547SPaul Burton#else
328fe2c547SPaul Burton# define STATUS_BITDEPS		0
338fe2c547SPaul Burton#endif
348fe2c547SPaul Burton
35609cf6f2SPaul Burton#ifdef CONFIG_MIPS_CPS_NS16550
36609cf6f2SPaul Burton
37609cf6f2SPaul Burton#define DUMP_EXCEP(name)		\
38609cf6f2SPaul Burton	PTR_LA	a0, 8f;			\
39609cf6f2SPaul Burton	jal	mips_cps_bev_dump;	\
40609cf6f2SPaul Burton	 nop;				\
41609cf6f2SPaul Burton	TEXT(name)
42609cf6f2SPaul Burton
43609cf6f2SPaul Burton#else /* !CONFIG_MIPS_CPS_NS16550 */
44609cf6f2SPaul Burton
45609cf6f2SPaul Burton#define DUMP_EXCEP(name)
46609cf6f2SPaul Burton
47609cf6f2SPaul Burton#endif /* !CONFIG_MIPS_CPS_NS16550 */
48609cf6f2SPaul Burton
49245a7868SPaul Burton	/*
50245a7868SPaul Burton	 * Set dest to non-zero if the core supports the MT ASE, else zero. If
51245a7868SPaul Burton	 * MT is not supported then branch to nomt.
52245a7868SPaul Burton	 */
53245a7868SPaul Burton	.macro	has_mt	dest, nomt
54245a7868SPaul Burton	mfc0	\dest, CP0_CONFIG, 1
55245a7868SPaul Burton	bgez	\dest, \nomt
56245a7868SPaul Burton	 mfc0	\dest, CP0_CONFIG, 2
57245a7868SPaul Burton	bgez	\dest, \nomt
58245a7868SPaul Burton	 mfc0	\dest, CP0_CONFIG, 3
59245a7868SPaul Burton	andi	\dest, \dest, MIPS_CONF3_MT
60245a7868SPaul Burton	beqz	\dest, \nomt
611e5fb282SPaul Burton	 nop
62245a7868SPaul Burton	.endm
630ee958e1SPaul Burton
645a3e7c02SPaul Burton	/*
655a3e7c02SPaul Burton	 * Set dest to non-zero if the core supports MIPSr6 multithreading
665a3e7c02SPaul Burton	 * (ie. VPs), else zero. If MIPSr6 multithreading is not supported then
675a3e7c02SPaul Burton	 * branch to nomt.
685a3e7c02SPaul Burton	 */
695a3e7c02SPaul Burton	.macro	has_vp	dest, nomt
705a3e7c02SPaul Burton	mfc0	\dest, CP0_CONFIG, 1
715a3e7c02SPaul Burton	bgez	\dest, \nomt
725a3e7c02SPaul Burton	 mfc0	\dest, CP0_CONFIG, 2
735a3e7c02SPaul Burton	bgez	\dest, \nomt
745a3e7c02SPaul Burton	 mfc0	\dest, CP0_CONFIG, 3
755a3e7c02SPaul Burton	bgez	\dest, \nomt
765a3e7c02SPaul Burton	 mfc0	\dest, CP0_CONFIG, 4
775a3e7c02SPaul Burton	bgez	\dest, \nomt
785a3e7c02SPaul Burton	 mfc0	\dest, CP0_CONFIG, 5
795a3e7c02SPaul Burton	andi	\dest, \dest, MIPS_CONF5_VP
805a3e7c02SPaul Burton	beqz	\dest, \nomt
815a3e7c02SPaul Burton	 nop
825a3e7c02SPaul Burton	.endm
835a3e7c02SPaul Burton
84f12401d7SPaul Burton
850ee958e1SPaul Burton.balign 0x1000
860ee958e1SPaul Burton
870ee958e1SPaul BurtonLEAF(mips_cps_core_entry)
880ee958e1SPaul Burton	/*
89fea8826dSJiaxun Yang	 * These first several instructions will be patched by cps_smp_setup to load the
90fea8826dSJiaxun Yang	 * CCA to use into register s0 and GCR base address to register s1.
910ee958e1SPaul Burton	 */
92fea8826dSJiaxun Yang	.rept   CPS_ENTRY_PATCH_INSNS
93fea8826dSJiaxun Yang	nop
94fea8826dSJiaxun Yang	.endr
95fea8826dSJiaxun Yang
96fea8826dSJiaxun Yang	.global mips_cps_core_entry_patch_end
97fea8826dSJiaxun Yangmips_cps_core_entry_patch_end:
980ee958e1SPaul Burton
990ee958e1SPaul Burton	/* Check whether we're here due to an NMI */
1000ee958e1SPaul Burton	mfc0	k0, CP0_STATUS
1010ee958e1SPaul Burton	and	k0, k0, ST0_NMI
1020ee958e1SPaul Burton	beqz	k0, not_nmi
1030ee958e1SPaul Burton	 nop
1040ee958e1SPaul Burton
1050ee958e1SPaul Burton	/* This is an NMI */
10681a02e34SMarkos Chandras	PTR_LA	k0, nmi_handler
1070ee958e1SPaul Burton	jr	k0
1080ee958e1SPaul Burton	 nop
1090ee958e1SPaul Burton
1100ee958e1SPaul Burtonnot_nmi:
1110ee958e1SPaul Burton	/* Setup Cause */
1120ee958e1SPaul Burton	li	t0, CAUSEF_IV
1130ee958e1SPaul Burton	mtc0	t0, CP0_CAUSE
1140ee958e1SPaul Burton
1150ee958e1SPaul Burton	/* Setup Status */
1168fe2c547SPaul Burton	li	t0, ST0_CU1 | ST0_CU0 | ST0_BEV | STATUS_BITDEPS
1170ee958e1SPaul Burton	mtc0	t0, CP0_STATUS
1180ee958e1SPaul Burton
119*aa45787cSJiaxun Yang	/* We don't know how to do coherence setup on earlier ISA */
120*aa45787cSJiaxun Yang#if MIPS_ISA_REV > 0
12187a70bcdSPaul Burton	/* Skip cache & coherence setup if we're already coherent */
122fea8826dSJiaxun Yang	lw	s7, GCR_CL_COHERENCE_OFS(s1)
12387a70bcdSPaul Burton	bnez	s7, 1f
12487a70bcdSPaul Burton	 nop
12587a70bcdSPaul Burton
1263dbc9971SPaul Burton	/* Initialize the L1 caches */
1273dbc9971SPaul Burton	jal	mips_cps_cache_init
1280ee958e1SPaul Burton	 nop
1290ee958e1SPaul Burton
13087a70bcdSPaul Burton	/* Enter the coherent domain */
13187a70bcdSPaul Burton	li	t0, 0xff
132fea8826dSJiaxun Yang	sw	t0, GCR_CL_COHERENCE_OFS(s1)
13387a70bcdSPaul Burton	ehb
134*aa45787cSJiaxun Yang#endif /* MIPS_ISA_REV > 0 */
13587a70bcdSPaul Burton
1360155a065SPaul Burton	/* Set Kseg0 CCA to that in s0 */
13787a70bcdSPaul Burton1:	mfc0	t0, CP0_CONFIG
1380ee958e1SPaul Burton	ori	t0, 0x7
1390155a065SPaul Burton	xori	t0, 0x7
1400155a065SPaul Burton	or	t0, t0, s0
1410ee958e1SPaul Burton	mtc0	t0, CP0_CONFIG
1420ee958e1SPaul Burton	ehb
1430ee958e1SPaul Burton
1440ee958e1SPaul Burton	/* Jump to kseg0 */
14581a02e34SMarkos Chandras	PTR_LA	t0, 1f
1460ee958e1SPaul Burton	jr	t0
1470ee958e1SPaul Burton	 nop
1480ee958e1SPaul Burton
149245a7868SPaul Burton	/*
15087a70bcdSPaul Burton	 * We're up, cached & coherent. Perform any EVA initialization necessary
15187a70bcdSPaul Burton	 * before we access memory.
152245a7868SPaul Burton	 */
15387a70bcdSPaul Burton1:	eva_init
1546521d9a4SMarkos Chandras
155f12401d7SPaul Burton	/* Retrieve boot configuration pointers */
156f12401d7SPaul Burton	jal	mips_cps_get_bootcfg
157f12401d7SPaul Burton	 nop
158f12401d7SPaul Burton
15987a70bcdSPaul Burton	/* Skip core-level init if we started up coherent */
16087a70bcdSPaul Burton	bnez	s7, 1f
16187a70bcdSPaul Burton	 nop
16287a70bcdSPaul Burton
16387a70bcdSPaul Burton	/* Perform any further required core-level initialisation */
16487a70bcdSPaul Burton	jal	mips_cps_core_init
16587a70bcdSPaul Burton	 nop
16687a70bcdSPaul Burton
1670ee958e1SPaul Burton	/*
168245a7868SPaul Burton	 * Boot any other VPEs within this core that should be online, and
169245a7868SPaul Burton	 * deactivate this VPE if it should be offline.
1700ee958e1SPaul Burton	 */
171f12401d7SPaul Burton	move	a1, t9
172245a7868SPaul Burton	jal	mips_cps_boot_vpes
173f12401d7SPaul Burton	 move	a0, v0
1740ee958e1SPaul Burton
1750ee958e1SPaul Burton	/* Off we go! */
17687a70bcdSPaul Burton1:	PTR_L	t1, VPEBOOTCFG_PC(v1)
177f12401d7SPaul Burton	PTR_L	gp, VPEBOOTCFG_GP(v1)
178f12401d7SPaul Burton	PTR_L	sp, VPEBOOTCFG_SP(v1)
1790ee958e1SPaul Burton	jr	t1
1800ee958e1SPaul Burton	 nop
1810ee958e1SPaul Burton	END(mips_cps_core_entry)
1820ee958e1SPaul Burton
1830ee958e1SPaul Burton.org 0x200
1840ee958e1SPaul BurtonLEAF(excep_tlbfill)
185609cf6f2SPaul Burton	DUMP_EXCEP("TLB Fill")
1860ee958e1SPaul Burton	b	.
1870ee958e1SPaul Burton	 nop
1880ee958e1SPaul Burton	END(excep_tlbfill)
1890ee958e1SPaul Burton
1900ee958e1SPaul Burton.org 0x280
1910ee958e1SPaul BurtonLEAF(excep_xtlbfill)
192609cf6f2SPaul Burton	DUMP_EXCEP("XTLB Fill")
1930ee958e1SPaul Burton	b	.
1940ee958e1SPaul Burton	 nop
1950ee958e1SPaul Burton	END(excep_xtlbfill)
1960ee958e1SPaul Burton
1970ee958e1SPaul Burton.org 0x300
1980ee958e1SPaul BurtonLEAF(excep_cache)
199609cf6f2SPaul Burton	DUMP_EXCEP("Cache")
2000ee958e1SPaul Burton	b	.
2010ee958e1SPaul Burton	 nop
2020ee958e1SPaul Burton	END(excep_cache)
2030ee958e1SPaul Burton
2040ee958e1SPaul Burton.org 0x380
2050ee958e1SPaul BurtonLEAF(excep_genex)
206609cf6f2SPaul Burton	DUMP_EXCEP("General")
2070ee958e1SPaul Burton	b	.
2080ee958e1SPaul Burton	 nop
2090ee958e1SPaul Burton	END(excep_genex)
2100ee958e1SPaul Burton
2110ee958e1SPaul Burton.org 0x400
2120ee958e1SPaul BurtonLEAF(excep_intex)
213609cf6f2SPaul Burton	DUMP_EXCEP("Interrupt")
2140ee958e1SPaul Burton	b	.
2150ee958e1SPaul Burton	 nop
2160ee958e1SPaul Burton	END(excep_intex)
2170ee958e1SPaul Burton
2180ee958e1SPaul Burton.org 0x480
2190ee958e1SPaul BurtonLEAF(excep_ejtag)
22081a02e34SMarkos Chandras	PTR_LA	k0, ejtag_debug_handler
2210ee958e1SPaul Burton	jr	k0
2220ee958e1SPaul Burton	 nop
2230ee958e1SPaul Burton	END(excep_ejtag)
224245a7868SPaul Burton
225245a7868SPaul BurtonLEAF(mips_cps_core_init)
2267a63076dSPaul Burton#ifdef CONFIG_MIPS_MT_SMP
227245a7868SPaul Burton	/* Check that the core implements the MT ASE */
228245a7868SPaul Burton	has_mt	t0, 3f
229245a7868SPaul Burton
230245a7868SPaul Burton	.set	push
23117278a91SJames Hogan	.set	MIPS_ISA_LEVEL_RAW
232245a7868SPaul Burton	.set	mt
233245a7868SPaul Burton
234245a7868SPaul Burton	/* Only allow 1 TC per VPE to execute... */
235245a7868SPaul Burton	dmt
236245a7868SPaul Burton
237245a7868SPaul Burton	/* ...and for the moment only 1 VPE */
238245a7868SPaul Burton	dvpe
23981a02e34SMarkos Chandras	PTR_LA	t1, 1f
240245a7868SPaul Burton	jr.hb	t1
241245a7868SPaul Burton	 nop
242245a7868SPaul Burton
243245a7868SPaul Burton	/* Enter VPE configuration state */
244245a7868SPaul Burton1:	mfc0	t0, CP0_MVPCONTROL
245245a7868SPaul Burton	ori	t0, t0, MVPCONTROL_VPC
246245a7868SPaul Burton	mtc0	t0, CP0_MVPCONTROL
247245a7868SPaul Burton
248245a7868SPaul Burton	/* Retrieve the number of VPEs within the core */
249245a7868SPaul Burton	mfc0	t0, CP0_MVPCONF0
250245a7868SPaul Burton	srl	t0, t0, MVPCONF0_PVPE_SHIFT
251245a7868SPaul Burton	andi	t0, t0, (MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT)
2520586ac75SMarkos Chandras	addiu	ta3, t0, 1
253245a7868SPaul Burton
254245a7868SPaul Burton	/* If there's only 1, we're done */
255245a7868SPaul Burton	beqz	t0, 2f
256245a7868SPaul Burton	 nop
257245a7868SPaul Burton
258245a7868SPaul Burton	/* Loop through each VPE within this core */
2590586ac75SMarkos Chandras	li	ta1, 1
260245a7868SPaul Burton
261245a7868SPaul Burton1:	/* Operate on the appropriate TC */
2620586ac75SMarkos Chandras	mtc0	ta1, CP0_VPECONTROL
263245a7868SPaul Burton	ehb
264245a7868SPaul Burton
265245a7868SPaul Burton	/* Bind TC to VPE (1:1 TC:VPE mapping) */
2660586ac75SMarkos Chandras	mttc0	ta1, CP0_TCBIND
267245a7868SPaul Burton
268245a7868SPaul Burton	/* Set exclusive TC, non-active, master */
269245a7868SPaul Burton	li	t0, VPECONF0_MVP
2700586ac75SMarkos Chandras	sll	t1, ta1, VPECONF0_XTC_SHIFT
271245a7868SPaul Burton	or	t0, t0, t1
272245a7868SPaul Burton	mttc0	t0, CP0_VPECONF0
273245a7868SPaul Burton
274245a7868SPaul Burton	/* Set TC non-active, non-allocatable */
275245a7868SPaul Burton	mttc0	zero, CP0_TCSTATUS
276245a7868SPaul Burton
277245a7868SPaul Burton	/* Set TC halted */
278245a7868SPaul Burton	li	t0, TCHALT_H
279245a7868SPaul Burton	mttc0	t0, CP0_TCHALT
280245a7868SPaul Burton
281245a7868SPaul Burton	/* Next VPE */
2820586ac75SMarkos Chandras	addiu	ta1, ta1, 1
2830586ac75SMarkos Chandras	slt	t0, ta1, ta3
284245a7868SPaul Burton	bnez	t0, 1b
285245a7868SPaul Burton	 nop
286245a7868SPaul Burton
287245a7868SPaul Burton	/* Leave VPE configuration state */
288245a7868SPaul Burton2:	mfc0	t0, CP0_MVPCONTROL
289245a7868SPaul Burton	xori	t0, t0, MVPCONTROL_VPC
290245a7868SPaul Burton	mtc0	t0, CP0_MVPCONTROL
291245a7868SPaul Burton
292245a7868SPaul Burton3:	.set	pop
293245a7868SPaul Burton#endif
294245a7868SPaul Burton	jr	ra
295245a7868SPaul Burton	 nop
296245a7868SPaul Burton	END(mips_cps_core_init)
297245a7868SPaul Burton
298f12401d7SPaul Burton/**
299f12401d7SPaul Burton * mips_cps_get_bootcfg() - retrieve boot configuration pointers
300f12401d7SPaul Burton *
301f12401d7SPaul Burton * Returns: pointer to struct core_boot_config in v0, pointer to
302f12401d7SPaul Burton *          struct vpe_boot_config in v1, VPE ID in t9
303f12401d7SPaul Burton */
304f12401d7SPaul BurtonLEAF(mips_cps_get_bootcfg)
305245a7868SPaul Burton	/* Calculate a pointer to this cores struct core_boot_config */
306fea8826dSJiaxun Yang	lw	t0, GCR_CL_ID_OFS(s1)
307245a7868SPaul Burton	li	t1, COREBOOTCFG_SIZE
308245a7868SPaul Burton	mul	t0, t0, t1
30981a02e34SMarkos Chandras	PTR_LA	t1, mips_cps_core_bootcfg
310b677bc03SMarkos Chandras	PTR_L	t1, 0(t1)
311f12401d7SPaul Burton	PTR_ADDU v0, t0, t1
312245a7868SPaul Burton
313245a7868SPaul Burton	/* Calculate this VPEs ID. If the core doesn't support MT use 0 */
314245a7868SPaul Burton	li	t9, 0
3155a3e7c02SPaul Burton#if defined(CONFIG_CPU_MIPSR6)
3165a3e7c02SPaul Burton	has_vp	ta2, 1f
3175a3e7c02SPaul Burton
3185a3e7c02SPaul Burton	/*
3195a3e7c02SPaul Burton	 * Assume non-contiguous numbering. Perhaps some day we'll need
3205a3e7c02SPaul Burton	 * to handle contiguous VP numbering, but no such systems yet
3215a3e7c02SPaul Burton	 * exist.
3225a3e7c02SPaul Burton	 */
32315e6529fSPaul Burton	mfc0	t9, CP0_GLOBALNUMBER
32415e6529fSPaul Burton	andi	t9, t9, MIPS_GLOBALNUMBER_VP
3255a3e7c02SPaul Burton#elif defined(CONFIG_MIPS_MT_SMP)
3261e5fb282SPaul Burton	has_mt	ta2, 1f
327245a7868SPaul Burton
328245a7868SPaul Burton	/* Find the number of VPEs present in the core */
329245a7868SPaul Burton	mfc0	t1, CP0_MVPCONF0
330245a7868SPaul Burton	srl	t1, t1, MVPCONF0_PVPE_SHIFT
331245a7868SPaul Burton	andi	t1, t1, MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT
332acac4108SMarkos Chandras	addiu	t1, t1, 1
333245a7868SPaul Burton
334245a7868SPaul Burton	/* Calculate a mask for the VPE ID from EBase.CPUNum */
335245a7868SPaul Burton	clz	t1, t1
336245a7868SPaul Burton	li	t2, 31
337245a7868SPaul Burton	subu	t1, t2, t1
338245a7868SPaul Burton	li	t2, 1
339245a7868SPaul Burton	sll	t1, t2, t1
340245a7868SPaul Burton	addiu	t1, t1, -1
341245a7868SPaul Burton
342245a7868SPaul Burton	/* Retrieve the VPE ID from EBase.CPUNum */
343245a7868SPaul Burton	mfc0	t9, $15, 1
344245a7868SPaul Burton	and	t9, t9, t1
345a5b0f6dbSPaul Burton#endif
346245a7868SPaul Burton
347245a7868SPaul Burton1:	/* Calculate a pointer to this VPEs struct vpe_boot_config */
348245a7868SPaul Burton	li	t1, VPEBOOTCFG_SIZE
349f12401d7SPaul Burton	mul	v1, t9, t1
350f12401d7SPaul Burton	PTR_L	ta3, COREBOOTCFG_VPECONFIG(v0)
351f12401d7SPaul Burton	PTR_ADDU v1, v1, ta3
352245a7868SPaul Burton
353245a7868SPaul Burton	jr	ra
354245a7868SPaul Burton	 nop
355f12401d7SPaul Burton	END(mips_cps_get_bootcfg)
356f12401d7SPaul Burton
357f12401d7SPaul BurtonLEAF(mips_cps_boot_vpes)
358fb2155e3SMatt Redfearn	lw	ta2, COREBOOTCFG_VPEMASK(a0)
359f12401d7SPaul Burton	PTR_L	ta3, COREBOOTCFG_VPECONFIG(a0)
360f12401d7SPaul Burton
3615a3e7c02SPaul Burton#if defined(CONFIG_CPU_MIPSR6)
3625a3e7c02SPaul Burton
3635a3e7c02SPaul Burton	has_vp	t0, 5f
3645a3e7c02SPaul Burton
3655a3e7c02SPaul Burton	/* Find base address of CPC */
366fea8826dSJiaxun Yang	PTR_LA	t1, mips_gcr_base
367fea8826dSJiaxun Yang	PTR_L	t1, 0(t1)
368fea8826dSJiaxun Yang	PTR_L	t1, GCR_CPC_BASE_OFS(t1)
3695a3e7c02SPaul Burton	PTR_LI	t2, ~0x7fff
3705a3e7c02SPaul Burton	and	t1, t1, t2
3715a3e7c02SPaul Burton	PTR_LI	t2, UNCAC_BASE
3725a3e7c02SPaul Burton	PTR_ADD	t1, t1, t2
3735a3e7c02SPaul Burton
374fa7a3b4aSPaul Burton	/* Start any other VPs that ought to be running */
3755a3e7c02SPaul Burton	PTR_S	ta2, CPC_CL_VC_RUN_OFS(t1)
376fa7a3b4aSPaul Burton
377fa7a3b4aSPaul Burton	/* Ensure this VP stops running if it shouldn't be */
378fa7a3b4aSPaul Burton	not	ta2
379fa7a3b4aSPaul Burton	PTR_S	ta2, CPC_CL_VC_STOP_OFS(t1)
3805a3e7c02SPaul Burton	ehb
3815a3e7c02SPaul Burton
3825a3e7c02SPaul Burton#elif defined(CONFIG_MIPS_MT)
383245a7868SPaul Burton
384f12401d7SPaul Burton	/* If the core doesn't support MT then return */
385f12401d7SPaul Burton	has_mt	t0, 5f
386f12401d7SPaul Burton
387f12401d7SPaul Burton	/* Enter VPE configuration state */
3888dbc1864SJames Hogan	.set	push
3898dbc1864SJames Hogan	.set	MIPS_ISA_LEVEL_RAW
3908dbc1864SJames Hogan	.set	mt
391245a7868SPaul Burton	dvpe
3928dbc1864SJames Hogan	.set	pop
3938dbc1864SJames Hogan
39481a02e34SMarkos Chandras	PTR_LA	t1, 1f
395245a7868SPaul Burton	jr.hb	t1
396245a7868SPaul Burton	 nop
397245a7868SPaul Burton1:	mfc0	t1, CP0_MVPCONTROL
398245a7868SPaul Burton	ori	t1, t1, MVPCONTROL_VPC
399245a7868SPaul Burton	mtc0	t1, CP0_MVPCONTROL
400245a7868SPaul Burton	ehb
401245a7868SPaul Burton
402245a7868SPaul Burton	/* Loop through each VPE */
4030586ac75SMarkos Chandras	move	t8, ta2
4040586ac75SMarkos Chandras	li	ta1, 0
405245a7868SPaul Burton
406245a7868SPaul Burton	/* Check whether the VPE should be running. If not, skip it */
4070586ac75SMarkos Chandras1:	andi	t0, ta2, 1
408245a7868SPaul Burton	beqz	t0, 2f
409245a7868SPaul Burton	 nop
410245a7868SPaul Burton
411245a7868SPaul Burton	/* Operate on the appropriate TC */
412245a7868SPaul Burton	mfc0	t0, CP0_VPECONTROL
413245a7868SPaul Burton	ori	t0, t0, VPECONTROL_TARGTC
414245a7868SPaul Burton	xori	t0, t0, VPECONTROL_TARGTC
4150586ac75SMarkos Chandras	or	t0, t0, ta1
416245a7868SPaul Burton	mtc0	t0, CP0_VPECONTROL
417245a7868SPaul Burton	ehb
418245a7868SPaul Burton
4198dbc1864SJames Hogan	.set	push
4208dbc1864SJames Hogan	.set	MIPS_ISA_LEVEL_RAW
4218dbc1864SJames Hogan	.set	mt
4228dbc1864SJames Hogan
423245a7868SPaul Burton	/* Skip the VPE if its TC is not halted */
424245a7868SPaul Burton	mftc0	t0, CP0_TCHALT
425245a7868SPaul Burton	beqz	t0, 2f
426245a7868SPaul Burton	 nop
427245a7868SPaul Burton
428245a7868SPaul Burton	/* Calculate a pointer to the VPEs struct vpe_boot_config */
429245a7868SPaul Burton	li	t0, VPEBOOTCFG_SIZE
4300586ac75SMarkos Chandras	mul	t0, t0, ta1
4310586ac75SMarkos Chandras	addu	t0, t0, ta3
432245a7868SPaul Burton
433245a7868SPaul Burton	/* Set the TC restart PC */
434245a7868SPaul Burton	lw	t1, VPEBOOTCFG_PC(t0)
435245a7868SPaul Burton	mttc0	t1, CP0_TCRESTART
436245a7868SPaul Burton
437245a7868SPaul Burton	/* Set the TC stack pointer */
438245a7868SPaul Burton	lw	t1, VPEBOOTCFG_SP(t0)
439245a7868SPaul Burton	mttgpr	t1, sp
440245a7868SPaul Burton
441245a7868SPaul Burton	/* Set the TC global pointer */
442245a7868SPaul Burton	lw	t1, VPEBOOTCFG_GP(t0)
443245a7868SPaul Burton	mttgpr	t1, gp
444245a7868SPaul Burton
445245a7868SPaul Burton	/* Copy config from this VPE */
446245a7868SPaul Burton	mfc0	t0, CP0_CONFIG
447245a7868SPaul Burton	mttc0	t0, CP0_CONFIG
448245a7868SPaul Burton
44963a8802fSMatt Redfearn	/*
45063a8802fSMatt Redfearn	 * Copy the EVA config from this VPE if the CPU supports it.
45163a8802fSMatt Redfearn	 * CONFIG3 must exist to be running MT startup - just read it.
45263a8802fSMatt Redfearn	 */
45363a8802fSMatt Redfearn	mfc0	t0, CP0_CONFIG, 3
45463a8802fSMatt Redfearn	and	t0, t0, MIPS_CONF3_SC
45563a8802fSMatt Redfearn	beqz	t0, 3f
45663a8802fSMatt Redfearn	 nop
45763a8802fSMatt Redfearn	mfc0    t0, CP0_SEGCTL0
45863a8802fSMatt Redfearn	mttc0	t0, CP0_SEGCTL0
45963a8802fSMatt Redfearn	mfc0    t0, CP0_SEGCTL1
46063a8802fSMatt Redfearn	mttc0	t0, CP0_SEGCTL1
46163a8802fSMatt Redfearn	mfc0    t0, CP0_SEGCTL2
46263a8802fSMatt Redfearn	mttc0	t0, CP0_SEGCTL2
46363a8802fSMatt Redfearn3:
464245a7868SPaul Burton	/* Ensure no software interrupts are pending */
465245a7868SPaul Burton	mttc0	zero, CP0_CAUSE
466245a7868SPaul Burton	mttc0	zero, CP0_STATUS
467245a7868SPaul Burton
468245a7868SPaul Burton	/* Set TC active, not interrupt exempt */
469245a7868SPaul Burton	mftc0	t0, CP0_TCSTATUS
470245a7868SPaul Burton	li	t1, ~TCSTATUS_IXMT
471245a7868SPaul Burton	and	t0, t0, t1
472245a7868SPaul Burton	ori	t0, t0, TCSTATUS_A
473245a7868SPaul Burton	mttc0	t0, CP0_TCSTATUS
474245a7868SPaul Burton
475245a7868SPaul Burton	/* Clear the TC halt bit */
476245a7868SPaul Burton	mttc0	zero, CP0_TCHALT
477245a7868SPaul Burton
478245a7868SPaul Burton	/* Set VPE active */
479245a7868SPaul Burton	mftc0	t0, CP0_VPECONF0
480245a7868SPaul Burton	ori	t0, t0, VPECONF0_VPA
481245a7868SPaul Burton	mttc0	t0, CP0_VPECONF0
482245a7868SPaul Burton
483245a7868SPaul Burton	/* Next VPE */
4840586ac75SMarkos Chandras2:	srl	ta2, ta2, 1
4850586ac75SMarkos Chandras	addiu	ta1, ta1, 1
4860586ac75SMarkos Chandras	bnez	ta2, 1b
487245a7868SPaul Burton	 nop
488245a7868SPaul Burton
489245a7868SPaul Burton	/* Leave VPE configuration state */
490245a7868SPaul Burton	mfc0	t1, CP0_MVPCONTROL
491245a7868SPaul Burton	xori	t1, t1, MVPCONTROL_VPC
492245a7868SPaul Burton	mtc0	t1, CP0_MVPCONTROL
493245a7868SPaul Burton	ehb
494245a7868SPaul Burton	evpe
495245a7868SPaul Burton
4968dbc1864SJames Hogan	.set	pop
4978dbc1864SJames Hogan
498245a7868SPaul Burton	/* Check whether this VPE is meant to be running */
499245a7868SPaul Burton	li	t0, 1
500f12401d7SPaul Burton	sll	t0, t0, a1
501245a7868SPaul Burton	and	t0, t0, t8
502245a7868SPaul Burton	bnez	t0, 2f
503245a7868SPaul Burton	 nop
504245a7868SPaul Burton
505245a7868SPaul Burton	/* This VPE should be offline, halt the TC */
506245a7868SPaul Burton	li	t0, TCHALT_H
507245a7868SPaul Burton	mtc0	t0, CP0_TCHALT
50881a02e34SMarkos Chandras	PTR_LA	t0, 1f
509245a7868SPaul Burton1:	jr.hb	t0
510245a7868SPaul Burton	 nop
511245a7868SPaul Burton
5128dbc1864SJames Hogan2:
513245a7868SPaul Burton
5147a63076dSPaul Burton#endif /* CONFIG_MIPS_MT_SMP */
515245a7868SPaul Burton
516245a7868SPaul Burton	/* Return */
517f12401d7SPaul Burton5:	jr	ra
518245a7868SPaul Burton	 nop
519245a7868SPaul Burton	END(mips_cps_boot_vpes)
5203179d37eSPaul Burton
521*aa45787cSJiaxun Yang#if MIPS_ISA_REV > 0
5223dbc9971SPaul BurtonLEAF(mips_cps_cache_init)
5233dbc9971SPaul Burton	/*
5243dbc9971SPaul Burton	 * Clear the bits used to index the caches. Note that the architecture
5253dbc9971SPaul Burton	 * dictates that writing to any of TagLo or TagHi selects 0 or 2 should
5263dbc9971SPaul Burton	 * be valid for all MIPS32 CPUs, even those for which said writes are
5273dbc9971SPaul Burton	 * unnecessary.
5283dbc9971SPaul Burton	 */
5293dbc9971SPaul Burton	mtc0	zero, CP0_TAGLO, 0
5303dbc9971SPaul Burton	mtc0	zero, CP0_TAGHI, 0
5313dbc9971SPaul Burton	mtc0	zero, CP0_TAGLO, 2
5323dbc9971SPaul Burton	mtc0	zero, CP0_TAGHI, 2
5333dbc9971SPaul Burton	ehb
5343dbc9971SPaul Burton
5353dbc9971SPaul Burton	/* Primary cache configuration is indicated by Config1 */
5363dbc9971SPaul Burton	mfc0	v0, CP0_CONFIG, 1
5373dbc9971SPaul Burton
5383dbc9971SPaul Burton	/* Detect I-cache line size */
5393dbc9971SPaul Burton	_EXT	t0, v0, MIPS_CONF1_IL_SHF, MIPS_CONF1_IL_SZ
5403dbc9971SPaul Burton	beqz	t0, icache_done
5413dbc9971SPaul Burton	 li	t1, 2
5423dbc9971SPaul Burton	sllv	t0, t1, t0
5433dbc9971SPaul Burton
5443dbc9971SPaul Burton	/* Detect I-cache size */
5453dbc9971SPaul Burton	_EXT	t1, v0, MIPS_CONF1_IS_SHF, MIPS_CONF1_IS_SZ
5463dbc9971SPaul Burton	xori	t2, t1, 0x7
5473dbc9971SPaul Burton	beqz	t2, 1f
5483dbc9971SPaul Burton	 li	t3, 32
5493dbc9971SPaul Burton	addiu	t1, t1, 1
5503dbc9971SPaul Burton	sllv	t1, t3, t1
5513dbc9971SPaul Burton1:	/* At this point t1 == I-cache sets per way */
5523dbc9971SPaul Burton	_EXT	t2, v0, MIPS_CONF1_IA_SHF, MIPS_CONF1_IA_SZ
5533dbc9971SPaul Burton	addiu	t2, t2, 1
5543dbc9971SPaul Burton	mul	t1, t1, t0
5553dbc9971SPaul Burton	mul	t1, t1, t2
5563dbc9971SPaul Burton
5573dbc9971SPaul Burton	li	a0, CKSEG0
5583dbc9971SPaul Burton	PTR_ADD	a1, a0, t1
5593dbc9971SPaul Burton1:	cache	Index_Store_Tag_I, 0(a0)
5603dbc9971SPaul Burton	PTR_ADD	a0, a0, t0
5613dbc9971SPaul Burton	bne	a0, a1, 1b
5623dbc9971SPaul Burton	 nop
5633dbc9971SPaul Burtonicache_done:
5643dbc9971SPaul Burton
5653dbc9971SPaul Burton	/* Detect D-cache line size */
5663dbc9971SPaul Burton	_EXT	t0, v0, MIPS_CONF1_DL_SHF, MIPS_CONF1_DL_SZ
5673dbc9971SPaul Burton	beqz	t0, dcache_done
5683dbc9971SPaul Burton	 li	t1, 2
5693dbc9971SPaul Burton	sllv	t0, t1, t0
5703dbc9971SPaul Burton
5713dbc9971SPaul Burton	/* Detect D-cache size */
5723dbc9971SPaul Burton	_EXT	t1, v0, MIPS_CONF1_DS_SHF, MIPS_CONF1_DS_SZ
5733dbc9971SPaul Burton	xori	t2, t1, 0x7
5743dbc9971SPaul Burton	beqz	t2, 1f
5753dbc9971SPaul Burton	 li	t3, 32
5763dbc9971SPaul Burton	addiu	t1, t1, 1
5773dbc9971SPaul Burton	sllv	t1, t3, t1
5783dbc9971SPaul Burton1:	/* At this point t1 == D-cache sets per way */
5793dbc9971SPaul Burton	_EXT	t2, v0, MIPS_CONF1_DA_SHF, MIPS_CONF1_DA_SZ
5803dbc9971SPaul Burton	addiu	t2, t2, 1
5813dbc9971SPaul Burton	mul	t1, t1, t0
5823dbc9971SPaul Burton	mul	t1, t1, t2
5833dbc9971SPaul Burton
5843dbc9971SPaul Burton	li	a0, CKSEG0
5853dbc9971SPaul Burton	PTR_ADDU a1, a0, t1
5863dbc9971SPaul Burton	PTR_SUBU a1, a1, t0
5873dbc9971SPaul Burton1:	cache	Index_Store_Tag_D, 0(a0)
5883dbc9971SPaul Burton	bne	a0, a1, 1b
5893dbc9971SPaul Burton	 PTR_ADD a0, a0, t0
5903dbc9971SPaul Burtondcache_done:
5913dbc9971SPaul Burton
5923dbc9971SPaul Burton	jr	ra
5933dbc9971SPaul Burton	 nop
5943dbc9971SPaul Burton	END(mips_cps_cache_init)
595*aa45787cSJiaxun Yang#endif /* MIPS_ISA_REV > 0 */
5963dbc9971SPaul Burton
5973179d37eSPaul Burton#if defined(CONFIG_MIPS_CPS_PM) && defined(CONFIG_CPU_PM)
5983179d37eSPaul Burton
5993179d37eSPaul Burton	/* Calculate a pointer to this CPUs struct mips_static_suspend_state */
6003179d37eSPaul Burton	.macro	psstate	dest
6013179d37eSPaul Burton	.set	push
6023179d37eSPaul Burton	.set	noat
6033179d37eSPaul Burton	lw	$1, TI_CPU(gp)
6043179d37eSPaul Burton	sll	$1, $1, LONGLOG
60581a02e34SMarkos Chandras	PTR_LA	\dest, __per_cpu_offset
6063179d37eSPaul Burton	addu	$1, $1, \dest
6073179d37eSPaul Burton	lw	$1, 0($1)
60881a02e34SMarkos Chandras	PTR_LA	\dest, cps_cpu_state
6093179d37eSPaul Burton	addu	\dest, \dest, $1
6103179d37eSPaul Burton	.set	pop
6113179d37eSPaul Burton	.endm
6123179d37eSPaul Burton
6133179d37eSPaul BurtonLEAF(mips_cps_pm_save)
6143179d37eSPaul Burton	/* Save CPU state */
6153179d37eSPaul Burton	SUSPEND_SAVE_REGS
6163179d37eSPaul Burton	psstate	t1
6173179d37eSPaul Burton	SUSPEND_SAVE_STATIC
6183179d37eSPaul Burton	jr	v0
6193179d37eSPaul Burton	 nop
6203179d37eSPaul Burton	END(mips_cps_pm_save)
6213179d37eSPaul Burton
6223179d37eSPaul BurtonLEAF(mips_cps_pm_restore)
6233179d37eSPaul Burton	/* Restore CPU state */
6243179d37eSPaul Burton	psstate	t1
6253179d37eSPaul Burton	RESUME_RESTORE_STATIC
6263179d37eSPaul Burton	RESUME_RESTORE_REGS_RETURN
6273179d37eSPaul Burton	END(mips_cps_pm_restore)
6283179d37eSPaul Burton
6293179d37eSPaul Burton#endif /* CONFIG_MIPS_CPS_PM && CONFIG_CPU_PM */
630