1*54fd6939SJiyong Park/* 2*54fd6939SJiyong Park * Copyright (c) 2014-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 <assert_macros.S> 9*54fd6939SJiyong Park#include <lib/psci/psci.h> 10*54fd6939SJiyong Park#include <platform_def.h> 11*54fd6939SJiyong Park 12*54fd6939SJiyong Park .globl psci_do_pwrdown_cache_maintenance 13*54fd6939SJiyong Park .globl psci_do_pwrup_cache_maintenance 14*54fd6939SJiyong Park .globl psci_power_down_wfi 15*54fd6939SJiyong Park 16*54fd6939SJiyong Park/* ----------------------------------------------------------------------- 17*54fd6939SJiyong Park * void psci_do_pwrdown_cache_maintenance(unsigned int power level); 18*54fd6939SJiyong Park * 19*54fd6939SJiyong Park * This function performs cache maintenance for the specified power 20*54fd6939SJiyong Park * level. The levels of cache affected are determined by the power 21*54fd6939SJiyong Park * level which is passed as the argument i.e. level 0 results 22*54fd6939SJiyong Park * in a flush of the L1 cache. Both the L1 and L2 caches are flushed 23*54fd6939SJiyong Park * for a higher power level. 24*54fd6939SJiyong Park * 25*54fd6939SJiyong Park * Additionally, this function also ensures that stack memory is correctly 26*54fd6939SJiyong Park * flushed out to avoid coherency issues due to a change in its memory 27*54fd6939SJiyong Park * attributes after the data cache is disabled. 28*54fd6939SJiyong Park * ----------------------------------------------------------------------- 29*54fd6939SJiyong Park */ 30*54fd6939SJiyong Parkfunc psci_do_pwrdown_cache_maintenance 31*54fd6939SJiyong Park stp x29, x30, [sp,#-16]! 32*54fd6939SJiyong Park stp x19, x20, [sp,#-16]! 33*54fd6939SJiyong Park 34*54fd6939SJiyong Park /* --------------------------------------------- 35*54fd6939SJiyong Park * Invoke CPU-specific power down operations for 36*54fd6939SJiyong Park * the appropriate level 37*54fd6939SJiyong Park * --------------------------------------------- 38*54fd6939SJiyong Park */ 39*54fd6939SJiyong Park bl prepare_cpu_pwr_dwn 40*54fd6939SJiyong Park 41*54fd6939SJiyong Park /* --------------------------------------------- 42*54fd6939SJiyong Park * Do stack maintenance by flushing the used 43*54fd6939SJiyong Park * stack to the main memory and invalidating the 44*54fd6939SJiyong Park * remainder. 45*54fd6939SJiyong Park * --------------------------------------------- 46*54fd6939SJiyong Park */ 47*54fd6939SJiyong Park bl plat_get_my_stack 48*54fd6939SJiyong Park 49*54fd6939SJiyong Park /* --------------------------------------------- 50*54fd6939SJiyong Park * Calculate and store the size of the used 51*54fd6939SJiyong Park * stack memory in x1. 52*54fd6939SJiyong Park * --------------------------------------------- 53*54fd6939SJiyong Park */ 54*54fd6939SJiyong Park mov x19, x0 55*54fd6939SJiyong Park mov x1, sp 56*54fd6939SJiyong Park sub x1, x0, x1 57*54fd6939SJiyong Park mov x0, sp 58*54fd6939SJiyong Park bl flush_dcache_range 59*54fd6939SJiyong Park 60*54fd6939SJiyong Park /* --------------------------------------------- 61*54fd6939SJiyong Park * Calculate and store the size of the unused 62*54fd6939SJiyong Park * stack memory in x1. Calculate and store the 63*54fd6939SJiyong Park * stack base address in x0. 64*54fd6939SJiyong Park * --------------------------------------------- 65*54fd6939SJiyong Park */ 66*54fd6939SJiyong Park sub x0, x19, #PLATFORM_STACK_SIZE 67*54fd6939SJiyong Park sub x1, sp, x0 68*54fd6939SJiyong Park bl inv_dcache_range 69*54fd6939SJiyong Park 70*54fd6939SJiyong Park ldp x19, x20, [sp], #16 71*54fd6939SJiyong Park ldp x29, x30, [sp], #16 72*54fd6939SJiyong Park ret 73*54fd6939SJiyong Parkendfunc psci_do_pwrdown_cache_maintenance 74*54fd6939SJiyong Park 75*54fd6939SJiyong Park 76*54fd6939SJiyong Park/* ----------------------------------------------------------------------- 77*54fd6939SJiyong Park * void psci_do_pwrup_cache_maintenance(void); 78*54fd6939SJiyong Park * 79*54fd6939SJiyong Park * This function performs cache maintenance after this cpu is powered up. 80*54fd6939SJiyong Park * Currently, this involves managing the used stack memory before turning 81*54fd6939SJiyong Park * on the data cache. 82*54fd6939SJiyong Park * ----------------------------------------------------------------------- 83*54fd6939SJiyong Park */ 84*54fd6939SJiyong Parkfunc psci_do_pwrup_cache_maintenance 85*54fd6939SJiyong Park stp x29, x30, [sp,#-16]! 86*54fd6939SJiyong Park 87*54fd6939SJiyong Park /* --------------------------------------------- 88*54fd6939SJiyong Park * Ensure any inflight stack writes have made it 89*54fd6939SJiyong Park * to main memory. 90*54fd6939SJiyong Park * --------------------------------------------- 91*54fd6939SJiyong Park */ 92*54fd6939SJiyong Park dmb st 93*54fd6939SJiyong Park 94*54fd6939SJiyong Park /* --------------------------------------------- 95*54fd6939SJiyong Park * Calculate and store the size of the used 96*54fd6939SJiyong Park * stack memory in x1. Calculate and store the 97*54fd6939SJiyong Park * stack base address in x0. 98*54fd6939SJiyong Park * --------------------------------------------- 99*54fd6939SJiyong Park */ 100*54fd6939SJiyong Park bl plat_get_my_stack 101*54fd6939SJiyong Park mov x1, sp 102*54fd6939SJiyong Park sub x1, x0, x1 103*54fd6939SJiyong Park mov x0, sp 104*54fd6939SJiyong Park bl inv_dcache_range 105*54fd6939SJiyong Park 106*54fd6939SJiyong Park /* --------------------------------------------- 107*54fd6939SJiyong Park * Enable the data cache. 108*54fd6939SJiyong Park * --------------------------------------------- 109*54fd6939SJiyong Park */ 110*54fd6939SJiyong Park mrs x0, sctlr_el3 111*54fd6939SJiyong Park orr x0, x0, #SCTLR_C_BIT 112*54fd6939SJiyong Park msr sctlr_el3, x0 113*54fd6939SJiyong Park isb 114*54fd6939SJiyong Park 115*54fd6939SJiyong Park ldp x29, x30, [sp], #16 116*54fd6939SJiyong Park ret 117*54fd6939SJiyong Parkendfunc psci_do_pwrup_cache_maintenance 118*54fd6939SJiyong Park 119*54fd6939SJiyong Park/* ----------------------------------------------------------------------- 120*54fd6939SJiyong Park * void psci_power_down_wfi(void); 121*54fd6939SJiyong Park * This function is called to indicate to the power controller that it 122*54fd6939SJiyong Park * is safe to power down this cpu. It should not exit the wfi and will 123*54fd6939SJiyong Park * be released from reset upon power up. 124*54fd6939SJiyong Park * ----------------------------------------------------------------------- 125*54fd6939SJiyong Park */ 126*54fd6939SJiyong Parkfunc psci_power_down_wfi 127*54fd6939SJiyong Park dsb sy // ensure write buffer empty 128*54fd6939SJiyong Park wfi 129*54fd6939SJiyong Park no_ret plat_panic_handler 130*54fd6939SJiyong Parkendfunc psci_power_down_wfi 131