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