1*91f16700Schasinglulu/* 2*91f16700Schasinglulu * Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu#include <asm_macros.S> 8*91f16700Schasinglulu#include <lib/psci/psci.h> 9*91f16700Schasinglulu#include <platform_def.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu .globl psci_do_pwrdown_cache_maintenance 12*91f16700Schasinglulu .globl psci_do_pwrup_cache_maintenance 13*91f16700Schasinglulu .globl psci_power_down_wfi 14*91f16700Schasinglulu 15*91f16700Schasinglulu/* ----------------------------------------------------------------------- 16*91f16700Schasinglulu * void psci_do_pwrdown_cache_maintenance(unsigned int power level); 17*91f16700Schasinglulu * 18*91f16700Schasinglulu * This function performs cache maintenance for the specified power 19*91f16700Schasinglulu * level. The levels of cache affected are determined by the power 20*91f16700Schasinglulu * level which is passed as the argument i.e. level 0 results 21*91f16700Schasinglulu * in a flush of the L1 cache. Both the L1 and L2 caches are flushed 22*91f16700Schasinglulu * for a higher power level. 23*91f16700Schasinglulu * 24*91f16700Schasinglulu * Additionally, this function also ensures that stack memory is correctly 25*91f16700Schasinglulu * flushed out to avoid coherency issues due to a change in its memory 26*91f16700Schasinglulu * attributes after the data cache is disabled. 27*91f16700Schasinglulu * ----------------------------------------------------------------------- 28*91f16700Schasinglulu */ 29*91f16700Schasinglulufunc psci_do_pwrdown_cache_maintenance 30*91f16700Schasinglulu push {r4, lr} 31*91f16700Schasinglulu 32*91f16700Schasinglulu /* ---------------------------------------------- 33*91f16700Schasinglulu * Turn OFF cache and do stack maintenance 34*91f16700Schasinglulu * prior to cpu operations . This sequence is 35*91f16700Schasinglulu * different from AArch64 because in AArch32 the 36*91f16700Schasinglulu * assembler routines for cpu operations utilize 37*91f16700Schasinglulu * the stack whereas in AArch64 it doesn't. 38*91f16700Schasinglulu * ---------------------------------------------- 39*91f16700Schasinglulu */ 40*91f16700Schasinglulu mov r4, r0 41*91f16700Schasinglulu bl do_stack_maintenance 42*91f16700Schasinglulu 43*91f16700Schasinglulu /* --------------------------------------------- 44*91f16700Schasinglulu * Invoke CPU-specifc power down operations for 45*91f16700Schasinglulu * the appropriate level 46*91f16700Schasinglulu * --------------------------------------------- 47*91f16700Schasinglulu */ 48*91f16700Schasinglulu mov r0, r4 49*91f16700Schasinglulu pop {r4, lr} 50*91f16700Schasinglulu b prepare_cpu_pwr_dwn 51*91f16700Schasingluluendfunc psci_do_pwrdown_cache_maintenance 52*91f16700Schasinglulu 53*91f16700Schasinglulu 54*91f16700Schasinglulu/* ----------------------------------------------------------------------- 55*91f16700Schasinglulu * void psci_do_pwrup_cache_maintenance(void); 56*91f16700Schasinglulu * 57*91f16700Schasinglulu * This function performs cache maintenance after this cpu is powered up. 58*91f16700Schasinglulu * Currently, this involves managing the used stack memory before turning 59*91f16700Schasinglulu * on the data cache. 60*91f16700Schasinglulu * ----------------------------------------------------------------------- 61*91f16700Schasinglulu */ 62*91f16700Schasinglulufunc psci_do_pwrup_cache_maintenance 63*91f16700Schasinglulu /* r12 is pushed to meet the 8 byte stack alignment requirement */ 64*91f16700Schasinglulu push {r12, lr} 65*91f16700Schasinglulu 66*91f16700Schasinglulu /* --------------------------------------------- 67*91f16700Schasinglulu * Ensure any inflight stack writes have made it 68*91f16700Schasinglulu * to main memory. 69*91f16700Schasinglulu * --------------------------------------------- 70*91f16700Schasinglulu */ 71*91f16700Schasinglulu dmb st 72*91f16700Schasinglulu 73*91f16700Schasinglulu /* --------------------------------------------- 74*91f16700Schasinglulu * Calculate and store the size of the used 75*91f16700Schasinglulu * stack memory in r1. Calculate and store the 76*91f16700Schasinglulu * stack base address in r0. 77*91f16700Schasinglulu * --------------------------------------------- 78*91f16700Schasinglulu */ 79*91f16700Schasinglulu bl plat_get_my_stack 80*91f16700Schasinglulu mov r1, sp 81*91f16700Schasinglulu sub r1, r0, r1 82*91f16700Schasinglulu mov r0, sp 83*91f16700Schasinglulu bl inv_dcache_range 84*91f16700Schasinglulu 85*91f16700Schasinglulu /* --------------------------------------------- 86*91f16700Schasinglulu * Enable the data cache. 87*91f16700Schasinglulu * --------------------------------------------- 88*91f16700Schasinglulu */ 89*91f16700Schasinglulu ldcopr r0, SCTLR 90*91f16700Schasinglulu orr r0, r0, #SCTLR_C_BIT 91*91f16700Schasinglulu stcopr r0, SCTLR 92*91f16700Schasinglulu isb 93*91f16700Schasinglulu 94*91f16700Schasinglulu pop {r12, pc} 95*91f16700Schasingluluendfunc psci_do_pwrup_cache_maintenance 96*91f16700Schasinglulu 97*91f16700Schasinglulu /* --------------------------------------------- 98*91f16700Schasinglulu * void do_stack_maintenance(void) 99*91f16700Schasinglulu * Do stack maintenance by flushing the used 100*91f16700Schasinglulu * stack to the main memory and invalidating the 101*91f16700Schasinglulu * remainder. 102*91f16700Schasinglulu * --------------------------------------------- 103*91f16700Schasinglulu */ 104*91f16700Schasinglulufunc do_stack_maintenance 105*91f16700Schasinglulu push {r4, lr} 106*91f16700Schasinglulu bl plat_get_my_stack 107*91f16700Schasinglulu 108*91f16700Schasinglulu /* Turn off the D-cache */ 109*91f16700Schasinglulu ldcopr r1, SCTLR 110*91f16700Schasinglulu bic r1, #SCTLR_C_BIT 111*91f16700Schasinglulu stcopr r1, SCTLR 112*91f16700Schasinglulu isb 113*91f16700Schasinglulu 114*91f16700Schasinglulu /* --------------------------------------------- 115*91f16700Schasinglulu * Calculate and store the size of the used 116*91f16700Schasinglulu * stack memory in r1. 117*91f16700Schasinglulu * --------------------------------------------- 118*91f16700Schasinglulu */ 119*91f16700Schasinglulu mov r4, r0 120*91f16700Schasinglulu mov r1, sp 121*91f16700Schasinglulu sub r1, r0, r1 122*91f16700Schasinglulu mov r0, sp 123*91f16700Schasinglulu bl flush_dcache_range 124*91f16700Schasinglulu 125*91f16700Schasinglulu /* --------------------------------------------- 126*91f16700Schasinglulu * Calculate and store the size of the unused 127*91f16700Schasinglulu * stack memory in r1. Calculate and store the 128*91f16700Schasinglulu * stack base address in r0. 129*91f16700Schasinglulu * --------------------------------------------- 130*91f16700Schasinglulu */ 131*91f16700Schasinglulu sub r0, r4, #PLATFORM_STACK_SIZE 132*91f16700Schasinglulu sub r1, sp, r0 133*91f16700Schasinglulu bl inv_dcache_range 134*91f16700Schasinglulu 135*91f16700Schasinglulu pop {r4, pc} 136*91f16700Schasingluluendfunc do_stack_maintenance 137*91f16700Schasinglulu 138*91f16700Schasinglulu/* ----------------------------------------------------------------------- 139*91f16700Schasinglulu * This function is called to indicate to the power controller that it 140*91f16700Schasinglulu * is safe to power down this cpu. It should not exit the wfi and will 141*91f16700Schasinglulu * be released from reset upon power up. 142*91f16700Schasinglulu * ----------------------------------------------------------------------- 143*91f16700Schasinglulu */ 144*91f16700Schasinglulufunc psci_power_down_wfi 145*91f16700Schasinglulu dsb sy // ensure write buffer empty 146*91f16700Schasinglulu1: 147*91f16700Schasinglulu wfi 148*91f16700Schasinglulu b 1b 149*91f16700Schasingluluendfunc psci_power_down_wfi 150