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 <lib/psci/psci.h> 9#include <platform_def.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 pop {r12, pc} 95endfunc psci_do_pwrup_cache_maintenance 96 97 /* --------------------------------------------- 98 * void do_stack_maintenance(void) 99 * Do stack maintenance by flushing the used 100 * stack to the main memory and invalidating the 101 * remainder. 102 * --------------------------------------------- 103 */ 104func do_stack_maintenance 105 push {r4, lr} 106 bl plat_get_my_stack 107 108 /* Turn off the D-cache */ 109 ldcopr r1, SCTLR 110 bic r1, #SCTLR_C_BIT 111 stcopr r1, SCTLR 112 isb 113 114 /* --------------------------------------------- 115 * Calculate and store the size of the used 116 * stack memory in r1. 117 * --------------------------------------------- 118 */ 119 mov r4, r0 120 mov r1, sp 121 sub r1, r0, r1 122 mov r0, sp 123 bl flush_dcache_range 124 125 /* --------------------------------------------- 126 * Calculate and store the size of the unused 127 * stack memory in r1. Calculate and store the 128 * stack base address in r0. 129 * --------------------------------------------- 130 */ 131 sub r0, r4, #PLATFORM_STACK_SIZE 132 sub r1, sp, r0 133 bl inv_dcache_range 134 135 pop {r4, pc} 136endfunc do_stack_maintenance 137 138/* ----------------------------------------------------------------------- 139 * This function is called to indicate to the power controller that it 140 * is safe to power down this cpu. It should not exit the wfi and will 141 * be released from reset upon power up. 142 * ----------------------------------------------------------------------- 143 */ 144func psci_power_down_wfi 145 dsb sy // ensure write buffer empty 146 wfi 147 no_ret plat_panic_handler 148endfunc psci_power_down_wfi 149