blob: 0c6b7ea7d6791d2382299e41bc8f16e292deb006 [file] [log] [blame]
Jiafei Panb9d543c2022-02-18 15:26:08 +08001/*
2 * Copyright 2022 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7.section .text, "ax"
8
9#include <asm_macros.S>
10#include <lib/psci/psci.h>
11#include <nxp_timer.h>
12#include <plat_gic.h>
13
14#include "bl31_data.h"
15#include "plat_psci.h"
16#include "platform_def.h"
17
18/*
19 * the BASE address for these offsets is AUX_01_DATA in the
20 * bootcore's psci data region
21 */
22#define DEVDISR2_MASK_OFFSET 0x0 /* references AUX_01_DATA */
23#define DEVDISR5_MASK_OFFSET 0x8 /* references AUX_02_DATA */
24
25/*
26 * the BASE address for these offsets is AUX_04_DATA in the
27 * bootcore's psci data region
28 */
29#define GICD_BASE_ADDR_OFFSET 0x0 /* references AUX_04_DATA */
30#define GICC_BASE_ADDR_OFFSET 0x8 /* references AUX_05_DATA */
31
32#define IPSTPACK_RETRY_CNT 0x10000
33#define DDR_SLEEP_RETRY_CNT 0x10000
34#define CPUACTLR_EL1 S3_1_C15_C2_0
35#define DDR_SDRAM_CFG_2_FRCSR 0x80000000
36#define DDR_SDRAM_CFG_2_OFFSET 0x114
37#define DDR_TIMING_CFG_4_OFFSET 0x160
38#define DDR_CNTRL_BASE_ADDR 0x01080000
39
40#define DLL_LOCK_MASK 0x3
41#define DLL_LOCK_VALUE 0x2
42
43#define ERROR_DDR_SLEEP -1
44#define ERROR_DDR_WAKE -2
45#define ERROR_NO_QUIESCE -3
46
47#define CORE_RESTARTABLE 0
48#define CORE_NOT_RESTARTABLE 1
49
50.global soc_init_lowlevel
51.global soc_init_percpu
52
53.global _soc_core_release
54.global _soc_core_restart
55.global _soc_ck_disabled
56.global _soc_sys_reset
57.global _soc_sys_off
58
59.global _soc_core_prep_off
60.global _soc_core_entr_off
61.global _soc_core_exit_off
62
63.global _soc_core_prep_stdby
64.global _soc_core_entr_stdby
65.global _soc_core_exit_stdby
66.global _soc_core_prep_pwrdn
67.global _soc_core_entr_pwrdn
68.global _soc_core_exit_pwrdn
69.global _soc_clstr_prep_stdby
70.global _soc_clstr_exit_stdby
71.global _soc_clstr_prep_pwrdn
72.global _soc_clstr_exit_pwrdn
73.global _soc_sys_prep_stdby
74.global _soc_sys_exit_stdby
75.global _soc_sys_prep_pwrdn
76.global _soc_sys_pwrdn_wfi
77.global _soc_sys_exit_pwrdn
78
79.global _set_platform_security
80.global _soc_set_start_addr
81
82.equ TZPCDECPROT_0_SET_BASE, 0x02200804
83.equ TZPCDECPROT_1_SET_BASE, 0x02200810
84.equ TZPCDECPROT_2_SET_BASE, 0x0220081C
85
86.equ TZASC_REGION_ATTRIBUTES_0_0, 0x01100110
87
88.equ MPIDR_AFFINITY0_MASK, 0x00FF
89.equ MPIDR_AFFINITY1_MASK, 0xFF00
90.equ CPUECTLR_DISABLE_TWALK_PREFETCH, 0x4000000000
91.equ CPUECTLR_INS_PREFETCH_MASK, 0x1800000000
92.equ CPUECTLR_DAT_PREFETCH_MASK, 0x0300000000
93.equ OSDLR_EL1_DLK_LOCK, 0x1
94.equ CNTP_CTL_EL0_EN, 0x1
95.equ CNTP_CTL_EL0_IMASK, 0x2
96/* shifted value for incrementing cluster count in mpidr */
97.equ MPIDR_CLUSTER, 0x100
98
99/*
100 * This function initialize the soc,
101 * in: none
102 * out: none
103 * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11
104 */
105func soc_init_lowlevel
106 /*
107 * called from C, so save the non-volatile regs
108 * save these as pairs of registers to maintain the
109 * required 16-byte alignment on the stack
110 */
111 stp x4, x5, [sp, #-16]!
112 stp x6, x7, [sp, #-16]!
113 stp x8, x9, [sp, #-16]!
114 stp x10, x11, [sp, #-16]!
115 stp x12, x13, [sp, #-16]!
116 stp x18, x30, [sp, #-16]!
117
118 /*
119 * make sure the personality has been established by releasing cores
120 * that are marked "to-be-disabled" from reset
121 */
122 bl release_disabled
123
124 /* set SCRATCHRW7 to 0x0 */
125 ldr x0, =DCFG_SCRATCHRW7_OFFSET
126 mov x1, xzr
127 bl _write_reg_dcfg
128
129 /* restore the aarch32/64 non-volatile registers */
130 ldp x18, x30, [sp], #16
131 ldp x12, x13, [sp], #16
132 ldp x10, x11, [sp], #16
133 ldp x8, x9, [sp], #16
134 ldp x6, x7, [sp], #16
135 ldp x4, x5, [sp], #16
136 ret
137endfunc soc_init_lowlevel
138
139/*
140 * void soc_init_percpu(void)
141 * this function performs any soc-specific initialization that is needed on
142 * a per-core basis
143 * in: none
144 * out: none
145 * uses x0, x1, x2, x3
146 */
147func soc_init_percpu
148 stp x4, x30, [sp, #-16]!
149
150 bl plat_my_core_mask
151 mov x2, x0
152
153 /* x2 = core mask */
154
155 /* see if this core is marked for prefetch disable */
156 mov x0, #PREFETCH_DIS_OFFSET
157 bl _get_global_data
158 tst x0, x2
159 b.eq 1f
160 bl _disable_ldstr_pfetch_A53
1611:
162 mov x0, #NXP_PMU_ADDR
163 bl enable_timer_base_to_cluster
164 ldp x4, x30, [sp], #16
165 ret
166endfunc soc_init_percpu
167
168/*
169 * this function sets the security mechanisms in the SoC to implement the
170 * Platform Security Policy
171 */
172func _set_platform_security
173 mov x3, x30
174
175#if (!SUPPRESS_TZC)
176 /* initialize the tzpc */
177 bl init_tzpc
178#endif
179
180#if (!SUPPRESS_SEC)
181 /* initialize secmon */
182 bl initSecMon
183#endif
184 mov x30, x3
185 ret
186endfunc _set_platform_security
187
188/*
189 * this function writes a 64-bit address to bootlocptrh/l
190 * in: x0, 64-bit address to write to BOOTLOCPTRL/H
191 * out: none
192 * uses x0, x1, x2
193 */
194func _soc_set_start_addr
195 /* get the 64-bit base address of the dcfg block */
196 ldr x2, =NXP_DCFG_ADDR
197
198 /* write the 32-bit BOOTLOCPTRL register */
199 mov x1, x0
200 str w1, [x2, #DCFG_BOOTLOCPTRL_OFFSET]
201
202 /* write the 32-bit BOOTLOCPTRH register */
203 lsr x1, x0, #32
204 str w1, [x2, #DCFG_BOOTLOCPTRH_OFFSET]
205 ret
206endfunc _soc_set_start_addr
207
208/*
209 * part of CPU_ON
210 * this function releases a secondary core from reset
211 * in: x0 = core_mask_lsb
212 * out: none
213 * uses: x0, x1, x2, x3
214 */
215_soc_core_release:
216 mov x3, x30
217
218 /* x0 = core mask */
219
220 ldr x1, =NXP_SEC_REGFILE_ADDR
221 /*
222 * write to CORE_HOLD to tell the bootrom that we want this core
223 * to run
224 */
225 str w0, [x1, #CORE_HOLD_OFFSET]
226
227 /* x0 = core mask */
228
229 /* read-modify-write BRRL to release core */
230 mov x1, #NXP_RESET_ADDR
231 ldr w2, [x1, #BRR_OFFSET]
232 orr w2, w2, w0
233 str w2, [x1, #BRR_OFFSET]
234 dsb sy
235 isb
236
237 /* send event */
238 sev
239 isb
240
241 mov x30, x3
242 ret
243
244/*
245 * this function determines if a core is disabled via COREDISABLEDSR
246 * in: w0 = core_mask_lsb
247 * out: w0 = 0, core not disabled
248 * w0 != 0, core disabled
249 * uses x0, x1
250 */
251_soc_ck_disabled:
252 /* get base addr of dcfg block */
253 ldr x1, =NXP_DCFG_ADDR
254
255 /* read COREDISABLEDSR */
256 ldr w1, [x1, #DCFG_COREDISABLEDSR_OFFSET]
257
258 /* test core bit */
259 and w0, w1, w0
260
261 ret
262
263/*
264 * part of CPU_ON
265 * this function restarts a core shutdown via _soc_core_entr_off
266 * in: x0 = core mask lsb (of the target cpu)
267 * out: x0 == 0, on success
268 * x0 != 0, on failure
269 * uses x0, x1, x2, x3, x4, x5, x6
270 */
271_soc_core_restart:
272 mov x6, x30
273 mov x4, x0
274
275 /* x4 = core mask lsb */
276
277 /* pgm GICD_CTLR - enable secure grp0 */
278 mov x5, #NXP_GICD_ADDR
279 ldr w2, [x5, #GICD_CTLR_OFFSET]
280 orr w2, w2, #GICD_CTLR_EN_GRP_0
281 str w2, [x5, #GICD_CTLR_OFFSET]
282 dsb sy
283 isb
284 /* poll on RWP til write completes */
2854:
286 ldr w2, [x5, #GICD_CTLR_OFFSET]
287 tst w2, #GICD_CTLR_RWP
288 b.ne 4b
289
290 /*
291 * x4 = core mask lsb
292 * x5 = gicd base addr
293 */
294
295 mov x0, x4
296 bl get_mpidr_value
297
298 /*
299 * x0 = mpidr of target core
300 * x4 = core mask lsb of target core
301 * x5 = gicd base addr
302 */
303
304 /* generate target list bit */
305 and x1, x0, #MPIDR_AFFINITY0_MASK
306 mov x2, #1
307 lsl x2, x2, x1
308 /* get the affinity1 field */
309 and x1, x0, #MPIDR_AFFINITY1_MASK
310 lsl x1, x1, #8
311 orr x2, x2, x1
312 /* insert the INTID for SGI15 */
313 orr x2, x2, #ICC_SGI0R_EL1_INTID
314 /* fire the SGI */
315 msr ICC_SGI0R_EL1, x2
316 dsb sy
317 isb
318
319 /* load '0' on success */
320 mov x0, xzr
321
322 mov x30, x6
323 ret
324
325/*
326 * part of CPU_OFF
327 * this function programs SoC & GIC registers in preparation for shutting down
328 * the core
329 * in: x0 = core mask lsb
330 * out: none
331 * uses x0, x1, x2, x3, x4, x5, x6, x7
332 */
333_soc_core_prep_off:
334 mov x8, x30
335 mov x7, x0
336
337 /* x7 = core mask lsb */
338
339 mrs x1, CPUECTLR_EL1
340 /* set smp and disable L2 snoops in cpuectlr */
341 orr x1, x1, #CPUECTLR_SMPEN_EN
342 orr x1, x1, #CPUECTLR_DISABLE_TWALK_PREFETCH
343 bic x1, x1, #CPUECTLR_INS_PREFETCH_MASK
344 bic x1, x1, #CPUECTLR_DAT_PREFETCH_MASK
345 /* set retention control in cpuectlr */
346 bic x1, x1, #CPUECTLR_TIMER_MASK
347 orr x1, x1, #CPUECTLR_TIMER_8TICKS
348 msr CPUECTLR_EL1, x1
349
350 /* get redistributor rd base addr for this core */
351 mov x0, x7
352 bl get_gic_rd_base
353 mov x6, x0
354
355 /* get redistributor sgi base addr for this core */
356 mov x0, x7
357 bl get_gic_sgi_base
358 mov x5, x0
359
360 /* x5 = gicr sgi base addr
361 * x6 = gicr rd base addr
362 * x7 = core mask lsb
363 */
364
365 /* disable SGI 15 at redistributor - GICR_ICENABLER0 */
366 mov w3, #GICR_ICENABLER0_SGI15
367 str w3, [x5, #GICR_ICENABLER0_OFFSET]
3682:
369 /* poll on rwp bit in GICR_CTLR */
370 ldr w4, [x6, #GICR_CTLR_OFFSET]
371 tst w4, #GICR_CTLR_RWP
372 b.ne 2b
373
374 /* disable GRP1 interrupts at cpu interface */
375 msr ICC_IGRPEN1_EL3, xzr
376
377 /* disable GRP0 ints at cpu interface */
378 msr ICC_IGRPEN0_EL1, xzr
379
380 /* program the redistributor - poll on GICR_CTLR.RWP as needed */
381
382 /* define SGI 15 as Grp0 - GICR_IGROUPR0 */
383 ldr w4, [x5, #GICR_IGROUPR0_OFFSET]
384 bic w4, w4, #GICR_IGROUPR0_SGI15
385 str w4, [x5, #GICR_IGROUPR0_OFFSET]
386
387 /* define SGI 15 as Grp0 - GICR_IGRPMODR0 */
388 ldr w3, [x5, #GICR_IGRPMODR0_OFFSET]
389 bic w3, w3, #GICR_IGRPMODR0_SGI15
390 str w3, [x5, #GICR_IGRPMODR0_OFFSET]
391
392 /* set priority of SGI 15 to highest (0x0) - GICR_IPRIORITYR3 */
393 ldr w4, [x5, #GICR_IPRIORITYR3_OFFSET]
394 bic w4, w4, #GICR_IPRIORITYR3_SGI15_MASK
395 str w4, [x5, #GICR_IPRIORITYR3_OFFSET]
396
397 /* enable SGI 15 at redistributor - GICR_ISENABLER0 */
398 mov w3, #GICR_ISENABLER0_SGI15
399 str w3, [x5, #GICR_ISENABLER0_OFFSET]
400 dsb sy
401 isb
4023:
403 /* poll on rwp bit in GICR_CTLR */
404 ldr w4, [x6, #GICR_CTLR_OFFSET]
405 tst w4, #GICR_CTLR_RWP
406 b.ne 3b
407
408 /* quiesce the debug interfaces */
409 mrs x3, osdlr_el1
410 orr x3, x3, #OSDLR_EL1_DLK_LOCK
411 msr osdlr_el1, x3
412 isb
413
414 /* enable grp0 ints */
415 mov x3, #ICC_IGRPEN0_EL1_EN
416 msr ICC_IGRPEN0_EL1, x3
417
418 /*
419 * x5 = gicr sgi base addr
420 * x6 = gicr rd base addr
421 * x7 = core mask lsb
422 */
423
424 /* clear any pending interrupts */
425 mvn w1, wzr
426 str w1, [x5, #GICR_ICPENDR0_OFFSET]
427
428 /* make sure system counter is enabled */
429 ldr x3, =NXP_TIMER_ADDR
430 ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
431 tst w0, #SYS_COUNTER_CNTCR_EN
432 b.ne 4f
433 orr w0, w0, #SYS_COUNTER_CNTCR_EN
434 str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
4354:
436 /* enable the core timer and mask timer interrupt */
437 mov x1, #CNTP_CTL_EL0_EN
438 orr x1, x1, #CNTP_CTL_EL0_IMASK
439 msr cntp_ctl_el0, x1
440
441 mov x30, x8
442 ret
443
444/*
445 * part of CPU_OFF
446 * this function performs the final steps to shutdown the core
447 * in: x0 = core mask lsb
448 * out: none
449 * uses x0, x1, x2, x3, x4, x5
450 */
451_soc_core_entr_off:
452 mov x5, x30
453 mov x4, x0
454
455 /* x4 = core mask */
4561:
457 /* enter low-power state by executing wfi */
458 wfi
459
460 /* see if SGI15 woke us up */
461 mrs x2, ICC_IAR0_EL1
462 mov x3, #ICC_IAR0_EL1_SGI15
463 cmp x2, x3
464 b.ne 2f
465
466 /* deactivate the int */
467 msr ICC_EOIR0_EL1, x2
468
469 /* x4 = core mask */
4702:
471 /* check if core has been turned on */
472 mov x0, x4
473 bl _getCoreState
474
475 /* x0 = core state */
476
477 cmp x0, #CORE_WAKEUP
478 b.ne 1b
479
480 /* if we get here, then we have exited the wfi */
481
482 mov x30, x5
483 ret
484
485/*
486 * part of CPU_OFF
487 * this function starts the process of starting a core back up
488 * in: x0 = core mask lsb
489 * out: none
490 * uses x0, x1, x2, x3, x4, x5, x6
491 */
492_soc_core_exit_off:
493 mov x6, x30
494 mov x5, x0
495
496 /* disable forwarding of GRP0 ints at cpu interface */
497 msr ICC_IGRPEN0_EL1, xzr
498
499 /* get redistributor sgi base addr for this core */
500 mov x0, x5
501 bl get_gic_sgi_base
502 mov x4, x0
503
504 /*
505 * x4 = gicr sgi base addr
506 * x5 = core mask
507 */
508
509 /* disable SGI 15 at redistributor - GICR_ICENABLER0 */
510 mov w1, #GICR_ICENABLER0_SGI15
511 str w1, [x4, #GICR_ICENABLER0_OFFSET]
512
513 /* get redistributor rd base addr for this core */
514 mov x0, x5
515 bl get_gic_rd_base
516 mov x4, x0
517
518 /* x4 = gicr rd base addr */
5192:
520 /* poll on rwp bit in GICR_CTLR */
521 ldr w2, [x4, #GICR_CTLR_OFFSET]
522 tst w2, #GICR_CTLR_RWP
523 b.ne 2b
524
525 /* x4 = gicr rd base addr */
526
527 /* unlock the debug interfaces */
528 mrs x3, osdlr_el1
529 bic x3, x3, #OSDLR_EL1_DLK_LOCK
530 msr osdlr_el1, x3
531 isb
532
533 dsb sy
534 isb
535 mov x30, x6
536 ret
537
538/*
539 * this function requests a reset of the entire SOC
540 * in: none
541 * out: none
542 * uses: x0, x1, x2, x3, x4, x5, x6
543 */
544_soc_sys_reset:
545 mov x3, x30
546
547 /* make sure the mask is cleared in the reset request mask register */
548 mov x0, #RST_RSTRQMR1_OFFSET
549 mov w1, wzr
550 bl _write_reg_reset
551
552 /* set the reset request */
553 mov x4, #RST_RSTCR_OFFSET
554 mov x0, x4
555 mov w1, #RSTCR_RESET_REQ
556 bl _write_reg_reset
557
558 /* x4 = RST_RSTCR_OFFSET */
559
560 /*
561 * just in case this address range is mapped as cacheable,
562 * flush the write out of the dcaches
563 */
564 mov x2, #NXP_RESET_ADDR
565 add x2, x2, x4
566 dc cvac, x2
567 dsb st
568 isb
569
570 /* this function does not return */
571 b .
572
573/*
574 * this function turns off the SoC
575 * Note: this function is not intended to return, and the only allowable
576 * recovery is POR
577 * in: none
578 * out: none
579 * uses x0, x1, x2, x3
580 */
581_soc_sys_off:
582 /*
583 * A-009810: LPM20 entry sequence might cause
584 * spurious timeout reset request
585 * workaround: MASK RESET REQ RPTOE
586 */
587 ldr x0, =NXP_RESET_ADDR
588 ldr w1, [x0, #RST_RSTRQMR1_OFFSET]
589 orr w1, w1, #RSTRQMR_RPTOE_MASK
590 str w1, [x0, #RST_RSTRQMR1_OFFSET]
591
592 /* disable SEC, QBman spi and qspi */
593 ldr x2, =NXP_DCFG_ADDR
594 ldr x0, =DCFG_DEVDISR1_OFFSET
595 ldr w1, =DCFG_DEVDISR1_SEC
596 str w1, [x2, x0]
597 ldr x0, =DCFG_DEVDISR3_OFFSET
598 ldr w1, =DCFG_DEVDISR3_QBMAIN
599 str w1, [x2, x0]
600 ldr x0, =DCFG_DEVDISR4_OFFSET
601 ldr w1, =DCFG_DEVDISR4_SPI_QSPI
602 str w1, [x2, x0]
603
604 /* set TPMWAKEMR0 */
605 ldr x0, =TPMWAKEMR0_ADDR
606 mov w1, #0x1
607 str w1, [x0]
608
609 /* disable icache, dcache, mmu @ EL1 */
610 mov x1, #SCTLR_I_C_M_MASK
611 mrs x0, sctlr_el1
612 bic x0, x0, x1
613 msr sctlr_el1, x0
614
615 /* disable L2 prefetches */
616 mrs x0, CPUECTLR_EL1
617 orr x0, x0, #CPUECTLR_SMPEN_EN
618 orr x0, x0, #CPUECTLR_TIMER_8TICKS
619 msr CPUECTLR_EL1, x0
620 dsb sy
621 isb
622
623 /* disable CCN snoop domain */
624 ldr x0, =NXP_CCI_ADDR
625 mov w1, #0x1
626 str w1, [x0]
627
628 mov x2, #DAIF_SET_MASK
629
630 mrs x1, spsr_el1
631 orr x1, x1, x2
632 msr spsr_el1, x1
633
634 mrs x1, spsr_el2
635 orr x1, x1, x2
636 msr spsr_el2, x1
637
638 bl get_pmu_idle_cluster_mask
639 mov x3, #NXP_PMU_ADDR
640
641 /* x3 = pmu base addr */
642
643 /* idle the ACP interfaces */
644 str w0, [x3, #PMU_CLAINACTSETR_OFFSET]
645
646 /* force the debug interface to be quiescent */
647 mrs x0, osdlr_el1
648 orr x0, x0, #0x1
649 msr osdlr_el1, x0
650
651 bl get_pmu_flush_cluster_mask
652 /* x3 = pmu base addr */
653 mov x3, #NXP_PMU_ADDR
654
655 /* clear flush request and status */
656 ldr x2, =PMU_CLSL2FLUSHCLRR_OFFSET
657 str w0, [x3, x2]
658
659 /* close the Skyros master port */
660 ldr x2, =PMU_CLSINACTSETR_OFFSET
661 str w0, [x3, x2]
662
663 /* request lpm20 */
664 ldr x0, =PMU_POWMGTCSR_OFFSET
665 ldr w1, =PMU_POWMGTCSR_VAL
666 str w1, [x3, x0]
667
668 /* this function does not return */
6691:
670 wfi
671 b 1b
672
673/*
674 * part of CPU_SUSPEND
675 * this function performs SoC-specific programming prior to standby
676 * in: x0 = core mask lsb
677 * out: none
678 * uses x0, x1
679 */
680_soc_core_prep_stdby:
681 /* clear CPUECTLR_EL1[2:0] */
682 mrs x1, CPUECTLR_EL1
683 bic x1, x1, #CPUECTLR_TIMER_MASK
684 msr CPUECTLR_EL1, x1
685
686 ret
687
688/*
689 * part of CPU_SUSPEND
690 * this function puts the calling core into standby state
691 * in: x0 = core mask lsb
692 * out: none
693 * uses x0
694 */
695_soc_core_entr_stdby:
696 /* X0 = core mask lsb */
697 dsb sy
698 isb
699 wfi
700
701 ret
702
703/*
704 * part of CPU_SUSPEND
705 * this function performs any SoC-specific cleanup after standby state
706 * in: x0 = core mask lsb
707 * out: none
708 * uses none
709 */
710_soc_core_exit_stdby:
711 ret
712
713/*
714 * part of CPU_SUSPEND
715 * this function performs SoC-specific programming prior to power-down
716 * in: x0 = core mask lsb
717 * out: none
718 * uses x0, x1, x2, x3
719 */
720_soc_core_prep_pwrdn:
721 /* make sure system counter is enabled */
722 ldr x3, =NXP_TIMER_ADDR
723 ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
724 tst w0, #SYS_COUNTER_CNTCR_EN
725 b.ne 1f
726 orr w0, w0, #SYS_COUNTER_CNTCR_EN
727 str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
7281:
729 /*
730 * enable dynamic retention control (CPUECTLR[2:0])
731 * set the SMPEN bit (CPUECTLR[6])
732 */
733 mrs x1, CPUECTLR_EL1
734 bic x1, x1, #CPUECTLR_RET_MASK
735 orr x1, x1, #CPUECTLR_TIMER_8TICKS
736 orr x1, x1, #CPUECTLR_SMPEN_EN
737 msr CPUECTLR_EL1, x1
738
739 isb
740 ret
741
742/*
743 * part of CPU_SUSPEND
744 * this function puts the calling core into a power-down state
745 * in: x0 = core mask lsb
746 * out: none
747 * uses x0
748 */
749_soc_core_entr_pwrdn:
750 /* X0 = core mask lsb */
751 dsb sy
752 isb
753 wfi
754
755 ret
756
757/*
758 * part of CPU_SUSPEND
759 * this function cleans up after a core exits power-down
760 * in: x0 = core mask lsb
761 * out: none
762 * uses
763 */
764_soc_core_exit_pwrdn:
765 ret
766
767/*
768 * part of CPU_SUSPEND
769 * this function performs SoC-specific programming prior to standby
770 * in: x0 = core mask lsb
771 * out: none
772 * uses x0, x1
773 */
774_soc_clstr_prep_stdby:
775 /* clear CPUECTLR_EL1[2:0] */
776 mrs x1, CPUECTLR_EL1
777 bic x1, x1, #CPUECTLR_TIMER_MASK
778 msr CPUECTLR_EL1, x1
779
780 ret
781
782/*
783 * part of CPU_SUSPEND
784 * this function performs any SoC-specific cleanup after standby state
785 * in: x0 = core mask lsb
786 * out: none
787 * uses none
788 */
789_soc_clstr_exit_stdby:
790 ret
791
792/*
793 * part of CPU_SUSPEND
794 * this function performs SoC-specific programming prior to power-down
795 * in: x0 = core mask lsb
796 * out: none
797 * uses x0, x1, x2, x3
798 */
799_soc_clstr_prep_pwrdn:
800 /* make sure system counter is enabled */
801 ldr x3, =NXP_TIMER_ADDR
802 ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
803 tst w0, #SYS_COUNTER_CNTCR_EN
804 b.ne 1f
805 orr w0, w0, #SYS_COUNTER_CNTCR_EN
806 str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
8071:
808 /*
809 * enable dynamic retention control (CPUECTLR[2:0])
810 * set the SMPEN bit (CPUECTLR[6])
811 */
812 mrs x1, CPUECTLR_EL1
813 bic x1, x1, #CPUECTLR_RET_MASK
814 orr x1, x1, #CPUECTLR_TIMER_8TICKS
815 orr x1, x1, #CPUECTLR_SMPEN_EN
816 msr CPUECTLR_EL1, x1
817
818 isb
819 ret
820
821/*
822 * part of CPU_SUSPEND
823 * this function cleans up after a core exits power-down
824 * in: x0 = core mask lsb
825 * out: none
826 * uses
827 */
828_soc_clstr_exit_pwrdn:
829 ret
830
831/*
832 * part of CPU_SUSPEND
833 * this function performs SoC-specific programming prior to standby
834 * in: x0 = core mask lsb
835 * out: none
836 * uses x0, x1
837 */
838_soc_sys_prep_stdby:
839 /* clear CPUECTLR_EL1[2:0] */
840 mrs x1, CPUECTLR_EL1
841 bic x1, x1, #CPUECTLR_TIMER_MASK
842 msr CPUECTLR_EL1, x1
843
844 ret
845
846/*
847 * part of CPU_SUSPEND
848 * this function performs any SoC-specific cleanup after standby state
849 * in: x0 = core mask lsb
850 * out: none
851 * uses none
852 */
853_soc_sys_exit_stdby:
854 ret
855
856/*
857 * part of CPU_SUSPEND
858 * this function performs SoC-specific programming prior to
859 * suspend-to-power-down
860 * in: x0 = core mask lsb
861 * out: none
862 * uses x0
863 */
864_soc_sys_prep_pwrdn:
865 /* set retention control */
866 mrs x0, CPUECTLR_EL1
867 bic x0, x0, #CPUECTLR_TIMER_MASK
868 orr x0, x0, #CPUECTLR_TIMER_8TICKS
869 orr x0, x0, #CPUECTLR_SMPEN_EN
870 msr CPUECTLR_EL1, x0
871 dsb sy
872 isb
873
874 ret
875
876/*
877 * part of CPU_SUSPEND
878 * this function puts the calling core, and potentially the soc, into a
879 * low-power state
880 * in: x0 = core mask lsb
881 * out: x0 = 0, success
882 * x0 < 0, failure
883 * uses x0, x1, x2, x3, x4, x5, x6, x7, x8
884 */
885_soc_sys_pwrdn_wfi:
886 /* Save LR to stack */
887 stp x18, x30, [sp, #-16]!
888
889 /* Poll PCPW20SR for all secondary cores to be placed in PW20 */
890 bl get_tot_num_cores
891 mov x3, #0x1
892 lsl x3, x3, x0
893 sub x3, x3, #2
8941:
895 mov x0, #NXP_PMU_ADDR
896 ldr w1, [x0, #PMU_PCPW20SR_OFFSET]
897 cmp w1, w3
898 b.ne 1b
899
900 /* backup EPU registers to stack */
901 mov x3, #NXP_PMU_ADDR
902 ldr x2, =NXP_EPU_ADDR
903 ldr w4, [x2, #EPU_EPIMCR10_OFFSET]
904 ldr w5, [x2, #EPU_EPCCR10_OFFSET]
905 ldr w6, [x2, #EPU_EPCTR10_OFFSET]
906 ldr w7, [x2, #EPU_EPGCR_OFFSET]
907 stp x4, x5, [sp, #-16]!
908 stp x6, x7, [sp, #-16]!
909
910 /*
911 * x2 = epu base addr
912 * x3 = pmu base addr
913 */
914
915 /* set up EPU event to receive the wake signal from PMU */
916 mov w4, #EPU_EPIMCR10_VAL
917 mov w5, #EPU_EPCCR10_VAL
918 mov w6, #EPU_EPCTR10_VAL
919 mov w7, #EPU_EPGCR_VAL
920 str w4, [x2, #EPU_EPIMCR10_OFFSET]
921 str w5, [x2, #EPU_EPCCR10_OFFSET]
922 str w6, [x2, #EPU_EPCTR10_OFFSET]
923 str w7, [x2, #EPU_EPGCR_OFFSET]
924
925 /*
926 * A-010194: There is logic problem
927 * in the path of GIC-to-PMU to issue
928 * wake request to core0
929 * Workaround: Re-target the wakeup interrupts
930 * to a core other than the last active core0
931 */
932 ldr x2, =NXP_GICD_ADDR
933
934 /* backup flextimer/mmc/usb interrupt router */
935 ldr x0, =GICD_IROUTER60_OFFSET
936 ldr x1, =GICD_IROUTER76_OFFSET
937 ldr w4, [x2, x0]
938 ldr w5, [x2, x1]
939 ldr x0, =GICD_IROUTER112_OFFSET
940 ldr x1, =GICD_IROUTER113_OFFSET
941 ldr w6, [x2, x0]
942 ldr w7, [x2, x1]
943 stp x4, x5, [sp, #-16]!
944 stp x6, x7, [sp, #-16]!
945
946 /*
947 * x2 = gicd base addr
948 * x0 = GICD_IROUTER112_OFFSET
949 * x1 = GICD_IROUTER113_OFFSET
950 */
951
952 /* re-route interrupt to cluster 1 */
953 ldr w4, =GICD_IROUTER_VALUE
954 str w4, [x2, x0]
955 str w4, [x2, x1]
956 ldr x0, =GICD_IROUTER60_OFFSET
957 ldr x1, =GICD_IROUTER76_OFFSET
958 str w4, [x2, x0]
959 str w4, [x2, x1]
960 dsb sy
961 isb
962
963 /* backup flextimer/mmc/usb interrupt enabler */
964 ldr x0, =GICD_ISENABLER_1
965 ldr w4, [x2, x0]
966 ldr x1, =GICD_ISENABLER_2
967 ldr w5, [x2, x1]
968 stp x4, x5, [sp, #-16]!
969
970 ldr x0, =GICD_ISENABLER_3
971 ldr w4, [x2, x0]
972 ldr x1, =GICD_ICENABLER_1
973 ldr w5, [x2, x1]
974 stp x4, x5, [sp, #-16]!
975
976 ldr x0, =GICD_ICENABLER_2
977 ldr w4, [x2, x0]
978 ldr x1, =GICD_ICENABLER_3
979 ldr w5, [x2, x1]
980 stp x4, x5, [sp, #-16]!
981
982 /* enable related interrupt routing */
983 ldr w4, =GICD_ISENABLER_1_VALUE
984 ldr x0, =GICD_ISENABLER_1
985 str w4, [x2, x0]
986 dsb sy
987 isb
988
989 ldr w4, =GICD_ISENABLER_2_VALUE
990 ldr x0, =GICD_ISENABLER_2
991 str w4, [x2, x0]
992 dsb sy
993 isb
994
995 ldr w4, =GICD_ISENABLER_3_VALUE
996 ldr x0, =GICD_ISENABLER_3
997 str w4, [x2, x0]
998 dsb sy
999 isb
1000
1001 /* set POWMGTDCR [STP_PV_EN] = 1 */
1002 ldr x2, =NXP_POWMGTDCR
1003 ldr w4, =0x01
1004 str w4, [x2]
1005
1006 /* program IPSTPCR for override stop request (except DDR) */
1007 mov x3, #NXP_PMU_ADDR
1008
1009 /* build an override mask for IPSTPCR4/IPSTPACK4/DEVDISR5 */
1010 ldr x2, =PMU_IPPDEXPCR4_OFFSET
1011 ldr w7, [x3, x2]
1012
1013 mov x5, xzr
1014 ldr x6, =IPPDEXPCR4_MASK
1015 and x6, x6, x7
1016 cbz x6, 1f
1017
1018 /*
1019 * x5 = override mask
1020 * x6 = IPPDEXPCR bits for DEVDISR5
1021 * x7 = IPPDEXPCR
1022 */
1023
1024 /* get the overrides */
1025 orr x4, x5, #DEVDISR5_FLX_TMR
1026 tst x6, #IPPDEXPCR_FLX_TMR
1027 csel x5, x5, x4, EQ
10281:
1029 /* store the DEVDISR5 override mask */
1030 ldr x2, =BC_PSCI_BASE
1031 add x2, x2, #AUX_01_DATA
1032 str w5, [x2, #DEVDISR5_MASK_OFFSET]
1033
1034 mov x3, #NXP_PMU_ADDR
1035
1036 /* write IPSTPCR0 - no overrides */
1037 ldr x2, =PMU_IPSTPCR0_OFFSET
1038 ldr w5, =IPSTPCR0_VALUE
1039 str w5, [x3, x2]
1040
1041 /* write IPSTPCR1 - no overrides */
1042 ldr x2, =PMU_IPSTPCR1_OFFSET
1043 ldr w5, =IPSTPCR1_VALUE
1044 str w5, [x3, x2]
1045
1046 /* write IPSTPCR2 - no overrides */
1047 ldr x2, =PMU_IPSTPCR2_OFFSET
1048 ldr w5, =IPSTPCR2_VALUE
1049 str w5, [x3, x2]
1050
1051 /* write IPSTPCR3 - no overrides */
1052 ldr x2, =PMU_IPSTPCR3_OFFSET
1053 ldr w5, =IPSTPCR3_VALUE
1054 str w5, [x3, x2]
1055
1056 /* write IPSTPCR4 - overrides possible */
1057 ldr x2, =BC_PSCI_BASE
1058 add x2, x2, #AUX_01_DATA
1059 ldr w6, [x2, #DEVDISR5_MASK_OFFSET]
1060 ldr x2, =PMU_IPSTPCR4_OFFSET
1061 ldr w5, =IPSTPCR4_VALUE
1062 bic x5, x5, x6
1063 str w5, [x3, x2]
1064
1065 /* write IPSTPCR5 - no overrides */
1066 ldr x2, =PMU_IPSTPCR5_OFFSET
1067 ldr w5, =IPSTPCR5_VALUE
1068 str w5, [x3, x2]
1069
1070 /* write IPSTPCR6 - no overrides */
1071 ldr x2, =PMU_IPSTPCR6_OFFSET
1072 ldr w5, =IPSTPCR6_VALUE
1073 str w5, [x3, x2]
1074
1075 /* poll IPSTPACK for IP stop acknowledgment (except DDR) */
1076 mov x3, #NXP_PMU_ADDR
1077
1078 /* poll on IPSTPACK0 */
1079 ldr x2, =PMU_IPSTPACK0_OFFSET
1080 ldr x4, =IPSTPCR0_VALUE
1081 ldr x7, =IPSTPACK_RETRY_CNT
10823:
1083 ldr w0, [x3, x2]
1084 cmp x0, x4
1085 b.eq 14f
1086 sub x7, x7, #1
1087 cbnz x7, 3b
1088
108914:
1090 /* poll on IPSTPACK1 */
1091 ldr x2, =PMU_IPSTPACK1_OFFSET
1092 ldr x4, =IPSTPCR1_VALUE
1093 ldr x7, =IPSTPACK_RETRY_CNT
10944:
1095 ldr w0, [x3, x2]
1096 cmp x0, x4
1097 b.eq 15f
1098 sub x7, x7, #1
1099 cbnz x7, 4b
1100
110115:
1102 /* poll on IPSTPACK2 */
1103 ldr x2, =PMU_IPSTPACK2_OFFSET
1104 ldr x4, =IPSTPCR2_VALUE
1105 ldr x7, =IPSTPACK_RETRY_CNT
11065:
1107 ldr w0, [x3, x2]
1108 cmp x0, x4
1109 b.eq 16f
1110 sub x7, x7, #1
1111 cbnz x7, 5b
1112
111316:
1114 /* poll on IPSTPACK3 */
1115 ldr x2, =PMU_IPSTPACK3_OFFSET
1116 ldr x4, =IPSTPCR3_VALUE
1117 ldr x7, =IPSTPACK_RETRY_CNT
11186:
1119 ldr w0, [x3, x2]
1120 cmp x0, x4
1121 b.eq 17f
1122 sub x7, x7, #1
1123 cbnz x7, 6b
1124
112517:
1126 /* poll on IPSTPACK4 */
1127 ldr x2, =PMU_IPSTPACK4_OFFSET
1128 ldr x4, =IPSTPCR4_VALUE
1129 ldr x7, =IPSTPACK_RETRY_CNT
11307:
1131 ldr w0, [x3, x2]
1132 cmp x0, x4
1133 b.eq 18f
1134 sub x7, x7, #1
1135 cbnz x7, 7b
1136
113718:
1138 /* poll on IPSTPACK5 */
1139 ldr x2, =PMU_IPSTPACK5_OFFSET
1140 ldr x4, =IPSTPCR5_VALUE
1141 ldr x7, =IPSTPACK_RETRY_CNT
11428:
1143 ldr w0, [x3, x2]
1144 cmp x0, x4
1145 b.eq 19f
1146 sub x7, x7, #1
1147 cbnz x7, 8b
1148
114919:
1150 /* poll on IPSTPACK6 */
1151 ldr x2, =PMU_IPSTPACK6_OFFSET
1152 ldr x4, =IPSTPCR6_VALUE
1153 ldr x7, =IPSTPACK_RETRY_CNT
11549:
1155 ldr w0, [x3, x2]
1156 cmp x0, x4
1157 b.eq 20f
1158 sub x7, x7, #1
1159 cbnz x7, 9b
1160
116120:
1162 /* save current DEVDISR states to DDR. */
1163 ldr x2, =NXP_DCFG_ADDR
1164
1165 /* save DEVDISR1 and load new value */
1166 ldr x0, =DCFG_DEVDISR1_OFFSET
1167 ldr w1, [x2, x0]
1168 mov w13, w1
1169 ldr x1, =DEVDISR1_VALUE
1170 str w1, [x2, x0]
1171 /* save DEVDISR2 and load new value */
1172 ldr x0, =DCFG_DEVDISR2_OFFSET
1173 ldr w1, [x2, x0]
1174 mov w14, w1
1175 ldr x1, =DEVDISR2_VALUE
1176 str w1, [x2, x0]
1177
1178 /* x6 = DEVDISR5 override mask */
1179
1180 /* save DEVDISR3 and load new value */
1181 ldr x0, =DCFG_DEVDISR3_OFFSET
1182 ldr w1, [x2, x0]
1183 mov w15, w1
1184 ldr x1, =DEVDISR3_VALUE
1185 str w1, [x2, x0]
1186
1187 /* save DEVDISR4 and load new value */
1188 ldr x0, =DCFG_DEVDISR4_OFFSET
1189 ldr w1, [x2, x0]
1190 mov w16, w1
1191 /* not stop uart print */
1192 ldr x1, =0x0000332
1193 str w1, [x2, x0]
1194
1195 /* save DEVDISR5 and load new value */
1196 ldr x0, =DCFG_DEVDISR5_OFFSET
1197 ldr w1, [x2, x0]
1198 mov w17, w1
1199 /* Enable this wakeup will fail, should enable OCRAM */
1200 ldr x1, =0x00102300
1201 str w1, [x2, x0]
1202
1203 /* save DEVDISR6 and load new value */
1204 ldr x0, =DCFG_DEVDISR6_OFFSET
1205 ldr w1, [x2, x0]
1206 mov w18, w1
1207 ldr x1, =DEVDISR6_VALUE
1208 str w1, [x2, x0]
1209
1210 /*
1211 * w13 = DEVDISR1 saved value
1212 * w14 = DEVDISR2 saved value
1213 * w15 = DEVDISR3 saved value
1214 * w16 = DEVDISR4 saved value
1215 * w17 = DEVDISR5 saved value
1216 * w18 = DEVDISR6 saved value
1217 */
1218 /*
1219 * A-009810: LPM20 entry sequence might cause
1220 * spurious timeout reset request
1221 * workaround: MASK RESET REQ RPTOE
1222 */
1223 ldr x0, =NXP_RESET_ADDR
1224 ldr w1, =RSTRQMR_RPTOE_MASK
1225 str w1, [x0, #RST_RSTRQMR1_OFFSET]
1226
1227 /* disable SEC, QBman spi and qspi */
1228 ldr x2, =NXP_DCFG_ADDR
1229 ldr x0, =DCFG_DEVDISR1_OFFSET
1230 ldr w1, =DCFG_DEVDISR1_SEC
1231 str w1, [x2, x0]
1232 ldr x0, =DCFG_DEVDISR3_OFFSET
1233 ldr w1, =DCFG_DEVDISR3_QBMAIN
1234 str w1, [x2, x0]
1235 ldr x0, =DCFG_DEVDISR4_OFFSET
1236 ldr w1, =DCFG_DEVDISR4_SPI_QSPI
1237 str w1, [x2, x0]
1238
1239 /*
1240 * write the GICR_WAKER.ProcessorSleep bits to 1
1241 * enable the WakeRequest signal
1242 * x3 is cpu mask starting from cpu7
1243 */
1244 bl get_tot_num_cores
1245 sub x0, x0, #1
1246 mov x3, #0x1
1247 lsl x3, x3, x0
12482:
1249 mov x0, x3
1250 bl get_gic_rd_base
1251 ldr w1, [x0, #GICR_WAKER_OFFSET]
1252 orr w1, w1, #GICR_WAKER_SLEEP_BIT
1253 str w1, [x0, #GICR_WAKER_OFFSET]
12541:
1255 ldr w1, [x0, #GICR_WAKER_OFFSET]
1256 cmp w1, #GICR_WAKER_ASLEEP
1257 b.ne 1b
1258
1259 lsr x3, x3, #1
1260 cbnz x3, 2b
1261
1262 /* x3 = pmu base addr */
1263
1264 /* perform Icache Warming Sequence */
1265 ldr x5, =IPSTPCR4_VALUE
1266 mov x6, DDR_CNTRL_BASE_ADDR
1267 mov x7, #NXP_PMU_ADDR
1268 mov x8, #NXP_DCFG_ADDR
1269 mov x10, #PMU_IPSTPCR4_OFFSET
1270 mov x11, #PMU_IPSTPACK4_OFFSET
1271 mov x12, #PMU_IPSTPCR3_OFFSET
1272 mov x18, #PMU_IPSTPCR2_OFFSET
1273 mov x19, #PMU_IPSTPCR1_OFFSET
1274 mov x21, #PMU_IPSTPCR0_OFFSET
1275 ldr x22, =DCFG_DEVDISR5_OFFSET
1276 ldr x23, =NXP_EPU_ADDR
1277 mov x9, #CORE_RESTARTABLE
1278 bl final_pwrdown
1279
1280 /*
1281 * disable the WakeRequest signal on cpu 0-7
1282 * x3 is cpu mask starting from cpu7
1283 */
1284 bl get_tot_num_cores
1285 sub x0, x0, #1
1286 mov x3, #0x1
1287 lsl x3, x3, x0
12882:
1289 mov x0, x3
1290 bl get_gic_rd_base
1291 ldr w1, [x0, #GICR_WAKER_OFFSET]
1292 bic w1, w1, #GICR_WAKER_SLEEP_BIT
1293 str w1, [x0, #GICR_WAKER_OFFSET]
12941:
1295 ldr w1, [x0, #GICR_WAKER_OFFSET]
1296 cbnz w1, 1b
1297
1298 lsr x3, x3, #1
1299 cbnz x3, 2b
1300
1301 /* set SGI for secondary core wakeup */
1302 ldr x0, =0x1000002
1303 msr S3_0_C12_C11_7, x0
1304 isb
1305 ldr x0, =0x2000004
1306 msr S3_0_C12_C11_7, x0
1307 isb
1308 ldr x0, =0x3000008
1309 msr S3_0_C12_C11_7, x0
1310 isb
1311 ldr x0, =0x4010001
1312 msr S3_0_C12_C11_7, x0
1313 isb
1314 ldr x0, =0x5010002
1315 msr S3_0_C12_C11_7, x0
1316 isb
1317 ldr x0, =0x6010004
1318 msr S3_0_C12_C11_7, x0
1319 isb
1320 ldr x0, =0x7010008
1321 msr S3_0_C12_C11_7, x0
1322
1323 /* enable SEC, QBman spi and qspi */
1324 ldr x2, =NXP_DCFG_ADDR
1325 str wzr, [x2, #DCFG_DEVDISR1_OFFSET]
1326 str wzr, [x2, #DCFG_DEVDISR3_OFFSET]
1327 str wzr, [x2, #DCFG_DEVDISR4_OFFSET]
1328
1329 /* clear POWMGTDCR [STP_PV_EN] */
1330 ldr x2, =NXP_POWMGTDCR
1331 ldr w4, [x2]
1332 bic w4, w4, #0x01
1333 str w4, [x2]
1334
1335 /* restore flextimer/mmc/usb interrupt enabler */
1336 ldr x3, =NXP_GICD_ADDR
1337 ldp x0, x2, [sp], #16
1338 ldr x1, =GICD_ICENABLER_2
1339 mvn w0, w0
1340 str w0, [x3, x1]
1341 ldr x1, =GICD_ICENABLER_3
1342 mvn w2, w2
1343 str w2, [x3, x1]
1344
1345 ldp x0, x2, [sp], #16
1346 ldr x1, =GICD_ISENABLER_3
1347 str w0, [x3, x1]
1348 ldr x1, =GICD_ICENABLER_1
1349 mvn w2, w2
1350 str w0, [x3, x1]
1351
1352 ldp x0, x2, [sp], #16
1353 ldr x1, =GICD_ISENABLER_1
1354 str w0, [x3, x1]
1355 ldr x1, =GICD_ISENABLER_2
1356 str w0, [x3, x1]
1357
1358 /* restore flextimer/mmc/usb interrupt router */
1359 ldr x3, =NXP_GICD_ADDR
1360 ldp x0, x2, [sp], #16
1361 ldr x1, =GICD_IROUTER113_OFFSET
1362 str w2, [x3, x1]
1363 ldr x1, =GICD_IROUTER112_OFFSET
1364 str w0, [x3, x1]
1365 ldp x0, x2, [sp], #16
1366 ldr x1, =GICD_IROUTER76_OFFSET
1367 str w2, [x3, x1]
1368 ldr x1, =GICD_IROUTER60_OFFSET
1369 str w0, [x3, x1]
1370
1371 /* restore EPU registers */
1372 ldr x3, =NXP_EPU_ADDR
1373 ldp x0, x2, [sp], #16
1374 str w2, [x3, #EPU_EPGCR_OFFSET]
1375 str w0, [x3, #EPU_EPCTR10_OFFSET]
1376 ldp x2, x1, [sp], #16
1377 str w1, [x3, #EPU_EPCCR10_OFFSET]
1378 str w2, [x3, #EPU_EPIMCR10_OFFSET]
1379
1380 isb
1381 /* Restor LR */
1382 ldp x18, x30, [sp], #16
1383 ret
1384
1385/*
1386 * part of CPU_SUSPEND
1387 * this function performs any SoC-specific cleanup after power-down
1388 * in: x0 = core mask lsb
1389 * out: none
1390 * uses x0, x1
1391 */
1392_soc_sys_exit_pwrdn:
1393 mrs x1, SCTLR_EL1
1394 orr x1, x1, #SCTLR_I_MASK
1395 msr SCTLR_EL1, x1
1396 isb
1397 ret
1398
1399/*
1400 * this function checks to see if cores which are to be disabled have been
1401 * released from reset - if not, it releases them
1402 * in: none
1403 * out: none
1404 * uses x0, x1, x2, x3, x4, x5, x6, x7, x8
1405 */
1406release_disabled:
1407 mov x8, x30
1408
1409 /* read COREDISABLESR */
1410 mov x0, #NXP_DCFG_ADDR
1411 ldr w4, [x0, #DCFG_COREDISABLEDSR_OFFSET]
1412
1413 /* get the number of cpus on this device */
1414 mov x6, #PLATFORM_CORE_COUNT
1415
1416 mov x0, #NXP_RESET_ADDR
1417 ldr w5, [x0, #BRR_OFFSET]
1418
1419 /* load the core mask for the first core */
1420 mov x7, #1
1421
1422 /*
1423 * x4 = COREDISABLESR
1424 * x5 = BRR
1425 * x6 = loop count
1426 * x7 = core mask bit
1427 */
14282:
1429 /* check if the core is to be disabled */
1430 tst x4, x7
1431 b.eq 1f
1432
1433 /* see if disabled cores have already been released from reset */
1434 tst x5, x7
1435 b.ne 1f
1436
1437 /* if core has not been released, then release it (0-3) */
1438 mov x0, x7
1439 bl _soc_core_release
1440
1441 /* record the core state in the data area (0-3) */
1442 mov x0, x7
1443 mov x1, #CORE_DISABLED
1444 bl _setCoreState
1445
14461:
1447 /* decrement the counter */
1448 subs x6, x6, #1
1449 b.le 3f
1450
1451 /* shift the core mask to the next core */
1452 lsl x7, x7, #1
1453 /* continue */
1454 b 2b
14553:
1456 mov x30, x8
1457 ret
1458
1459/*
1460 * write a register in the DCFG block
1461 * in: x0 = offset
1462 * in: w1 = value to write
1463 * uses x0, x1, x2
1464 */
1465_write_reg_dcfg:
1466 ldr x2, =NXP_DCFG_ADDR
1467 str w1, [x2, x0]
1468 ret
1469
1470/*
1471 * read a register in the DCFG block
1472 * in: x0 = offset
1473 * out: w0 = value read
1474 * uses x0, x1
1475 */
1476_read_reg_dcfg:
1477 ldr x1, =NXP_DCFG_ADDR
1478 ldr w0, [x1, x0]
1479 ret
1480
1481/*
1482 * this function sets up the TrustZone Address Space Controller (TZASC)
1483 * in: none
1484 * out: none
1485 * uses x0, x1
1486 */
1487init_tzpc:
1488 /*
1489 * set Non Secure access for all devices protected via TZPC
1490 * decode Protection-0 Set Reg
1491 */
1492 ldr x1, =TZPCDECPROT_0_SET_BASE
1493 /* set decode region to NS, Bits[7:0] */
1494 mov w0, #0xFF
1495 str w0, [x1]
1496
1497 /* decode Protection-1 Set Reg */
1498 ldr x1, =TZPCDECPROT_1_SET_BASE
1499 /* set decode region to NS, Bits[7:0] */
1500 mov w0, #0xFF
1501 str w0, [x1]
1502
1503 /* decode Protection-2 Set Reg */
1504 ldr x1, =TZPCDECPROT_2_SET_BASE
1505 /* set decode region to NS, Bits[7:0] */
1506 mov w0, #0xFF
1507 str w0, [x1]
1508
1509 /*
1510 * entire SRAM as NS
1511 * secure RAM region size Reg
1512 */
1513 ldr x1, =NXP_OCRAM_TZPC_ADDR
1514 /* 0x00000000 = no secure region */
1515 mov w0, #0x00000000
1516 str w0, [x1]
1517
1518 ret
1519
1520/* this function performs initialization on SecMon for boot services */
1521initSecMon:
1522 /* read the register hpcomr */
1523 ldr x1, =NXP_SNVS_ADDR
1524 ldr w0, [x1, #SECMON_HPCOMR_OFFSET]
1525 /* turn off secure access for the privileged registers */
1526 orr w0, w0, #SECMON_HPCOMR_NPSWAEN
1527 /* write back */
1528 str w0, [x1, #SECMON_HPCOMR_OFFSET]
1529
1530 ret
1531
1532/*
1533 * this function returns the redistributor base address for the core specified
1534 * in x1
1535 * in: x0 - core mask lsb of specified core
1536 * out: x0 = redistributor rd base address for specified core
1537 * uses x0, x1, x2
1538 */
1539get_gic_rd_base:
1540 /* get the 0-based core number */
1541 clz w1, w0
1542 mov w2, #0x20
1543 sub w2, w2, w1
1544 sub w2, w2, #1
1545
1546 /* x2 = core number / loop counter */
1547
1548 ldr x0, =NXP_GICR_ADDR
1549 mov x1, #GIC_RD_OFFSET
15502:
1551 cbz x2, 1f
1552 add x0, x0, x1
1553 sub x2, x2, #1
1554 b 2b
15551:
1556 ret
1557
1558/*
1559 * this function returns the redistributor base address for the core specified
1560 * in x1
1561 * in: x0 - core mask lsb of specified core
1562 * out: x0 = redistributor sgi base address for specified core
1563 * uses x0, x1, x2
1564 */
1565get_gic_sgi_base:
1566 /* get the 0-based core number */
1567 clz w1, w0
1568 mov w2, #0x20
1569 sub w2, w2, w1
1570 sub w2, w2, #1
1571
1572 /* x2 = core number / loop counter */
1573
1574 ldr x0, =NXP_GICR_SGI_ADDR
1575 mov x1, #GIC_SGI_OFFSET
15762:
1577 cbz x2, 1f
1578 add x0, x0, x1
1579 sub x2, x2, #1
1580 b 2b
15811:
1582 ret
1583
1584/*
1585 * this function returns an mpidr value for a core, given a core_mask_lsb
1586 * in: x0 = core mask lsb
1587 * out: x0 = affinity2:affinity1:affinity0, where affinity is 8-bits
1588 * uses x0, x1
1589 */
1590get_mpidr_value:
1591 /* convert a core mask to an SoC core number */
1592 clz w0, w0
1593 mov w1, #31
1594 sub w0, w1, w0
1595
1596 /* w0 = SoC core number */
1597
1598 mov w1, wzr
15992:
1600 cmp w0, #CORES_PER_CLUSTER
1601 b.lt 1f
1602 sub w0, w0, #CORES_PER_CLUSTER
1603 add w1, w1, #MPIDR_CLUSTER
1604 b 2b
1605
1606 /* insert the mpidr core number */
16071:
1608 orr w0, w1, w0
1609 ret
1610
1611/*
1612 * write a register in the RESET block
1613 * in: x0 = offset
1614 * in: w1 = value to write
1615 * uses x0, x1, x2
1616 */
1617_write_reg_reset:
1618 ldr x2, =NXP_RESET_ADDR
1619 str w1, [x2, x0]
1620 ret
1621
1622/*
1623 * read a register in the RESET block
1624 * in: x0 = offset
1625 * out: w0 = value read
1626 * uses x0, x1
1627 */
1628_read_reg_reset:
1629 ldr x1, =NXP_RESET_ADDR
1630 ldr w0, [x1, x0]
1631 ret
1632
1633/*
1634 * this function will pwrdown ddr and the final core - it will do this
1635 * by loading itself into the icache and then executing from there
1636 * in: x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK)
1637 * x6 = DDR_CNTRL_BASE_ADDR
1638 * x7 = NXP_PMU_ADDR
1639 * x8 = NXP_DCFG_ADDR
1640 * x9 = 0, restartable
1641 * = 1, non-restartable
1642 * x10 = PMU_IPSTPCR4_OFFSET
1643 * x11 = PMU_IPSTPACK4_OFFSET
1644 * x12 = PMU_IPSTPCR3_OFFSET
1645 * x18 = PMU_IPSTPCR2_OFFSET
1646 * x19 = PMU_IPSTPCR1_OFFSET
1647 * x21 = PMU_IPSTPCR0_OFFSET
1648 * w13 = DEVDISR1 saved value
1649 * w14 = DEVDISR2 saved value
1650 * w15 = DEVDISR3 saved value
1651 * w16 = DEVDISR4 saved value
1652 * w17 = DEVDISR5 saved value
1653 * x22 = DCFG_DEVDISR5_OFFSET
1654 * x23 = NXP_EPU_ADDR
1655 * out: none
1656 * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x13, x14, x15, x16, x17
1657 * x10, x11, x12, x18, x19, x21, x22, x23
1658 */
1659
1660final_pwrdown:
1661 /* delay */
1662 mov w4, #0xffffff
1663554:
1664 sub w4, w4, #1
1665 cmp w4, #0
1666 b.ge 554b
1667
1668 mov x0, xzr
1669 b touch_line_0
1670
1671/* 4Kb aligned */
1672.align 12
1673start_line_0:
1674 mov x0, #1
1675 /* put ddr in self refresh - start */
1676 mov x2, #DDR_SDRAM_CFG_2_FRCSR
1677 ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET]
1678 orr w3, w3, w2
1679 /* put ddr in self refresh - end */
1680 str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET]
1681 nop
1682 nop
1683touch_line_0:
1684 cbz x0, touch_line_1
1685
1686start_line_1:
1687 /* quiesce ddr clocks - start */
1688 orr w3, w5, #DCFG_DEVDISR5_MEM
1689 mov w4, w3
1690 /* quiesce ddr clocks - end */
1691 str w4, [x7, x10]
1692 mov w3, #DCFG_DEVDISR5_MEM
1693 /* poll on ipstpack4 - start */
1694 mov x2, #DDR_SLEEP_RETRY_CNT
1695 nop
1696 nop
1697touch_line_1:
1698 cbz x0, touch_line_2
1699
1700start_line_2:
1701 /* x11 = PMU_IPSTPACK4_OFFSET */
1702 ldr w1, [x7, x11]
1703 tst w1, w3
1704 b.ne 5f
1705 subs x2, x2, #1
1706 /* poll on ipstpack4 - end */
1707 b.gt start_line_2
1708
1709 /* if we get here, we have a timeout err */
1710 mov w4, w5
1711 /* x10 = PMU_IPSTPCR4_OFFSET re-enable ddr clks interface */
1712 str w4, [x7, x10]
1713touch_line_2:
1714 cbz x0, touch_line_3
1715
1716start_line_3:
1717 /* load error code */
1718 mov x0, #ERROR_DDR_SLEEP
1719 b 2f
17205:
1721 wfe
1722 ldr w1, [x23, #EPU_EPCTR10_OFFSET]
1723 cbz w1, 5b
1724
1725 mov w4, w5
1726touch_line_3:
1727 cbz x0, touch_line_4
1728
1729start_line_4:
1730 /* re-enable ddr in devdisr5 */
1731 str w4, [x8, x22]
1732 /* re-enable ddr clk in ipstpcr4 */
1733 str w4, [x7, x10]
173413:
1735 /* poll on ipstpack4 - start */
1736 ldr w1, [x7, x11]
1737 tst w1, w3
1738 b.eq 2f
1739 nop
1740 b 13b
1741 /* poll on ipstpack4 - end */
17422:
1743touch_line_4:
1744 cbz x0, touch_line_5
1745
1746start_line_5:
1747 /* take ddr out-of self refresh - start */
1748 mov x2, #DDR_SDRAM_CFG_2_FRCSR
1749 ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET]
1750 mov w4, w3
1751 bic w4, w4, w2
1752 mov w3, w4
1753 /* wait for ddr cntrlr clock- start */
1754 mov x1, #DDR_SLEEP_RETRY_CNT
17553:
1756 subs x1, x1, #1
1757touch_line_5:
1758 cbz x0, touch_line_6
1759
1760start_line_6:
1761 /* wait for ddr cntrlr clock - end */
1762 b.gt 3b
1763 /* take ddr out-of self refresh - end */
1764 str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET]
1765 mov w1, w17
1766 /* reset devdisr5 */
1767 str w1, [x8, #DCFG_DEVDISR5_OFFSET]
1768 mov w1, w16
1769 /* reset devdisr4 */
1770 str w1, [x8, #DCFG_DEVDISR4_OFFSET]
1771 mov w1, w15
1772touch_line_6:
1773 cbz x0, touch_line_7
1774
1775start_line_7:
1776 /* reset devdisr3 */
1777 str w1, [x8, #DCFG_DEVDISR3_OFFSET]
1778 mov w1, w14
1779 /* reset devdisr2 */
1780 str w1, [x8, #DCFG_DEVDISR2_OFFSET]
1781 mov w1, w13
1782 /* reset devdisr1 */
1783 str w1, [x8, #DCFG_DEVDISR1_OFFSET]
1784 /* reset ipstpcr4 */
1785 str wzr, [x7, x10]
1786 /* reset ipstpcr3 */
1787 str wzr, [x7, x12]
1788touch_line_7:
1789 cbz x0, touch_line_8
1790
1791start_line_8:
1792 /* reset ipstpcr2 */
1793 str wzr, [x7, x18]
1794 /* reset ipstpcr1 */
1795 str wzr, [x7, x19]
1796 /* reset ipstpcr0 */
1797 str wzr, [x7, x21]
1798
1799touch_line_8:
1800 cbz x0, touch_line_9
1801
1802start_line_9:
1803 b continue_restart
1804touch_line_9:
1805 cbz x0, start_line_0
1806
1807/* execute here after ddr is back up */
1808continue_restart:
1809 /*
1810 * if x0 = 1, all is well
1811 * if x0 < 1, we had an error
1812 */
1813 cmp x0, #1
1814 b.ne 4f
1815 mov x0, #0
18164:
1817 ret