1/*
2 * Copyright 2020-2022 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include <asm_macros.S>
9#include <dcfg_lsch2.h>
10#include <nxp_timer.h>
11#include <plat_gic.h>
12#include <scfg.h>
13
14#include <bl31_data.h>
15#include <plat_psci.h>
16#include <platform_def.h>
17
18#define DAIF_DATA		AUX_01_DATA
19#define TIMER_CNTRL_DATA	AUX_02_DATA
20
21.global soc_init_lowlevel
22.global soc_init_percpu
23.global _soc_core_release
24.global _soc_core_restart
25.global _soc_ck_disabled
26.global _soc_sys_reset
27.global _soc_sys_off
28.global _soc_set_start_addr
29.global _getGICC_BaseAddr
30.global _getGICD_BaseAddr
31.global _soc_core_prep_off
32.global _soc_core_entr_off
33.global _soc_core_exit_off
34.global _soc_core_prep_stdby
35.global _soc_core_entr_stdby
36.global _soc_core_exit_stdby
37.global _soc_core_prep_pwrdn
38.global _soc_core_entr_pwrdn
39.global _soc_core_exit_pwrdn
40.global _soc_clstr_prep_stdby
41.global _soc_clstr_exit_stdby
42.global _soc_clstr_prep_pwrdn
43.global _soc_clstr_exit_pwrdn
44.global _soc_sys_prep_stdby
45.global _soc_sys_exit_stdby
46.global _soc_sys_prep_pwrdn
47.global _soc_sys_pwrdn_wfi
48.global _soc_sys_exit_pwrdn
49
50
51/* This function initialize the soc
52 * in: void
53 * out: void
54 */
55func soc_init_lowlevel
56    ret
57endfunc soc_init_lowlevel
58
59
60/* void soc_init_percpu(void)
61 * this function performs any soc-specific initialization that is needed on
62 * a per-core basis
63 * in:  none
64 * out: none
65 * uses x0, x1, x2, x3
66 */
67func soc_init_percpu
68	mov	x3, x30
69
70	bl	plat_my_core_mask
71	mov	x2, x0
72
73	/* see if this core is marked for prefetch disable */
74	mov	x0, #PREFETCH_DIS_OFFSET
75	bl	_get_global_data  /* 0-1 */
76	tst	x0, x2
77	b.eq	1f
78	bl	_disable_ldstr_pfetch_A72  /* 0 */
791:
80	mov	x30, x3
81	ret
82endfunc soc_init_percpu
83
84/* part of CPU_ON
85 * this function releases a secondary core from reset
86 * in:   x0 = core_mask_lsb
87 * out:  none
88 * uses: x0, x1, x2, x3
89 */
90func _soc_core_release
91
92#if (TEST_BL31)
93	rbit	w2, w0
94	/* x2 = core mask msb */
95#else
96	mov	x2, x0
97#endif
98	/* write COREBCR */
99	mov	x1, #NXP_SCFG_ADDR
100	rev	w3, w2
101	str	w3, [x1, #SCFG_COREBCR_OFFSET]
102	isb
103
104	/* read-modify-write BRR */
105	mov	x1, #NXP_DCFG_ADDR
106	ldr	w2, [x1, #DCFG_BRR_OFFSET]
107	rev	w3, w2
108	orr	w3, w3, w0
109	rev	w2, w3
110	str	w2, [x1, #DCFG_BRR_OFFSET]
111	isb
112
113	/* send event */
114	sev
115	isb
116	ret
117endfunc _soc_core_release
118
119
120/* part of CPU_ON
121 * this function restarts a core shutdown via _soc_core_entr_off
122 * in:  x0 = core mask lsb (of the target cpu)
123 * out: x0 == 0, on success
124 *      x0 != 0, on failure
125 * uses x0, x1, x2, x3, x4, x5
126 */
127func _soc_core_restart
128	mov	x5, x30
129	mov	x3, x0
130
131	/*
132	 * unset ph20 request in RCPM_PCPH20CLEARR
133	 * this is an lsb-0 register
134	 */
135	ldr	x1, =NXP_RCPM_ADDR
136	rev	w2, w3
137	str	w2, [x1, #RCPM_PCPH20CLRR_OFFSET]
138	dsb	sy
139	isb
140
141	bl	_getGICD_BaseAddr
142	mov	x4, x0
143
144	/* enable forwarding of group 0 interrupts by setting GICD_CTLR[0] = 1 */
145	ldr	w1, [x4, #GICD_CTLR_OFFSET]
146	orr	w1, w1, #GICD_CTLR_EN_GRP0
147	str	w1, [x4, #GICD_CTLR_OFFSET]
148	dsb	sy
149	isb
150
151
152	/*
153	 * fire SGI by writing to GICD_SGIR the following values:
154	 * [25:24] = 0x0 (forward interrupt to the CPU interfaces
155	 *           specified in CPUTargetList field)
156	 * [23:16] = core mask lsb[7:0] (forward interrupt to target cpu)
157	 * [15]    = 0 (forward SGI only if it is configured as group 0 interrupt)
158	 * [3:0]   = 0xF (interrupt ID = 15)
159	 */
160	lsl	w1, w3, #16
161	orr	w1, w1, #0xF
162	str	w1, [x4, #GICD_SGIR_OFFSET]
163	dsb	sy
164	isb
165
166	/* load '0' on success */
167	mov	x0, xzr
168
169	mov	x30, x5
170	ret
171endfunc _soc_core_restart
172
173/*
174 * This function determines if a core is disabled via COREDISR
175 * in:  w0  = core_mask_lsb
176 * out: w0  = 0, core not disabled
177 *      w0 != 0, core disabled
178 * uses x0, x1, x2
179 */
180func _soc_ck_disabled
181	/* get base addr of dcfg block */
182	mov	x1, #NXP_DCFG_ADDR
183
184	/* read COREDISR */
185	ldr	w1, [x1, #DCFG_COREDISR_OFFSET]
186	rev	w2, w1
187
188	/* test core bit */
189	and	w0, w2, w0
190	ret
191endfunc _soc_ck_disabled
192
193/*
194 *This function resets the system via SoC-specific methods
195 * in:  none
196 * out: none
197 * uses x0, x1, x2, x3
198 */
199func _soc_sys_reset
200	ldr	x2, =NXP_DCFG_ADDR
201
202	/* make sure the mask is cleared in the reset request mask register */
203	mov	w1, wzr
204	str	w1, [x2, #DCFG_RSTRQMR1_OFFSET]
205
206	/* set the reset request */
207	ldr	w1, =RSTCR_RESET_REQ
208	ldr	x3, =DCFG_RSTCR_OFFSET
209	rev	w0, w1
210	str	w0, [x2, x3]
211
212	/*
213	 * just in case this address range is mapped as cacheable,
214	 * flush the write out of the dcaches
215	 */
216	add	x3, x2, x3
217	dc	cvac, x3
218	dsb	st
219	isb
220
221	/* Note: this function does not return */
2221:
223	wfi
224	b	1b
225endfunc _soc_sys_reset
226
227/*
228 * Part of SYSTEM_OFF
229 * this function turns off the SoC clocks
230 * Note: this function is not intended to return, and the only allowable
231 *       recovery is POR
232 * in:  none
233 * out: none
234 * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9
235 */
236func _soc_sys_off
237
238	/* mask interrupts at the core */
239	mrs	x1, DAIF
240	mov	x0, #DAIF_SET_MASK
241	orr	x0, x1, x0
242	msr	DAIF, x0
243
244	/* disable icache, dcache, mmu @ EL1 */
245	mov	x1, #SCTLR_I_C_M_MASK
246	mrs	x0, sctlr_el1
247	bic	x0, x0, x1
248	msr	sctlr_el1, x0
249
250	/* disable dcache for EL3 */
251	mrs	x1, SCTLR_EL3
252	bic	x1, x1, #SCTLR_C_MASK
253	/* make sure icache is enabled */
254	orr	x1, x1, #SCTLR_I_MASK
255	msr	SCTLR_EL3, x1
256	isb
257
258	/* Enable dynamic retention ctrl (CPUECTLR[2:0]) and SMP (CPUECTLR[6]) */
259	mrs	x0, CORTEX_A72_ECTLR_EL1
260	orr	x0, x0, #CPUECTLR_TIMER_8TICKS
261	orr	x0, x0, #CPUECTLR_SMPEN_EN
262	msr	CORTEX_A72_ECTLR_EL1, x0
263
264	/* set WFIL2EN in SCFG_CLUSTERPMCR */
265	ldr	x0, =SCFG_COREPMCR_OFFSET
266	ldr	x1, =COREPMCR_WFIL2
267	bl	write_reg_scfg
268
269	/* request LPM20 */
270	mov	x0, #RCPM_POWMGTCSR_OFFSET
271	bl	read_reg_rcpm
272	orr	x1, x0, #RCPM_POWMGTCSR_LPM20_REQ
273	mov	x0, #RCPM_POWMGTCSR_OFFSET
274	bl	write_reg_rcpm
275
276	dsb  sy
277	isb
2781:
279	wfi
280	b	1b
281endfunc _soc_sys_off
282
283/*
284 * Write a register in the RCPM block
285 * in:  x0 = offset
286 * in:  w1 = value to write
287 * uses x0, x1, x2, x3
288 */
289func write_reg_rcpm
290	ldr	x2, =NXP_RCPM_ADDR
291	/* swap for BE */
292	rev	w3, w1
293	str	w3, [x2, x0]
294	ret
295endfunc write_reg_rcpm
296
297/*
298 * Read a register in the RCPM block
299 * in:  x0 = offset
300 * out: w0 = value read
301 * uses x0, x1, x2
302 */
303func read_reg_rcpm
304	ldr	x2, =NXP_RCPM_ADDR
305	ldr	w1, [x2, x0]
306	/* swap for BE */
307	rev	w0, w1
308	ret
309endfunc read_reg_rcpm
310
311/*
312 * Write a register in the SCFG block
313 * in:  x0 = offset
314 * in:  w1 = value to write
315 * uses x0, x1, x2, x3
316 */
317func write_reg_scfg
318	mov	x2, #NXP_SCFG_ADDR
319	/* swap for BE */
320	rev	w3, w1
321	str	w3, [x2, x0]
322	ret
323endfunc write_reg_scfg
324
325/*
326 * Read a register in the SCFG block
327 * in:  x0 = offset
328 * out: w0 = value read
329 * uses x0, x1, x2
330 */
331func read_reg_scfg
332	mov	x2, #NXP_SCFG_ADDR
333	ldr	w1, [x2, x0]
334	/* swap for BE */
335	rev	w0, w1
336	ret
337endfunc read_reg_scfg
338
339/*
340 * Part of CPU_OFF
341 * this function programs SoC & GIC registers in preparation for shutting down
342 * the core
343 * in:  x0 = core mask lsb
344 * out: none
345 * uses x0, x1, x2, x3, x4, x5, x6, x7
346 */
347func _soc_core_prep_off
348	mov	x7, x30
349	mov	x6, x0
350
351	/* Set retention control in CPUECTLR make sure smpen bit is set */
352	mrs	x4, CORTEX_A72_ECTLR_EL1
353	bic	x4, x4, #CPUECTLR_RET_MASK
354	orr	x4, x4, #CPUECTLR_TIMER_8TICKS
355	orr	x4, x4, #CPUECTLR_SMPEN_EN
356	msr	CORTEX_A72_ECTLR_EL1, x4
357
358	/* save timer control current value */
359	mov	x5, #NXP_TIMER_ADDR
360	ldr	w4, [x5, #SYS_COUNTER_CNTCR_OFFSET]
361	mov	w2, w4
362	mov	x0, x6
363	mov	x1, #TIMER_CNTRL_DATA
364	bl	_setCoreData
365
366	/* enable the timer */
367	orr	w4, w4, #CNTCR_EN_MASK
368	str	w4, [x5, #SYS_COUNTER_CNTCR_OFFSET]
369
370	bl	_getGICC_BaseAddr
371	mov	x5, x0
372
373	/* disable signaling of ints */
374	ldr	w3, [x5, #GICC_CTLR_OFFSET]
375	bic	w3, w3, #GICC_CTLR_EN_GRP0
376	bic	w3, w3, #GICC_CTLR_EN_GRP1
377	str	w3, [x5, #GICC_CTLR_OFFSET]
378	dsb	sy
379	isb
380
381
382	/*
383	 * set retention control in SCFG_RETREQCR
384	 * Note: this register is msb 0
385	 */
386	ldr	x4, =SCFG_RETREQCR_OFFSET
387	mov	x0, x4
388	bl	read_reg_scfg
389	rbit	w1, w6
390	orr	w1, w0, w1
391	mov	x0, x4
392	bl	write_reg_scfg
393
394	/* set the priority filter */
395	ldr	w2, [x5, #GICC_PMR_OFFSET]
396	orr	w2, w2, #GICC_PMR_FILTER
397	str	w2, [x5, #GICC_PMR_OFFSET]
398
399	/* setup GICC_CTLR */
400	bic	w3, w3, #GICC_CTLR_ACKCTL_MASK
401	orr	w3, w3, #GICC_CTLR_FIQ_EN_MASK
402	orr	w3, w3, #GICC_CTLR_EOImodeS_MASK
403	orr	w3, w3, #GICC_CTLR_CBPR_MASK
404	str	w3, [x5, #GICC_CTLR_OFFSET]
405
406	/* setup the banked-per-core GICD registers */
407	bl	_getGICD_BaseAddr
408	mov	x5, x0
409
410	/* define SGI15 as Grp0 */
411	ldr	w2, [x5, #GICD_IGROUPR0_OFFSET]
412	bic	w2, w2, #GICD_IGROUP0_SGI15
413	str	w2, [x5, #GICD_IGROUPR0_OFFSET]
414
415	/* set priority of SGI 15 to highest... */
416	ldr	w2, [x5, #GICD_IPRIORITYR3_OFFSET]
417	bic	w2, w2, #GICD_IPRIORITY_SGI15_MASK
418	str	w2, [x5, #GICD_IPRIORITYR3_OFFSET]
419
420	/* enable SGI 15 */
421	ldr	w2, [x5, #GICD_ISENABLER0_OFFSET]
422	orr	w2, w2, #GICD_ISENABLE0_SGI15
423	str	w2, [x5, #GICD_ISENABLER0_OFFSET]
424
425	/* enable the cpu interface */
426	bl	_getGICC_BaseAddr
427	mov	x2, x0
428	orr	w3, w3, #GICC_CTLR_EN_GRP0
429	str	w3, [x2, #GICC_CTLR_OFFSET]
430
431
432	/* clear any pending SGIs */
433	ldr	x2, =GICD_CPENDSGIR_CLR_MASK
434	add	x0, x5, #GICD_CPENDSGIR3_OFFSET
435	str	w2, [x0]
436
437	/*
438	 * Set the PC_PH20_REQ bit in RCPM_PCPH20SETR
439	 * this is an lsb-0 register
440	 */
441	mov	x1, x6
442	mov	x0, #RCPM_PCPH20SETR_OFFSET
443	bl	write_reg_rcpm
444
445	dsb	sy
446	isb
447	mov	x30, x7
448	ret
449endfunc _soc_core_prep_off
450
451/*
452 * Part of CPU_OFF
453 * this function performs the final steps to shutdown the core
454 * in:  x0 = core mask lsb
455 * out: none
456 * uses x0, x1, x2, x3, x4, x5
457 */
458func _soc_core_entr_off
459	mov	x5, x30
460	mov	x4, x0
461
462	bl	_getGICD_BaseAddr
463	mov	x3, x0
464
4653:
466	/* enter low-power state by executing wfi */
467	wfi
468
469	/* see if we got hit by SGI 15 */
470	add	x0, x3, #GICD_SPENDSGIR3_OFFSET
471	ldr	w2, [x0]
472	and	w2, w2, #GICD_SPENDSGIR3_SGI15_MASK
473	cbz	w2, 4f
474
475	/* clear the pending SGI */
476	ldr	x2, =GICD_CPENDSGIR_CLR_MASK
477	add	x0, x3, #GICD_CPENDSGIR3_OFFSET
478	str	w2, [x0]
4794:
480	/* check if core has been turned on */
481	mov	x0, x4
482	bl	_getCoreState
483
484	cmp	x0, #CORE_WAKEUP
485	b.ne	3b
486
487	/* if we get here, then we have exited the wfi */
488	dsb	sy
489	isb
490	mov	x30, x5
491	ret
492endfunc _soc_core_entr_off
493
494/*
495 * Part of CPU_OFF
496 * this function starts the process of starting a core back up
497 * in:  x0 = core mask lsb
498 * out: none
499 * uses x0, x1, x2, x3, x4, x5, x6
500 */
501func _soc_core_exit_off
502	mov	x6, x30
503	mov	x5, x0
504
505	/*
506	 * Clear ph20 request in RCPM_PCPH20CLRR - no need
507	 * to do that here, it has been done in _soc_core_restart
508	 */
509	bl	_getGICC_BaseAddr
510	mov	x1, x0
511
512	/* read GICC_IAR */
513	ldr	w0, [x1, #GICC_IAR_OFFSET]
514
515	/* write GICC_EIOR - signal end-of-interrupt */
516	str	w0, [x1, #GICC_EOIR_OFFSET]
517
518	/* write GICC_DIR - disable interrupt */
519	str	w0, [x1, #GICC_DIR_OFFSET]
520
521	/* disable signaling of grp0 ints */
522	ldr	w3, [x1, #GICC_CTLR_OFFSET]
523	bic	w3, w3, #GICC_CTLR_EN_GRP0
524	str	w3, [x1, #GICC_CTLR_OFFSET]
525
526	/*
527	 * Unset retention request in SCFG_RETREQCR
528	 * Note: this register is msb-0
529	 */
530	ldr	x4, =SCFG_RETREQCR_OFFSET
531	mov	x0, x4
532	bl	read_reg_scfg
533	rbit	w1, w5
534	bic	w1, w0, w1
535	mov	x0, x4
536	bl	write_reg_scfg
537
538	/* restore timer ctrl */
539	mov	x0, x5
540	mov	x1, #TIMER_CNTRL_DATA
541	bl	_getCoreData
542	/* w0 = timer ctrl saved value */
543	mov	x2, #NXP_TIMER_ADDR
544	str	w0, [x2, #SYS_COUNTER_CNTCR_OFFSET]
545
546	dsb	sy
547	isb
548	mov	x30, x6
549	ret
550endfunc _soc_core_exit_off
551
552/*
553 * Function loads a 64-bit execution address of the core in the soc registers
554 * BOOTLOCPTRL/H
555 * in:  x0, 64-bit address to write to BOOTLOCPTRL/H
556 * uses x0, x1, x2, x3
557 */
558func _soc_set_start_addr
559	/* get the 64-bit base address of the scfg block */
560	ldr	x2, =NXP_SCFG_ADDR
561
562	/* write the 32-bit BOOTLOCPTRL register */
563	mov	x1, x0
564	rev	w3, w1
565	str	w3, [x2, #SCFG_BOOTLOCPTRL_OFFSET]
566
567	/* write the 32-bit BOOTLOCPTRH register */
568	lsr	x1, x0, #32
569	rev	w3, w1
570	str	w3, [x2, #SCFG_BOOTLOCPTRH_OFFSET]
571	ret
572endfunc _soc_set_start_addr
573
574/*
575 * This function returns the base address of the gic distributor
576 * in:  none
577 * out: x0 = base address of gic distributor
578 * uses x0
579 */
580func _getGICD_BaseAddr
581#if (TEST_BL31)
582	/* defect in simulator - gic base addresses are on 4Kb boundary */
583	ldr	x0, =NXP_GICD_4K_ADDR
584#else
585	ldr	x0, =NXP_GICD_64K_ADDR
586#endif
587	ret
588endfunc _getGICD_BaseAddr
589
590/*
591 * This function returns the base address of the gic controller
592 * in:  none
593 * out: x0 = base address of gic controller
594 * uses x0
595 */
596func _getGICC_BaseAddr
597#if (TEST_BL31)
598	/* defect in simulator - gic base addresses are on 4Kb boundary */
599	ldr	x0, =NXP_GICC_4K_ADDR
600#else
601	ldr	x0, =NXP_GICC_64K_ADDR
602#endif
603	ret
604endfunc _getGICC_BaseAddr
605
606/*
607 * Part of CPU_SUSPEND
608 * this function puts the calling core into standby state
609 * in:  x0 = core mask lsb
610 * out: none
611 * uses x0
612 */
613func _soc_core_entr_stdby
614	dsb	sy
615	isb
616	wfi
617
618	ret
619endfunc _soc_core_entr_stdby
620
621
622/*
623 * Part of CPU_SUSPEND
624 * this function performs SoC-specific programming prior to standby
625 * in:  x0 = core mask lsb
626 * out: none
627 * uses x0, x1
628 */
629func _soc_core_prep_stdby
630	/* clear CORTEX_A72_ECTLR_EL1[2:0] */
631	mrs	x1, CORTEX_A72_ECTLR_EL1
632	bic	x1, x1, #CPUECTLR_TIMER_MASK
633	msr	CORTEX_A72_ECTLR_EL1, x1
634
635	ret
636endfunc _soc_core_prep_stdby
637
638/*
639 * Part of CPU_SUSPEND
640 * this function performs any SoC-specific cleanup after standby state
641 * in:  x0 = core mask lsb
642 * out: none
643 * uses none
644 */
645func _soc_core_exit_stdby
646	ret
647endfunc _soc_core_exit_stdby
648
649/*
650 * Part of CPU_SUSPEND
651 * this function performs SoC-specific programming prior to power-down
652 * in:  x0 = core mask lsb
653 * out: none
654 * uses x0, x1, x2, x3, x4, x5
655 */
656func _soc_core_prep_pwrdn
657	mov	x5, x30
658	mov	x4, x0
659
660	/* enable CPU retention + set smp */
661	mrs	x1, CORTEX_A72_ECTLR_EL1
662	orr	x1, x1, #0x1
663	orr	x1, x1, #CPUECTLR_SMPEN_MASK
664	msr	CORTEX_A72_ECTLR_EL1, x1
665
666	/*
667	 * set the retention request in SCFG_RETREQCR
668	 * this is an msb-0 register
669	 */
670	ldr	x3, =SCFG_RETREQCR_OFFSET
671	mov	x0, x3
672	bl	read_reg_scfg
673	rbit	w1, w4
674	orr	w1, w0, w1
675	mov	x0, x3
676	bl	write_reg_scfg
677
678	/*
679	 * Set the PC_PH20_REQ bit in RCPM_PCPH20SETR
680	 * this is an lsb-0 register
681	 */
682	mov	x1, x4
683	mov	x0, #RCPM_PCPH20SETR_OFFSET
684	bl	write_reg_rcpm
685
686	mov	x30, x5
687	ret
688endfunc _soc_core_prep_pwrdn
689
690/*
691 * Part of CPU_SUSPEND
692 * this function puts the calling core into a power-down state
693 * in:  x0 = core mask lsb
694 * out: none
695 * uses x0
696 */
697func _soc_core_entr_pwrdn
698	dsb	sy
699	isb
700	wfi
701
702	ret
703endfunc _soc_core_entr_pwrdn
704
705/*
706 * Part of CPU_SUSPEND
707 * this function cleans up after a core exits power-down
708 * in:  x0 = core mask lsb
709 * out: none
710 * uses x0, x1, x2, x3, x4, x5
711 */
712func _soc_core_exit_pwrdn
713	mov	x5, x30
714	mov	x4, x0
715
716	/*
717	 * Set the PC_PH20_REQ bit in RCPM_PCPH20CLRR
718	 * this is an lsb-0 register
719	 */
720	mov	x1, x4
721	mov	x0, #RCPM_PCPH20CLRR_OFFSET
722	bl	write_reg_rcpm
723
724	/*
725	 * Unset the retention request in SCFG_RETREQCR
726	 * this is an msb-0 register
727	 */
728	ldr	x3, =SCFG_RETREQCR_OFFSET
729	mov	x0, x3
730	bl	read_reg_scfg
731	rbit	w1, w4
732	bic	w1, w0, w1
733	mov	x0, x3
734	bl	write_reg_scfg
735
736	mov	x30, x5
737	ret
738endfunc _soc_core_exit_pwrdn
739
740/*
741 * Part of CPU_SUSPEND
742 * this function performs SoC-specific programming prior to standby
743 * in:  x0 = core mask lsb
744 * out: none
745 * uses none
746 */
747func _soc_clstr_prep_stdby
748	/* clear CORTEX_A72_ECTLR_EL1[2:0] */
749	mrs	x1, CORTEX_A72_ECTLR_EL1
750	bic	x1, x1, #CPUECTLR_TIMER_MASK
751	msr	CORTEX_A72_ECTLR_EL1, x1
752
753	ret
754endfunc _soc_clstr_prep_stdby
755
756/*
757 * Part of CPU_SUSPEND
758 * this function performs any SoC-specific cleanup after standby state
759 * in:  x0 = core mask lsb
760 * out: none
761 * uses none
762 */
763func _soc_clstr_exit_stdby
764	ret
765endfunc _soc_clstr_exit_stdby
766
767/*
768 * Part of CPU_SUSPEND
769 * this function performs SoC-specific programming prior to power-down
770 * in:  x0 = core mask lsb
771 * out: none
772 * uses x0, x1, x2, x3, x4, x5
773 */
774func _soc_clstr_prep_pwrdn
775	mov	x5, x30
776	mov	x4, x0
777
778	/* enable CPU retention + set smp */
779	mrs	x1, CORTEX_A72_ECTLR_EL1
780	orr	x1, x1, #0x1
781	orr	x1, x1, #CPUECTLR_SMPEN_MASK
782	msr	CORTEX_A72_ECTLR_EL1, x1
783
784	/*
785	 * Set the retention request in SCFG_RETREQCR
786	 * this is an msb-0 register.
787	 */
788	ldr	x3, =SCFG_RETREQCR_OFFSET
789	mov	x0, x3
790	bl	read_reg_scfg
791	rbit	w1, w4
792	orr	w1, w0, w1
793	mov	x0, x3
794	bl	write_reg_scfg
795
796	/*
797	 * Set the PC_PH20_REQ bit in RCPM_PCPH20SETR
798	 * this is an lsb-0 register.
799	 */
800	mov	x1, x4
801	mov	x0, #RCPM_PCPH20SETR_OFFSET
802	bl	write_reg_rcpm
803
804	mov	x30, x5
805	ret
806endfunc _soc_clstr_prep_pwrdn
807
808/*
809 * Part of CPU_SUSPEND
810 * this function cleans up after a core exits power-down
811 * in:  x0 = core mask lsb
812 * out: none
813 * uses x0, x1, x2, x3, x4, x5
814 */
815func _soc_clstr_exit_pwrdn
816	mov	x5, x30
817	mov	x4, x0
818
819	/*
820	 * Set the PC_PH20_REQ bit in RCPM_PCPH20CLRR
821	 * this is an lsb-0 register.
822	 */
823	mov	x1, x4
824	mov	x0, #RCPM_PCPH20CLRR_OFFSET
825	bl	write_reg_rcpm
826
827	/*
828	 * Unset the retention request in SCFG_RETREQCR
829	 * this is an msb-0 register.
830	 */
831	ldr	x3, =SCFG_RETREQCR_OFFSET
832	mov	x0, x3
833	bl	read_reg_scfg
834	rbit	w1, w4
835	bic	w1, w0, w1
836	mov	x0, x3
837	bl	write_reg_scfg
838
839	mov	x30, x5
840	ret
841endfunc _soc_clstr_exit_pwrdn
842
843/*
844 * Part of CPU_SUSPEND
845 * this function performs SoC-specific programming prior to standby
846 * in:  x0 = core mask lsb
847 * out: none
848 * uses none
849 */
850func _soc_sys_prep_stdby
851	/* clear CORTEX_A72_ECTLR_EL1[2:0] */
852	mrs	x1, CORTEX_A72_ECTLR_EL1
853	bic	x1, x1, #CPUECTLR_TIMER_MASK
854	msr	CORTEX_A72_ECTLR_EL1, x1
855
856	ret
857endfunc _soc_sys_prep_stdby
858
859/* Part of CPU_SUSPEND
860 * this function performs any SoC-specific cleanup after standby state
861 * in:  x0 = core mask lsb
862 * out: none
863 * uses none
864 */
865func _soc_sys_exit_stdby
866	ret
867endfunc _soc_sys_exit_stdby
868
869/*
870 * Part of CPU_SUSPEND
871 * this function performs SoC-specific programming prior to
872 * suspend-to-power-down
873 * in:  x0 = core mask lsb
874 * out: none
875 * uses x0, x1, x2, x3, x4
876 */
877func _soc_sys_prep_pwrdn
878	mov	x4, x30
879
880	/* Enable dynamic retention contrl (CPUECTLR[2:0]) and SMP (CPUECTLR[6]) */
881	mrs	x0, CORTEX_A72_ECTLR_EL1
882	bic	x0, x0, #CPUECTLR_TIMER_MASK
883	orr	x0, x0, #CPUECTLR_TIMER_8TICKS
884	orr	x0, x0, #CPUECTLR_SMPEN_EN
885	msr	CORTEX_A72_ECTLR_EL1, x0
886
887	/* Set WFIL2EN in SCFG_CLUSTERPMCR */
888	ldr	x0, =SCFG_COREPMCR_OFFSET
889	ldr	x1, =COREPMCR_WFIL2
890	bl	write_reg_scfg
891
892	isb
893	mov	x30, x4
894	ret
895endfunc _soc_sys_prep_pwrdn
896
897/*
898 * Part of CPU_SUSPEND
899 * this function puts the calling core, and potentially the soc, into a
900 * low-power state
901 * in:  x0 = core mask lsb
902 * out: x0 = 0, success
903 *      x0 < 0, failure
904 * uses x0, x1, x2, x3, x4
905 */
906func _soc_sys_pwrdn_wfi
907	mov	x4, x30
908
909	/* request LPM20 */
910	mov	x0, #RCPM_POWMGTCSR_OFFSET
911	bl	read_reg_rcpm
912	orr	x1, x0, #RCPM_POWMGTCSR_LPM20_REQ
913	mov	x0, #RCPM_POWMGTCSR_OFFSET
914	bl	write_reg_rcpm
915
916	dsb	sy
917	isb
918	wfi
919
920	mov	x30, x4
921	ret
922endfunc _soc_sys_pwrdn_wfi
923
924/*
925 * Part of CPU_SUSPEND
926 * this function performs any SoC-specific cleanup after power-down
927 * in:  x0 = core mask lsb
928 * out: none
929 * uses x0, x1
930 */
931func _soc_sys_exit_pwrdn
932	/* clear WFIL2_EN in SCFG_COREPMCR */
933	mov	x1, #NXP_SCFG_ADDR
934	str	wzr, [x1, #SCFG_COREPMCR_OFFSET]
935
936	ret
937endfunc _soc_sys_exit_pwrdn
938