12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637 |
- /*
- * Copyright 2018-2021 NXP
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <asm_macros.S>
- #include <cortex_a53.h>
- #include <dcfg_lsch2.h>
- #include <plat_gic.h>
- #include <scfg.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 */
- #define CPUACTLR_DATA_OFFSET 0x10 /* references AUX_03_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 DAIF_DATA AUX_06_DATA /* references AUX_06_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
- #define RESET_RETRY_CNT 800
- .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 _getGICD_BaseAddr
- .global _getGICC_BaseAddr
- .global _soc_set_start_addr
- .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
- /*
- * This function initialize the soc.
- * in: void
- * out: void
- */
- func soc_init_lowlevel
- 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
- mov x3, x30
- bl plat_my_core_mask
- mov x2, x0
- /* see if this core is marked for prefetch disable */
- mov x0, #PREFETCH_DIS_OFFSET
- bl _get_global_data /* 0-1 */
- tst x0, x2
- b.eq 1f
- bl _disable_ldstr_pfetch_A53 /* 0 */
- 1:
- mov x30, x3
- ret
- endfunc soc_init_percpu
- /*
- * 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:
- #if (TEST_BL31)
- mov w2, w0
- CoreMaskMsb w2, w3
- /* x2 = core mask msb */
- #else
- mov x2, x0
- #endif
- /* write COREBCR */
- ldr x1, =NXP_SCFG_ADDR
- rev w3, w2
- str w3, [x1, #SCFG_COREBCR_OFFSET]
- isb
- /* read-modify-write BRR */
- mov x1, #NXP_DCFG_ADDR
- ldr w2, [x1, #DCFG_BRR_OFFSET]
- rev w3, w2
- orr w3, w3, w0
- rev w2, w3
- str w2, [x1, #DCFG_BRR_OFFSET]
- isb
- /* send event */
- sev
- isb
- 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 ~ x5
- */
- _soc_core_restart:
- mov x5, x30
- mov x3, x0
- /* x3 = core mask lsb */
- bl _getGICD_BaseAddr
- mov x4, x0
- /* x4 = GICD_BASE_ADDR */
- /* enable forwarding of group 0 interrupts by setting GICD_CTLR[0] = 1 */
- ldr w1, [x4, #GICD_CTLR_OFFSET]
- orr w1, w1, #GICD_CTLR_EN_GRP0
- str w1, [x4, #GICD_CTLR_OFFSET]
- dsb sy
- isb
- /*
- * fire SGI by writing to GICD_SGIR the following values:
- * [25:24] = 0x0 (forward interrupt to the CPU interfaces specified in CPUTargetList field)
- * [23:16] = core mask lsb[7:0] (forward interrupt to target cpu)
- * [15] = 0 (forward SGI only if it is configured as group 0 interrupt)
- * [3:0] = 0xF (interrupt ID = 15)
- */
- lsl w1, w3, #16
- orr w1, w1, #0xF
- str w1, [x4, #GICD_SGIR_OFFSET]
- dsb sy
- isb
- /* load '0' on success */
- mov x0, xzr
- mov x30, x5
- ret
- /*
- * this function determines if a core is disabled via COREDISR
- * in: w0 = core_mask_lsb
- * out: w0 = 0, core not disabled
- * w0 != 0, core disabled
- * uses x0, x1, x2
- */
- _soc_ck_disabled:
- /* get base addr of dcfg block */
- ldr x1, =NXP_DCFG_ADDR
- /* read COREDISR */
- ldr w1, [x1, #DCFG_COREDISR_OFFSET]
- rev w2, w1
- /* test core bit */
- and w0, w2, w0
- ret
- /*
- * this function resets the system via SoC-specific methods
- * in: none
- * out: none
- * uses x0, x1, x2, x3
- */
- _soc_sys_reset:
- ldr x2, =NXP_DCFG_ADDR
- /* make sure the mask is cleared in the reset request mask register */
- mov w1, wzr
- str w1, [x2, #DCFG_RSTRQMR1_OFFSET]
- /* x2 = NXP_DCFG_ADDR */
- /* set the reset request */
- ldr w1, =RSTCR_RESET_REQ
- ldr x3, =DCFG_RSTCR_OFFSET
- rev w0, w1
- str w0, [x2, x3]
- /* x2 = NXP_DCFG_ADDR */
- /* x3 = DCFG_RSTCR_OFFSET */
- /* just in case this address range is mapped as cacheable,
- * flush the write out of the dcaches */
- add x3, x2, x3
- dc cvac, x3
- dsb st
- isb
- /* Note: this function does not return */
- 1:
- wfi
- b 1b
- /*
- * part of SYSTEM_OFF
- * this function turns off the SoC clocks
- * Note: this function is not intended to return, and the only allowable
- * recovery is POR
- * in: none
- * out: none
- * uses x0 ~ x8
- */
- _soc_sys_off:
- /* mask interrupts at the core */
- mrs x1, DAIF
- mov x0, #DAIF_SET_MASK
- orr x0, x1, x0
- msr DAIF, 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 dcache for EL3 */
- mrs x1, SCTLR_EL3
- bic x1, x1, #SCTLR_C_MASK
- /* make sure icache is enabled */
- orr x1, x1, #SCTLR_I_MASK
- msr SCTLR_EL3, x1
- isb
- /* set WFIL2_EN in SCFG_COREPMCR */
- ldr x0, =SCFG_COREPMCR_OFFSET
- ldr x1, =COREPMCR_WFIL2
- bl write_reg_scfg
- /* set OVRD_EN in RCPM2_POWMGTDCR */
- ldr x0, =RCPM2_POWMGTDCR_OFFSET
- ldr x1, =POWMGTDCR_OVRD_EN
- bl write_reg_rcpm2
- /* read IPPDEXPCR0 @ RCPM_IPPDEXPCR0 */
- ldr x0, =RCPM_IPPDEXPCR0_OFFSET
- bl read_reg_rcpm
- mov x7, x0
- /* build an override mask for IPSTPCR4/IPSTPACK4/DEVDISR5 */
- mov x5, xzr
- ldr x6, =IPPDEXPCR_MASK2
- and x6, x6, x7
- cbz x6, 1f
- /* x5 = override mask
- * x6 = IPPDEXPCR bits for DEVDISR5
- * x7 = IPPDEXPCR */
- /* get the overrides */
- orr x4, x5, #DEVDISR5_I2C_1
- tst x6, #IPPDEXPCR_I2C1
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR5_LPUART1
- tst x6, #IPPDEXPCR_LPUART1
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR5_FLX_TMR
- tst x6, #IPPDEXPCR_FLX_TMR1
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR5_OCRAM1
- tst x6, #IPPDEXPCR_OCRAM1
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR5_GPIO
- tst x6, #IPPDEXPCR_GPIO1
- 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]
- /* build an override mask for IPSTPCR1/IPSTPACK1/DEVDISR2 */
- mov x5, xzr
- ldr x6, =IPPDEXPCR_MASK1
- and x6, x6, x7
- cbz x6, 2f
- /* x5 = override mask */
- /* x6 = IPPDEXPCR bits for DEVDISR2 */
- /* get the overrides */
- orr x4, x5, #DEVDISR2_FMAN1_MAC1
- tst x6, #IPPDEXPCR_MAC1_1
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR2_FMAN1_MAC2
- tst x6, #IPPDEXPCR_MAC1_2
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR2_FMAN1_MAC3
- tst x6, #IPPDEXPCR_MAC1_3
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR2_FMAN1_MAC4
- tst x6, #IPPDEXPCR_MAC1_4
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR2_FMAN1_MAC5
- tst x6, #IPPDEXPCR_MAC1_5
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR2_FMAN1_MAC6
- tst x6, #IPPDEXPCR_MAC1_6
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR2_FMAN1_MAC9
- tst x6, #IPPDEXPCR_MAC1_9
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR2_FMAN1
- tst x6, #IPPDEXPCR_FM1
- csel x5, x5, x4, EQ
- 2:
- /* store the DEVDISR2 override mask */
- ldr x2, =BC_PSCI_BASE
- add x2, x2, #AUX_01_DATA
- str w5, [x2, #DEVDISR2_MASK_OFFSET]
- /* x5 = DEVDISR2 override mask */
- /* write IPSTPCR0 - no overrides */
- ldr x0, =RCPM2_IPSTPCR0_OFFSET
- ldr x1, =IPSTPCR0_VALUE
- bl write_reg_rcpm2
- /* x5 = DEVDISR2 override mask */
- /* write IPSTPCR1 - overrides possible */
- ldr x0, =RCPM2_IPSTPCR1_OFFSET
- ldr x1, =IPSTPCR1_VALUE
- bic x1, x1, x5
- bl write_reg_rcpm2
- /* write IPSTPCR2 - no overrides */
- ldr x0, =RCPM2_IPSTPCR2_OFFSET
- ldr x1, =IPSTPCR2_VALUE
- bl write_reg_rcpm2
- /* write IPSTPCR3 - no overrides */
- ldr x0, =RCPM2_IPSTPCR3_OFFSET
- ldr x1, =IPSTPCR3_VALUE
- bl write_reg_rcpm2
- /* write IPSTPCR4 - overrides possible */
- ldr x2, =BC_PSCI_BASE
- add x2, x2, #AUX_01_DATA
- ldr w6, [x2, #DEVDISR5_MASK_OFFSET]
- ldr x0, =RCPM2_IPSTPCR4_OFFSET
- ldr x1, =IPSTPCR4_VALUE
- bic x1, x1, x6
- bl write_reg_rcpm2
- /* x5 = DEVDISR2 override mask */
- /* x6 = DEVDISR5 override mask */
- /* poll on IPSTPACK0 */
- ldr x3, =RCPM2_IPSTPACKR0_OFFSET
- ldr x4, =IPSTPCR0_VALUE
- ldr x7, =IPSTPACK_RETRY_CNT
- 3:
- mov x0, x3
- bl read_reg_rcpm2
- cmp x0, x4
- b.eq 14f
- sub x7, x7, #1
- cbnz x7, 3b
- 14:
- /* poll on IPSTPACK1 */
- ldr x3, =IPSTPCR1_VALUE
- ldr x7, =IPSTPACK_RETRY_CNT
- bic x4, x3, x5
- ldr x3, =RCPM2_IPSTPACKR1_OFFSET
- 4:
- mov x0, x3
- bl read_reg_rcpm2
- cmp x0, x4
- b.eq 15f
- sub x7, x7, #1
- cbnz x7, 4b
- 15:
- /* poll on IPSTPACK2 */
- ldr x3, =RCPM2_IPSTPACKR2_OFFSET
- ldr x4, =IPSTPCR2_VALUE
- ldr x7, =IPSTPACK_RETRY_CNT
- 5:
- mov x0, x3
- bl read_reg_rcpm2
- cmp x0, x4
- b.eq 16f
- sub x7, x7, #1
- cbnz x7, 5b
- 16:
- /* poll on IPSTPACK3 */
- ldr x3, =RCPM2_IPSTPACKR3_OFFSET
- ldr x4, =IPSTPCR3_VALUE
- ldr x7, =IPSTPACK_RETRY_CNT
- 6:
- mov x0, x3
- bl read_reg_rcpm2
- cmp x0, x4
- b.eq 17f
- sub x7, x7, #1
- cbnz x7, 6b
- 17:
- /* poll on IPSTPACK4 */
- ldr x3, =IPSTPCR4_VALUE
- ldr x7, =IPSTPACK_RETRY_CNT
- bic x4, x3, x6
- ldr x3, =RCPM2_IPSTPACKR4_OFFSET
- 7:
- mov x0, x3
- bl read_reg_rcpm2
- cmp x0, x4
- b.eq 18f
- sub x7, x7, #1
- cbnz x7, 7b
- 18:
- ldr x7, =BC_PSCI_BASE
- add x7, x7, #AUX_01_DATA
- /* x5 = DEVDISR2 override mask
- * x6 = DEVDISR5 override mask
- * x7 = [soc_data_area] */
- /* DEVDISR1 - load new value */
- mov x0, #DCFG_DEVDISR1_OFFSET
- bl read_reg_dcfg
- mov x0, #DCFG_DEVDISR1_OFFSET
- ldr x1, =DEVDISR1_VALUE
- bl write_reg_dcfg
- /* DEVDISR2 - load new value */
- mov x0, #DCFG_DEVDISR2_OFFSET
- bl read_reg_dcfg
- mov x0, #DCFG_DEVDISR2_OFFSET
- ldr x1, =DEVDISR2_VALUE
- bic x1, x1, x5
- bl write_reg_dcfg
- /* x6 = DEVDISR5 override mask */
- /* x7 = [soc_data_area] */
- /* DEVDISR3 - load new value */
- mov x0, #DCFG_DEVDISR3_OFFSET
- bl read_reg_dcfg
- mov x0, #DCFG_DEVDISR3_OFFSET
- ldr x1, =DEVDISR3_VALUE
- bl write_reg_dcfg
- /* DEVDISR4 - load new value */
- mov x0, #DCFG_DEVDISR4_OFFSET
- bl read_reg_dcfg
- mov x0, #DCFG_DEVDISR4_OFFSET
- ldr x1, =DEVDISR4_VALUE
- bl write_reg_dcfg
- /* DEVDISR5 - load new value */
- mov x0, #DCFG_DEVDISR5_OFFSET
- bl read_reg_dcfg
- mov x0, #DCFG_DEVDISR5_OFFSET
- ldr x1, =DEVDISR5_VALUE
- bic x1, x1, x6
- bl write_reg_dcfg
- /* x7 = [soc_data_area] */
- /* disable data prefetch */
- mrs x0, CPUACTLR_EL1
- bic x0, x0, #CPUACTLR_L1PCTL_MASK
- msr CPUACTLR_EL1, x0
- /* x6 = DEVDISR5 override mask */
- /* setup registers for cache-only execution */
- ldr x5, =IPSTPCR4_VALUE
- bic x5, x5, x6
- mov x6, #DDR_CNTRL_BASE_ADDR
- mov x7, #DCSR_RCPM2_BASE
- mov x8, #NXP_DCFG_ADDR
- dsb sy
- isb
- /* set the DLL_LOCK cycle count */
- ldr w1, [x6, #DDR_TIMING_CFG_4_OFFSET]
- rev w2, w1
- bic w2, w2, #DLL_LOCK_MASK
- orr w2, w2, #DLL_LOCK_VALUE
- rev w1, w2
- str w1, [x6, #DDR_TIMING_CFG_4_OFFSET]
- /* x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK)
- * x6 = DDR_CNTRL_BASE_ADDR
- * x7 = DCSR_RCPM2_BASE
- * x8 = NXP_DCFG_ADDR */
- /* enter the cache-only sequence - there is no return */
- b final_shutdown
- /*
- * 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 ~ x7
- */
- _soc_core_prep_off:
- mov x7, x30
- mov x6, x0
- /* make sure the smpen bit is set */
- mrs x2, CORTEX_A53_ECTLR_EL1
- orr x2, x2, #CPUECTLR_SMPEN_MASK
- msr CORTEX_A53_ECTLR_EL1, x2
- isb
- /* configure the cpu interface */
- /* disable signaling of ints */
- bl _getGICC_BaseAddr // 0-1
- mov x4, x0
- ldr w3, [x4, #GICC_CTLR_OFFSET]
- bic w3, w3, #GICC_CTLR_EN_GRP0
- bic w3, w3, #GICC_CTLR_EN_GRP1
- str w3, [x4, #GICC_CTLR_OFFSET]
- dsb sy
- isb
- /*
- * x3 = GICC_CTRL
- * x4 = GICC_BASE_ADDR
- * x6 = core mask
- */
- /* set the priority filter */
- ldr w2, [x4, #GICC_PMR_OFFSET]
- orr w2, w2, #GICC_PMR_FILTER
- str w2, [x4, #GICC_PMR_OFFSET]
- /* setup GICC_CTLR */
- bic w3, w3, #GICC_CTLR_ACKCTL_MASK
- orr w3, w3, #GICC_CTLR_FIQ_EN_MASK
- orr w3, w3, #GICC_CTLR_EOImodeS_MASK
- orr w3, w3, #GICC_CTLR_CBPR_MASK
- str w3, [x4, #GICC_CTLR_OFFSET]
- /* x3 = GICC_CTRL */
- /* x4 = GICC_BASE_ADDR */
- /* setup the banked-per-core GICD registers */
- bl _getGICD_BaseAddr
- /*
- * x0 = GICD_BASE_ADDR
- * x3 = GICC_CTRL
- * x4 = GICC_BASE_ADDR
- * x6 = core mask
- */
- /* define SGI15 as Grp0 */
- ldr w2, [x0, #GICD_IGROUPR0_OFFSET]
- bic w2, w2, #GICD_IGROUP0_SGI15
- str w2, [x0, #GICD_IGROUPR0_OFFSET]
- /* set priority of SGI 15 to highest... */
- ldr w2, [x0, #GICD_IPRIORITYR3_OFFSET]
- bic w2, w2, #GICD_IPRIORITY_SGI15_MASK
- str w2, [x0, #GICD_IPRIORITYR3_OFFSET]
- /* enable SGI 15 */
- ldr w2, [x0, #GICD_ISENABLER0_OFFSET]
- orr w2, w2, #GICD_ISENABLE0_SGI15
- str w2, [x0, #GICD_ISENABLER0_OFFSET]
- /* enable the cpu interface */
- orr w3, w3, #GICC_CTLR_EN_GRP0
- str w3, [x4, #GICC_CTLR_OFFSET]
- /* x0 = GICD_BASE_ADDR
- * x6 = core mask */
- /* clear any pending SGIs */
- add x0, x0, #GICD_CPENDSGIR3_OFFSET
- ldr x2, =GICD_CPENDSGIR_CLR_MASK
- str w2, [x0]
- dsb sy
- isb
- mov x30, x7
- ret
- /*
- * part of CPU_OFF
- * this function performs the final steps to shutdown the core
- * in: x0 = core mask lsb
- * out: none
- * uses x0 ~ x5
- */
- _soc_core_entr_off:
- mov x5, x30
- mov x4, x0
- bl _getGICD_BaseAddr
- mov x3, x0
- /* x3 = GICD_BASE_ADDR */
- /* x4 = core mask (lsb) */
- 3:
- /* enter low-power state by executing wfi */
- wfi
- /* x3 = GICD_BASE_ADDR */
- /* x4 = core mask (lsb) */
- /* see if we got hit by SGI 15 */
- add x0, x3, #GICD_SPENDSGIR3_OFFSET
- ldr w2, [x0]
- and w2, w2, #GICD_SPENDSGIR3_SGI15_MASK
- cbz w2, 4f
- /* clear the pending SGI */
- ldr x2, =GICD_CPENDSGIR_CLR_MASK
- add x0, x3, #GICD_CPENDSGIR3_OFFSET
- str w2, [x0]
- 4:
- /* check if core has been turned on */
- mov x0, x4
- bl _getCoreState
- /* x0 = core state */
- cmp x0, #CORE_WAKEUP
- b.ne 3b
- /* if we get here, then we have exited the wfi */
- dsb sy
- isb
- 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 ~ x5
- */
- _soc_core_exit_off:
- mov x5, x30
- mov x4, x0
- /* x4 = core mask */
- bl _getGICC_BaseAddr
- mov x2, x0
- /* read GICC_IAR */
- ldr w0, [x2, #GICC_IAR_OFFSET]
- /* write GICC_EIOR - signal end-of-interrupt */
- str w0, [x2, #GICC_EOIR_OFFSET]
- /* write GICC_DIR - disable interrupt */
- str w0, [x2, #GICC_DIR_OFFSET]
- /* x2 = GICC_BASE_ADDR */
- /* disable signaling of grp0 ints */
- ldr w1, [x2, #GICC_CTLR_OFFSET]
- bic w1, w1, #GICC_CTLR_EN_GRP0
- str w1, [x2, #GICC_CTLR_OFFSET]
- dsb sy
- isb
- mov x30, x5
- ret
- /*
- * this function loads a 64-bit execution address of the core in the soc registers
- * BOOTLOCPTRL/H
- * in: x0, 64-bit address to write to BOOTLOCPTRL/H
- * uses x0, x1, x2, x3
- */
- _soc_set_start_addr:
- /* get the 64-bit base address of the scfg block */
- ldr x2, =NXP_SCFG_ADDR
- /* write the 32-bit BOOTLOCPTRL register (offset 0x604 in the scfg block) */
- mov x1, x0
- rev w3, w1
- str w3, [x2, #SCFG_BOOTLOCPTRL_OFFSET]
- /* write the 32-bit BOOTLOCPTRH register (offset 0x600 in the scfg block) */
- lsr x1, x0, #32
- rev w3, w1
- str w3, [x2, #SCFG_BOOTLOCPTRH_OFFSET]
- 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:
- dsb sy
- isb
- wfi
- 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_core_prep_stdby:
- /* clear CORTEX_A53_ECTLR_EL1[2:0] */
- mrs x1, CORTEX_A53_ECTLR_EL1
- bic x1, x1, #CPUECTLR_TIMER_MASK
- msr CORTEX_A53_ECTLR_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_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
- */
- _soc_core_prep_pwrdn:
- /* make sure the smp bit is set */
- mrs x1, CORTEX_A53_ECTLR_EL1
- orr x1, x1, #CPUECTLR_SMPEN_MASK
- msr CORTEX_A53_ECTLR_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:
- dsb sy
- isb
- wfi
- ret
- /*
- * part of CPU_SUSPEND
- * this function performs any SoC-specific cleanup after power-down
- * in: x0 = core mask lsb
- * out: none
- * uses none
- */
- _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 CORTEX_A53_ECTLR_EL1[2:0] */
- mrs x1, CORTEX_A53_ECTLR_EL1
- bic x1, x1, #CPUECTLR_TIMER_MASK
- msr CORTEX_A53_ECTLR_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
- */
- _soc_clstr_prep_pwrdn:
- /* make sure the smp bit is set */
- mrs x1, CORTEX_A53_ECTLR_EL1
- orr x1, x1, #CPUECTLR_SMPEN_MASK
- msr CORTEX_A53_ECTLR_EL1, x1
- isb
- ret
- /*
- * part of CPU_SUSPEND
- * this function performs any SoC-specific cleanup after power-down
- * in: x0 = core mask lsb
- * out: none
- * uses none
- */
- _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 CORTEX_A53_ECTLR_EL1[2:0] */
- mrs x1, CORTEX_A53_ECTLR_EL1
- bic x1, x1, #CPUECTLR_TIMER_MASK
- msr CORTEX_A53_ECTLR_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, x1, x2, x3, x4
- */
- _soc_sys_prep_pwrdn:
- mov x4, x30
- /* make sure the smp bit is set */
- mrs x1, CORTEX_A53_ECTLR_EL1
- orr x1, x1, #CPUECTLR_SMPEN_MASK
- msr CORTEX_A53_ECTLR_EL1, x1
- isb
- /* set WFIL2_EN in SCFG_COREPMCR */
- ldr x0, =SCFG_COREPMCR_OFFSET
- ldr x1, =COREPMCR_WFIL2
- bl write_reg_scfg // 0-3
- /* set OVRD_EN in RCPM2_POWMGTDCR */
- ldr x0, =RCPM2_POWMGTDCR_OFFSET
- ldr x1, =POWMGTDCR_OVRD_EN
- bl write_reg_rcpm2 // 0-3
- mov x30, x4
- 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 ~ x9
- */
- _soc_sys_pwrdn_wfi:
- mov x18, x30
- /* read IPPDEXPCR0 @ RCPM_IPPDEXPCR0 */
- ldr x0, =RCPM_IPPDEXPCR0_OFFSET
- bl read_reg_rcpm
- mov x7, x0
- /* build an override mask for IPSTPCR4/IPSTPACK4/DEVDISR5 */
- mov x5, xzr
- ldr x6, =IPPDEXPCR_MASK2
- and x6, x6, x7
- cbz x6, 1f
- /* x5 = override mask
- * x6 = IPPDEXPCR bits for DEVDISR5
- * x7 = IPPDEXPCR */
- /* get the overrides */
- orr x4, x5, #DEVDISR5_I2C_1
- tst x6, #IPPDEXPCR_I2C1
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR5_LPUART1
- tst x6, #IPPDEXPCR_LPUART1
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR5_FLX_TMR
- tst x6, #IPPDEXPCR_FLX_TMR1
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR5_OCRAM1
- tst x6, #IPPDEXPCR_OCRAM1
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR5_GPIO
- tst x6, #IPPDEXPCR_GPIO1
- 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]
- /* build an override mask for IPSTPCR1/IPSTPACK1/DEVDISR2 */
- mov x5, xzr
- ldr x6, =IPPDEXPCR_MASK1
- and x6, x6, x7
- cbz x6, 2f
- /* x5 = override mask */
- /* x6 = IPPDEXPCR bits for DEVDISR2 */
- /* get the overrides */
- orr x4, x5, #DEVDISR2_FMAN1_MAC1
- tst x6, #IPPDEXPCR_MAC1_1
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR2_FMAN1_MAC2
- tst x6, #IPPDEXPCR_MAC1_2
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR2_FMAN1_MAC3
- tst x6, #IPPDEXPCR_MAC1_3
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR2_FMAN1_MAC4
- tst x6, #IPPDEXPCR_MAC1_4
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR2_FMAN1_MAC5
- tst x6, #IPPDEXPCR_MAC1_5
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR2_FMAN1_MAC6
- tst x6, #IPPDEXPCR_MAC1_6
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR2_FMAN1_MAC9
- tst x6, #IPPDEXPCR_MAC1_9
- csel x5, x5, x4, EQ
- orr x4, x5, #DEVDISR2_FMAN1
- tst x6, #IPPDEXPCR_FM1
- csel x5, x5, x4, EQ
- 2:
- /* store the DEVDISR2 override mask */
- ldr x2, =BC_PSCI_BASE
- add x2, x2, #AUX_01_DATA
- str w5, [x2, #DEVDISR2_MASK_OFFSET]
- /* x5 = DEVDISR2 override mask */
- /* write IPSTPCR0 - no overrides */
- ldr x0, =RCPM2_IPSTPCR0_OFFSET
- ldr x1, =IPSTPCR0_VALUE
- bl write_reg_rcpm2
- /* x5 = DEVDISR2 override mask */
- /* write IPSTPCR1 - overrides possible */
- ldr x0, =RCPM2_IPSTPCR1_OFFSET
- ldr x1, =IPSTPCR1_VALUE
- bic x1, x1, x5
- bl write_reg_rcpm2
- /* write IPSTPCR2 - no overrides */
- ldr x0, =RCPM2_IPSTPCR2_OFFSET
- ldr x1, =IPSTPCR2_VALUE
- bl write_reg_rcpm2
- /* write IPSTPCR3 - no overrides */
- ldr x0, =RCPM2_IPSTPCR3_OFFSET
- ldr x1, =IPSTPCR3_VALUE
- bl write_reg_rcpm2
- /* write IPSTPCR4 - overrides possible */
- ldr x2, =BC_PSCI_BASE
- add x2, x2, #AUX_01_DATA
- ldr w6, [x2, #DEVDISR5_MASK_OFFSET]
- ldr x0, =RCPM2_IPSTPCR4_OFFSET
- ldr x1, =IPSTPCR4_VALUE
- bic x1, x1, x6
- bl write_reg_rcpm2
- /* x5 = DEVDISR2 override mask */
- /* x6 = DEVDISR5 override mask */
- /* poll on IPSTPACK0 */
- ldr x3, =RCPM2_IPSTPACKR0_OFFSET
- ldr x4, =IPSTPCR0_VALUE
- ldr x7, =IPSTPACK_RETRY_CNT
- 3:
- mov x0, x3
- bl read_reg_rcpm2
- cmp x0, x4
- b.eq 14f
- sub x7, x7, #1
- cbnz x7, 3b
- 14:
- /* poll on IPSTPACK1 */
- ldr x3, =IPSTPCR1_VALUE
- ldr x7, =IPSTPACK_RETRY_CNT
- bic x4, x3, x5
- ldr x3, =RCPM2_IPSTPACKR1_OFFSET
- 4:
- mov x0, x3
- bl read_reg_rcpm2
- cmp x0, x4
- b.eq 15f
- sub x7, x7, #1
- cbnz x7, 4b
- 15:
- /* poll on IPSTPACK2 */
- ldr x3, =RCPM2_IPSTPACKR2_OFFSET
- ldr x4, =IPSTPCR2_VALUE
- ldr x7, =IPSTPACK_RETRY_CNT
- 5:
- mov x0, x3
- bl read_reg_rcpm2
- cmp x0, x4
- b.eq 16f
- sub x7, x7, #1
- cbnz x7, 5b
- 16:
- /* poll on IPSTPACK3 */
- ldr x3, =RCPM2_IPSTPACKR3_OFFSET
- ldr x4, =IPSTPCR3_VALUE
- ldr x7, =IPSTPACK_RETRY_CNT
- 6:
- mov x0, x3
- bl read_reg_rcpm2
- cmp x0, x4
- b.eq 17f
- sub x7, x7, #1
- cbnz x7, 6b
- 17:
- /* poll on IPSTPACK4 */
- ldr x3, =IPSTPCR4_VALUE
- ldr x7, =IPSTPACK_RETRY_CNT
- bic x4, x3, x6
- ldr x3, =RCPM2_IPSTPACKR4_OFFSET
- 7:
- mov x0, x3
- bl read_reg_rcpm2
- cmp x0, x4
- b.eq 18f
- sub x7, x7, #1
- cbnz x7, 7b
- 18:
- ldr x7, =BC_PSCI_BASE
- add x7, x7, #AUX_01_DATA
- /* x5 = DEVDISR2 override mask
- * x6 = DEVDISR5 override mask
- * x7 = [soc_data_area] */
- /* save DEVDISR1 and load new value */
- mov x0, #DCFG_DEVDISR1_OFFSET
- bl read_reg_dcfg
- mov w13, w0
- mov x0, #DCFG_DEVDISR1_OFFSET
- ldr x1, =DEVDISR1_VALUE
- bl write_reg_dcfg
- /* save DEVDISR2 and load new value */
- mov x0, #DCFG_DEVDISR2_OFFSET
- bl read_reg_dcfg
- mov w14, w0
- mov x0, #DCFG_DEVDISR2_OFFSET
- ldr x1, =DEVDISR2_VALUE
- bic x1, x1, x5
- bl write_reg_dcfg
- /* x6 = DEVDISR5 override mask */
- /* x7 = [soc_data_area] */
- /* save DEVDISR3 and load new value */
- mov x0, #DCFG_DEVDISR3_OFFSET
- bl read_reg_dcfg
- mov w15, w0
- mov x0, #DCFG_DEVDISR3_OFFSET
- ldr x1, =DEVDISR3_VALUE
- bl write_reg_dcfg
- /* save DEVDISR4 and load new value */
- mov x0, #DCFG_DEVDISR4_OFFSET
- bl read_reg_dcfg
- mov w16, w0
- mov x0, #DCFG_DEVDISR4_OFFSET
- ldr x1, =DEVDISR4_VALUE
- bl write_reg_dcfg
- /* save DEVDISR5 and load new value */
- mov x0, #DCFG_DEVDISR5_OFFSET
- bl read_reg_dcfg
- mov w17, w0
- mov x0, #DCFG_DEVDISR5_OFFSET
- ldr x1, =DEVDISR5_VALUE
- bic x1, x1, x6
- bl write_reg_dcfg
- /* x7 = [soc_data_area] */
- /* save cpuactlr and disable data prefetch */
- mrs x0, CPUACTLR_EL1
- str w0, [x7, #CPUACTLR_DATA_OFFSET]
- bic x0, x0, #CPUACTLR_L1PCTL_MASK
- msr CPUACTLR_EL1, x0
- /* x6 = DEVDISR5 override mask */
- /* setup registers for cache-only execution */
- ldr x5, =IPSTPCR4_VALUE
- bic x5, x5, x6
- mov x6, #DDR_CNTRL_BASE_ADDR
- mov x7, #DCSR_RCPM2_BASE
- mov x8, #NXP_DCFG_ADDR
- dsb sy
- isb
- /* set the DLL_LOCK cycle count */
- ldr w1, [x6, #DDR_TIMING_CFG_4_OFFSET]
- rev w2, w1
- bic w2, w2, #DLL_LOCK_MASK
- orr w2, w2, #DLL_LOCK_VALUE
- rev w1, w2
- str w1, [x6, #DDR_TIMING_CFG_4_OFFSET]
- /*
- * x5 = ipstpcr4 (IPSTPCR4_VALUE bic DEVDISR5_MASK)
- * x6 = DDR_CNTRL_BASE_ADDR
- * x7 = DCSR_RCPM2_BASE
- * x8 = NXP_DCFG_ADDR
- * w13 = DEVDISR1 saved value
- * w14 = DEVDISR2 saved value
- * w15 = DEVDISR3 saved value
- * w16 = DEVDISR4 saved value
- * w17 = DEVDISR5 saved value
- */
- /* enter the cache-only sequence */
- mov x9, #CORE_RESTARTABLE
- bl final_pwrdown
- /* when we are here, the core has come out of wfi and the SoC is back up */
- mov x30, x18
- 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:
- /* clear POWMGTDCR */
- mov x1, #DCSR_RCPM2_BASE
- str wzr, [x1, #RCPM2_POWMGTDCR_OFFSET]
- /* clear WFIL2_EN in SCFG_COREPMCR */
- mov x1, #NXP_SCFG_ADDR
- str wzr, [x1, #SCFG_COREPMCR_OFFSET]
- ret
- /*
- * write a register in the SCFG block
- * in: x0 = offset
- * in: w1 = value to write
- * uses x0, x1, x2, x3
- */
- write_reg_scfg:
- ldr x2, =NXP_SCFG_ADDR
- /* swap for BE */
- rev w3, w1
- str w3, [x2, x0]
- ret
- /*
- * read a register in the SCFG block
- * in: x0 = offset
- * out: w0 = value read
- * uses x0, x1, x2
- */
- read_reg_scfg:
- ldr x2, =NXP_SCFG_ADDR
- ldr w1, [x2, x0]
- /* swap for BE */
- rev w0, w1
- ret
- /*
- * write a register in the DCFG block
- * in: x0 = offset
- * in: w1 = value to write
- * uses x0, x1, x2, x3
- */
- write_reg_dcfg:
- ldr x2, =NXP_DCFG_ADDR
- /* swap for BE */
- rev w3, w1
- str w3, [x2, x0]
- ret
- /*
- * read a register in the DCFG block
- * in: x0 = offset
- * out: w0 = value read
- * uses x0, x1, x2
- */
- read_reg_dcfg:
- ldr x2, =NXP_DCFG_ADDR
- ldr w1, [x2, x0]
- /* swap for BE */
- rev w0, w1
- ret
- /*
- * write a register in the RCPM block
- * in: x0 = offset
- * in: w1 = value to write
- * uses x0, x1, x2, x3
- */
- write_reg_rcpm:
- ldr x2, =NXP_RCPM_ADDR
- /* swap for BE */
- rev w3, w1
- str w3, [x2, x0]
- ret
- /*
- * read a register in the RCPM block
- * in: x0 = offset
- * out: w0 = value read
- * uses x0, x1, x2
- */
- read_reg_rcpm:
- ldr x2, =NXP_RCPM_ADDR
- ldr w1, [x2, x0]
- /* swap for BE */
- rev w0, w1
- ret
- /*
- * write a register in the DCSR-RCPM2 block
- * in: x0 = offset
- * in: w1 = value to write
- * uses x0, x1, x2, x3
- */
- write_reg_rcpm2:
- ldr x2, =DCSR_RCPM2_BASE
- /* swap for BE */
- rev w3, w1
- str w3, [x2, x0]
- ret
- /*
- * read a register in the DCSR-RCPM2 block
- * in: x0 = offset
- * out: w0 = value read
- * uses x0, x1, x2
- */
- read_reg_rcpm2:
- ldr x2, =DCSR_RCPM2_BASE
- ldr w1, [x2, x0]
- /* swap for BE */
- rev w0, w1
- ret
- /*
- * this function returns the base address of the gic distributor
- * in: none
- * out: x0 = base address of gic distributor
- * uses x0, x1
- */
- _getGICD_BaseAddr:
- /* read SVR and get the SoC version */
- mov x0, #NXP_DCFG_ADDR
- ldr w1, [x0, #DCFG_SVR_OFFSET]
- rev w0, w1
- /* x0 = svr */
- and w0, w0, #SVR_MIN_VER_MASK
- cmp w0, #SVR_MINOR_VER_0
- b.ne 8f
- /* load the gic base addresses for rev 1.0 parts */
- ldr x0, =NXP_GICD_4K_ADDR
- b 10f
- 8:
- /* for rev 1.1 and later parts, the GIC base addresses */
- /* can be at 4k or 64k offsets */
- /* read the scfg reg GIC400_ADDR_ALIGN */
- mov x0, #NXP_SCFG_ADDR
- ldr w1, [x0, #SCFG_GIC400_ADDR_ALIGN_OFFSET]
- rev w0, w1
- /* x0 = GIC400_ADDR_ALIGN value */
- and x0, x0, #SCFG_GIC400_ADDR_ALIGN_4KMODE_MASK
- mov x1, #SCFG_GIC400_ADDR_ALIGN_4KMODE_EN
- cmp x0, x1
- b.ne 9f
- /* load the base addresses for 4k offsets */
- ldr x0, =NXP_GICD_4K_ADDR
- b 10f
- 9:
- /* load the base address for 64k offsets */
- ldr x0, =NXP_GICD_64K_ADDR
- 10:
- ret
- /*
- * this function returns the base address of the gic distributor
- * in: none
- * out: x0 = base address of gic controller
- * uses x0, x1
- */
- _getGICC_BaseAddr:
- /* read SVR and get the SoC version */
- mov x0, #NXP_DCFG_ADDR
- ldr w1, [x0, #DCFG_SVR_OFFSET]
- rev w0, w1
- /* x0 = svr */
- and w0, w0, #SVR_MIN_VER_MASK
- cmp w0, #SVR_MINOR_VER_0
- b.ne 8f
- /* load the gic base addresses for rev 1.0 parts */
- ldr x0, =NXP_GICC_4K_ADDR
- b 10f
- 8:
- /* for rev 1.1 and later parts, the GIC base addresses */
- /* can be at 4k or 64k offsets */
- /* read the scfg reg GIC400_ADDR_ALIGN */
- mov x0, #NXP_SCFG_ADDR
- ldr w1, [x0, #SCFG_GIC400_ADDR_ALIGN_OFFSET]
- rev w0, w1
- /* x0 = GIC400_ADDR_ALIGN value */
- and x0, x0, #SCFG_GIC400_ADDR_ALIGN_4KMODE_MASK
- mov x1, #SCFG_GIC400_ADDR_ALIGN_4KMODE_EN
- cmp x0, x1
- b.ne 9f
- /* load the base addresses for 4k offsets */
- ldr x0, =NXP_GICC_4K_ADDR
- b 10f
- 9:
- /* load the base address for 64k offsets */
- ldr x0, =NXP_GICC_64K_ADDR
- 10:
- 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 = DCSR_RCPM2_BASE
- * x8 = NXP_DCFG_ADDR
- * x9 = 0, restartable
- * = 1, non-restartable
- * w13 = DEVDISR1 saved value
- * w14 = DEVDISR2 saved value
- * w15 = DEVDISR3 saved value
- * w16 = DEVDISR4 saved value
- * w17 = DEVDISR5 saved value
- * out: none
- * uses x0 ~ x9
- */
- /* 4Kb aligned */
- .align 12
- final_pwrdown:
- mov x0, xzr
- b touch_line_0
- start_line_0:
- mov x0, #1
- mov x2, #DDR_SDRAM_CFG_2_FRCSR /* put ddr in self refresh - start */
- ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET]
- rev w4, w3
- orr w4, w4, w2
- rev w3, w4
- str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] /* put ddr in self refresh - end */
- orr w3, w5, #DEVDISR5_MEM /* quiesce ddr clocks - start */
- rev w4, w3
- str w4, [x7, #RCPM2_IPSTPCR4_OFFSET] /* quiesce ddr clocks - end */
- mov w3, #DEVDISR5_MEM
- rev w3, w3 /* polling mask */
- mov x2, #DDR_SLEEP_RETRY_CNT /* poll on ipstpack4 - start */
- touch_line_0:
- cbz x0, touch_line_1
- start_line_1:
- ldr w1, [x7, #RCPM2_IPSTPACKR4_OFFSET]
- tst w1, w3
- b.ne 1f
- subs x2, x2, #1
- b.gt start_line_1 /* poll on ipstpack4 - end */
- /* if we get here, we have a timeout err */
- rev w4, w5
- str w4, [x7, #RCPM2_IPSTPCR4_OFFSET] /* re-enable ddr clks interface */
- mov x0, #ERROR_DDR_SLEEP /* load error code */
- b 2f
- 1:
- str w4, [x8, #DCFG_DEVDISR5_OFFSET] /* disable ddr cntrlr clk in devdisr5 */
- 5:
- wfi /* stop the final core */
- cbnz x9, 5b /* if non-restartable, keep in wfi */
- rev w4, w5
- str w4, [x8, #DCFG_DEVDISR5_OFFSET] /* re-enable ddr in devdisr5 */
- str w4, [x7, #RCPM2_IPSTPCR4_OFFSET] /* re-enable ddr clk in ipstpcr4 */
- touch_line_1:
- cbz x0, touch_line_2
- start_line_2:
- ldr w1, [x7, #RCPM2_IPSTPACKR4_OFFSET] /* poll on ipstpack4 - start */
- tst w1, w3
- b.eq 2f
- nop
- b start_line_2 /* poll on ipstpack4 - end */
- 2:
- mov x2, #DDR_SDRAM_CFG_2_FRCSR /* take ddr out-of self refresh - start */
- ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET]
- rev w4, w3
- bic w4, w4, w2
- rev w3, w4
- mov x1, #DDR_SLEEP_RETRY_CNT /* wait for ddr cntrlr clock - start */
- 3:
- subs x1, x1, #1
- b.gt 3b /* wait for ddr cntrlr clock - end */
- str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] /* take ddr out-of self refresh - end */
- rev w1, w17
- touch_line_2:
- cbz x0, touch_line_3
- start_line_3:
- str w1, [x8, #DCFG_DEVDISR5_OFFSET] /* reset devdisr5 */
- rev w1, w16
- str w1, [x8, #DCFG_DEVDISR4_OFFSET] /* reset devdisr4 */
- rev w1, w15
- str w1, [x8, #DCFG_DEVDISR3_OFFSET] /* reset devdisr3 */
- rev w1, w14
- str w1, [x8, #DCFG_DEVDISR2_OFFSET] /* reset devdisr2 */
- rev w1, w13
- str w1, [x8, #DCFG_DEVDISR1_OFFSET] /* reset devdisr1 */
- str wzr, [x7, #RCPM2_IPSTPCR4_OFFSET] /* reset ipstpcr4 */
- str wzr, [x7, #RCPM2_IPSTPCR3_OFFSET] /* reset ipstpcr3 */
- str wzr, [x7, #RCPM2_IPSTPCR2_OFFSET] /* reset ipstpcr2 */
- str wzr, [x7, #RCPM2_IPSTPCR1_OFFSET] /* reset ipstpcr1 */
- str wzr, [x7, #RCPM2_IPSTPCR0_OFFSET] /* reset ipstpcr0 */
- b continue_restart
- touch_line_3:
- 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
- /*
- * Note: there is no return from this function
- * this function will shutdown 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 = DCSR_RCPM2_BASE
- * x8 = NXP_DCFG_ADDR
- * out: none
- * uses x0 ~ x8
- */
- /* 4Kb aligned */
- .align 12
- final_shutdown:
- mov x0, xzr
- b touch_line0
- start_line0:
- mov x0, #1
- mov x2, #DDR_SDRAM_CFG_2_FRCSR /* put ddr in self refresh - start */
- ldr w3, [x6, #DDR_SDRAM_CFG_2_OFFSET]
- rev w4, w3
- orr w4, w4, w2
- rev w3, w4
- str w3, [x6, #DDR_SDRAM_CFG_2_OFFSET] /* put ddr in self refresh - end */
- orr w3, w5, #DEVDISR5_MEM /* quiesce ddr clocks - start */
- rev w4, w3
- str w4, [x7, #RCPM2_IPSTPCR4_OFFSET] /* quiesce ddr clocks - end */
- mov w3, #DEVDISR5_MEM
- rev w3, w3 /* polling mask */
- mov x2, #DDR_SLEEP_RETRY_CNT /* poll on ipstpack4 - start */
- touch_line0:
- cbz x0, touch_line1
- start_line1:
- ldr w1, [x7, #RCPM2_IPSTPACKR4_OFFSET]
- tst w1, w3
- b.ne 1f
- subs x2, x2, #1
- b.gt start_line1 /* poll on ipstpack4 - end */
- nop
- nop
- nop
- nop
- 1:
- str w4, [x8, #DCFG_DEVDISR5_OFFSET] /* disable ddr cntrlr clk in devdisr5 */
- 5:
- wfi /* stop the final core */
- b 5b /* stay here until POR */
- nop
- nop
- nop
- touch_line1:
- cbz x0, start_line0
|