1/* 2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. 9 * 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * Neither the name of ARM nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without specific 16 * prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include <asm_macros.S> 32#include <platform_def.h> 33#include <psci.h> 34 35 .globl psci_do_pwrdown_cache_maintenance 36 .globl psci_do_pwrup_cache_maintenance 37 .globl psci_power_down_wfi 38 39/* ----------------------------------------------------------------------- 40 * void psci_do_pwrdown_cache_maintenance(unsigned int power level); 41 * 42 * This function performs cache maintenance for the specified power 43 * level. The levels of cache affected are determined by the power 44 * level which is passed as the argument i.e. level 0 results 45 * in a flush of the L1 cache. Both the L1 and L2 caches are flushed 46 * for a higher power level. 47 * 48 * Additionally, this function also ensures that stack memory is correctly 49 * flushed out to avoid coherency issues due to a change in its memory 50 * attributes after the data cache is disabled. 51 * ----------------------------------------------------------------------- 52 */ 53func psci_do_pwrdown_cache_maintenance 54 push {r4, lr} 55 56 /* ---------------------------------------------- 57 * Turn OFF cache and do stack maintenance 58 * prior to cpu operations . This sequence is 59 * different from AArch64 because in AArch32 the 60 * assembler routines for cpu operations utilize 61 * the stack whereas in AArch64 it doesn't. 62 * ---------------------------------------------- 63 */ 64 mov r4, r0 65 bl do_stack_maintenance 66 67 /* --------------------------------------------- 68 * Invoke CPU-specifc power down operations for 69 * the appropriate level 70 * --------------------------------------------- 71 */ 72 mov r0, r4 73 pop {r4, lr} 74 b prepare_cpu_pwr_dwn 75endfunc psci_do_pwrdown_cache_maintenance 76 77 78/* ----------------------------------------------------------------------- 79 * void psci_do_pwrup_cache_maintenance(void); 80 * 81 * This function performs cache maintenance after this cpu is powered up. 82 * Currently, this involves managing the used stack memory before turning 83 * on the data cache. 84 * ----------------------------------------------------------------------- 85 */ 86func psci_do_pwrup_cache_maintenance 87 /* r12 is pushed to meet the 8 byte stack alignment requirement */ 88 push {r12, lr} 89 90 /* --------------------------------------------- 91 * Ensure any inflight stack writes have made it 92 * to main memory. 93 * --------------------------------------------- 94 */ 95 dmb st 96 97 /* --------------------------------------------- 98 * Calculate and store the size of the used 99 * stack memory in r1. Calculate and store the 100 * stack base address in r0. 101 * --------------------------------------------- 102 */ 103 bl plat_get_my_stack 104 mov r1, sp 105 sub r1, r0, r1 106 mov r0, sp 107 bl inv_dcache_range 108 109 /* --------------------------------------------- 110 * Enable the data cache. 111 * --------------------------------------------- 112 */ 113 ldcopr r0, SCTLR 114 orr r0, r0, #SCTLR_C_BIT 115 stcopr r0, SCTLR 116 isb 117 118 pop {r12, pc} 119endfunc psci_do_pwrup_cache_maintenance 120 121 /* --------------------------------------------- 122 * void do_stack_maintenance(void) 123 * Do stack maintenance by flushing the used 124 * stack to the main memory and invalidating the 125 * remainder. 126 * --------------------------------------------- 127 */ 128func do_stack_maintenance 129 push {r4, lr} 130 bl plat_get_my_stack 131 132 /* Turn off the D-cache */ 133 ldcopr r1, SCTLR 134 bic r1, #SCTLR_C_BIT 135 stcopr r1, SCTLR 136 isb 137 138 /* --------------------------------------------- 139 * Calculate and store the size of the used 140 * stack memory in r1. 141 * --------------------------------------------- 142 */ 143 mov r4, r0 144 mov r1, sp 145 sub r1, r0, r1 146 mov r0, sp 147 bl flush_dcache_range 148 149 /* --------------------------------------------- 150 * Calculate and store the size of the unused 151 * stack memory in r1. Calculate and store the 152 * stack base address in r0. 153 * --------------------------------------------- 154 */ 155 sub r0, r4, #PLATFORM_STACK_SIZE 156 sub r1, sp, r0 157 bl inv_dcache_range 158 159 pop {r4, pc} 160endfunc do_stack_maintenance 161 162/* ----------------------------------------------------------------------- 163 * This function is called to indicate to the power controller that it 164 * is safe to power down this cpu. It should not exit the wfi and will 165 * be released from reset upon power up. 166 * ----------------------------------------------------------------------- 167 */ 168func psci_power_down_wfi 169 dsb sy // ensure write buffer empty 170 wfi 171 no_ret plat_panic_handler 172endfunc psci_power_down_wfi 173