| /* |
| * Copyright 2020-2022 NXP |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| * |
| */ |
| |
| #include <asm_macros.S> |
| #include <dcfg_lsch2.h> |
| #include <nxp_timer.h> |
| #include <plat_gic.h> |
| #include <scfg.h> |
| |
| #include <bl31_data.h> |
| #include <plat_psci.h> |
| #include <platform_def.h> |
| |
| #define DAIF_DATA AUX_01_DATA |
| #define TIMER_CNTRL_DATA AUX_02_DATA |
| |
| .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_set_start_addr |
| .global _getGICC_BaseAddr |
| .global _getGICD_BaseAddr |
| .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_A72 /* 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 |
| */ |
| func _soc_core_release |
| |
| #if (TEST_BL31) |
| rbit w2, w0 |
| /* x2 = core mask msb */ |
| #else |
| mov x2, x0 |
| #endif |
| /* write COREBCR */ |
| mov 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 |
| endfunc _soc_core_release |
| |
| |
| /* 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 |
| */ |
| func _soc_core_restart |
| mov x5, x30 |
| mov x3, x0 |
| |
| /* |
| * unset ph20 request in RCPM_PCPH20CLEARR |
| * this is an lsb-0 register |
| */ |
| ldr x1, =NXP_RCPM_ADDR |
| rev w2, w3 |
| str w2, [x1, #RCPM_PCPH20CLRR_OFFSET] |
| dsb sy |
| isb |
| |
| bl _getGICD_BaseAddr |
| mov x4, x0 |
| |
| /* 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 |
| endfunc _soc_core_restart |
| |
| /* |
| * 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 |
| */ |
| func _soc_ck_disabled |
| /* get base addr of dcfg block */ |
| mov x1, #NXP_DCFG_ADDR |
| |
| /* read COREDISR */ |
| ldr w1, [x1, #DCFG_COREDISR_OFFSET] |
| rev w2, w1 |
| |
| /* test core bit */ |
| and w0, w2, w0 |
| ret |
| endfunc _soc_ck_disabled |
| |
| /* |
| *This function resets the system via SoC-specific methods |
| * in: none |
| * out: none |
| * uses x0, x1, x2, x3 |
| */ |
| func _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] |
| |
| /* set the reset request */ |
| ldr w1, =RSTCR_RESET_REQ |
| ldr x3, =DCFG_RSTCR_OFFSET |
| rev w0, w1 |
| str w0, [x2, x3] |
| |
| /* |
| * 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 |
| endfunc _soc_sys_reset |
| |
| /* |
| * 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, x1, x2, x3, x4, x5, x6, x7, x8, x9 |
| */ |
| func _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 |
| |
| /* Enable dynamic retention ctrl (CPUECTLR[2:0]) and SMP (CPUECTLR[6]) */ |
| mrs x0, CORTEX_A72_ECTLR_EL1 |
| orr x0, x0, #CPUECTLR_TIMER_8TICKS |
| orr x0, x0, #CPUECTLR_SMPEN_EN |
| msr CORTEX_A72_ECTLR_EL1, x0 |
| |
| /* set WFIL2EN in SCFG_CLUSTERPMCR */ |
| ldr x0, =SCFG_COREPMCR_OFFSET |
| ldr x1, =COREPMCR_WFIL2 |
| bl write_reg_scfg |
| |
| /* request LPM20 */ |
| mov x0, #RCPM_POWMGTCSR_OFFSET |
| bl read_reg_rcpm |
| orr x1, x0, #RCPM_POWMGTCSR_LPM20_REQ |
| mov x0, #RCPM_POWMGTCSR_OFFSET |
| bl write_reg_rcpm |
| |
| dsb sy |
| isb |
| 1: |
| wfi |
| b 1b |
| endfunc _soc_sys_off |
| |
| /* |
| * Write a register in the RCPM block |
| * in: x0 = offset |
| * in: w1 = value to write |
| * uses x0, x1, x2, x3 |
| */ |
| func write_reg_rcpm |
| ldr x2, =NXP_RCPM_ADDR |
| /* swap for BE */ |
| rev w3, w1 |
| str w3, [x2, x0] |
| ret |
| endfunc write_reg_rcpm |
| |
| /* |
| * Read a register in the RCPM block |
| * in: x0 = offset |
| * out: w0 = value read |
| * uses x0, x1, x2 |
| */ |
| func read_reg_rcpm |
| ldr x2, =NXP_RCPM_ADDR |
| ldr w1, [x2, x0] |
| /* swap for BE */ |
| rev w0, w1 |
| ret |
| endfunc read_reg_rcpm |
| |
| /* |
| * Write a register in the SCFG block |
| * in: x0 = offset |
| * in: w1 = value to write |
| * uses x0, x1, x2, x3 |
| */ |
| func write_reg_scfg |
| mov x2, #NXP_SCFG_ADDR |
| /* swap for BE */ |
| rev w3, w1 |
| str w3, [x2, x0] |
| ret |
| endfunc write_reg_scfg |
| |
| /* |
| * Read a register in the SCFG block |
| * in: x0 = offset |
| * out: w0 = value read |
| * uses x0, x1, x2 |
| */ |
| func read_reg_scfg |
| mov x2, #NXP_SCFG_ADDR |
| ldr w1, [x2, x0] |
| /* swap for BE */ |
| rev w0, w1 |
| ret |
| endfunc read_reg_scfg |
| |
| /* |
| * 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 |
| */ |
| func _soc_core_prep_off |
| mov x7, x30 |
| mov x6, x0 |
| |
| /* Set retention control in CPUECTLR make sure smpen bit is set */ |
| mrs x4, CORTEX_A72_ECTLR_EL1 |
| bic x4, x4, #CPUECTLR_RET_MASK |
| orr x4, x4, #CPUECTLR_TIMER_8TICKS |
| orr x4, x4, #CPUECTLR_SMPEN_EN |
| msr CORTEX_A72_ECTLR_EL1, x4 |
| |
| /* save timer control current value */ |
| mov x5, #NXP_TIMER_ADDR |
| ldr w4, [x5, #SYS_COUNTER_CNTCR_OFFSET] |
| mov w2, w4 |
| mov x0, x6 |
| mov x1, #TIMER_CNTRL_DATA |
| bl _setCoreData |
| |
| /* enable the timer */ |
| orr w4, w4, #CNTCR_EN_MASK |
| str w4, [x5, #SYS_COUNTER_CNTCR_OFFSET] |
| |
| bl _getGICC_BaseAddr |
| mov x5, x0 |
| |
| /* disable signaling of ints */ |
| ldr w3, [x5, #GICC_CTLR_OFFSET] |
| bic w3, w3, #GICC_CTLR_EN_GRP0 |
| bic w3, w3, #GICC_CTLR_EN_GRP1 |
| str w3, [x5, #GICC_CTLR_OFFSET] |
| dsb sy |
| isb |
| |
| |
| /* |
| * set retention control in SCFG_RETREQCR |
| * Note: this register is msb 0 |
| */ |
| ldr x4, =SCFG_RETREQCR_OFFSET |
| mov x0, x4 |
| bl read_reg_scfg |
| rbit w1, w6 |
| orr w1, w0, w1 |
| mov x0, x4 |
| bl write_reg_scfg |
| |
| /* set the priority filter */ |
| ldr w2, [x5, #GICC_PMR_OFFSET] |
| orr w2, w2, #GICC_PMR_FILTER |
| str w2, [x5, #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, [x5, #GICC_CTLR_OFFSET] |
| |
| /* setup the banked-per-core GICD registers */ |
| bl _getGICD_BaseAddr |
| mov x5, x0 |
| |
| /* define SGI15 as Grp0 */ |
| ldr w2, [x5, #GICD_IGROUPR0_OFFSET] |
| bic w2, w2, #GICD_IGROUP0_SGI15 |
| str w2, [x5, #GICD_IGROUPR0_OFFSET] |
| |
| /* set priority of SGI 15 to highest... */ |
| ldr w2, [x5, #GICD_IPRIORITYR3_OFFSET] |
| bic w2, w2, #GICD_IPRIORITY_SGI15_MASK |
| str w2, [x5, #GICD_IPRIORITYR3_OFFSET] |
| |
| /* enable SGI 15 */ |
| ldr w2, [x5, #GICD_ISENABLER0_OFFSET] |
| orr w2, w2, #GICD_ISENABLE0_SGI15 |
| str w2, [x5, #GICD_ISENABLER0_OFFSET] |
| |
| /* enable the cpu interface */ |
| bl _getGICC_BaseAddr |
| mov x2, x0 |
| orr w3, w3, #GICC_CTLR_EN_GRP0 |
| str w3, [x2, #GICC_CTLR_OFFSET] |
| |
| |
| /* clear any pending SGIs */ |
| ldr x2, =GICD_CPENDSGIR_CLR_MASK |
| add x0, x5, #GICD_CPENDSGIR3_OFFSET |
| str w2, [x0] |
| |
| /* |
| * Set the PC_PH20_REQ bit in RCPM_PCPH20SETR |
| * this is an lsb-0 register |
| */ |
| mov x1, x6 |
| mov x0, #RCPM_PCPH20SETR_OFFSET |
| bl write_reg_rcpm |
| |
| dsb sy |
| isb |
| mov x30, x7 |
| ret |
| endfunc _soc_core_prep_off |
| |
| /* |
| * 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 |
| */ |
| func _soc_core_entr_off |
| mov x5, x30 |
| mov x4, x0 |
| |
| bl _getGICD_BaseAddr |
| mov x3, x0 |
| |
| 3: |
| /* enter low-power state by executing wfi */ |
| wfi |
| |
| /* 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 |
| |
| cmp x0, #CORE_WAKEUP |
| b.ne 3b |
| |
| /* if we get here, then we have exited the wfi */ |
| dsb sy |
| isb |
| mov x30, x5 |
| ret |
| endfunc _soc_core_entr_off |
| |
| /* |
| * 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 |
| */ |
| func _soc_core_exit_off |
| mov x6, x30 |
| mov x5, x0 |
| |
| /* |
| * Clear ph20 request in RCPM_PCPH20CLRR - no need |
| * to do that here, it has been done in _soc_core_restart |
| */ |
| bl _getGICC_BaseAddr |
| mov x1, x0 |
| |
| /* read GICC_IAR */ |
| ldr w0, [x1, #GICC_IAR_OFFSET] |
| |
| /* write GICC_EIOR - signal end-of-interrupt */ |
| str w0, [x1, #GICC_EOIR_OFFSET] |
| |
| /* write GICC_DIR - disable interrupt */ |
| str w0, [x1, #GICC_DIR_OFFSET] |
| |
| /* disable signaling of grp0 ints */ |
| ldr w3, [x1, #GICC_CTLR_OFFSET] |
| bic w3, w3, #GICC_CTLR_EN_GRP0 |
| str w3, [x1, #GICC_CTLR_OFFSET] |
| |
| /* |
| * Unset retention request in SCFG_RETREQCR |
| * Note: this register is msb-0 |
| */ |
| ldr x4, =SCFG_RETREQCR_OFFSET |
| mov x0, x4 |
| bl read_reg_scfg |
| rbit w1, w5 |
| bic w1, w0, w1 |
| mov x0, x4 |
| bl write_reg_scfg |
| |
| /* restore timer ctrl */ |
| mov x0, x5 |
| mov x1, #TIMER_CNTRL_DATA |
| bl _getCoreData |
| /* w0 = timer ctrl saved value */ |
| mov x2, #NXP_TIMER_ADDR |
| str w0, [x2, #SYS_COUNTER_CNTCR_OFFSET] |
| |
| dsb sy |
| isb |
| mov x30, x6 |
| ret |
| endfunc _soc_core_exit_off |
| |
| /* |
| * 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 |
| */ |
| func _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 */ |
| mov x1, x0 |
| rev w3, w1 |
| str w3, [x2, #SCFG_BOOTLOCPTRL_OFFSET] |
| |
| /* write the 32-bit BOOTLOCPTRH register */ |
| lsr x1, x0, #32 |
| rev w3, w1 |
| str w3, [x2, #SCFG_BOOTLOCPTRH_OFFSET] |
| ret |
| endfunc _soc_set_start_addr |
| |
| /* |
| * This function returns the base address of the gic distributor |
| * in: none |
| * out: x0 = base address of gic distributor |
| * uses x0 |
| */ |
| func _getGICD_BaseAddr |
| #if (TEST_BL31) |
| /* defect in simulator - gic base addresses are on 4Kb boundary */ |
| ldr x0, =NXP_GICD_4K_ADDR |
| #else |
| ldr x0, =NXP_GICD_64K_ADDR |
| #endif |
| ret |
| endfunc _getGICD_BaseAddr |
| |
| /* |
| * This function returns the base address of the gic controller |
| * in: none |
| * out: x0 = base address of gic controller |
| * uses x0 |
| */ |
| func _getGICC_BaseAddr |
| #if (TEST_BL31) |
| /* defect in simulator - gic base addresses are on 4Kb boundary */ |
| ldr x0, =NXP_GICC_4K_ADDR |
| #else |
| ldr x0, =NXP_GICC_64K_ADDR |
| #endif |
| ret |
| endfunc _getGICC_BaseAddr |
| |
| /* |
| * Part of CPU_SUSPEND |
| * this function puts the calling core into standby state |
| * in: x0 = core mask lsb |
| * out: none |
| * uses x0 |
| */ |
| func _soc_core_entr_stdby |
| dsb sy |
| isb |
| wfi |
| |
| ret |
| endfunc _soc_core_entr_stdby |
| |
| |
| /* |
| * Part of CPU_SUSPEND |
| * this function performs SoC-specific programming prior to standby |
| * in: x0 = core mask lsb |
| * out: none |
| * uses x0, x1 |
| */ |
| func _soc_core_prep_stdby |
| /* clear CORTEX_A72_ECTLR_EL1[2:0] */ |
| mrs x1, CORTEX_A72_ECTLR_EL1 |
| bic x1, x1, #CPUECTLR_TIMER_MASK |
| msr CORTEX_A72_ECTLR_EL1, x1 |
| |
| ret |
| endfunc _soc_core_prep_stdby |
| |
| /* |
| * Part of CPU_SUSPEND |
| * this function performs any SoC-specific cleanup after standby state |
| * in: x0 = core mask lsb |
| * out: none |
| * uses none |
| */ |
| func _soc_core_exit_stdby |
| ret |
| endfunc _soc_core_exit_stdby |
| |
| /* |
| * 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, x4, x5 |
| */ |
| func _soc_core_prep_pwrdn |
| mov x5, x30 |
| mov x4, x0 |
| |
| /* enable CPU retention + set smp */ |
| mrs x1, CORTEX_A72_ECTLR_EL1 |
| orr x1, x1, #0x1 |
| orr x1, x1, #CPUECTLR_SMPEN_MASK |
| msr CORTEX_A72_ECTLR_EL1, x1 |
| |
| /* |
| * set the retention request in SCFG_RETREQCR |
| * this is an msb-0 register |
| */ |
| ldr x3, =SCFG_RETREQCR_OFFSET |
| mov x0, x3 |
| bl read_reg_scfg |
| rbit w1, w4 |
| orr w1, w0, w1 |
| mov x0, x3 |
| bl write_reg_scfg |
| |
| /* |
| * Set the PC_PH20_REQ bit in RCPM_PCPH20SETR |
| * this is an lsb-0 register |
| */ |
| mov x1, x4 |
| mov x0, #RCPM_PCPH20SETR_OFFSET |
| bl write_reg_rcpm |
| |
| mov x30, x5 |
| ret |
| endfunc _soc_core_prep_pwrdn |
| |
| /* |
| * Part of CPU_SUSPEND |
| * this function puts the calling core into a power-down state |
| * in: x0 = core mask lsb |
| * out: none |
| * uses x0 |
| */ |
| func _soc_core_entr_pwrdn |
| dsb sy |
| isb |
| wfi |
| |
| ret |
| endfunc _soc_core_entr_pwrdn |
| |
| /* |
| * Part of CPU_SUSPEND |
| * this function cleans up after a core exits power-down |
| * in: x0 = core mask lsb |
| * out: none |
| * uses x0, x1, x2, x3, x4, x5 |
| */ |
| func _soc_core_exit_pwrdn |
| mov x5, x30 |
| mov x4, x0 |
| |
| /* |
| * Set the PC_PH20_REQ bit in RCPM_PCPH20CLRR |
| * this is an lsb-0 register |
| */ |
| mov x1, x4 |
| mov x0, #RCPM_PCPH20CLRR_OFFSET |
| bl write_reg_rcpm |
| |
| /* |
| * Unset the retention request in SCFG_RETREQCR |
| * this is an msb-0 register |
| */ |
| ldr x3, =SCFG_RETREQCR_OFFSET |
| mov x0, x3 |
| bl read_reg_scfg |
| rbit w1, w4 |
| bic w1, w0, w1 |
| mov x0, x3 |
| bl write_reg_scfg |
| |
| mov x30, x5 |
| ret |
| endfunc _soc_core_exit_pwrdn |
| |
| /* |
| * Part of CPU_SUSPEND |
| * this function performs SoC-specific programming prior to standby |
| * in: x0 = core mask lsb |
| * out: none |
| * uses none |
| */ |
| func _soc_clstr_prep_stdby |
| /* clear CORTEX_A72_ECTLR_EL1[2:0] */ |
| mrs x1, CORTEX_A72_ECTLR_EL1 |
| bic x1, x1, #CPUECTLR_TIMER_MASK |
| msr CORTEX_A72_ECTLR_EL1, x1 |
| |
| ret |
| endfunc _soc_clstr_prep_stdby |
| |
| /* |
| * Part of CPU_SUSPEND |
| * this function performs any SoC-specific cleanup after standby state |
| * in: x0 = core mask lsb |
| * out: none |
| * uses none |
| */ |
| func _soc_clstr_exit_stdby |
| ret |
| endfunc _soc_clstr_exit_stdby |
| |
| /* |
| * 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, x4, x5 |
| */ |
| func _soc_clstr_prep_pwrdn |
| mov x5, x30 |
| mov x4, x0 |
| |
| /* enable CPU retention + set smp */ |
| mrs x1, CORTEX_A72_ECTLR_EL1 |
| orr x1, x1, #0x1 |
| orr x1, x1, #CPUECTLR_SMPEN_MASK |
| msr CORTEX_A72_ECTLR_EL1, x1 |
| |
| /* |
| * Set the retention request in SCFG_RETREQCR |
| * this is an msb-0 register. |
| */ |
| ldr x3, =SCFG_RETREQCR_OFFSET |
| mov x0, x3 |
| bl read_reg_scfg |
| rbit w1, w4 |
| orr w1, w0, w1 |
| mov x0, x3 |
| bl write_reg_scfg |
| |
| /* |
| * Set the PC_PH20_REQ bit in RCPM_PCPH20SETR |
| * this is an lsb-0 register. |
| */ |
| mov x1, x4 |
| mov x0, #RCPM_PCPH20SETR_OFFSET |
| bl write_reg_rcpm |
| |
| mov x30, x5 |
| ret |
| endfunc _soc_clstr_prep_pwrdn |
| |
| /* |
| * Part of CPU_SUSPEND |
| * this function cleans up after a core exits power-down |
| * in: x0 = core mask lsb |
| * out: none |
| * uses x0, x1, x2, x3, x4, x5 |
| */ |
| func _soc_clstr_exit_pwrdn |
| mov x5, x30 |
| mov x4, x0 |
| |
| /* |
| * Set the PC_PH20_REQ bit in RCPM_PCPH20CLRR |
| * this is an lsb-0 register. |
| */ |
| mov x1, x4 |
| mov x0, #RCPM_PCPH20CLRR_OFFSET |
| bl write_reg_rcpm |
| |
| /* |
| * Unset the retention request in SCFG_RETREQCR |
| * this is an msb-0 register. |
| */ |
| ldr x3, =SCFG_RETREQCR_OFFSET |
| mov x0, x3 |
| bl read_reg_scfg |
| rbit w1, w4 |
| bic w1, w0, w1 |
| mov x0, x3 |
| bl write_reg_scfg |
| |
| mov x30, x5 |
| ret |
| endfunc _soc_clstr_exit_pwrdn |
| |
| /* |
| * Part of CPU_SUSPEND |
| * this function performs SoC-specific programming prior to standby |
| * in: x0 = core mask lsb |
| * out: none |
| * uses none |
| */ |
| func _soc_sys_prep_stdby |
| /* clear CORTEX_A72_ECTLR_EL1[2:0] */ |
| mrs x1, CORTEX_A72_ECTLR_EL1 |
| bic x1, x1, #CPUECTLR_TIMER_MASK |
| msr CORTEX_A72_ECTLR_EL1, x1 |
| |
| ret |
| endfunc _soc_sys_prep_stdby |
| |
| /* Part of CPU_SUSPEND |
| * this function performs any SoC-specific cleanup after standby state |
| * in: x0 = core mask lsb |
| * out: none |
| * uses none |
| */ |
| func _soc_sys_exit_stdby |
| ret |
| endfunc _soc_sys_exit_stdby |
| |
| /* |
| * 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 |
| */ |
| func _soc_sys_prep_pwrdn |
| mov x4, x30 |
| |
| /* Enable dynamic retention contrl (CPUECTLR[2:0]) and SMP (CPUECTLR[6]) */ |
| mrs x0, CORTEX_A72_ECTLR_EL1 |
| bic x0, x0, #CPUECTLR_TIMER_MASK |
| orr x0, x0, #CPUECTLR_TIMER_8TICKS |
| orr x0, x0, #CPUECTLR_SMPEN_EN |
| msr CORTEX_A72_ECTLR_EL1, x0 |
| |
| /* Set WFIL2EN in SCFG_CLUSTERPMCR */ |
| ldr x0, =SCFG_COREPMCR_OFFSET |
| ldr x1, =COREPMCR_WFIL2 |
| bl write_reg_scfg |
| |
| isb |
| mov x30, x4 |
| ret |
| endfunc _soc_sys_prep_pwrdn |
| |
| /* |
| * 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 |
| */ |
| func _soc_sys_pwrdn_wfi |
| mov x4, x30 |
| |
| /* request LPM20 */ |
| mov x0, #RCPM_POWMGTCSR_OFFSET |
| bl read_reg_rcpm |
| orr x1, x0, #RCPM_POWMGTCSR_LPM20_REQ |
| mov x0, #RCPM_POWMGTCSR_OFFSET |
| bl write_reg_rcpm |
| |
| dsb sy |
| isb |
| wfi |
| |
| mov x30, x4 |
| ret |
| endfunc _soc_sys_pwrdn_wfi |
| |
| /* |
| * Part of CPU_SUSPEND |
| * this function performs any SoC-specific cleanup after power-down |
| * in: x0 = core mask lsb |
| * out: none |
| * uses x0, x1 |
| */ |
| func _soc_sys_exit_pwrdn |
| /* clear WFIL2_EN in SCFG_COREPMCR */ |
| mov x1, #NXP_SCFG_ADDR |
| str wzr, [x1, #SCFG_COREPMCR_OFFSET] |
| |
| ret |
| endfunc _soc_sys_exit_pwrdn |