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