12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817 |
- /*
- * Copyright 2022 NXP
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- .section .text, "ax"
- #include <asm_macros.S>
- #include <lib/psci/psci.h>
- #include <nxp_timer.h>
- #include <plat_gic.h>
- #include "bl31_data.h"
- #include "plat_psci.h"
- #include "platform_def.h"
- /*
- * the BASE address for these offsets is AUX_01_DATA in the
- * bootcore's psci data region
- */
- #define DEVDISR2_MASK_OFFSET 0x0 /* references AUX_01_DATA */
- #define DEVDISR5_MASK_OFFSET 0x8 /* references AUX_02_DATA */
- /*
- * the BASE address for these offsets is AUX_04_DATA in the
- * bootcore's psci data region
- */
- #define GICD_BASE_ADDR_OFFSET 0x0 /* references AUX_04_DATA */
- #define GICC_BASE_ADDR_OFFSET 0x8 /* references AUX_05_DATA */
- #define IPSTPACK_RETRY_CNT 0x10000
- #define DDR_SLEEP_RETRY_CNT 0x10000
- #define CPUACTLR_EL1 S3_1_C15_C2_0
- #define DDR_SDRAM_CFG_2_FRCSR 0x80000000
- #define DDR_SDRAM_CFG_2_OFFSET 0x114
- #define DDR_TIMING_CFG_4_OFFSET 0x160
- #define DDR_CNTRL_BASE_ADDR 0x01080000
- #define DLL_LOCK_MASK 0x3
- #define DLL_LOCK_VALUE 0x2
- #define ERROR_DDR_SLEEP -1
- #define ERROR_DDR_WAKE -2
- #define ERROR_NO_QUIESCE -3
- #define CORE_RESTARTABLE 0
- #define CORE_NOT_RESTARTABLE 1
- .global soc_init_lowlevel
- .global soc_init_percpu
- .global _soc_core_release
- .global _soc_core_restart
- .global _soc_ck_disabled
- .global _soc_sys_reset
- .global _soc_sys_off
- .global _soc_core_prep_off
- .global _soc_core_entr_off
- .global _soc_core_exit_off
- .global _soc_core_prep_stdby
- .global _soc_core_entr_stdby
- .global _soc_core_exit_stdby
- .global _soc_core_prep_pwrdn
- .global _soc_core_entr_pwrdn
- .global _soc_core_exit_pwrdn
- .global _soc_clstr_prep_stdby
- .global _soc_clstr_exit_stdby
- .global _soc_clstr_prep_pwrdn
- .global _soc_clstr_exit_pwrdn
- .global _soc_sys_prep_stdby
- .global _soc_sys_exit_stdby
- .global _soc_sys_prep_pwrdn
- .global _soc_sys_pwrdn_wfi
- .global _soc_sys_exit_pwrdn
- .global _set_platform_security
- .global _soc_set_start_addr
- .equ TZPCDECPROT_0_SET_BASE, 0x02200804
- .equ TZPCDECPROT_1_SET_BASE, 0x02200810
- .equ TZPCDECPROT_2_SET_BASE, 0x0220081C
- .equ TZASC_REGION_ATTRIBUTES_0_0, 0x01100110
- .equ MPIDR_AFFINITY0_MASK, 0x00FF
- .equ MPIDR_AFFINITY1_MASK, 0xFF00
- .equ CPUECTLR_DISABLE_TWALK_PREFETCH, 0x4000000000
- .equ CPUECTLR_INS_PREFETCH_MASK, 0x1800000000
- .equ CPUECTLR_DAT_PREFETCH_MASK, 0x0300000000
- .equ OSDLR_EL1_DLK_LOCK, 0x1
- .equ CNTP_CTL_EL0_EN, 0x1
- .equ CNTP_CTL_EL0_IMASK, 0x2
- /* shifted value for incrementing cluster count in mpidr */
- .equ MPIDR_CLUSTER, 0x100
- /*
- * This function initialize the soc,
- * in: none
- * out: none
- * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11
- */
- func soc_init_lowlevel
- /*
- * called from C, so save the non-volatile regs
- * save these as pairs of registers to maintain the
- * required 16-byte alignment on the stack
- */
- stp x4, x5, [sp, #-16]!
- stp x6, x7, [sp, #-16]!
- stp x8, x9, [sp, #-16]!
- stp x10, x11, [sp, #-16]!
- stp x12, x13, [sp, #-16]!
- stp x18, x30, [sp, #-16]!
- /*
- * make sure the personality has been established by releasing cores
- * that are marked "to-be-disabled" from reset
- */
- bl release_disabled
- /* set SCRATCHRW7 to 0x0 */
- ldr x0, =DCFG_SCRATCHRW7_OFFSET
- mov x1, xzr
- bl _write_reg_dcfg
- /* restore the aarch32/64 non-volatile registers */
- ldp x18, x30, [sp], #16
- ldp x12, x13, [sp], #16
- ldp x10, x11, [sp], #16
- ldp x8, x9, [sp], #16
- ldp x6, x7, [sp], #16
- ldp x4, x5, [sp], #16
- ret
- endfunc soc_init_lowlevel
- /*
- * void soc_init_percpu(void)
- * this function performs any soc-specific initialization that is needed on
- * a per-core basis
- * in: none
- * out: none
- * uses x0, x1, x2, x3
- */
- func soc_init_percpu
- stp x4, x30, [sp, #-16]!
- bl plat_my_core_mask
- mov x2, x0
- /* x2 = core mask */
- /* see if this core is marked for prefetch disable */
- mov x0, #PREFETCH_DIS_OFFSET
- bl _get_global_data
- tst x0, x2
- b.eq 1f
- bl _disable_ldstr_pfetch_A53
- 1:
- mov x0, #NXP_PMU_ADDR
- bl enable_timer_base_to_cluster
- ldp x4, x30, [sp], #16
- ret
- endfunc soc_init_percpu
- /*
- * this function sets the security mechanisms in the SoC to implement the
- * Platform Security Policy
- */
- func _set_platform_security
- mov x3, x30
- #if (!SUPPRESS_TZC)
- /* initialize the tzpc */
- bl init_tzpc
- #endif
- #if (!SUPPRESS_SEC)
- /* initialize secmon */
- bl initSecMon
- #endif
- mov x30, x3
- ret
- endfunc _set_platform_security
- /*
- * this function writes a 64-bit address to bootlocptrh/l
- * in: x0, 64-bit address to write to BOOTLOCPTRL/H
- * out: none
- * uses x0, x1, x2
- */
- func _soc_set_start_addr
- /* get the 64-bit base address of the dcfg block */
- ldr x2, =NXP_DCFG_ADDR
- /* write the 32-bit BOOTLOCPTRL register */
- mov x1, x0
- str w1, [x2, #DCFG_BOOTLOCPTRL_OFFSET]
- /* write the 32-bit BOOTLOCPTRH register */
- lsr x1, x0, #32
- str w1, [x2, #DCFG_BOOTLOCPTRH_OFFSET]
- ret
- endfunc _soc_set_start_addr
- /*
- * part of CPU_ON
- * this function releases a secondary core from reset
- * in: x0 = core_mask_lsb
- * out: none
- * uses: x0, x1, x2, x3
- */
- _soc_core_release:
- mov x3, x30
- /* x0 = core mask */
- ldr x1, =NXP_SEC_REGFILE_ADDR
- /*
- * write to CORE_HOLD to tell the bootrom that we want this core
- * to run
- */
- str w0, [x1, #CORE_HOLD_OFFSET]
- /* x0 = core mask */
- /* read-modify-write BRRL to release core */
- mov x1, #NXP_RESET_ADDR
- ldr w2, [x1, #BRR_OFFSET]
- orr w2, w2, w0
- str w2, [x1, #BRR_OFFSET]
- dsb sy
- isb
- /* send event */
- sev
- isb
- mov x30, x3
- ret
- /*
- * this function determines if a core is disabled via COREDISABLEDSR
- * in: w0 = core_mask_lsb
- * out: w0 = 0, core not disabled
- * w0 != 0, core disabled
- * uses x0, x1
- */
- _soc_ck_disabled:
- /* get base addr of dcfg block */
- ldr x1, =NXP_DCFG_ADDR
- /* read COREDISABLEDSR */
- ldr w1, [x1, #DCFG_COREDISABLEDSR_OFFSET]
- /* test core bit */
- and w0, w1, w0
- ret
- /*
- * part of CPU_ON
- * this function restarts a core shutdown via _soc_core_entr_off
- * in: x0 = core mask lsb (of the target cpu)
- * out: x0 == 0, on success
- * x0 != 0, on failure
- * uses x0, x1, x2, x3, x4, x5, x6
- */
- _soc_core_restart:
- mov x6, x30
- mov x4, x0
- /* x4 = core mask lsb */
- /* pgm GICD_CTLR - enable secure grp0 */
- mov x5, #NXP_GICD_ADDR
- ldr w2, [x5, #GICD_CTLR_OFFSET]
- orr w2, w2, #GICD_CTLR_EN_GRP_0
- str w2, [x5, #GICD_CTLR_OFFSET]
- dsb sy
- isb
- /* poll on RWP til write completes */
- 4:
- ldr w2, [x5, #GICD_CTLR_OFFSET]
- tst w2, #GICD_CTLR_RWP
- b.ne 4b
- /*
- * x4 = core mask lsb
- * x5 = gicd base addr
- */
- mov x0, x4
- bl get_mpidr_value
- /*
- * x0 = mpidr of target core
- * x4 = core mask lsb of target core
- * x5 = gicd base addr
- */
- /* generate target list bit */
- and x1, x0, #MPIDR_AFFINITY0_MASK
- mov x2, #1
- lsl x2, x2, x1
- /* get the affinity1 field */
- and x1, x0, #MPIDR_AFFINITY1_MASK
- lsl x1, x1, #8
- orr x2, x2, x1
- /* insert the INTID for SGI15 */
- orr x2, x2, #ICC_SGI0R_EL1_INTID
- /* fire the SGI */
- msr ICC_SGI0R_EL1, x2
- dsb sy
- isb
- /* load '0' on success */
- mov x0, xzr
- mov x30, x6
- ret
- /*
- * part of CPU_OFF
- * this function programs SoC & GIC registers in preparation for shutting down
- * the core
- * in: x0 = core mask lsb
- * out: none
- * uses x0, x1, x2, x3, x4, x5, x6, x7
- */
- _soc_core_prep_off:
- mov x8, x30
- mov x7, x0
- /* x7 = core mask lsb */
- mrs x1, CPUECTLR_EL1
- /* set smp and disable L2 snoops in cpuectlr */
- orr x1, x1, #CPUECTLR_SMPEN_EN
- orr x1, x1, #CPUECTLR_DISABLE_TWALK_PREFETCH
- bic x1, x1, #CPUECTLR_INS_PREFETCH_MASK
- bic x1, x1, #CPUECTLR_DAT_PREFETCH_MASK
- /* set retention control in cpuectlr */
- bic x1, x1, #CPUECTLR_TIMER_MASK
- orr x1, x1, #CPUECTLR_TIMER_8TICKS
- msr CPUECTLR_EL1, x1
- /* get redistributor rd base addr for this core */
- mov x0, x7
- bl get_gic_rd_base
- mov x6, x0
- /* get redistributor sgi base addr for this core */
- mov x0, x7
- bl get_gic_sgi_base
- mov x5, x0
- /* x5 = gicr sgi base addr
- * x6 = gicr rd base addr
- * x7 = core mask lsb
- */
- /* disable SGI 15 at redistributor - GICR_ICENABLER0 */
- mov w3, #GICR_ICENABLER0_SGI15
- str w3, [x5, #GICR_ICENABLER0_OFFSET]
- 2:
- /* poll on rwp bit in GICR_CTLR */
- ldr w4, [x6, #GICR_CTLR_OFFSET]
- tst w4, #GICR_CTLR_RWP
- b.ne 2b
- /* disable GRP1 interrupts at cpu interface */
- msr ICC_IGRPEN1_EL3, xzr
- /* disable GRP0 ints at cpu interface */
- msr ICC_IGRPEN0_EL1, xzr
- /* program the redistributor - poll on GICR_CTLR.RWP as needed */
- /* define SGI 15 as Grp0 - GICR_IGROUPR0 */
- ldr w4, [x5, #GICR_IGROUPR0_OFFSET]
- bic w4, w4, #GICR_IGROUPR0_SGI15
- str w4, [x5, #GICR_IGROUPR0_OFFSET]
- /* define SGI 15 as Grp0 - GICR_IGRPMODR0 */
- ldr w3, [x5, #GICR_IGRPMODR0_OFFSET]
- bic w3, w3, #GICR_IGRPMODR0_SGI15
- str w3, [x5, #GICR_IGRPMODR0_OFFSET]
- /* set priority of SGI 15 to highest (0x0) - GICR_IPRIORITYR3 */
- ldr w4, [x5, #GICR_IPRIORITYR3_OFFSET]
- bic w4, w4, #GICR_IPRIORITYR3_SGI15_MASK
- str w4, [x5, #GICR_IPRIORITYR3_OFFSET]
- /* enable SGI 15 at redistributor - GICR_ISENABLER0 */
- mov w3, #GICR_ISENABLER0_SGI15
- str w3, [x5, #GICR_ISENABLER0_OFFSET]
- dsb sy
- isb
- 3:
- /* poll on rwp bit in GICR_CTLR */
- ldr w4, [x6, #GICR_CTLR_OFFSET]
- tst w4, #GICR_CTLR_RWP
- b.ne 3b
- /* quiesce the debug interfaces */
- mrs x3, osdlr_el1
- orr x3, x3, #OSDLR_EL1_DLK_LOCK
- msr osdlr_el1, x3
- isb
- /* enable grp0 ints */
- mov x3, #ICC_IGRPEN0_EL1_EN
- msr ICC_IGRPEN0_EL1, x3
- /*
- * x5 = gicr sgi base addr
- * x6 = gicr rd base addr
- * x7 = core mask lsb
- */
- /* clear any pending interrupts */
- mvn w1, wzr
- str w1, [x5, #GICR_ICPENDR0_OFFSET]
- /* make sure system counter is enabled */
- ldr x3, =NXP_TIMER_ADDR
- ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
- tst w0, #SYS_COUNTER_CNTCR_EN
- b.ne 4f
- orr w0, w0, #SYS_COUNTER_CNTCR_EN
- str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
- 4:
- /* enable the core timer and mask timer interrupt */
- mov x1, #CNTP_CTL_EL0_EN
- orr x1, x1, #CNTP_CTL_EL0_IMASK
- msr cntp_ctl_el0, x1
- mov x30, x8
- ret
- /*
- * part of CPU_OFF
- * this function performs the final steps to shutdown the core
- * in: x0 = core mask lsb
- * out: none
- * uses x0, x1, x2, x3, x4, x5
- */
- _soc_core_entr_off:
- mov x5, x30
- mov x4, x0
- /* x4 = core mask */
- 1:
- /* enter low-power state by executing wfi */
- wfi
- /* see if SGI15 woke us up */
- mrs x2, ICC_IAR0_EL1
- mov x3, #ICC_IAR0_EL1_SGI15
- cmp x2, x3
- b.ne 2f
- /* deactivate the int */
- msr ICC_EOIR0_EL1, x2
- /* x4 = core mask */
- 2:
- /* check if core has been turned on */
- mov x0, x4
- bl _getCoreState
- /* x0 = core state */
- cmp x0, #CORE_WAKEUP
- b.ne 1b
- /* if we get here, then we have exited the wfi */
- mov x30, x5
- ret
- /*
- * part of CPU_OFF
- * this function starts the process of starting a core back up
- * in: x0 = core mask lsb
- * out: none
- * uses x0, x1, x2, x3, x4, x5, x6
- */
- _soc_core_exit_off:
- mov x6, x30
- mov x5, x0
- /* disable forwarding of GRP0 ints at cpu interface */
- msr ICC_IGRPEN0_EL1, xzr
- /* get redistributor sgi base addr for this core */
- mov x0, x5
- bl get_gic_sgi_base
- mov x4, x0
- /*
- * x4 = gicr sgi base addr
- * x5 = core mask
- */
- /* disable SGI 15 at redistributor - GICR_ICENABLER0 */
- mov w1, #GICR_ICENABLER0_SGI15
- str w1, [x4, #GICR_ICENABLER0_OFFSET]
- /* get redistributor rd base addr for this core */
- mov x0, x5
- bl get_gic_rd_base
- mov x4, x0
- /* x4 = gicr rd base addr */
- 2:
- /* poll on rwp bit in GICR_CTLR */
- ldr w2, [x4, #GICR_CTLR_OFFSET]
- tst w2, #GICR_CTLR_RWP
- b.ne 2b
- /* x4 = gicr rd base addr */
- /* unlock the debug interfaces */
- mrs x3, osdlr_el1
- bic x3, x3, #OSDLR_EL1_DLK_LOCK
- msr osdlr_el1, x3
- isb
- dsb sy
- isb
- mov x30, x6
- ret
- /*
- * this function requests a reset of the entire SOC
- * in: none
- * out: none
- * uses: x0, x1, x2, x3, x4, x5, x6
- */
- _soc_sys_reset:
- mov x3, x30
- /* make sure the mask is cleared in the reset request mask register */
- mov x0, #RST_RSTRQMR1_OFFSET
- mov w1, wzr
- bl _write_reg_reset
- /* set the reset request */
- mov x4, #RST_RSTCR_OFFSET
- mov x0, x4
- mov w1, #RSTCR_RESET_REQ
- bl _write_reg_reset
- /* x4 = RST_RSTCR_OFFSET */
- /*
- * just in case this address range is mapped as cacheable,
- * flush the write out of the dcaches
- */
- mov x2, #NXP_RESET_ADDR
- add x2, x2, x4
- dc cvac, x2
- dsb st
- isb
- /* this function does not return */
- b .
- /*
- * this function turns off the SoC
- * Note: this function is not intended to return, and the only allowable
- * recovery is POR
- * in: none
- * out: none
- * uses x0, x1, x2, x3
- */
- _soc_sys_off:
- /*
- * A-009810: LPM20 entry sequence might cause
- * spurious timeout reset request
- * workaround: MASK RESET REQ RPTOE
- */
- ldr x0, =NXP_RESET_ADDR
- ldr w1, [x0, #RST_RSTRQMR1_OFFSET]
- orr w1, w1, #RSTRQMR_RPTOE_MASK
- str w1, [x0, #RST_RSTRQMR1_OFFSET]
- /* disable SEC, QBman spi and qspi */
- ldr x2, =NXP_DCFG_ADDR
- ldr x0, =DCFG_DEVDISR1_OFFSET
- ldr w1, =DCFG_DEVDISR1_SEC
- str w1, [x2, x0]
- ldr x0, =DCFG_DEVDISR3_OFFSET
- ldr w1, =DCFG_DEVDISR3_QBMAIN
- str w1, [x2, x0]
- ldr x0, =DCFG_DEVDISR4_OFFSET
- ldr w1, =DCFG_DEVDISR4_SPI_QSPI
- str w1, [x2, x0]
- /* set TPMWAKEMR0 */
- ldr x0, =TPMWAKEMR0_ADDR
- mov w1, #0x1
- str w1, [x0]
- /* disable icache, dcache, mmu @ EL1 */
- mov x1, #SCTLR_I_C_M_MASK
- mrs x0, sctlr_el1
- bic x0, x0, x1
- msr sctlr_el1, x0
- /* disable L2 prefetches */
- mrs x0, CPUECTLR_EL1
- orr x0, x0, #CPUECTLR_SMPEN_EN
- orr x0, x0, #CPUECTLR_TIMER_8TICKS
- msr CPUECTLR_EL1, x0
- dsb sy
- isb
- /* disable CCN snoop domain */
- ldr x0, =NXP_CCI_ADDR
- mov w1, #0x1
- str w1, [x0]
- mov x2, #DAIF_SET_MASK
- mrs x1, spsr_el1
- orr x1, x1, x2
- msr spsr_el1, x1
- mrs x1, spsr_el2
- orr x1, x1, x2
- msr spsr_el2, x1
- bl get_pmu_idle_cluster_mask
- mov x3, #NXP_PMU_ADDR
- /* x3 = pmu base addr */
- /* idle the ACP interfaces */
- str w0, [x3, #PMU_CLAINACTSETR_OFFSET]
- /* force the debug interface to be quiescent */
- mrs x0, osdlr_el1
- orr x0, x0, #0x1
- msr osdlr_el1, x0
- bl get_pmu_flush_cluster_mask
- /* x3 = pmu base addr */
- mov x3, #NXP_PMU_ADDR
- /* clear flush request and status */
- ldr x2, =PMU_CLSL2FLUSHCLRR_OFFSET
- str w0, [x3, x2]
- /* close the Skyros master port */
- ldr x2, =PMU_CLSINACTSETR_OFFSET
- str w0, [x3, x2]
- /* request lpm20 */
- ldr x0, =PMU_POWMGTCSR_OFFSET
- ldr w1, =PMU_POWMGTCSR_VAL
- str w1, [x3, x0]
- /* this function does not return */
- 1:
- wfi
- b 1b
- /*
- * part of CPU_SUSPEND
- * this function performs SoC-specific programming prior to standby
- * in: x0 = core mask lsb
- * out: none
- * uses x0, x1
- */
- _soc_core_prep_stdby:
- /* clear CPUECTLR_EL1[2:0] */
- mrs x1, CPUECTLR_EL1
- bic x1, x1, #CPUECTLR_TIMER_MASK
- msr CPUECTLR_EL1, x1
- ret
- /*
- * part of CPU_SUSPEND
- * this function puts the calling core into standby state
- * in: x0 = core mask lsb
- * out: none
- * uses x0
- */
- _soc_core_entr_stdby:
- /* X0 = core mask lsb */
- dsb sy
- isb
- wfi
- ret
- /*
- * part of CPU_SUSPEND
- * this function performs any SoC-specific cleanup after standby state
- * in: x0 = core mask lsb
- * out: none
- * uses none
- */
- _soc_core_exit_stdby:
- ret
- /*
- * part of CPU_SUSPEND
- * this function performs SoC-specific programming prior to power-down
- * in: x0 = core mask lsb
- * out: none
- * uses x0, x1, x2, x3
- */
- _soc_core_prep_pwrdn:
- /* make sure system counter is enabled */
- ldr x3, =NXP_TIMER_ADDR
- ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
- tst w0, #SYS_COUNTER_CNTCR_EN
- b.ne 1f
- orr w0, w0, #SYS_COUNTER_CNTCR_EN
- str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
- 1:
- /*
- * enable dynamic retention control (CPUECTLR[2:0])
- * set the SMPEN bit (CPUECTLR[6])
- */
- mrs x1, CPUECTLR_EL1
- bic x1, x1, #CPUECTLR_RET_MASK
- orr x1, x1, #CPUECTLR_TIMER_8TICKS
- orr x1, x1, #CPUECTLR_SMPEN_EN
- msr CPUECTLR_EL1, x1
- isb
- ret
- /*
- * part of CPU_SUSPEND
- * this function puts the calling core into a power-down state
- * in: x0 = core mask lsb
- * out: none
- * uses x0
- */
- _soc_core_entr_pwrdn:
- /* X0 = core mask lsb */
- dsb sy
- isb
- wfi
- ret
- /*
- * part of CPU_SUSPEND
- * this function cleans up after a core exits power-down
- * in: x0 = core mask lsb
- * out: none
- * uses
- */
- _soc_core_exit_pwrdn:
- ret
- /*
- * part of CPU_SUSPEND
- * this function performs SoC-specific programming prior to standby
- * in: x0 = core mask lsb
- * out: none
- * uses x0, x1
- */
- _soc_clstr_prep_stdby:
- /* clear CPUECTLR_EL1[2:0] */
- mrs x1, CPUECTLR_EL1
- bic x1, x1, #CPUECTLR_TIMER_MASK
- msr CPUECTLR_EL1, x1
- ret
- /*
- * part of CPU_SUSPEND
- * this function performs any SoC-specific cleanup after standby state
- * in: x0 = core mask lsb
- * out: none
- * uses none
- */
- _soc_clstr_exit_stdby:
- ret
- /*
- * part of CPU_SUSPEND
- * this function performs SoC-specific programming prior to power-down
- * in: x0 = core mask lsb
- * out: none
- * uses x0, x1, x2, x3
- */
- _soc_clstr_prep_pwrdn:
- /* make sure system counter is enabled */
- ldr x3, =NXP_TIMER_ADDR
- ldr w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
- tst w0, #SYS_COUNTER_CNTCR_EN
- b.ne 1f
- orr w0, w0, #SYS_COUNTER_CNTCR_EN
- str w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
- 1:
- /*
- * enable dynamic retention control (CPUECTLR[2:0])
- * set the SMPEN bit (CPUECTLR[6])
- */
- mrs x1, CPUECTLR_EL1
- bic x1, x1, #CPUECTLR_RET_MASK
- orr x1, x1, #CPUECTLR_TIMER_8TICKS
- orr x1, x1, #CPUECTLR_SMPEN_EN
- msr CPUECTLR_EL1, x1
- isb
- ret
- /*
- * part of CPU_SUSPEND
- * this function cleans up after a core exits power-down
- * in: x0 = core mask lsb
- * out: none
- * uses
- */
- _soc_clstr_exit_pwrdn:
- ret
- /*
- * part of CPU_SUSPEND
- * this function performs SoC-specific programming prior to standby
- * in: x0 = core mask lsb
- * out: none
- * uses x0, x1
- */
- _soc_sys_prep_stdby:
- /* clear CPUECTLR_EL1[2:0] */
- mrs x1, CPUECTLR_EL1
- bic x1, x1, #CPUECTLR_TIMER_MASK
- msr CPUECTLR_EL1, x1
- ret
- /*
- * part of CPU_SUSPEND
- * this function performs any SoC-specific cleanup after standby state
- * in: x0 = core mask lsb
- * out: none
- * uses none
- */
- _soc_sys_exit_stdby:
- ret
- /*
- * part of CPU_SUSPEND
- * this function performs SoC-specific programming prior to
- * suspend-to-power-down
- * in: x0 = core mask lsb
- * out: none
- * uses x0
- */
- _soc_sys_prep_pwrdn:
- /* set retention control */
- mrs x0, CPUECTLR_EL1
- bic x0, x0, #CPUECTLR_TIMER_MASK
- orr x0, x0, #CPUECTLR_TIMER_8TICKS
- orr x0, x0, #CPUECTLR_SMPEN_EN
- msr CPUECTLR_EL1, x0
- dsb sy
- isb
- ret
- /*
- * part of CPU_SUSPEND
- * this function puts the calling core, and potentially the soc, into a
- * low-power state
- * in: x0 = core mask lsb
- * out: x0 = 0, success
- * x0 < 0, failure
- * uses x0, x1, x2, x3, x4, x5, x6, x7, x8
- */
- _soc_sys_pwrdn_wfi:
- /* Save LR to stack */
- stp x18, x30, [sp, #-16]!
- /* Poll PCPW20SR for all secondary cores to be placed in PW20 */
- bl get_tot_num_cores
- mov x3, #0x1
- lsl x3, x3, x0
- sub x3, x3, #2
- 1:
- mov x0, #NXP_PMU_ADDR
- ldr w1, [x0, #PMU_PCPW20SR_OFFSET]
- cmp w1, w3
- b.ne 1b
- /* backup EPU registers to stack */
- mov x3, #NXP_PMU_ADDR
- ldr x2, =NXP_EPU_ADDR
- ldr w4, [x2, #EPU_EPIMCR10_OFFSET]
- ldr w5, [x2, #EPU_EPCCR10_OFFSET]
- ldr w6, [x2, #EPU_EPCTR10_OFFSET]
- ldr w7, [x2, #EPU_EPGCR_OFFSET]
- stp x4, x5, [sp, #-16]!
- stp x6, x7, [sp, #-16]!
- /*
- * x2 = epu base addr
- * x3 = pmu base addr
- */
- /* set up EPU event to receive the wake signal from PMU */
- mov w4, #EPU_EPIMCR10_VAL
- mov w5, #EPU_EPCCR10_VAL
- mov w6, #EPU_EPCTR10_VAL
- mov w7, #EPU_EPGCR_VAL
- str w4, [x2, #EPU_EPIMCR10_OFFSET]
- str w5, [x2, #EPU_EPCCR10_OFFSET]
- str w6, [x2, #EPU_EPCTR10_OFFSET]
- str w7, [x2, #EPU_EPGCR_OFFSET]
- /*
- * A-010194: There is logic problem
- * in the path of GIC-to-PMU to issue
- * wake request to core0
- * Workaround: Re-target the wakeup interrupts
- * to a core other than the last active core0
- */
- ldr x2, =NXP_GICD_ADDR
- /* backup flextimer/mmc/usb interrupt router */
- ldr x0, =GICD_IROUTER60_OFFSET
- ldr x1, =GICD_IROUTER76_OFFSET
- ldr w4, [x2, x0]
- ldr w5, [x2, x1]
- ldr x0, =GICD_IROUTER112_OFFSET
- ldr x1, =GICD_IROUTER113_OFFSET
- ldr w6, [x2, x0]
- ldr w7, [x2, x1]
- stp x4, x5, [sp, #-16]!
- stp x6, x7, [sp, #-16]!
- /*
- * x2 = gicd base addr
- * x0 = GICD_IROUTER112_OFFSET
- * x1 = GICD_IROUTER113_OFFSET
- */
- /* re-route interrupt to cluster 1 */
- ldr w4, =GICD_IROUTER_VALUE
- str w4, [x2, x0]
- str w4, [x2, x1]
- ldr x0, =GICD_IROUTER60_OFFSET
- ldr x1, =GICD_IROUTER76_OFFSET
- str w4, [x2, x0]
- str w4, [x2, x1]
- dsb sy
- isb
- /* backup flextimer/mmc/usb interrupt enabler */
- ldr x0, =GICD_ISENABLER_1
- ldr w4, [x2, x0]
- ldr x1, =GICD_ISENABLER_2
- ldr w5, [x2, x1]
- stp x4, x5, [sp, #-16]!
- ldr x0, =GICD_ISENABLER_3
- ldr w4, [x2, x0]
- ldr x1, =GICD_ICENABLER_1
- ldr w5, [x2, x1]
- stp x4, x5, [sp, #-16]!
- ldr x0, =GICD_ICENABLER_2
- ldr w4, [x2, x0]
- ldr x1, =GICD_ICENABLER_3
- ldr w5, [x2, x1]
- stp x4, x5, [sp, #-16]!
- /* enable related interrupt routing */
- ldr w4, =GICD_ISENABLER_1_VALUE
- ldr x0, =GICD_ISENABLER_1
- str w4, [x2, x0]
- dsb sy
- isb
- ldr w4, =GICD_ISENABLER_2_VALUE
- ldr x0, =GICD_ISENABLER_2
- str w4, [x2, x0]
- dsb sy
- isb
- ldr w4, =GICD_ISENABLER_3_VALUE
- ldr x0, =GICD_ISENABLER_3
- str w4, [x2, x0]
- dsb sy
- isb
- /* set POWMGTDCR [STP_PV_EN] = 1 */
- ldr x2, =NXP_POWMGTDCR
- ldr w4, =0x01
- str w4, [x2]
- /* program IPSTPCR for override stop request (except DDR) */
- mov x3, #NXP_PMU_ADDR
- /* build an override mask for IPSTPCR4/IPSTPACK4/DEVDISR5 */
- ldr x2, =PMU_IPPDEXPCR4_OFFSET
- ldr w7, [x3, x2]
- mov x5, xzr
- ldr x6, =IPPDEXPCR4_MASK
- and x6, x6, x7
- cbz x6, 1f
- /*
- * x5 = override mask
- * x6 = IPPDEXPCR bits for DEVDISR5
- * x7 = IPPDEXPCR
- */
- /* get the overrides */
- orr x4, x5, #DEVDISR5_FLX_TMR
- tst x6, #IPPDEXPCR_FLX_TMR
- csel x5, x5, x4, EQ
- 1:
- /* store the DEVDISR5 override mask */
- ldr x2, =BC_PSCI_BASE
- add x2, x2, #AUX_01_DATA
- str w5, [x2, #DEVDISR5_MASK_OFFSET]
- mov x3, #NXP_PMU_ADDR
- /* write IPSTPCR0 - no overrides */
- ldr x2, =PMU_IPSTPCR0_OFFSET
- ldr w5, =IPSTPCR0_VALUE
- str w5, [x3, x2]
- /* write IPSTPCR1 - no overrides */
- ldr x2, =PMU_IPSTPCR1_OFFSET
- ldr w5, =IPSTPCR1_VALUE
- str w5, [x3, x2]
- /* write IPSTPCR2 - no overrides */
- ldr x2, =PMU_IPSTPCR2_OFFSET
- ldr w5, =IPSTPCR2_VALUE
- str w5, [x3, x2]
- /* write IPSTPCR3 - no overrides */
- ldr x2, =PMU_IPSTPCR3_OFFSET
- ldr w5, =IPSTPCR3_VALUE
- str w5, [x3, x2]
- /* write IPSTPCR4 - overrides possible */
- ldr x2, =BC_PSCI_BASE
- add x2, x2, #AUX_01_DATA
- ldr w6, [x2, #DEVDISR5_MASK_OFFSET]
- ldr x2, =PMU_IPSTPCR4_OFFSET
- ldr w5, =IPSTPCR4_VALUE
- bic x5, x5, x6
- str w5, [x3, x2]
- /* write IPSTPCR5 - no overrides */
- ldr x2, =PMU_IPSTPCR5_OFFSET
- ldr w5, =IPSTPCR5_VALUE
- str w5, [x3, x2]
- /* write IPSTPCR6 - no overrides */
- ldr x2, =PMU_IPSTPCR6_OFFSET
- ldr w5, =IPSTPCR6_VALUE
- str w5, [x3, x2]
- /* poll IPSTPACK for IP stop acknowledgment (except DDR) */
- mov x3, #NXP_PMU_ADDR
- /* poll on IPSTPACK0 */
- ldr x2, =PMU_IPSTPACK0_OFFSET
- ldr x4, =IPSTPCR0_VALUE
- ldr x7, =IPSTPACK_RETRY_CNT
- 3:
- ldr w0, [x3, x2]
- cmp x0, x4
- b.eq 14f
- sub x7, x7, #1
- cbnz x7, 3b
- 14:
- /* poll on IPSTPACK1 */
- ldr x2, =PMU_IPSTPACK1_OFFSET
- ldr x4, =IPSTPCR1_VALUE
- ldr x7, =IPSTPACK_RETRY_CNT
- 4:
- ldr w0, [x3, x2]
- cmp x0, x4
- b.eq 15f
- sub x7, x7, #1
- cbnz x7, 4b
- 15:
- /* poll on IPSTPACK2 */
- ldr x2, =PMU_IPSTPACK2_OFFSET
- ldr x4, =IPSTPCR2_VALUE
- ldr x7, =IPSTPACK_RETRY_CNT
- 5:
- ldr w0, [x3, x2]
- cmp x0, x4
- b.eq 16f
- sub x7, x7, #1
- cbnz x7, 5b
- 16:
- /* poll on IPSTPACK3 */
- ldr x2, =PMU_IPSTPACK3_OFFSET
- ldr x4, =IPSTPCR3_VALUE
- ldr x7, =IPSTPACK_RETRY_CNT
- 6:
- ldr w0, [x3, x2]
- cmp x0, x4
- b.eq 17f
- sub x7, x7, #1
- cbnz x7, 6b
- 17:
- /* poll on IPSTPACK4 */
- ldr x2, =PMU_IPSTPACK4_OFFSET
- ldr x4, =IPSTPCR4_VALUE
- ldr x7, =IPSTPACK_RETRY_CNT
- 7:
- ldr w0, [x3, x2]
- cmp x0, x4
- b.eq 18f
- sub x7, x7, #1
- cbnz x7, 7b
- 18:
- /* poll on IPSTPACK5 */
- ldr x2, =PMU_IPSTPACK5_OFFSET
- ldr x4, =IPSTPCR5_VALUE
- ldr x7, =IPSTPACK_RETRY_CNT
- 8:
- ldr w0, [x3, x2]
- cmp x0, x4
- b.eq 19f
- sub x7, x7, #1
- cbnz x7, 8b
- 19:
- /* poll on IPSTPACK6 */
- ldr x2, =PMU_IPSTPACK6_OFFSET
- ldr x4, =IPSTPCR6_VALUE
- ldr x7, =IPSTPACK_RETRY_CNT
- 9:
- ldr w0, [x3, x2]
- cmp x0, x4
- b.eq 20f
- sub x7, x7, #1
- cbnz x7, 9b
- 20:
- /* save current DEVDISR states to DDR. */
- ldr x2, =NXP_DCFG_ADDR
- /* save DEVDISR1 and load new value */
- ldr x0, =DCFG_DEVDISR1_OFFSET
- ldr w1, [x2, x0]
- mov w13, w1
- ldr x1, =DEVDISR1_VALUE
- str w1, [x2, x0]
- /* save DEVDISR2 and load new value */
- ldr x0, =DCFG_DEVDISR2_OFFSET
- ldr w1, [x2, x0]
- mov w14, w1
- ldr x1, =DEVDISR2_VALUE
- str w1, [x2, x0]
- /* x6 = DEVDISR5 override mask */
- /* save DEVDISR3 and load new value */
- ldr x0, =DCFG_DEVDISR3_OFFSET
- ldr w1, [x2, x0]
- mov w15, w1
- ldr x1, =DEVDISR3_VALUE
- str w1, [x2, x0]
- /* save DEVDISR4 and load new value */
- ldr x0, =DCFG_DEVDISR4_OFFSET
- ldr w1, [x2, x0]
- mov w16, w1
- /* not stop uart print */
- ldr x1, =0x0000332
- str w1, [x2, x0]
- /* save DEVDISR5 and load new value */
- ldr x0, =DCFG_DEVDISR5_OFFSET
- ldr w1, [x2, x0]
- mov w17, w1
- /* Enable this wakeup will fail, should enable OCRAM */
- ldr x1, =0x00102300
- str w1, [x2, x0]
- /* save DEVDISR6 and load new value */
- ldr x0, =DCFG_DEVDISR6_OFFSET
- ldr w1, [x2, x0]
- mov w18, w1
- ldr x1, =DEVDISR6_VALUE
- str w1, [x2, x0]
- /*
- * w13 = DEVDISR1 saved value
- * w14 = DEVDISR2 saved value
- * w15 = DEVDISR3 saved value
- * w16 = DEVDISR4 saved value
- * w17 = DEVDISR5 saved value
- * w18 = DEVDISR6 saved value
- */
- /*
- * A-009810: LPM20 entry sequence might cause
- * spurious timeout reset request
- * workaround: MASK RESET REQ RPTOE
- */
- ldr x0, =NXP_RESET_ADDR
- ldr w1, =RSTRQMR_RPTOE_MASK
- str w1, [x0, #RST_RSTRQMR1_OFFSET]
- /* disable SEC, QBman spi and qspi */
- ldr x2, =NXP_DCFG_ADDR
- ldr x0, =DCFG_DEVDISR1_OFFSET
- ldr w1, =DCFG_DEVDISR1_SEC
- str w1, [x2, x0]
- ldr x0, =DCFG_DEVDISR3_OFFSET
- ldr w1, =DCFG_DEVDISR3_QBMAIN
- str w1, [x2, x0]
- ldr x0, =DCFG_DEVDISR4_OFFSET
- ldr w1, =DCFG_DEVDISR4_SPI_QSPI
- str w1, [x2, x0]
- /*
- * write the GICR_WAKER.ProcessorSleep bits to 1
- * enable the WakeRequest signal
- * x3 is cpu mask starting from cpu7
- */
- bl get_tot_num_cores
- sub x0, x0, #1
- mov x3, #0x1
- lsl x3, x3, x0
- 2:
- mov x0, x3
- bl get_gic_rd_base
- ldr w1, [x0, #GICR_WAKER_OFFSET]
- orr w1, w1, #GICR_WAKER_SLEEP_BIT
- str w1, [x0, #GICR_WAKER_OFFSET]
- 1:
- ldr w1, [x0, #GICR_WAKER_OFFSET]
- cmp w1, #GICR_WAKER_ASLEEP
- b.ne 1b
- lsr x3, x3, #1
- cbnz x3, 2b
- /* x3 = pmu base addr */
- /* perform Icache Warming Sequence */
- ldr x5, =IPSTPCR4_VALUE
- mov x6, DDR_CNTRL_BASE_ADDR
- mov x7, #NXP_PMU_ADDR
- mov x8, #NXP_DCFG_ADDR
- mov x10, #PMU_IPSTPCR4_OFFSET
- mov x11, #PMU_IPSTPACK4_OFFSET
- mov x12, #PMU_IPSTPCR3_OFFSET
- mov x18, #PMU_IPSTPCR2_OFFSET
- mov x19, #PMU_IPSTPCR1_OFFSET
- mov x21, #PMU_IPSTPCR0_OFFSET
- ldr x22, =DCFG_DEVDISR5_OFFSET
- ldr x23, =NXP_EPU_ADDR
- mov x9, #CORE_RESTARTABLE
- bl final_pwrdown
- /*
- * disable the WakeRequest signal on cpu 0-7
- * x3 is cpu mask starting from cpu7
- */
- bl get_tot_num_cores
- sub x0, x0, #1
- mov x3, #0x1
- lsl x3, x3, x0
- 2:
- mov x0, x3
- bl get_gic_rd_base
- ldr w1, [x0, #GICR_WAKER_OFFSET]
- bic w1, w1, #GICR_WAKER_SLEEP_BIT
- str w1, [x0, #GICR_WAKER_OFFSET]
- 1:
- ldr w1, [x0, #GICR_WAKER_OFFSET]
- cbnz w1, 1b
- lsr x3, x3, #1
- cbnz x3, 2b
- /* set SGI for secondary core wakeup */
- ldr x0, =0x1000002
- msr S3_0_C12_C11_7, x0
- isb
- ldr x0, =0x2000004
- msr S3_0_C12_C11_7, x0
- isb
- ldr x0, =0x3000008
- msr S3_0_C12_C11_7, x0
- isb
- ldr x0, =0x4010001
- msr S3_0_C12_C11_7, x0
- isb
- ldr x0, =0x5010002
- msr S3_0_C12_C11_7, x0
- isb
- ldr x0, =0x6010004
- msr S3_0_C12_C11_7, x0
- isb
- ldr x0, =0x7010008
- msr S3_0_C12_C11_7, x0
- /* enable SEC, QBman spi and qspi */
- ldr x2, =NXP_DCFG_ADDR
- str wzr, [x2, #DCFG_DEVDISR1_OFFSET]
- str wzr, [x2, #DCFG_DEVDISR3_OFFSET]
- str wzr, [x2, #DCFG_DEVDISR4_OFFSET]
- /* clear POWMGTDCR [STP_PV_EN] */
- ldr x2, =NXP_POWMGTDCR
- ldr w4, [x2]
- bic w4, w4, #0x01
- str w4, [x2]
- /* restore flextimer/mmc/usb interrupt enabler */
- ldr x3, =NXP_GICD_ADDR
- ldp x0, x2, [sp], #16
- ldr x1, =GICD_ICENABLER_2
- mvn w0, w0
- str w0, [x3, x1]
- ldr x1, =GICD_ICENABLER_3
- mvn w2, w2
- str w2, [x3, x1]
- ldp x0, x2, [sp], #16
- ldr x1, =GICD_ISENABLER_3
- str w0, [x3, x1]
- ldr x1, =GICD_ICENABLER_1
- mvn w2, w2
- str w0, [x3, x1]
- ldp x0, x2, [sp], #16
- ldr x1, =GICD_ISENABLER_1
- str w0, [x3, x1]
- ldr x1, =GICD_ISENABLER_2
- str w0, [x3, x1]
- /* restore flextimer/mmc/usb interrupt router */
- ldr x3, =NXP_GICD_ADDR
- ldp x0, x2, [sp], #16
- ldr x1, =GICD_IROUTER113_OFFSET
- str w2, [x3, x1]
- ldr x1, =GICD_IROUTER112_OFFSET
- str w0, [x3, x1]
- ldp x0, x2, [sp], #16
- ldr x1, =GICD_IROUTER76_OFFSET
- str w2, [x3, x1]
- ldr x1, =GICD_IROUTER60_OFFSET
- str w0, [x3, x1]
- /* restore EPU registers */
- ldr x3, =NXP_EPU_ADDR
- ldp x0, x2, [sp], #16
- str w2, [x3, #EPU_EPGCR_OFFSET]
- str w0, [x3, #EPU_EPCTR10_OFFSET]
- ldp x2, x1, [sp], #16
- str w1, [x3, #EPU_EPCCR10_OFFSET]
- str w2, [x3, #EPU_EPIMCR10_OFFSET]
- isb
- /* Restor LR */
- ldp x18, x30, [sp], #16
- ret
- /*
- * part of CPU_SUSPEND
- * this function performs any SoC-specific cleanup after power-down
- * in: x0 = core mask lsb
- * out: none
- * uses x0, x1
- */
- _soc_sys_exit_pwrdn:
- mrs x1, SCTLR_EL1
- orr x1, x1, #SCTLR_I_MASK
- msr SCTLR_EL1, x1
- isb
- ret
- /*
- * this function checks to see if cores which are to be disabled have been
- * released from reset - if not, it releases them
- * in: none
- * out: none
- * uses x0, x1, x2, x3, x4, x5, x6, x7, x8
- */
- release_disabled:
- mov x8, x30
- /* read COREDISABLESR */
- mov x0, #NXP_DCFG_ADDR
- ldr w4, [x0, #DCFG_COREDISABLEDSR_OFFSET]
- /* get the number of cpus on this device */
- mov x6, #PLATFORM_CORE_COUNT
- mov x0, #NXP_RESET_ADDR
- ldr w5, [x0, #BRR_OFFSET]
- /* load the core mask for the first core */
- mov x7, #1
- /*
- * x4 = COREDISABLESR
- * x5 = BRR
- * x6 = loop count
- * x7 = core mask bit
- */
- 2:
- /* check if the core is to be disabled */
- tst x4, x7
- b.eq 1f
- /* see if disabled cores have already been released from reset */
- tst x5, x7
- b.ne 1f
- /* if core has not been released, then release it (0-3) */
- mov x0, x7
- bl _soc_core_release
- /* record the core state in the data area (0-3) */
- mov x0, x7
- mov x1, #CORE_DISABLED
- bl _setCoreState
- 1:
- /* decrement the counter */
- subs x6, x6, #1
- b.le 3f
- /* shift the core mask to the next core */
- lsl x7, x7, #1
- /* continue */
- b 2b
- 3:
- mov x30, x8
- ret
- /*
- * write a register in the DCFG block
- * in: x0 = offset
- * in: w1 = value to write
- * uses x0, x1, x2
- */
- _write_reg_dcfg:
- ldr x2, =NXP_DCFG_ADDR
- str w1, [x2, x0]
- ret
- /*
- * read a register in the DCFG block
- * in: x0 = offset
- * out: w0 = value read
- * uses x0, x1
- */
- _read_reg_dcfg:
- ldr x1, =NXP_DCFG_ADDR
- ldr w0, [x1, x0]
- ret
- /*
- * this function sets up the TrustZone Address Space Controller (TZASC)
- * in: none
- * out: none
- * uses x0, x1
- */
- init_tzpc:
- /*
- * set Non Secure access for all devices protected via TZPC
- * decode Protection-0 Set Reg
- */
- ldr x1, =TZPCDECPROT_0_SET_BASE
- /* set decode region to NS, Bits[7:0] */
- mov w0, #0xFF
- str w0, [x1]
- /* decode Protection-1 Set Reg */
- ldr x1, =TZPCDECPROT_1_SET_BASE
- /* set decode region to NS, Bits[7:0] */
- mov w0, #0xFF
- str w0, [x1]
- /* decode Protection-2 Set Reg */
- ldr x1, =TZPCDECPROT_2_SET_BASE
- /* set decode region to NS, Bits[7:0] */
- mov w0, #0xFF
- str w0, [x1]
- /*
- * entire SRAM as NS
- * secure RAM region size Reg
- */
- ldr x1, =NXP_OCRAM_TZPC_ADDR
- /* 0x00000000 = no secure region */
- mov w0, #0x00000000
- str w0, [x1]
- ret
- /* this function performs initialization on SecMon for boot services */
- initSecMon:
- /* read the register hpcomr */
- ldr x1, =NXP_SNVS_ADDR
- ldr w0, [x1, #SECMON_HPCOMR_OFFSET]
- /* turn off secure access for the privileged registers */
- orr w0, w0, #SECMON_HPCOMR_NPSWAEN
- /* write back */
- str w0, [x1, #SECMON_HPCOMR_OFFSET]
- ret
- /*
- * this function returns the redistributor base address for the core specified
- * in x1
- * in: x0 - core mask lsb of specified core
- * out: x0 = redistributor rd base address for specified core
- * uses x0, x1, x2
- */
- get_gic_rd_base:
- /* get the 0-based core number */
- clz w1, w0
- mov w2, #0x20
- sub w2, w2, w1
- sub w2, w2, #1
- /* x2 = core number / loop counter */
- ldr x0, =NXP_GICR_ADDR
- mov x1, #GIC_RD_OFFSET
- 2:
- cbz x2, 1f
- add x0, x0, x1
- sub x2, x2, #1
- b 2b
- 1:
- ret
- /*
- * this function returns the redistributor base address for the core specified
- * in x1
- * in: x0 - core mask lsb of specified core
- * out: x0 = redistributor sgi base address for specified core
- * uses x0, x1, x2
- */
- get_gic_sgi_base:
- /* get the 0-based core number */
- clz w1, w0
- mov w2, #0x20
- sub w2, w2, w1
- sub w2, w2, #1
- /* x2 = core number / loop counter */
- ldr x0, =NXP_GICR_SGI_ADDR
- mov x1, #GIC_SGI_OFFSET
- 2:
- cbz x2, 1f
- add x0, x0, x1
- sub x2, x2, #1
- b 2b
- 1:
- ret
- /*
- * this function returns an mpidr value for a core, given a core_mask_lsb
- * in: x0 = core mask lsb
- * out: x0 = affinity2:affinity1:affinity0, where affinity is 8-bits
- * uses x0, x1
- */
- get_mpidr_value:
- /* convert a core mask to an SoC core number */
- clz w0, w0
- mov w1, #31
- sub w0, w1, w0
- /* w0 = SoC core number */
- mov w1, wzr
- 2:
- cmp w0, #CORES_PER_CLUSTER
- b.lt 1f
- sub w0, w0, #CORES_PER_CLUSTER
- add w1, w1, #MPIDR_CLUSTER
- b 2b
- /* insert the mpidr core number */
- 1:
- orr w0, w1, w0
- ret
- /*
- * write a register in the RESET block
- * in: x0 = offset
- * in: w1 = value to write
- * uses x0, x1, x2
- */
- _write_reg_reset:
- ldr x2, =NXP_RESET_ADDR
- str w1, [x2, x0]
- ret
- /*
- * read a register in the RESET block
- * in: x0 = offset
- * out: w0 = value read
- * uses x0, x1
- */
- _read_reg_reset:
- ldr x1, =NXP_RESET_ADDR
- ldr w0, [x1, x0]
- ret
- /*
- * this function will pwrdown ddr and the final core - it will do this
- * by loading itself into the icache and then executing from there
- * in: x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK)
- * x6 = DDR_CNTRL_BASE_ADDR
- * x7 = NXP_PMU_ADDR
- * x8 = NXP_DCFG_ADDR
- * x9 = 0, restartable
- * = 1, non-restartable
- * x10 = PMU_IPSTPCR4_OFFSET
- * x11 = PMU_IPSTPACK4_OFFSET
- * x12 = PMU_IPSTPCR3_OFFSET
- * x18 = PMU_IPSTPCR2_OFFSET
- * x19 = PMU_IPSTPCR1_OFFSET
- * x21 = PMU_IPSTPCR0_OFFSET
- * w13 = DEVDISR1 saved value
- * w14 = DEVDISR2 saved value
- * w15 = DEVDISR3 saved value
- * w16 = DEVDISR4 saved value
- * w17 = DEVDISR5 saved value
- * x22 = DCFG_DEVDISR5_OFFSET
- * x23 = NXP_EPU_ADDR
- * out: none
- * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x13, x14, x15, x16, x17
- * x10, x11, x12, x18, x19, x21, x22, x23
- */
- final_pwrdown:
- /* delay */
- mov w4, #0xffffff
- 554:
- sub w4, w4, #1
- cmp w4, #0
- b.ge 554b
- mov x0, xzr
- b touch_line_0
- /* 4Kb aligned */
- .align 12
- start_line_0:
- mov x0, #1
- /* put ddr in self refresh - start */
- mov x2, #DDR_SDRAM_CFG_2_FRCSR
- ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET]
- orr w3, w3, w2
- /* put ddr in self refresh - end */
- str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET]
- nop
- nop
- touch_line_0:
- cbz x0, touch_line_1
- start_line_1:
- /* quiesce ddr clocks - start */
- orr w3, w5, #DCFG_DEVDISR5_MEM
- mov w4, w3
- /* quiesce ddr clocks - end */
- str w4, [x7, x10]
- mov w3, #DCFG_DEVDISR5_MEM
- /* poll on ipstpack4 - start */
- mov x2, #DDR_SLEEP_RETRY_CNT
- nop
- nop
- touch_line_1:
- cbz x0, touch_line_2
- start_line_2:
- /* x11 = PMU_IPSTPACK4_OFFSET */
- ldr w1, [x7, x11]
- tst w1, w3
- b.ne 5f
- subs x2, x2, #1
- /* poll on ipstpack4 - end */
- b.gt start_line_2
- /* if we get here, we have a timeout err */
- mov w4, w5
- /* x10 = PMU_IPSTPCR4_OFFSET re-enable ddr clks interface */
- str w4, [x7, x10]
- touch_line_2:
- cbz x0, touch_line_3
- start_line_3:
- /* load error code */
- mov x0, #ERROR_DDR_SLEEP
- b 2f
- 5:
- wfe
- ldr w1, [x23, #EPU_EPCTR10_OFFSET]
- cbz w1, 5b
- mov w4, w5
- touch_line_3:
- cbz x0, touch_line_4
- start_line_4:
- /* re-enable ddr in devdisr5 */
- str w4, [x8, x22]
- /* re-enable ddr clk in ipstpcr4 */
- str w4, [x7, x10]
- 13:
- /* poll on ipstpack4 - start */
- ldr w1, [x7, x11]
- tst w1, w3
- b.eq 2f
- nop
- b 13b
- /* poll on ipstpack4 - end */
- 2:
- touch_line_4:
- cbz x0, touch_line_5
- start_line_5:
- /* take ddr out-of self refresh - start */
- mov x2, #DDR_SDRAM_CFG_2_FRCSR
- ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET]
- mov w4, w3
- bic w4, w4, w2
- mov w3, w4
- /* wait for ddr cntrlr clock- start */
- mov x1, #DDR_SLEEP_RETRY_CNT
- 3:
- subs x1, x1, #1
- touch_line_5:
- cbz x0, touch_line_6
- start_line_6:
- /* wait for ddr cntrlr clock - end */
- b.gt 3b
- /* take ddr out-of self refresh - end */
- str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET]
- mov w1, w17
- /* reset devdisr5 */
- str w1, [x8, #DCFG_DEVDISR5_OFFSET]
- mov w1, w16
- /* reset devdisr4 */
- str w1, [x8, #DCFG_DEVDISR4_OFFSET]
- mov w1, w15
- touch_line_6:
- cbz x0, touch_line_7
- start_line_7:
- /* reset devdisr3 */
- str w1, [x8, #DCFG_DEVDISR3_OFFSET]
- mov w1, w14
- /* reset devdisr2 */
- str w1, [x8, #DCFG_DEVDISR2_OFFSET]
- mov w1, w13
- /* reset devdisr1 */
- str w1, [x8, #DCFG_DEVDISR1_OFFSET]
- /* reset ipstpcr4 */
- str wzr, [x7, x10]
- /* reset ipstpcr3 */
- str wzr, [x7, x12]
- touch_line_7:
- cbz x0, touch_line_8
- start_line_8:
- /* reset ipstpcr2 */
- str wzr, [x7, x18]
- /* reset ipstpcr1 */
- str wzr, [x7, x19]
- /* reset ipstpcr0 */
- str wzr, [x7, x21]
- touch_line_8:
- cbz x0, touch_line_9
- start_line_9:
- b continue_restart
- touch_line_9:
- cbz x0, start_line_0
- /* execute here after ddr is back up */
- continue_restart:
- /*
- * if x0 = 1, all is well
- * if x0 < 1, we had an error
- */
- cmp x0, #1
- b.ne 4f
- mov x0, #0
- 4:
- ret
|