xref: /aosp_15_r20/external/arm-trusted-firmware/plat/nxp/soc-ls1028a/aarch64/ls1028a.S (revision 54fd6939e177f8ff529b10183254802c76df6d08)
1*54fd6939SJiyong Park/*
2*54fd6939SJiyong Park * Copyright 2018-2021 NXP
3*54fd6939SJiyong Park *
4*54fd6939SJiyong Park * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park */
6*54fd6939SJiyong Park
7*54fd6939SJiyong Park	.section .text, "ax"
8*54fd6939SJiyong Park
9*54fd6939SJiyong Park#include <asm_macros.S>
10*54fd6939SJiyong Park
11*54fd6939SJiyong Park#include <lib/psci/psci.h>
12*54fd6939SJiyong Park#include <nxp_timer.h>
13*54fd6939SJiyong Park#include <plat_gic.h>
14*54fd6939SJiyong Park#include <pmu.h>
15*54fd6939SJiyong Park
16*54fd6939SJiyong Park#include <bl31_data.h>
17*54fd6939SJiyong Park#include <plat_psci.h>
18*54fd6939SJiyong Park#include <platform_def.h>
19*54fd6939SJiyong Park
20*54fd6939SJiyong Park	.global soc_init_lowlevel
21*54fd6939SJiyong Park	.global soc_init_percpu
22*54fd6939SJiyong Park	.global _set_platform_security
23*54fd6939SJiyong Park	.global _soc_set_start_addr
24*54fd6939SJiyong Park
25*54fd6939SJiyong Park	.global _soc_core_release
26*54fd6939SJiyong Park	.global _soc_ck_disabled
27*54fd6939SJiyong Park	.global _soc_core_restart
28*54fd6939SJiyong Park	.global _soc_core_prep_off
29*54fd6939SJiyong Park	.global _soc_core_entr_off
30*54fd6939SJiyong Park	.global _soc_core_exit_off
31*54fd6939SJiyong Park	.global _soc_sys_reset
32*54fd6939SJiyong Park	.global _soc_sys_off
33*54fd6939SJiyong Park	.global _soc_core_prep_stdby
34*54fd6939SJiyong Park	.global _soc_core_entr_stdby
35*54fd6939SJiyong Park	.global _soc_core_exit_stdby
36*54fd6939SJiyong Park	.global _soc_core_prep_pwrdn
37*54fd6939SJiyong Park	.global _soc_core_entr_pwrdn
38*54fd6939SJiyong Park	.global _soc_core_exit_pwrdn
39*54fd6939SJiyong Park	.global _soc_clstr_prep_stdby
40*54fd6939SJiyong Park	.global _soc_clstr_exit_stdby
41*54fd6939SJiyong Park	.global _soc_clstr_prep_pwrdn
42*54fd6939SJiyong Park	.global _soc_clstr_exit_pwrdn
43*54fd6939SJiyong Park	.global _soc_sys_prep_stdby
44*54fd6939SJiyong Park	.global _soc_sys_exit_stdby
45*54fd6939SJiyong Park	.global _soc_sys_prep_pwrdn
46*54fd6939SJiyong Park	.global _soc_sys_pwrdn_wfi
47*54fd6939SJiyong Park	.global _soc_sys_exit_pwrdn
48*54fd6939SJiyong Park
49*54fd6939SJiyong Park	.equ TZPCDECPROT_0_SET_BASE, 0x02200804
50*54fd6939SJiyong Park	.equ TZPCDECPROT_1_SET_BASE, 0x02200810
51*54fd6939SJiyong Park	.equ TZPCDECPROT_2_SET_BASE, 0x0220081C
52*54fd6939SJiyong Park
53*54fd6939SJiyong Park	.equ TZASC_REGION_ATTRIBUTES_0_0, 0x01100110
54*54fd6939SJiyong Park
55*54fd6939SJiyong Park/*
56*54fd6939SJiyong Park * This function initialize the soc.
57*54fd6939SJiyong Park * in: void
58*54fd6939SJiyong Park * out: void
59*54fd6939SJiyong Park * uses x0 - x11
60*54fd6939SJiyong Park */
61*54fd6939SJiyong Parkfunc soc_init_lowlevel
62*54fd6939SJiyong Park	/*
63*54fd6939SJiyong Park	 * Called from C, so save the non-volatile regs
64*54fd6939SJiyong Park	 * save these as pairs of registers to maintain the
65*54fd6939SJiyong Park	 * required 16-byte alignment on the stack
66*54fd6939SJiyong Park	 */
67*54fd6939SJiyong Park	stp	x4,  x5,  [sp, #-16]!
68*54fd6939SJiyong Park	stp	x6,  x7,  [sp, #-16]!
69*54fd6939SJiyong Park	stp	x8,  x9,  [sp, #-16]!
70*54fd6939SJiyong Park	stp	x10, x11, [sp, #-16]!
71*54fd6939SJiyong Park	stp	x12, x13, [sp, #-16]!
72*54fd6939SJiyong Park	stp	x18, x30, [sp, #-16]!
73*54fd6939SJiyong Park
74*54fd6939SJiyong Park	/*
75*54fd6939SJiyong Park	 * Make sure the personality has been established by releasing cores
76*54fd6939SJiyong Park	 * that are marked "to-be-disabled" from reset
77*54fd6939SJiyong Park	 */
78*54fd6939SJiyong Park	bl	release_disabled  /* 0-8 */
79*54fd6939SJiyong Park
80*54fd6939SJiyong Park	/* Set SCRATCHRW7 to 0x0 */
81*54fd6939SJiyong Park	ldr	x0, =DCFG_SCRATCHRW7_OFFSET
82*54fd6939SJiyong Park	mov	x1, xzr
83*54fd6939SJiyong Park	bl	_write_reg_dcfg
84*54fd6939SJiyong Park
85*54fd6939SJiyong Park	/* Restore the aarch32/64 non-volatile registers */
86*54fd6939SJiyong Park	ldp	x18, x30, [sp], #16
87*54fd6939SJiyong Park	ldp	x12, x13, [sp], #16
88*54fd6939SJiyong Park	ldp	x10, x11, [sp], #16
89*54fd6939SJiyong Park	ldp	x8,  x9,  [sp], #16
90*54fd6939SJiyong Park	ldp	x6,  x7,  [sp], #16
91*54fd6939SJiyong Park	ldp	x4,  x5,  [sp], #16
92*54fd6939SJiyong Park	ret
93*54fd6939SJiyong Parkendfunc soc_init_lowlevel
94*54fd6939SJiyong Park
95*54fd6939SJiyong Park/*
96*54fd6939SJiyong Park * void soc_init_percpu(void)
97*54fd6939SJiyong Park *
98*54fd6939SJiyong Park * This function performs any soc-specific initialization that is needed on
99*54fd6939SJiyong Park * a per-core basis
100*54fd6939SJiyong Park * in:  none
101*54fd6939SJiyong Park * out: none
102*54fd6939SJiyong Park * uses x0 - x3
103*54fd6939SJiyong Park */
104*54fd6939SJiyong Parkfunc soc_init_percpu
105*54fd6939SJiyong Park	stp	x4,  x30,  [sp, #-16]!
106*54fd6939SJiyong Park
107*54fd6939SJiyong Park	bl	plat_my_core_mask
108*54fd6939SJiyong Park	mov	x2, x0
109*54fd6939SJiyong Park
110*54fd6939SJiyong Park	/* x2 = core mask */
111*54fd6939SJiyong Park
112*54fd6939SJiyong Park	/* see if this core is marked for prefetch disable */
113*54fd6939SJiyong Park	mov	x0, #PREFETCH_DIS_OFFSET
114*54fd6939SJiyong Park	bl	_get_global_data  /* 0-1 */
115*54fd6939SJiyong Park	tst	x0, x2
116*54fd6939SJiyong Park	b.eq	1f
117*54fd6939SJiyong Park	bl	_disable_ldstr_pfetch_A72  /* 0 */
118*54fd6939SJiyong Park1:
119*54fd6939SJiyong Park	mov	x0, #NXP_PMU_ADDR
120*54fd6939SJiyong Park	bl	enable_timer_base_to_cluster
121*54fd6939SJiyong Park
122*54fd6939SJiyong Park	ldp	x4,  x30,  [sp], #16
123*54fd6939SJiyong Park	ret
124*54fd6939SJiyong Parkendfunc soc_init_percpu
125*54fd6939SJiyong Park
126*54fd6939SJiyong Park/*
127*54fd6939SJiyong Park * This function determines if a core is disabled via COREDISABLEDSR
128*54fd6939SJiyong Park * in:  w0  = core_mask_lsb
129*54fd6939SJiyong Park * out: w0  = 0, core not disabled
130*54fd6939SJiyong Park *      w0 != 0, core disabled
131*54fd6939SJiyong Park * uses x0, x1
132*54fd6939SJiyong Park */
133*54fd6939SJiyong Parkfunc _soc_ck_disabled
134*54fd6939SJiyong Park	/* get base addr of dcfg block */
135*54fd6939SJiyong Park	ldr	x1, =NXP_DCFG_ADDR
136*54fd6939SJiyong Park
137*54fd6939SJiyong Park	/* read COREDISABLEDSR */
138*54fd6939SJiyong Park	ldr	w1, [x1, #DCFG_COREDISABLEDSR_OFFSET]
139*54fd6939SJiyong Park
140*54fd6939SJiyong Park	/* test core bit */
141*54fd6939SJiyong Park	and	w0, w1, w0
142*54fd6939SJiyong Park
143*54fd6939SJiyong Park	ret
144*54fd6939SJiyong Parkendfunc _soc_ck_disabled
145*54fd6939SJiyong Park
146*54fd6939SJiyong Park/*
147*54fd6939SJiyong Park * This function sets the security mechanisms in the SoC to implement the
148*54fd6939SJiyong Park * Platform Security Policy
149*54fd6939SJiyong Park */
150*54fd6939SJiyong Parkfunc _set_platform_security
151*54fd6939SJiyong Park	mov	x3, x30
152*54fd6939SJiyong Park
153*54fd6939SJiyong Park#if (!SUPPRESS_TZC)
154*54fd6939SJiyong Park	/* initialize the tzpc */
155*54fd6939SJiyong Park	bl	init_tzpc
156*54fd6939SJiyong Park#endif
157*54fd6939SJiyong Park
158*54fd6939SJiyong Park#if (!SUPPRESS_SEC)
159*54fd6939SJiyong Park	/* initialize secmon */
160*54fd6939SJiyong Park	bl	initSecMon
161*54fd6939SJiyong Park#endif
162*54fd6939SJiyong Park
163*54fd6939SJiyong Park	mov	x30, x3
164*54fd6939SJiyong Park	ret
165*54fd6939SJiyong Parkendfunc _set_platform_security
166*54fd6939SJiyong Park
167*54fd6939SJiyong Park/*
168*54fd6939SJiyong Park * Part of CPU_ON
169*54fd6939SJiyong Park *
170*54fd6939SJiyong Park * This function releases a secondary core from reset
171*54fd6939SJiyong Park * in:   x0 = core_mask_lsb
172*54fd6939SJiyong Park * out:  none
173*54fd6939SJiyong Park * uses: x0 - x3
174*54fd6939SJiyong Park */
175*54fd6939SJiyong Park_soc_core_release:
176*54fd6939SJiyong Park	mov	x3, x30
177*54fd6939SJiyong Park
178*54fd6939SJiyong Park	/*
179*54fd6939SJiyong Park	 * Write to CORE_HOLD to tell the bootrom that we want this core
180*54fd6939SJiyong Park	 * to run
181*54fd6939SJiyong Park	 */
182*54fd6939SJiyong Park	ldr	x1, =NXP_SEC_REGFILE_ADDR
183*54fd6939SJiyong Park	str	w0, [x1, #CORE_HOLD_OFFSET]
184*54fd6939SJiyong Park
185*54fd6939SJiyong Park	/* Read-modify-write BRRL to release core */
186*54fd6939SJiyong Park	mov	x1, #NXP_RESET_ADDR
187*54fd6939SJiyong Park	ldr	w2, [x1, #BRR_OFFSET]
188*54fd6939SJiyong Park	orr	w2, w2, w0
189*54fd6939SJiyong Park	str	w2, [x1, #BRR_OFFSET]
190*54fd6939SJiyong Park	dsb	sy
191*54fd6939SJiyong Park	isb
192*54fd6939SJiyong Park
193*54fd6939SJiyong Park	/* Send event */
194*54fd6939SJiyong Park	sev
195*54fd6939SJiyong Park	isb
196*54fd6939SJiyong Park
197*54fd6939SJiyong Park	mov	x30, x3
198*54fd6939SJiyong Park	ret
199*54fd6939SJiyong Park
200*54fd6939SJiyong Park/*
201*54fd6939SJiyong Park * This function writes a 64-bit address to bootlocptrh/l
202*54fd6939SJiyong Park * in:  x0, 64-bit address to write to BOOTLOCPTRL/H
203*54fd6939SJiyong Park * uses x0, x1, x2
204*54fd6939SJiyong Park */
205*54fd6939SJiyong Parkfunc _soc_set_start_addr
206*54fd6939SJiyong Park	/* Get the 64-bit base address of the dcfg block */
207*54fd6939SJiyong Park	ldr	x2, =NXP_DCFG_ADDR
208*54fd6939SJiyong Park
209*54fd6939SJiyong Park	/* Write the 32-bit BOOTLOCPTRL register */
210*54fd6939SJiyong Park	mov	x1, x0
211*54fd6939SJiyong Park	str	w1, [x2, #DCFG_BOOTLOCPTRL_OFFSET]
212*54fd6939SJiyong Park
213*54fd6939SJiyong Park	/* Write the 32-bit BOOTLOCPTRH register */
214*54fd6939SJiyong Park	lsr	x1, x0, #32
215*54fd6939SJiyong Park	str	w1, [x2, #DCFG_BOOTLOCPTRH_OFFSET]
216*54fd6939SJiyong Park	ret
217*54fd6939SJiyong Parkendfunc _soc_set_start_addr
218*54fd6939SJiyong Park
219*54fd6939SJiyong Park/*
220*54fd6939SJiyong Park * Part of CPU_ON
221*54fd6939SJiyong Park *
222*54fd6939SJiyong Park * This function restarts a core shutdown via _soc_core_entr_off
223*54fd6939SJiyong Park * in:  x0 = core mask lsb (of the target cpu)
224*54fd6939SJiyong Park * out: x0 == 0, on success
225*54fd6939SJiyong Park *      x0 != 0, on failure
226*54fd6939SJiyong Park * uses x0 - x6
227*54fd6939SJiyong Park */
228*54fd6939SJiyong Park_soc_core_restart:
229*54fd6939SJiyong Park	mov	x6, x30
230*54fd6939SJiyong Park	mov	x4, x0
231*54fd6939SJiyong Park
232*54fd6939SJiyong Park	/* pgm GICD_CTLR - enable secure grp0  */
233*54fd6939SJiyong Park	mov	x5, #NXP_GICD_ADDR
234*54fd6939SJiyong Park	ldr	w2, [x5, #GICD_CTLR_OFFSET]
235*54fd6939SJiyong Park	orr	w2, w2, #GICD_CTLR_EN_GRP_0
236*54fd6939SJiyong Park	str	w2, [x5, #GICD_CTLR_OFFSET]
237*54fd6939SJiyong Park	dsb	sy
238*54fd6939SJiyong Park	isb
239*54fd6939SJiyong Park
240*54fd6939SJiyong Park	/* Poll on RWP til write completes */
241*54fd6939SJiyong Park4:
242*54fd6939SJiyong Park	ldr	w2, [x5, #GICD_CTLR_OFFSET]
243*54fd6939SJiyong Park	tst	w2, #GICD_CTLR_RWP
244*54fd6939SJiyong Park	b.ne	4b
245*54fd6939SJiyong Park
246*54fd6939SJiyong Park	/*
247*54fd6939SJiyong Park	 * x4 = core mask lsb
248*54fd6939SJiyong Park	 * x5 = gicd base addr
249*54fd6939SJiyong Park	 */
250*54fd6939SJiyong Park
251*54fd6939SJiyong Park	mov	x0, x4
252*54fd6939SJiyong Park	bl	get_mpidr_value
253*54fd6939SJiyong Park
254*54fd6939SJiyong Park	/* Generate target list bit */
255*54fd6939SJiyong Park	and	x1, x0, #MPIDR_AFFINITY0_MASK
256*54fd6939SJiyong Park	mov	x2, #1
257*54fd6939SJiyong Park	lsl	x2, x2, x1
258*54fd6939SJiyong Park
259*54fd6939SJiyong Park	/* Get the affinity1 field */
260*54fd6939SJiyong Park	and	x1, x0, #MPIDR_AFFINITY1_MASK
261*54fd6939SJiyong Park	lsl	x1, x1, #8
262*54fd6939SJiyong Park	orr	x2, x2, x1
263*54fd6939SJiyong Park
264*54fd6939SJiyong Park	/* Insert the INTID for SGI15 */
265*54fd6939SJiyong Park	orr	x2, x2, #ICC_SGI0R_EL1_INTID
266*54fd6939SJiyong Park
267*54fd6939SJiyong Park	/* Fire the SGI */
268*54fd6939SJiyong Park	msr	ICC_SGI0R_EL1, x2
269*54fd6939SJiyong Park	dsb	sy
270*54fd6939SJiyong Park	isb
271*54fd6939SJiyong Park
272*54fd6939SJiyong Park	/* Load '0' on success */
273*54fd6939SJiyong Park	mov	x0, xzr
274*54fd6939SJiyong Park
275*54fd6939SJiyong Park	mov	x30, x6
276*54fd6939SJiyong Park	ret
277*54fd6939SJiyong Park
278*54fd6939SJiyong Park/*
279*54fd6939SJiyong Park * Part of CPU_OFF
280*54fd6939SJiyong Park *
281*54fd6939SJiyong Park * This function programs SoC & GIC registers in preparation for shutting down
282*54fd6939SJiyong Park * the core
283*54fd6939SJiyong Park * in:  x0 = core mask lsb
284*54fd6939SJiyong Park * out: none
285*54fd6939SJiyong Park * uses x0 - x7
286*54fd6939SJiyong Park */
287*54fd6939SJiyong Park_soc_core_prep_off:
288*54fd6939SJiyong Park	mov	x8, x30
289*54fd6939SJiyong Park	mov	x7, x0
290*54fd6939SJiyong Park
291*54fd6939SJiyong Park	/* x7 = core mask lsb */
292*54fd6939SJiyong Park
293*54fd6939SJiyong Park	mrs	x1, CPUECTLR_EL1
294*54fd6939SJiyong Park
295*54fd6939SJiyong Park	/* Set smp and disable L2 snoops in cpuectlr */
296*54fd6939SJiyong Park	orr	x1, x1, #CPUECTLR_SMPEN_EN
297*54fd6939SJiyong Park	orr	x1, x1, #CPUECTLR_DISABLE_TWALK_PREFETCH
298*54fd6939SJiyong Park	bic	x1, x1, #CPUECTLR_INS_PREFETCH_MASK
299*54fd6939SJiyong Park	bic	x1, x1, #CPUECTLR_DAT_PREFETCH_MASK
300*54fd6939SJiyong Park
301*54fd6939SJiyong Park	/* Set retention control in cpuectlr */
302*54fd6939SJiyong Park	bic	x1, x1, #CPUECTLR_TIMER_MASK
303*54fd6939SJiyong Park	orr	x1, x1, #CPUECTLR_TIMER_2TICKS
304*54fd6939SJiyong Park	msr	CPUECTLR_EL1, x1
305*54fd6939SJiyong Park
306*54fd6939SJiyong Park	/* Get redistributor rd base addr for this core */
307*54fd6939SJiyong Park	mov	x0, x7
308*54fd6939SJiyong Park	bl	get_gic_rd_base
309*54fd6939SJiyong Park	mov	x6, x0
310*54fd6939SJiyong Park
311*54fd6939SJiyong Park	/* Get redistributor sgi base addr for this core */
312*54fd6939SJiyong Park	mov	x0, x7
313*54fd6939SJiyong Park	bl	get_gic_sgi_base
314*54fd6939SJiyong Park	mov	x5, x0
315*54fd6939SJiyong Park
316*54fd6939SJiyong Park	/*
317*54fd6939SJiyong Park	 * x5 = gicr sgi base addr
318*54fd6939SJiyong Park	 * x6 = gicr rd  base addr
319*54fd6939SJiyong Park	 * x7 = core mask lsb
320*54fd6939SJiyong Park	 */
321*54fd6939SJiyong Park
322*54fd6939SJiyong Park	/* Disable SGI 15 at redistributor - GICR_ICENABLER0 */
323*54fd6939SJiyong Park	mov	w3, #GICR_ICENABLER0_SGI15
324*54fd6939SJiyong Park	str	w3, [x5, #GICR_ICENABLER0_OFFSET]
325*54fd6939SJiyong Park2:
326*54fd6939SJiyong Park	/* Poll on rwp bit in GICR_CTLR */
327*54fd6939SJiyong Park	ldr	w4, [x6, #GICR_CTLR_OFFSET]
328*54fd6939SJiyong Park	tst	w4, #GICR_CTLR_RWP
329*54fd6939SJiyong Park	b.ne	2b
330*54fd6939SJiyong Park
331*54fd6939SJiyong Park	/* Disable GRP1 interrupts at cpu interface */
332*54fd6939SJiyong Park	msr	ICC_IGRPEN1_EL3, xzr
333*54fd6939SJiyong Park
334*54fd6939SJiyong Park	/* Disable GRP0 ints at cpu interface */
335*54fd6939SJiyong Park	msr	ICC_IGRPEN0_EL1, xzr
336*54fd6939SJiyong Park
337*54fd6939SJiyong Park	/* Program the redistributor - poll on GICR_CTLR.RWP as needed */
338*54fd6939SJiyong Park
339*54fd6939SJiyong Park	/* Define SGI 15 as Grp0 - GICR_IGROUPR0 */
340*54fd6939SJiyong Park	ldr	w4, [x5, #GICR_IGROUPR0_OFFSET]
341*54fd6939SJiyong Park	bic	w4, w4, #GICR_IGROUPR0_SGI15
342*54fd6939SJiyong Park	str	w4, [x5, #GICR_IGROUPR0_OFFSET]
343*54fd6939SJiyong Park
344*54fd6939SJiyong Park	/* Define SGI 15 as Grp0 - GICR_IGRPMODR0 */
345*54fd6939SJiyong Park	ldr	w3, [x5, #GICR_IGRPMODR0_OFFSET]
346*54fd6939SJiyong Park	bic	w3, w3, #GICR_IGRPMODR0_SGI15
347*54fd6939SJiyong Park	str	w3, [x5, #GICR_IGRPMODR0_OFFSET]
348*54fd6939SJiyong Park
349*54fd6939SJiyong Park	/* Set priority of SGI 15 to highest (0x0) - GICR_IPRIORITYR3 */
350*54fd6939SJiyong Park	ldr	w4, [x5, #GICR_IPRIORITYR3_OFFSET]
351*54fd6939SJiyong Park	bic	w4, w4, #GICR_IPRIORITYR3_SGI15_MASK
352*54fd6939SJiyong Park	str	w4, [x5, #GICR_IPRIORITYR3_OFFSET]
353*54fd6939SJiyong Park
354*54fd6939SJiyong Park	/* Enable SGI 15 at redistributor - GICR_ISENABLER0 */
355*54fd6939SJiyong Park	mov	w3, #GICR_ISENABLER0_SGI15
356*54fd6939SJiyong Park	str	w3, [x5, #GICR_ISENABLER0_OFFSET]
357*54fd6939SJiyong Park	dsb	sy
358*54fd6939SJiyong Park	isb
359*54fd6939SJiyong Park3:
360*54fd6939SJiyong Park	/* Poll on rwp bit in GICR_CTLR */
361*54fd6939SJiyong Park	ldr	w4, [x6, #GICR_CTLR_OFFSET]
362*54fd6939SJiyong Park	tst	w4, #GICR_CTLR_RWP
363*54fd6939SJiyong Park	b.ne	3b
364*54fd6939SJiyong Park
365*54fd6939SJiyong Park	/* Quiesce the debug interfaces */
366*54fd6939SJiyong Park	mrs	x3, osdlr_el1
367*54fd6939SJiyong Park	orr	x3, x3, #OSDLR_EL1_DLK_LOCK
368*54fd6939SJiyong Park	msr	osdlr_el1, x3
369*54fd6939SJiyong Park	isb
370*54fd6939SJiyong Park
371*54fd6939SJiyong Park	/* Enable grp0 ints */
372*54fd6939SJiyong Park	mov	x3, #ICC_IGRPEN0_EL1_EN
373*54fd6939SJiyong Park	msr	ICC_IGRPEN0_EL1, x3
374*54fd6939SJiyong Park
375*54fd6939SJiyong Park	/*
376*54fd6939SJiyong Park	 * x5 = gicr sgi base addr
377*54fd6939SJiyong Park	 * x6 = gicr rd  base addr
378*54fd6939SJiyong Park	 * x7 = core mask lsb
379*54fd6939SJiyong Park	 */
380*54fd6939SJiyong Park
381*54fd6939SJiyong Park	/* Clear any pending interrupts */
382*54fd6939SJiyong Park	mvn	w1, wzr
383*54fd6939SJiyong Park	str	w1, [x5, #GICR_ICPENDR0_OFFSET]
384*54fd6939SJiyong Park
385*54fd6939SJiyong Park	/* Make sure system counter is enabled */
386*54fd6939SJiyong Park	ldr	x3, =NXP_TIMER_ADDR
387*54fd6939SJiyong Park	ldr	w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
388*54fd6939SJiyong Park	tst	w0, #SYS_COUNTER_CNTCR_EN
389*54fd6939SJiyong Park	b.ne	4f
390*54fd6939SJiyong Park	orr	w0, w0, #SYS_COUNTER_CNTCR_EN
391*54fd6939SJiyong Park	str	w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
392*54fd6939SJiyong Park4:
393*54fd6939SJiyong Park	/* Enable the core timer and mask timer interrupt */
394*54fd6939SJiyong Park	mov	x1, #CNTP_CTL_EL0_EN
395*54fd6939SJiyong Park	orr	x1, x1, #CNTP_CTL_EL0_IMASK
396*54fd6939SJiyong Park	msr	cntp_ctl_el0, x1
397*54fd6939SJiyong Park
398*54fd6939SJiyong Park	isb
399*54fd6939SJiyong Park	mov	x30, x8
400*54fd6939SJiyong Park	ret
401*54fd6939SJiyong Park
402*54fd6939SJiyong Park/*
403*54fd6939SJiyong Park * Part of CPU_OFF
404*54fd6939SJiyong Park *
405*54fd6939SJiyong Park * This function performs the final steps to shutdown the core
406*54fd6939SJiyong Park * in:  x0 = core mask lsb
407*54fd6939SJiyong Park * out: none
408*54fd6939SJiyong Park * uses x0 - x5
409*54fd6939SJiyong Park */
410*54fd6939SJiyong Park_soc_core_entr_off:
411*54fd6939SJiyong Park	mov	x5, x30
412*54fd6939SJiyong Park	mov	x4, x0
413*54fd6939SJiyong Park
414*54fd6939SJiyong Park	/* x4 = core mask */
415*54fd6939SJiyong Park1:
416*54fd6939SJiyong Park	/* Enter low-power state by executing wfi */
417*54fd6939SJiyong Park	wfi
418*54fd6939SJiyong Park
419*54fd6939SJiyong Park	/* See if SGI15 woke us up */
420*54fd6939SJiyong Park	mrs	x2, ICC_IAR0_EL1
421*54fd6939SJiyong Park	mov	x3, #ICC_IAR0_EL1_SGI15
422*54fd6939SJiyong Park	cmp	x2, x3
423*54fd6939SJiyong Park	b.ne	1b
424*54fd6939SJiyong Park
425*54fd6939SJiyong Park	/* Deactivate the int */
426*54fd6939SJiyong Park	msr	ICC_EOIR0_EL1, x2
427*54fd6939SJiyong Park
428*54fd6939SJiyong Park	/* x4 = core mask */
429*54fd6939SJiyong Park2:
430*54fd6939SJiyong Park	/* Check if core has been turned on */
431*54fd6939SJiyong Park	mov	x0, x4
432*54fd6939SJiyong Park	bl	_getCoreState
433*54fd6939SJiyong Park
434*54fd6939SJiyong Park	/* x0 = core state */
435*54fd6939SJiyong Park
436*54fd6939SJiyong Park	cmp	x0, #CORE_WAKEUP
437*54fd6939SJiyong Park	b.ne	1b
438*54fd6939SJiyong Park
439*54fd6939SJiyong Park	/* If we get here, then we have exited the wfi */
440*54fd6939SJiyong Park	mov	x30, x5
441*54fd6939SJiyong Park	ret
442*54fd6939SJiyong Park
443*54fd6939SJiyong Park/*
444*54fd6939SJiyong Park * Part of CPU_OFF
445*54fd6939SJiyong Park *
446*54fd6939SJiyong Park * This function starts the process of starting a core back up
447*54fd6939SJiyong Park * in:  x0 = core mask lsb
448*54fd6939SJiyong Park * out: none
449*54fd6939SJiyong Park * uses x0, x1, x2, x3, x4, x5, x6
450*54fd6939SJiyong Park */
451*54fd6939SJiyong Park_soc_core_exit_off:
452*54fd6939SJiyong Park	mov	x6, x30
453*54fd6939SJiyong Park	mov	x5, x0
454*54fd6939SJiyong Park
455*54fd6939SJiyong Park	/* Disable forwarding of GRP0 ints at cpu interface */
456*54fd6939SJiyong Park	msr	ICC_IGRPEN0_EL1, xzr
457*54fd6939SJiyong Park
458*54fd6939SJiyong Park	/* Get redistributor sgi base addr for this core */
459*54fd6939SJiyong Park	mov	x0, x5
460*54fd6939SJiyong Park	bl	get_gic_sgi_base
461*54fd6939SJiyong Park	mov	x4, x0
462*54fd6939SJiyong Park
463*54fd6939SJiyong Park	/* x4 = gicr sgi base addr */
464*54fd6939SJiyong Park	/* x5 = core mask */
465*54fd6939SJiyong Park
466*54fd6939SJiyong Park	/* Disable SGI 15 at redistributor - GICR_ICENABLER0 */
467*54fd6939SJiyong Park	mov	w1, #GICR_ICENABLER0_SGI15
468*54fd6939SJiyong Park	str	w1, [x4, #GICR_ICENABLER0_OFFSET]
469*54fd6939SJiyong Park
470*54fd6939SJiyong Park	/* Get redistributor rd base addr for this core */
471*54fd6939SJiyong Park	mov	x0, x5
472*54fd6939SJiyong Park	bl	get_gic_rd_base
473*54fd6939SJiyong Park	mov	x4, x0
474*54fd6939SJiyong Park
475*54fd6939SJiyong Park	/* x4 = gicr rd  base addr */
476*54fd6939SJiyong Park2:
477*54fd6939SJiyong Park	/* Poll on rwp bit in GICR_CTLR */
478*54fd6939SJiyong Park	ldr	w2, [x4, #GICR_CTLR_OFFSET]
479*54fd6939SJiyong Park	tst	w2, #GICR_CTLR_RWP
480*54fd6939SJiyong Park	b.ne	2b
481*54fd6939SJiyong Park
482*54fd6939SJiyong Park	/* x4 = gicr rd  base addr */
483*54fd6939SJiyong Park
484*54fd6939SJiyong Park	/* Unlock the debug interfaces */
485*54fd6939SJiyong Park	mrs	x3, osdlr_el1
486*54fd6939SJiyong Park	bic	x3, x3, #OSDLR_EL1_DLK_LOCK
487*54fd6939SJiyong Park	msr	osdlr_el1, x3
488*54fd6939SJiyong Park	isb
489*54fd6939SJiyong Park
490*54fd6939SJiyong Park	dsb	sy
491*54fd6939SJiyong Park	isb
492*54fd6939SJiyong Park	mov	x30, x6
493*54fd6939SJiyong Park	ret
494*54fd6939SJiyong Park
495*54fd6939SJiyong Park/*
496*54fd6939SJiyong Park * This function requests a reset of the entire SOC
497*54fd6939SJiyong Park * in:  none
498*54fd6939SJiyong Park * out: none
499*54fd6939SJiyong Park * uses: x0, x1, x2, x3, x4, x5, x6
500*54fd6939SJiyong Park */
501*54fd6939SJiyong Park_soc_sys_reset:
502*54fd6939SJiyong Park	mov	x3, x30
503*54fd6939SJiyong Park
504*54fd6939SJiyong Park	/* Make sure the mask is cleared in the reset request mask register */
505*54fd6939SJiyong Park	mov	x0, #RST_RSTRQMR1_OFFSET
506*54fd6939SJiyong Park	mov	w1, wzr
507*54fd6939SJiyong Park	bl	_write_reg_reset
508*54fd6939SJiyong Park
509*54fd6939SJiyong Park	/* Set the reset request */
510*54fd6939SJiyong Park	mov	x4, #RST_RSTCR_OFFSET
511*54fd6939SJiyong Park	mov	x0, x4
512*54fd6939SJiyong Park	mov	w1, #RSTCR_RESET_REQ
513*54fd6939SJiyong Park	bl	_write_reg_reset
514*54fd6939SJiyong Park
515*54fd6939SJiyong Park	/* x4 = RST_RSTCR_OFFSET */
516*54fd6939SJiyong Park
517*54fd6939SJiyong Park	/*
518*54fd6939SJiyong Park	 * Just in case this address range is mapped as cacheable,
519*54fd6939SJiyong Park	 * flush the write out of the dcaches
520*54fd6939SJiyong Park	 */
521*54fd6939SJiyong Park	mov	x2, #NXP_RESET_ADDR
522*54fd6939SJiyong Park	add	x2, x2, x4
523*54fd6939SJiyong Park	dc	cvac, x2
524*54fd6939SJiyong Park	dsb	st
525*54fd6939SJiyong Park	isb
526*54fd6939SJiyong Park
527*54fd6939SJiyong Park	/* This function does not return */
528*54fd6939SJiyong Park1:
529*54fd6939SJiyong Park	wfi
530*54fd6939SJiyong Park	b	1b
531*54fd6939SJiyong Park
532*54fd6939SJiyong Park/*
533*54fd6939SJiyong Park * Part of SYSTEM_OFF
534*54fd6939SJiyong Park *
535*54fd6939SJiyong Park * This function turns off the SoC clocks
536*54fd6939SJiyong Park * Note: this function is not intended to return, and the only allowable
537*54fd6939SJiyong Park *       recovery is POR
538*54fd6939SJiyong Park * in:  none
539*54fd6939SJiyong Park * out: none
540*54fd6939SJiyong Park * uses x0, x1, x2, x3
541*54fd6939SJiyong Park */
542*54fd6939SJiyong Park_soc_sys_off:
543*54fd6939SJiyong Park	/*
544*54fd6939SJiyong Park	 * Disable sec, spi and flexspi
545*54fd6939SJiyong Park	 * TBD - Check if eNETC needs to be disabled
546*54fd6939SJiyong Park	 */
547*54fd6939SJiyong Park	ldr	x2, =NXP_DCFG_ADDR
548*54fd6939SJiyong Park	ldr	x0, =DCFG_DEVDISR1_OFFSET
549*54fd6939SJiyong Park	ldr	w1, =DCFG_DEVDISR1_SEC
550*54fd6939SJiyong Park	str	w1, [x2, x0]
551*54fd6939SJiyong Park	ldr	x0, =DCFG_DEVDISR4_OFFSET
552*54fd6939SJiyong Park	ldr	w1, =DCFG_DEVDISR4_SPI_QSPI
553*54fd6939SJiyong Park	str	w1, [x2, x0]
554*54fd6939SJiyong Park
555*54fd6939SJiyong Park	/* Set TPMWAKEMR0 */
556*54fd6939SJiyong Park	ldr	x0, =TPMWAKEMR0_ADDR
557*54fd6939SJiyong Park	mov	w1, #0x1
558*54fd6939SJiyong Park	str	w1, [x0]
559*54fd6939SJiyong Park
560*54fd6939SJiyong Park	/* Disable icache, dcache, mmu @ EL1 */
561*54fd6939SJiyong Park	mov	x1, #SCTLR_I_C_M_MASK
562*54fd6939SJiyong Park	mrs	x0, sctlr_el1
563*54fd6939SJiyong Park	bic	x0, x0, x1
564*54fd6939SJiyong Park	msr	sctlr_el1, x0
565*54fd6939SJiyong Park
566*54fd6939SJiyong Park	/* Disable L2 prefetches */
567*54fd6939SJiyong Park	mrs	x0, CPUECTLR_EL1
568*54fd6939SJiyong Park	orr	x0, x0, #CPUECTLR_SMPEN_EN
569*54fd6939SJiyong Park	bic	x0, x0, #CPUECTLR_TIMER_MASK
570*54fd6939SJiyong Park	orr	x0, x0, #CPUECTLR_TIMER_2TICKS
571*54fd6939SJiyong Park	msr	CPUECTLR_EL1, x0
572*54fd6939SJiyong Park	dsb	sy
573*54fd6939SJiyong Park	isb
574*54fd6939SJiyong Park
575*54fd6939SJiyong Park	/* Disable CCI snoop domain */
576*54fd6939SJiyong Park	ldr	x0, =NXP_CCI_ADDR
577*54fd6939SJiyong Park	mov	w1, #0x1
578*54fd6939SJiyong Park	str	w1, [x0]
579*54fd6939SJiyong Park
580*54fd6939SJiyong Park	bl	get_pmu_idle_core_mask
581*54fd6939SJiyong Park
582*54fd6939SJiyong Park	/* x3 = pmu base addr */
583*54fd6939SJiyong Park	mov	x3, #NXP_PMU_ADDR
584*54fd6939SJiyong Park4:
585*54fd6939SJiyong Park	ldr	w1, [x3, #PMU_PCPW20SR_OFFSET]
586*54fd6939SJiyong Park	cmp	w1, w0
587*54fd6939SJiyong Park	b.ne	4b
588*54fd6939SJiyong Park
589*54fd6939SJiyong Park	bl	get_pmu_idle_cluster_mask
590*54fd6939SJiyong Park	mov	x3, #NXP_PMU_ADDR
591*54fd6939SJiyong Park	str	w0, [x3, #PMU_CLAINACTSETR_OFFSET]
592*54fd6939SJiyong Park
593*54fd6939SJiyong Park	bl	get_pmu_idle_core_mask
594*54fd6939SJiyong Park	mov	x3, #NXP_PMU_ADDR
595*54fd6939SJiyong Park1:
596*54fd6939SJiyong Park	ldr	w1, [x3, #PMU_PCPW20SR_OFFSET]
597*54fd6939SJiyong Park	cmp	w1, w0
598*54fd6939SJiyong Park	b.ne	1b
599*54fd6939SJiyong Park
600*54fd6939SJiyong Park	bl	get_pmu_flush_cluster_mask
601*54fd6939SJiyong Park	mov	x3, #NXP_PMU_ADDR
602*54fd6939SJiyong Park	str	w0, [x3, #PMU_CLL2FLUSHSETR_OFFSET]
603*54fd6939SJiyong Park2:
604*54fd6939SJiyong Park	ldr	w1, [x3, #PMU_CLL2FLUSHSR_OFFSET]
605*54fd6939SJiyong Park	cmp	w1, w0
606*54fd6939SJiyong Park	b.ne	2b
607*54fd6939SJiyong Park
608*54fd6939SJiyong Park	str	w0, [x3, #PMU_CLSL2FLUSHCLRR_OFFSET]
609*54fd6939SJiyong Park
610*54fd6939SJiyong Park	str	w0, [x3, #PMU_CLSINACTSETR_OFFSET]
611*54fd6939SJiyong Park
612*54fd6939SJiyong Park	mov	x2, #DAIF_SET_MASK
613*54fd6939SJiyong Park	mrs	x1, spsr_el1
614*54fd6939SJiyong Park	orr	x1, x1, x2
615*54fd6939SJiyong Park	msr	spsr_el1, x1
616*54fd6939SJiyong Park
617*54fd6939SJiyong Park	mrs	x1, spsr_el2
618*54fd6939SJiyong Park	orr	x1, x1, x2
619*54fd6939SJiyong Park	msr	spsr_el2, x1
620*54fd6939SJiyong Park
621*54fd6939SJiyong Park	/* Force the debug interface to be quiescent */
622*54fd6939SJiyong Park	mrs	x0, osdlr_el1
623*54fd6939SJiyong Park	orr	x0, x0, #0x1
624*54fd6939SJiyong Park	msr	osdlr_el1, x0
625*54fd6939SJiyong Park
626*54fd6939SJiyong Park	/* Invalidate all TLB entries at all 3 exception levels */
627*54fd6939SJiyong Park	tlbi	alle1
628*54fd6939SJiyong Park	tlbi	alle2
629*54fd6939SJiyong Park	tlbi	alle3
630*54fd6939SJiyong Park
631*54fd6939SJiyong Park	/* x3 = pmu base addr */
632*54fd6939SJiyong Park
633*54fd6939SJiyong Park	/* Request lpm20 */
634*54fd6939SJiyong Park	ldr	x0, =PMU_POWMGTCSR_OFFSET
635*54fd6939SJiyong Park	ldr	w1, =PMU_POWMGTCSR_VAL
636*54fd6939SJiyong Park	str	w1, [x3, x0]
637*54fd6939SJiyong Park	isb
638*54fd6939SJiyong Park	dsb	sy
639*54fd6939SJiyong Park5:
640*54fd6939SJiyong Park	wfe
641*54fd6939SJiyong Park	b.eq	5b
642*54fd6939SJiyong Park
643*54fd6939SJiyong Park/*
644*54fd6939SJiyong Park * Part of CPU_SUSPEND
645*54fd6939SJiyong Park *
646*54fd6939SJiyong Park * This function performs SoC-specific programming prior to standby
647*54fd6939SJiyong Park * in:  x0 = core mask lsb
648*54fd6939SJiyong Park * out: none
649*54fd6939SJiyong Park * uses x0, x1
650*54fd6939SJiyong Park */
651*54fd6939SJiyong Park_soc_core_prep_stdby:
652*54fd6939SJiyong Park	/* Clear CPUECTLR_EL1[2:0] */
653*54fd6939SJiyong Park	mrs	x1, CPUECTLR_EL1
654*54fd6939SJiyong Park	bic	x1, x1, #CPUECTLR_TIMER_MASK
655*54fd6939SJiyong Park	msr	CPUECTLR_EL1, x1
656*54fd6939SJiyong Park
657*54fd6939SJiyong Park	ret
658*54fd6939SJiyong Park
659*54fd6939SJiyong Park/*
660*54fd6939SJiyong Park * Part of CPU_SUSPEND
661*54fd6939SJiyong Park *
662*54fd6939SJiyong Park * This function puts the calling core into standby state
663*54fd6939SJiyong Park * in:  x0 = core mask lsb
664*54fd6939SJiyong Park * out: none
665*54fd6939SJiyong Park * uses x0
666*54fd6939SJiyong Park */
667*54fd6939SJiyong Park_soc_core_entr_stdby:
668*54fd6939SJiyong Park	/* X0 = core mask lsb */
669*54fd6939SJiyong Park	dsb	sy
670*54fd6939SJiyong Park	isb
671*54fd6939SJiyong Park	wfi
672*54fd6939SJiyong Park
673*54fd6939SJiyong Park	ret
674*54fd6939SJiyong Park
675*54fd6939SJiyong Park/*
676*54fd6939SJiyong Park * Part of CPU_SUSPEND
677*54fd6939SJiyong Park *
678*54fd6939SJiyong Park * This function performs any SoC-specific cleanup after standby state
679*54fd6939SJiyong Park * in:  x0 = core mask lsb
680*54fd6939SJiyong Park * out: none
681*54fd6939SJiyong Park * uses none
682*54fd6939SJiyong Park */
683*54fd6939SJiyong Park_soc_core_exit_stdby:
684*54fd6939SJiyong Park	ret
685*54fd6939SJiyong Park
686*54fd6939SJiyong Park/*
687*54fd6939SJiyong Park * Part of CPU_SUSPEND
688*54fd6939SJiyong Park *
689*54fd6939SJiyong Park * This function performs SoC-specific programming prior to power-down
690*54fd6939SJiyong Park * in:  x0 = core mask lsb
691*54fd6939SJiyong Park * out: none
692*54fd6939SJiyong Park * uses x0, x1, x2
693*54fd6939SJiyong Park */
694*54fd6939SJiyong Park_soc_core_prep_pwrdn:
695*54fd6939SJiyong Park	/* Make sure system counter is enabled */
696*54fd6939SJiyong Park	ldr	x2, =NXP_TIMER_ADDR
697*54fd6939SJiyong Park	ldr	w0, [x2, #SYS_COUNTER_CNTCR_OFFSET]
698*54fd6939SJiyong Park	tst	w0, #SYS_COUNTER_CNTCR_EN
699*54fd6939SJiyong Park	b.ne	1f
700*54fd6939SJiyong Park	orr	w0, w0, #SYS_COUNTER_CNTCR_EN
701*54fd6939SJiyong Park	str	w0, [x2, #SYS_COUNTER_CNTCR_OFFSET]
702*54fd6939SJiyong Park1:
703*54fd6939SJiyong Park	/*
704*54fd6939SJiyong Park	 * Enable dynamic retention control (CPUECTLR[2:0])
705*54fd6939SJiyong Park	 * Set the SMPEN bit (CPUECTLR[6])
706*54fd6939SJiyong Park	 */
707*54fd6939SJiyong Park	mrs	x1, CPUECTLR_EL1
708*54fd6939SJiyong Park	bic	x1, x1, #CPUECTLR_RET_MASK
709*54fd6939SJiyong Park	orr	x1, x1, #CPUECTLR_TIMER_2TICKS
710*54fd6939SJiyong Park	orr	x1, x1, #CPUECTLR_SMPEN_EN
711*54fd6939SJiyong Park	msr	CPUECTLR_EL1, x1
712*54fd6939SJiyong Park
713*54fd6939SJiyong Park	isb
714*54fd6939SJiyong Park	ret
715*54fd6939SJiyong Park
716*54fd6939SJiyong Park/*
717*54fd6939SJiyong Park * Part of CPU_SUSPEND
718*54fd6939SJiyong Park *
719*54fd6939SJiyong Park * This function puts the calling core into a power-down state
720*54fd6939SJiyong Park * in:  x0 = core mask lsb
721*54fd6939SJiyong Park * out: none
722*54fd6939SJiyong Park * uses x0
723*54fd6939SJiyong Park */
724*54fd6939SJiyong Park_soc_core_entr_pwrdn:
725*54fd6939SJiyong Park	/* X0 = core mask lsb */
726*54fd6939SJiyong Park	dsb	sy
727*54fd6939SJiyong Park	isb
728*54fd6939SJiyong Park	wfi
729*54fd6939SJiyong Park
730*54fd6939SJiyong Park	ret
731*54fd6939SJiyong Park
732*54fd6939SJiyong Park/*
733*54fd6939SJiyong Park * Part of CPU_SUSPEND
734*54fd6939SJiyong Park *
735*54fd6939SJiyong Park * This function performs any SoC-specific cleanup after power-down state
736*54fd6939SJiyong Park * in:  x0 = core mask lsb
737*54fd6939SJiyong Park * out: none
738*54fd6939SJiyong Park * uses none
739*54fd6939SJiyong Park */
740*54fd6939SJiyong Park_soc_core_exit_pwrdn:
741*54fd6939SJiyong Park	ret
742*54fd6939SJiyong Park
743*54fd6939SJiyong Park/*
744*54fd6939SJiyong Park * Part of CPU_SUSPEND
745*54fd6939SJiyong Park *
746*54fd6939SJiyong Park * This function performs SoC-specific programming prior to standby
747*54fd6939SJiyong Park * in:  x0 = core mask lsb
748*54fd6939SJiyong Park * out: none
749*54fd6939SJiyong Park * uses x0, x1
750*54fd6939SJiyong Park */
751*54fd6939SJiyong Park_soc_clstr_prep_stdby:
752*54fd6939SJiyong Park	/* Clear CPUECTLR_EL1[2:0] */
753*54fd6939SJiyong Park	mrs	x1, CPUECTLR_EL1
754*54fd6939SJiyong Park	bic	x1, x1, #CPUECTLR_TIMER_MASK
755*54fd6939SJiyong Park	msr	CPUECTLR_EL1, x1
756*54fd6939SJiyong Park
757*54fd6939SJiyong Park	ret
758*54fd6939SJiyong Park
759*54fd6939SJiyong Park/*
760*54fd6939SJiyong Park * Part of CPU_SUSPEND
761*54fd6939SJiyong Park *
762*54fd6939SJiyong Park * This function performs any SoC-specific cleanup after standby state
763*54fd6939SJiyong Park * in:  x0 = core mask lsb
764*54fd6939SJiyong Park * out: none
765*54fd6939SJiyong Park * uses none
766*54fd6939SJiyong Park */
767*54fd6939SJiyong Park_soc_clstr_exit_stdby:
768*54fd6939SJiyong Park	ret
769*54fd6939SJiyong Park
770*54fd6939SJiyong Park/*
771*54fd6939SJiyong Park * Part of CPU_SUSPEND
772*54fd6939SJiyong Park *
773*54fd6939SJiyong Park * This function performs SoC-specific programming prior to power-down
774*54fd6939SJiyong Park * in:  x0 = core mask lsb
775*54fd6939SJiyong Park * out: none
776*54fd6939SJiyong Park * uses x0, x1, x2
777*54fd6939SJiyong Park */
778*54fd6939SJiyong Park_soc_clstr_prep_pwrdn:
779*54fd6939SJiyong Park	/* Make sure system counter is enabled */
780*54fd6939SJiyong Park	ldr	x2, =NXP_TIMER_ADDR
781*54fd6939SJiyong Park	ldr	w0, [x2, #SYS_COUNTER_CNTCR_OFFSET]
782*54fd6939SJiyong Park	tst	w0, #SYS_COUNTER_CNTCR_EN
783*54fd6939SJiyong Park	b.ne	1f
784*54fd6939SJiyong Park	orr	w0, w0, #SYS_COUNTER_CNTCR_EN
785*54fd6939SJiyong Park	str	w0, [x2, #SYS_COUNTER_CNTCR_OFFSET]
786*54fd6939SJiyong Park1:
787*54fd6939SJiyong Park	/*
788*54fd6939SJiyong Park	 * Enable dynamic retention control (CPUECTLR[2:0])
789*54fd6939SJiyong Park	 * Set the SMPEN bit (CPUECTLR[6])
790*54fd6939SJiyong Park	 */
791*54fd6939SJiyong Park	mrs	x1, CPUECTLR_EL1
792*54fd6939SJiyong Park	bic	x1, x1, #CPUECTLR_RET_MASK
793*54fd6939SJiyong Park	orr	x1, x1, #CPUECTLR_TIMER_2TICKS
794*54fd6939SJiyong Park	orr	x1, x1, #CPUECTLR_SMPEN_EN
795*54fd6939SJiyong Park	msr	CPUECTLR_EL1, x1
796*54fd6939SJiyong Park
797*54fd6939SJiyong Park	isb
798*54fd6939SJiyong Park	ret
799*54fd6939SJiyong Park
800*54fd6939SJiyong Park/*
801*54fd6939SJiyong Park * Part of CPU_SUSPEND
802*54fd6939SJiyong Park *
803*54fd6939SJiyong Park * This function performs any SoC-specific cleanup after power-down state
804*54fd6939SJiyong Park * in:  x0 = core mask lsb
805*54fd6939SJiyong Park * out: none
806*54fd6939SJiyong Park * uses none
807*54fd6939SJiyong Park */
808*54fd6939SJiyong Park_soc_clstr_exit_pwrdn:
809*54fd6939SJiyong Park	ret
810*54fd6939SJiyong Park
811*54fd6939SJiyong Park/*
812*54fd6939SJiyong Park * Part of CPU_SUSPEND
813*54fd6939SJiyong Park *
814*54fd6939SJiyong Park * This function performs SoC-specific programming prior to standby
815*54fd6939SJiyong Park * in:  x0 = core mask lsb
816*54fd6939SJiyong Park * out: none
817*54fd6939SJiyong Park * uses x0, x1
818*54fd6939SJiyong Park */
819*54fd6939SJiyong Park_soc_sys_prep_stdby:
820*54fd6939SJiyong Park	/* Clear CPUECTLR_EL1[2:0] */
821*54fd6939SJiyong Park	mrs	x1, CPUECTLR_EL1
822*54fd6939SJiyong Park	bic	x1, x1, #CPUECTLR_TIMER_MASK
823*54fd6939SJiyong Park	msr	CPUECTLR_EL1, x1
824*54fd6939SJiyong Park
825*54fd6939SJiyong Park	ret
826*54fd6939SJiyong Park
827*54fd6939SJiyong Park/*
828*54fd6939SJiyong Park * Part of CPU_SUSPEND
829*54fd6939SJiyong Park *
830*54fd6939SJiyong Park * This function performs any SoC-specific cleanup after standby state
831*54fd6939SJiyong Park * in:  x0 = core mask lsb
832*54fd6939SJiyong Park * out: none
833*54fd6939SJiyong Park * uses none
834*54fd6939SJiyong Park */
835*54fd6939SJiyong Park_soc_sys_exit_stdby:
836*54fd6939SJiyong Park	ret
837*54fd6939SJiyong Park
838*54fd6939SJiyong Park/*
839*54fd6939SJiyong Park * Part of CPU_SUSPEND
840*54fd6939SJiyong Park *
841*54fd6939SJiyong Park * This function performs SoC-specific programming prior to
842*54fd6939SJiyong Park * suspend-to-power-down
843*54fd6939SJiyong Park * in:  x0 = core mask lsb
844*54fd6939SJiyong Park * out: none
845*54fd6939SJiyong Park * uses x0, x1, x2, x3, x4
846*54fd6939SJiyong Park */
847*54fd6939SJiyong Park_soc_sys_prep_pwrdn:
848*54fd6939SJiyong Park	/* Set retention control */
849*54fd6939SJiyong Park	mrs	x0, CPUECTLR_EL1
850*54fd6939SJiyong Park	bic	x0, x0, #CPUECTLR_TIMER_MASK
851*54fd6939SJiyong Park	orr	x0, x0, #CPUECTLR_TIMER_2TICKS
852*54fd6939SJiyong Park	orr	x0, x0, #CPUECTLR_SMPEN_EN
853*54fd6939SJiyong Park	msr	CPUECTLR_EL1, x0
854*54fd6939SJiyong Park	dsb	sy
855*54fd6939SJiyong Park	isb
856*54fd6939SJiyong Park	ret
857*54fd6939SJiyong Park
858*54fd6939SJiyong Park/*
859*54fd6939SJiyong Park * Part of CPU_SUSPEND
860*54fd6939SJiyong Park *
861*54fd6939SJiyong Park * This function puts the calling core, and potentially the soc, into a
862*54fd6939SJiyong Park * low-power state
863*54fd6939SJiyong Park * in:  x0 = core mask lsb
864*54fd6939SJiyong Park * out: x0 = 0, success
865*54fd6939SJiyong Park *      x0 < 0, failure
866*54fd6939SJiyong Park * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x13, x14, x15,
867*54fd6939SJiyong Park *      x16, x17, x18
868*54fd6939SJiyong Park */
869*54fd6939SJiyong Park_soc_sys_pwrdn_wfi:
870*54fd6939SJiyong Park	mov	x18, x30
871*54fd6939SJiyong Park
872*54fd6939SJiyong Park	mov	x3, #NXP_PMU_ADDR
873*54fd6939SJiyong Park
874*54fd6939SJiyong Park	/* x3 = pmu base addr */
875*54fd6939SJiyong Park
876*54fd6939SJiyong Park	/* Backup epu registers to stack */
877*54fd6939SJiyong Park	ldr	x2, =NXP_EPU_ADDR
878*54fd6939SJiyong Park	ldr	w4, [x2, #EPU_EPIMCR10_OFFSET]
879*54fd6939SJiyong Park	ldr	w5, [x2, #EPU_EPCCR10_OFFSET]
880*54fd6939SJiyong Park	ldr	w6, [x2, #EPU_EPCTR10_OFFSET]
881*54fd6939SJiyong Park	ldr	w7, [x2, #EPU_EPGCR_OFFSET]
882*54fd6939SJiyong Park	stp	x4,  x5,  [sp, #-16]!
883*54fd6939SJiyong Park	stp	x6,  x7,  [sp, #-16]!
884*54fd6939SJiyong Park
885*54fd6939SJiyong Park	/*
886*54fd6939SJiyong Park	 * x2 = epu base addr
887*54fd6939SJiyong Park	 * x3 = pmu base addr
888*54fd6939SJiyong Park	 */
889*54fd6939SJiyong Park
890*54fd6939SJiyong Park	/* Set up EPU event to receive the wake signal from PMU */
891*54fd6939SJiyong Park	mov	w4, #EPU_EPIMCR10_VAL
892*54fd6939SJiyong Park	mov	w5, #EPU_EPCCR10_VAL
893*54fd6939SJiyong Park	mov	w6, #EPU_EPCTR10_VAL
894*54fd6939SJiyong Park	mov	w7, #EPU_EPGCR_VAL
895*54fd6939SJiyong Park	str	w4, [x2, #EPU_EPIMCR10_OFFSET]
896*54fd6939SJiyong Park	str	w5, [x2, #EPU_EPCCR10_OFFSET]
897*54fd6939SJiyong Park	str	w6, [x2, #EPU_EPCTR10_OFFSET]
898*54fd6939SJiyong Park	str	w7, [x2, #EPU_EPGCR_OFFSET]
899*54fd6939SJiyong Park
900*54fd6939SJiyong Park	ldr	x2, =NXP_GICD_ADDR
901*54fd6939SJiyong Park
902*54fd6939SJiyong Park	/*
903*54fd6939SJiyong Park	 * x2 = gicd base addr
904*54fd6939SJiyong Park	 * x3 = pmu base addr
905*54fd6939SJiyong Park	 */
906*54fd6939SJiyong Park
907*54fd6939SJiyong Park	/* Backup flextimer/mmc/usb interrupt router */
908*54fd6939SJiyong Park	ldr	x0, =GICD_IROUTER60_OFFSET
909*54fd6939SJiyong Park	ldr	x1, =GICD_IROUTER76_OFFSET
910*54fd6939SJiyong Park	ldr	w4, [x2, x0]
911*54fd6939SJiyong Park	ldr	w5, [x2, x1]
912*54fd6939SJiyong Park	ldr	x0, =GICD_IROUTER112_OFFSET
913*54fd6939SJiyong Park	ldr	x1, =GICD_IROUTER113_OFFSET
914*54fd6939SJiyong Park	ldr	w6, [x2, x0]
915*54fd6939SJiyong Park	ldr	w7, [x2, x1]
916*54fd6939SJiyong Park	stp	x4,  x5,  [sp, #-16]!
917*54fd6939SJiyong Park	stp	x6,  x7,  [sp, #-16]!
918*54fd6939SJiyong Park
919*54fd6939SJiyong Park	/*
920*54fd6939SJiyong Park	 * x2 = gicd base addr
921*54fd6939SJiyong Park	 * x3 = pmu base addr
922*54fd6939SJiyong Park	 * x0 = GICD_IROUTER112_OFFSET
923*54fd6939SJiyong Park	 * x1 = GICD_IROUTER113_OFFSET
924*54fd6939SJiyong Park	 */
925*54fd6939SJiyong Park
926*54fd6939SJiyong Park	/* Re-route interrupt to cluster 1 */
927*54fd6939SJiyong Park	ldr	w4, =GICD_IROUTER_VALUE
928*54fd6939SJiyong Park	str	w4, [x2, x0]
929*54fd6939SJiyong Park	str	w4, [x2, x1]
930*54fd6939SJiyong Park	ldr	x0, =GICD_IROUTER60_OFFSET
931*54fd6939SJiyong Park	ldr	x1, =GICD_IROUTER76_OFFSET
932*54fd6939SJiyong Park	str	w4, [x2, x0]
933*54fd6939SJiyong Park	str	w4, [x2, x1]
934*54fd6939SJiyong Park	dsb	sy
935*54fd6939SJiyong Park	isb
936*54fd6939SJiyong Park
937*54fd6939SJiyong Park	/* x3 = pmu base addr */
938*54fd6939SJiyong Park
939*54fd6939SJiyong Park	/* Disable sec, Check for eNETC, spi and qspi */
940*54fd6939SJiyong Park	ldr	x2, =NXP_DCFG_ADDR
941*54fd6939SJiyong Park	ldr	x0, =DCFG_DEVDISR1_OFFSET
942*54fd6939SJiyong Park	ldr	w1, =DCFG_DEVDISR1_SEC
943*54fd6939SJiyong Park	str	w1, [x2, x0]
944*54fd6939SJiyong Park
945*54fd6939SJiyong Park	ldr	x0, =DCFG_DEVDISR4_OFFSET
946*54fd6939SJiyong Park	ldr	w1, =DCFG_DEVDISR4_SPI_QSPI
947*54fd6939SJiyong Park	str	w1, [x2, x0]
948*54fd6939SJiyong Park
949*54fd6939SJiyong Park	/* x3 = pmu base addr */
950*54fd6939SJiyong Park
951*54fd6939SJiyong Park	/* Set TPMWAKEMR0 */
952*54fd6939SJiyong Park	ldr	x0, =TPMWAKEMR0_ADDR
953*54fd6939SJiyong Park	mov	w1, #0x1
954*54fd6939SJiyong Park	str	w1, [x0]
955*54fd6939SJiyong Park
956*54fd6939SJiyong Park	/* Disable CCI snoop domain */
957*54fd6939SJiyong Park	ldr	x0, =NXP_CCI_ADDR
958*54fd6939SJiyong Park	mov	w1, #0x1
959*54fd6939SJiyong Park	str	w1, [x0]
960*54fd6939SJiyong Park
961*54fd6939SJiyong Park	/* Setup retention control */
962*54fd6939SJiyong Park	mrs	x0, CPUECTLR_EL1
963*54fd6939SJiyong Park	orr	x0, x0, #CPUECTLR_SMPEN_EN
964*54fd6939SJiyong Park	orr	x0, x0, #CPUECTLR_TIMER_2TICKS
965*54fd6939SJiyong Park	msr	CPUECTLR_EL1, x0
966*54fd6939SJiyong Park	dsb	sy
967*54fd6939SJiyong Park	isb
968*54fd6939SJiyong Park
969*54fd6939SJiyong Park	bl	get_pmu_idle_core_mask
970*54fd6939SJiyong Park	mov	x3, #NXP_PMU_ADDR
971*54fd6939SJiyong Park8:
972*54fd6939SJiyong Park	ldr	w1, [x3, #PMU_PCPW20SR_OFFSET]
973*54fd6939SJiyong Park	cmp	w1, w0
974*54fd6939SJiyong Park	b.ne	8b
975*54fd6939SJiyong Park
976*54fd6939SJiyong Park	/* x3 = NXP_PMU_ADDR */
977*54fd6939SJiyong Park	/* 1 cluster SoC */
978*54fd6939SJiyong Park
979*54fd6939SJiyong Park	bl	get_pmu_idle_cluster_mask
980*54fd6939SJiyong Park	mov	x3, #NXP_PMU_ADDR
981*54fd6939SJiyong Park
982*54fd6939SJiyong Park	str	w0, [x3, #PMU_CLAINACTSETR_OFFSET]
983*54fd6939SJiyong Park
984*54fd6939SJiyong Park	bl	get_pmu_idle_core_mask
985*54fd6939SJiyong Park	/* x3 = NXP_PMU_ADDR */
986*54fd6939SJiyong Park	mov	x3, #NXP_PMU_ADDR
987*54fd6939SJiyong Park1:
988*54fd6939SJiyong Park	ldr	w1, [x3, #PMU_PCPW20SR_OFFSET]
989*54fd6939SJiyong Park	cmp	w1, w0
990*54fd6939SJiyong Park	b.ne	1b
991*54fd6939SJiyong Park
992*54fd6939SJiyong Park	/* x3 = NXP_PMU_ADDR */
993*54fd6939SJiyong Park	bl	get_pmu_flush_cluster_mask
994*54fd6939SJiyong Park	mov	x3, #NXP_PMU_ADDR
995*54fd6939SJiyong Park
996*54fd6939SJiyong Park	str	w0, [x3, #PMU_CLL2FLUSHSETR_OFFSET]
997*54fd6939SJiyong Park
998*54fd6939SJiyong Park	/* x3 = NXP_PMU_ADDR */
999*54fd6939SJiyong Park2:
1000*54fd6939SJiyong Park	ldr	w1, [x3, #PMU_CLL2FLUSHSR_OFFSET]
1001*54fd6939SJiyong Park	cmp	w1, w0
1002*54fd6939SJiyong Park	b.ne	2b
1003*54fd6939SJiyong Park
1004*54fd6939SJiyong Park	/* x3 = NXP_PMU_ADDR */
1005*54fd6939SJiyong Park
1006*54fd6939SJiyong Park	str	w0, [x3, #PMU_CLSL2FLUSHCLRR_OFFSET]
1007*54fd6939SJiyong Park
1008*54fd6939SJiyong Park	str	w0, [x3, #PMU_CLSINACTSETR_OFFSET]
1009*54fd6939SJiyong Park
1010*54fd6939SJiyong Park	/* Force the debug interface to be quiescent */
1011*54fd6939SJiyong Park	mrs	x0, osdlr_el1
1012*54fd6939SJiyong Park	orr	x0, x0, #0x1
1013*54fd6939SJiyong Park	msr	osdlr_el1, x0
1014*54fd6939SJiyong Park
1015*54fd6939SJiyong Park	/*
1016*54fd6939SJiyong Park	 * Enable the WakeRequest signal
1017*54fd6939SJiyong Park	 * x3 is cpu mask starting from cpu1 to cpu0
1018*54fd6939SJiyong Park	 */
1019*54fd6939SJiyong Park	bl	get_tot_num_cores
1020*54fd6939SJiyong Park	sub	x0, x0, #1
1021*54fd6939SJiyong Park	mov	x3, #0x1
1022*54fd6939SJiyong Park	lsl	x3, x3, x0
1023*54fd6939SJiyong Park2:
1024*54fd6939SJiyong Park	mov	x0, x3
1025*54fd6939SJiyong Park	bl	get_gic_rd_base  // 0-2
1026*54fd6939SJiyong Park	ldr	w1, [x0, #GICR_WAKER_OFFSET]
1027*54fd6939SJiyong Park	orr	w1, w1, #GICR_WAKER_SLEEP_BIT
1028*54fd6939SJiyong Park	str	w1, [x0, #GICR_WAKER_OFFSET]
1029*54fd6939SJiyong Park1:
1030*54fd6939SJiyong Park	ldr	w1, [x0, #GICR_WAKER_OFFSET]
1031*54fd6939SJiyong Park	cmp	w1, #GICR_WAKER_ASLEEP
1032*54fd6939SJiyong Park	b.ne	1b
1033*54fd6939SJiyong Park
1034*54fd6939SJiyong Park	lsr	x3, x3, #1
1035*54fd6939SJiyong Park	cbnz	x3, 2b
1036*54fd6939SJiyong Park
1037*54fd6939SJiyong Park	/* Invalidate all TLB entries at all 3 exception levels */
1038*54fd6939SJiyong Park	tlbi	alle1
1039*54fd6939SJiyong Park	tlbi	alle2
1040*54fd6939SJiyong Park	tlbi	alle3
1041*54fd6939SJiyong Park
1042*54fd6939SJiyong Park	/* Request lpm20 */
1043*54fd6939SJiyong Park	mov	x3, #NXP_PMU_ADDR
1044*54fd6939SJiyong Park	ldr	x0, =PMU_POWMGTCSR_OFFSET
1045*54fd6939SJiyong Park	ldr	w1, =PMU_POWMGTCSR_VAL
1046*54fd6939SJiyong Park	str	w1, [x3, x0]
1047*54fd6939SJiyong Park
1048*54fd6939SJiyong Park	ldr	x5, =NXP_EPU_ADDR
1049*54fd6939SJiyong Park4:
1050*54fd6939SJiyong Park	wfe
1051*54fd6939SJiyong Park	ldr	w1, [x5, #EPU_EPCTR10_OFFSET]
1052*54fd6939SJiyong Park	cmp	w1, #0
1053*54fd6939SJiyong Park	b.eq	4b
1054*54fd6939SJiyong Park
1055*54fd6939SJiyong Park	/* x3 = NXP_PMU_ADDR */
1056*54fd6939SJiyong Park
1057*54fd6939SJiyong Park	bl	get_pmu_idle_cluster_mask
1058*54fd6939SJiyong Park	mov	x3, NXP_PMU_ADDR
1059*54fd6939SJiyong Park
1060*54fd6939SJiyong Park	/* Re-enable the GPP ACP */
1061*54fd6939SJiyong Park	str	w0, [x3, #PMU_CLAINACTCLRR_OFFSET]
1062*54fd6939SJiyong Park	str	w0, [x3, #PMU_CLSINACTCLRR_OFFSET]
1063*54fd6939SJiyong Park
1064*54fd6939SJiyong Park	/* x3 = NXP_PMU_ADDR */
1065*54fd6939SJiyong Park3:
1066*54fd6939SJiyong Park	ldr	w1, [x3, #PMU_CLAINACTSETR_OFFSET]
1067*54fd6939SJiyong Park	cbnz	w1, 3b
1068*54fd6939SJiyong Park4:
1069*54fd6939SJiyong Park	ldr	w1, [x3, #PMU_CLSINACTSETR_OFFSET]
1070*54fd6939SJiyong Park	cbnz	w1, 4b
1071*54fd6939SJiyong Park
1072*54fd6939SJiyong Park	/*
1073*54fd6939SJiyong Park	 * Enable the WakeRequest signal on cpu 0-1
1074*54fd6939SJiyong Park	 * x3 is cpu mask starting from cpu1
1075*54fd6939SJiyong Park	 */
1076*54fd6939SJiyong Park	bl	get_tot_num_cores
1077*54fd6939SJiyong Park	sub	x0, x0, #1
1078*54fd6939SJiyong Park	mov	x3, #0x1
1079*54fd6939SJiyong Park	lsl	x3, x3, x0
1080*54fd6939SJiyong Park2:
1081*54fd6939SJiyong Park	mov	x0, x3
1082*54fd6939SJiyong Park	bl	get_gic_rd_base  // 0-2
1083*54fd6939SJiyong Park	ldr	w1, [x0, #GICR_WAKER_OFFSET]
1084*54fd6939SJiyong Park	bic	w1, w1, #GICR_WAKER_SLEEP_BIT
1085*54fd6939SJiyong Park	str	w1, [x0, #GICR_WAKER_OFFSET]
1086*54fd6939SJiyong Park1:
1087*54fd6939SJiyong Park	ldr	w1, [x0, #GICR_WAKER_OFFSET]
1088*54fd6939SJiyong Park	cbnz	w1, 1b
1089*54fd6939SJiyong Park
1090*54fd6939SJiyong Park	lsr	x3, x3, #1
1091*54fd6939SJiyong Park	cbnz	x3, 2b
1092*54fd6939SJiyong Park
1093*54fd6939SJiyong Park	/* Enable CCI snoop domain */
1094*54fd6939SJiyong Park	ldr	x0, =NXP_CCI_ADDR
1095*54fd6939SJiyong Park	str	wzr, [x0]
1096*54fd6939SJiyong Park	dsb	sy
1097*54fd6939SJiyong Park	isb
1098*54fd6939SJiyong Park
1099*54fd6939SJiyong Park	ldr	x3, =NXP_EPU_ADDR
1100*54fd6939SJiyong Park
1101*54fd6939SJiyong Park	/* x3 = epu base addr */
1102*54fd6939SJiyong Park
1103*54fd6939SJiyong Park	/* Enable sec, enetc, spi and qspi */
1104*54fd6939SJiyong Park	ldr	x2, =NXP_DCFG_ADDR
1105*54fd6939SJiyong Park	str	wzr, [x2, #DCFG_DEVDISR1_OFFSET]
1106*54fd6939SJiyong Park	str	wzr, [x2, #DCFG_DEVDISR2_OFFSET]
1107*54fd6939SJiyong Park	str	wzr, [x2, #DCFG_DEVDISR4_OFFSET]
1108*54fd6939SJiyong Park
1109*54fd6939SJiyong Park	/* Restore flextimer/mmc/usb interrupt router */
1110*54fd6939SJiyong Park	ldr	x3, =NXP_GICD_ADDR
1111*54fd6939SJiyong Park	ldp	x0, x2, [sp], #16
1112*54fd6939SJiyong Park	ldr	x1, =GICD_IROUTER113_OFFSET
1113*54fd6939SJiyong Park	str	w2, [x3, x1]
1114*54fd6939SJiyong Park	ldr	x1, =GICD_IROUTER112_OFFSET
1115*54fd6939SJiyong Park	str	w0, [x3, x1]
1116*54fd6939SJiyong Park	ldp	x0, x2, [sp], #16
1117*54fd6939SJiyong Park	ldr	x1, =GICD_IROUTER76_OFFSET
1118*54fd6939SJiyong Park	str	w2, [x3, x1]
1119*54fd6939SJiyong Park	ldr	x1, =GICD_IROUTER60_OFFSET
1120*54fd6939SJiyong Park	str	w0, [x3, x1]
1121*54fd6939SJiyong Park
1122*54fd6939SJiyong Park	/* Restore EPU registers */
1123*54fd6939SJiyong Park	ldr	x3, =NXP_EPU_ADDR
1124*54fd6939SJiyong Park	ldp	x0, x2, [sp], #16
1125*54fd6939SJiyong Park	str	w2, [x3, #EPU_EPGCR_OFFSET]
1126*54fd6939SJiyong Park	str	w0, [x3, #EPU_EPCTR10_OFFSET]
1127*54fd6939SJiyong Park	ldp	x2, x1, [sp], #16
1128*54fd6939SJiyong Park	str	w1, [x3, #EPU_EPCCR10_OFFSET]
1129*54fd6939SJiyong Park	str	w2, [x3, #EPU_EPIMCR10_OFFSET]
1130*54fd6939SJiyong Park
1131*54fd6939SJiyong Park	dsb	sy
1132*54fd6939SJiyong Park	isb
1133*54fd6939SJiyong Park	mov	x30, x18
1134*54fd6939SJiyong Park	ret
1135*54fd6939SJiyong Park
1136*54fd6939SJiyong Park/*
1137*54fd6939SJiyong Park * Part of CPU_SUSPEND
1138*54fd6939SJiyong Park *
1139*54fd6939SJiyong Park * This function performs any SoC-specific cleanup after power-down
1140*54fd6939SJiyong Park * in:  x0 = core mask lsb
1141*54fd6939SJiyong Park * out: none
1142*54fd6939SJiyong Park * uses x0, x1
1143*54fd6939SJiyong Park */
1144*54fd6939SJiyong Park_soc_sys_exit_pwrdn:
1145*54fd6939SJiyong Park	/* Enable stack alignment checking */
1146*54fd6939SJiyong Park	mrs	x1, SCTLR_EL1
1147*54fd6939SJiyong Park	orr	x1, x1, #0x4
1148*54fd6939SJiyong Park	msr	SCTLR_EL1, x1
1149*54fd6939SJiyong Park
1150*54fd6939SJiyong Park	/* Enable debug interface */
1151*54fd6939SJiyong Park	mrs	x1, osdlr_el1
1152*54fd6939SJiyong Park	bic	x1, x1, #OSDLR_EL1_DLK_LOCK
1153*54fd6939SJiyong Park	msr	osdlr_el1, x1
1154*54fd6939SJiyong Park
1155*54fd6939SJiyong Park	/* Enable i-cache */
1156*54fd6939SJiyong Park	mrs	x1, SCTLR_EL3
1157*54fd6939SJiyong Park	orr	x1, x1, #SCTLR_I_MASK
1158*54fd6939SJiyong Park	msr	SCTLR_EL3, x1
1159*54fd6939SJiyong Park
1160*54fd6939SJiyong Park	isb
1161*54fd6939SJiyong Park	ret
1162*54fd6939SJiyong Park
1163*54fd6939SJiyong Park/*
1164*54fd6939SJiyong Park * This function setc up the TrustZone Address Space Controller (TZASC)
1165*54fd6939SJiyong Park * in:  none
1166*54fd6939SJiyong Park * out: none
1167*54fd6939SJiyong Park * uses x0, x1
1168*54fd6939SJiyong Park */
1169*54fd6939SJiyong Parkinit_tzpc:
1170*54fd6939SJiyong Park	/* Set Non Secure access for all devices protected via TZPC */
1171*54fd6939SJiyong Park	ldr	x1, =TZPCDECPROT_0_SET_BASE   /* decode Protection-0 Set Reg */
1172*54fd6939SJiyong Park	mov	w0, #0xFF		      /* set decode region to NS, Bits[7:0] */
1173*54fd6939SJiyong Park	str	w0, [x1]
1174*54fd6939SJiyong Park
1175*54fd6939SJiyong Park	ldr	x1, =TZPCDECPROT_1_SET_BASE   /* decode Protection-1 Set Reg */
1176*54fd6939SJiyong Park	mov	w0, #0xFF		      /* set decode region to NS, Bits[7:0] */
1177*54fd6939SJiyong Park	str	w0, [x1]
1178*54fd6939SJiyong Park
1179*54fd6939SJiyong Park	ldr	x1, =TZPCDECPROT_2_SET_BASE   /* decode Protection-2 Set Reg */
1180*54fd6939SJiyong Park	mov	w0, #0xFF		      /* set decode region to NS, Bits[7:0] */
1181*54fd6939SJiyong Park	str	w0, [x1]
1182*54fd6939SJiyong Park
1183*54fd6939SJiyong Park	 /* entire SRAM as NS */
1184*54fd6939SJiyong Park	ldr	x1, =NXP_OCRAM_TZPC_ADDR      /* secure RAM region size Reg */
1185*54fd6939SJiyong Park	mov	w0, #0x00000000		      /* 0x00000000 = no secure region */
1186*54fd6939SJiyong Park	str	w0, [x1]
1187*54fd6939SJiyong Park
1188*54fd6939SJiyong Park	ret
1189*54fd6939SJiyong Park
1190*54fd6939SJiyong Park/*
1191*54fd6939SJiyong Park * This function performs any needed initialization on SecMon for
1192*54fd6939SJiyong Park * boot services
1193*54fd6939SJiyong Park */
1194*54fd6939SJiyong ParkinitSecMon:
1195*54fd6939SJiyong Park	/* Read the register hpcomr */
1196*54fd6939SJiyong Park	ldr	x1, =NXP_SNVS_ADDR
1197*54fd6939SJiyong Park	ldr	w0, [x1, #SECMON_HPCOMR_OFFSET]
1198*54fd6939SJiyong Park	/* Turn off secure access for the privileged registers */
1199*54fd6939SJiyong Park	orr	w0, w0, #SECMON_HPCOMR_NPSWAEN
1200*54fd6939SJiyong Park	/* Write back */
1201*54fd6939SJiyong Park	str	w0, [x1, #SECMON_HPCOMR_OFFSET]
1202*54fd6939SJiyong Park
1203*54fd6939SJiyong Park	ret
1204*54fd6939SJiyong Park
1205*54fd6939SJiyong Park/*
1206*54fd6939SJiyong Park * This function checks to see if cores which are to be disabled have been
1207*54fd6939SJiyong Park * released from reset - if not, it releases them
1208*54fd6939SJiyong Park * in:  none
1209*54fd6939SJiyong Park * out: none
1210*54fd6939SJiyong Park * uses x0, x1, x2, x3, x4, x5, x6, x7, x8
1211*54fd6939SJiyong Park */
1212*54fd6939SJiyong Parkrelease_disabled:
1213*54fd6939SJiyong Park	stp	x18, x30, [sp, #-16]!
1214*54fd6939SJiyong Park
1215*54fd6939SJiyong Park	/*
1216*54fd6939SJiyong Park	 * Get the number of cpus on this device
1217*54fd6939SJiyong Park	 * Calling the below c function.
1218*54fd6939SJiyong Park	 * No need to Callee saved registers x9-x15,
1219*54fd6939SJiyong Park	 * as these registers are not used by the callee
1220*54fd6939SJiyong Park	 * prior to calling the below C-routine.
1221*54fd6939SJiyong Park	 */
1222*54fd6939SJiyong Park	bl	get_tot_num_cores
1223*54fd6939SJiyong Park	mov	x6, x0
1224*54fd6939SJiyong Park
1225*54fd6939SJiyong Park	/* Read COREDISABLESR */
1226*54fd6939SJiyong Park	mov	x0, #NXP_DCFG_ADDR
1227*54fd6939SJiyong Park	ldr	w4, [x0, #DCFG_COREDISABLEDSR_OFFSET]
1228*54fd6939SJiyong Park
1229*54fd6939SJiyong Park	mov	x0, #NXP_RESET_ADDR
1230*54fd6939SJiyong Park	ldr	w5, [x0, #BRR_OFFSET]
1231*54fd6939SJiyong Park
1232*54fd6939SJiyong Park	/* Load the core mask for the first core */
1233*54fd6939SJiyong Park	mov	x7, #1
1234*54fd6939SJiyong Park
1235*54fd6939SJiyong Park	/*
1236*54fd6939SJiyong Park	 * x4 = COREDISABLESR
1237*54fd6939SJiyong Park	 * x5 = BRR
1238*54fd6939SJiyong Park	 * x6 = loop count
1239*54fd6939SJiyong Park	 * x7 = core mask bit
1240*54fd6939SJiyong Park	 */
1241*54fd6939SJiyong Park2:
1242*54fd6939SJiyong Park	/* Check if the core is to be disabled */
1243*54fd6939SJiyong Park	tst	x4, x7
1244*54fd6939SJiyong Park	b.eq	1f
1245*54fd6939SJiyong Park
1246*54fd6939SJiyong Park	/* See if disabled cores have already been released from reset */
1247*54fd6939SJiyong Park	tst	x5, x7
1248*54fd6939SJiyong Park	b.ne	1f
1249*54fd6939SJiyong Park
1250*54fd6939SJiyong Park	/* If core has not been released, then release it (0-3) */
1251*54fd6939SJiyong Park	mov	x0, x7
1252*54fd6939SJiyong Park	bl	_soc_core_release
1253*54fd6939SJiyong Park
1254*54fd6939SJiyong Park	/* Record the core state in the data area (0-3) */
1255*54fd6939SJiyong Park	mov	x0, x7
1256*54fd6939SJiyong Park	mov	x1, #CORE_DISABLED
1257*54fd6939SJiyong Park	bl	_setCoreState
1258*54fd6939SJiyong Park1:
1259*54fd6939SJiyong Park	/* Decrement the counter */
1260*54fd6939SJiyong Park	subs	x6, x6, #1
1261*54fd6939SJiyong Park	b.le	3f
1262*54fd6939SJiyong Park	/* Shift the core mask to the next core */
1263*54fd6939SJiyong Park	lsl	x7, x7, #1
1264*54fd6939SJiyong Park	/* Continue */
1265*54fd6939SJiyong Park	b	2b
1266*54fd6939SJiyong Park3:
1267*54fd6939SJiyong Park	ldp	x18, x30, [sp], #16
1268*54fd6939SJiyong Park	ret
1269*54fd6939SJiyong Park
1270*54fd6939SJiyong Park/*
1271*54fd6939SJiyong Park * Write a register in the DCFG block
1272*54fd6939SJiyong Park * in:  x0 = offset
1273*54fd6939SJiyong Park * in:  w1 = value to write
1274*54fd6939SJiyong Park * uses x0, x1, x2
1275*54fd6939SJiyong Park */
1276*54fd6939SJiyong Park_write_reg_dcfg:
1277*54fd6939SJiyong Park	ldr	x2, =NXP_DCFG_ADDR
1278*54fd6939SJiyong Park	str	w1, [x2, x0]
1279*54fd6939SJiyong Park	ret
1280*54fd6939SJiyong Park
1281*54fd6939SJiyong Park/*
1282*54fd6939SJiyong Park * Read a register in the DCFG block
1283*54fd6939SJiyong Park * in:  x0 = offset
1284*54fd6939SJiyong Park * out: w0 = value read
1285*54fd6939SJiyong Park * uses x0, x1, x2
1286*54fd6939SJiyong Park */
1287*54fd6939SJiyong Park_read_reg_dcfg:
1288*54fd6939SJiyong Park	ldr	x2, =NXP_DCFG_ADDR
1289*54fd6939SJiyong Park	ldr	w1, [x2, x0]
1290*54fd6939SJiyong Park	mov	w0, w1
1291*54fd6939SJiyong Park	ret
1292*54fd6939SJiyong Park
1293*54fd6939SJiyong Park/*
1294*54fd6939SJiyong Park * This function returns an mpidr value for a core, given a core_mask_lsb
1295*54fd6939SJiyong Park * in:  x0 = core mask lsb
1296*54fd6939SJiyong Park * out: x0 = affinity2:affinity1:affinity0, where affinity is 8-bits
1297*54fd6939SJiyong Park * uses x0, x1
1298*54fd6939SJiyong Park */
1299*54fd6939SJiyong Parkget_mpidr_value:
1300*54fd6939SJiyong Park	/* Convert a core mask to an SoC core number */
1301*54fd6939SJiyong Park	clz	w0, w0
1302*54fd6939SJiyong Park	mov	w1, #31
1303*54fd6939SJiyong Park	sub	w0, w1, w0
1304*54fd6939SJiyong Park
1305*54fd6939SJiyong Park	/* Get the mpidr core number from the SoC core number */
1306*54fd6939SJiyong Park	mov	w1, wzr
1307*54fd6939SJiyong Park	tst	x0, #1
1308*54fd6939SJiyong Park	b.eq	1f
1309*54fd6939SJiyong Park	orr	w1, w1, #1
1310*54fd6939SJiyong Park1:
1311*54fd6939SJiyong Park	/* Extract the cluster number */
1312*54fd6939SJiyong Park	lsr	w0, w0, #1
1313*54fd6939SJiyong Park	orr	w0, w1, w0, lsl #8
1314*54fd6939SJiyong Park
1315*54fd6939SJiyong Park	ret
1316*54fd6939SJiyong Park
1317*54fd6939SJiyong Park/*
1318*54fd6939SJiyong Park * This function returns the redistributor base address for the core specified
1319*54fd6939SJiyong Park * in x1
1320*54fd6939SJiyong Park * in:  x0 - core mask lsb of specified core
1321*54fd6939SJiyong Park * out: x0 = redistributor rd base address for specified core
1322*54fd6939SJiyong Park * uses x0, x1, x2
1323*54fd6939SJiyong Park */
1324*54fd6939SJiyong Parkget_gic_rd_base:
1325*54fd6939SJiyong Park	/* Get the 0-based core number */
1326*54fd6939SJiyong Park	clz	w1, w0
1327*54fd6939SJiyong Park	mov	w2, #0x20
1328*54fd6939SJiyong Park	sub	w2, w2, w1
1329*54fd6939SJiyong Park	sub	w2, w2, #1
1330*54fd6939SJiyong Park
1331*54fd6939SJiyong Park	/* x2 = core number / loop counter */
1332*54fd6939SJiyong Park	ldr	x0, =NXP_GICR_ADDR
1333*54fd6939SJiyong Park	mov	x1, #GIC_RD_OFFSET
1334*54fd6939SJiyong Park2:
1335*54fd6939SJiyong Park	cbz	x2, 1f
1336*54fd6939SJiyong Park	add	x0, x0, x1
1337*54fd6939SJiyong Park	sub	x2, x2, #1
1338*54fd6939SJiyong Park	b	2b
1339*54fd6939SJiyong Park1:
1340*54fd6939SJiyong Park	ret
1341*54fd6939SJiyong Park
1342*54fd6939SJiyong Park/*
1343*54fd6939SJiyong Park * This function returns the redistributor base address for the core specified
1344*54fd6939SJiyong Park * in x1
1345*54fd6939SJiyong Park * in:  x0 - core mask lsb of specified core
1346*54fd6939SJiyong Park * out: x0 = redistributor sgi base address for specified core
1347*54fd6939SJiyong Park * uses x0, x1, x2
1348*54fd6939SJiyong Park */
1349*54fd6939SJiyong Parkget_gic_sgi_base:
1350*54fd6939SJiyong Park	/* Get the 0-based core number */
1351*54fd6939SJiyong Park	clz	w1, w0
1352*54fd6939SJiyong Park	mov	w2, #0x20
1353*54fd6939SJiyong Park	sub	w2, w2, w1
1354*54fd6939SJiyong Park	sub	w2, w2, #1
1355*54fd6939SJiyong Park
1356*54fd6939SJiyong Park	/* x2 = core number / loop counter */
1357*54fd6939SJiyong Park	ldr	x0, =NXP_GICR_SGI_ADDR
1358*54fd6939SJiyong Park	mov	x1, #GIC_SGI_OFFSET
1359*54fd6939SJiyong Park2:
1360*54fd6939SJiyong Park	cbz	x2, 1f
1361*54fd6939SJiyong Park	add	x0, x0, x1
1362*54fd6939SJiyong Park	sub	x2, x2, #1
1363*54fd6939SJiyong Park	b	2b
1364*54fd6939SJiyong Park1:
1365*54fd6939SJiyong Park	ret
1366*54fd6939SJiyong Park
1367*54fd6939SJiyong Park/*
1368*54fd6939SJiyong Park * Write a register in the RESET block
1369*54fd6939SJiyong Park * in:  x0 = offset
1370*54fd6939SJiyong Park * in:  w1 = value to write
1371*54fd6939SJiyong Park * uses x0, x1, x2
1372*54fd6939SJiyong Park */
1373*54fd6939SJiyong Park_write_reg_reset:
1374*54fd6939SJiyong Park	ldr	x2, =NXP_RESET_ADDR
1375*54fd6939SJiyong Park	str	w1, [x2, x0]
1376*54fd6939SJiyong Park	ret
1377*54fd6939SJiyong Park
1378*54fd6939SJiyong Park/*
1379*54fd6939SJiyong Park * Read a register in the RESET block
1380*54fd6939SJiyong Park * in:  x0 = offset
1381*54fd6939SJiyong Park * out: w0 = value read
1382*54fd6939SJiyong Park * uses x0, x1
1383*54fd6939SJiyong Park */
1384*54fd6939SJiyong Park_read_reg_reset:
1385*54fd6939SJiyong Park	ldr	x1, =NXP_RESET_ADDR
1386*54fd6939SJiyong Park	ldr	w0, [x1, x0]
1387*54fd6939SJiyong Park	ret
1388