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 * Determine how many levels of cache will be 69 * subject to cache maintenance. Power level 70 * 0 implies that only the cpu is being powered 71 * down. Only the L1 data cache needs to be 72 * flushed to the PoU in this case. For a higher 73 * power level we are assuming that a flush 74 * of L1 data and L2 unified cache is enough. 75 * This information should be provided by the 76 * platform. 77 * --------------------------------------------- 78 */ 79 cmp r4, #PSCI_CPU_PWR_LVL 80 pop {r4,lr} 81 82 beq prepare_core_pwr_dwn 83 b prepare_cluster_pwr_dwn 84endfunc psci_do_pwrdown_cache_maintenance 85 86 87/* ----------------------------------------------------------------------- 88 * void psci_do_pwrup_cache_maintenance(void); 89 * 90 * This function performs cache maintenance after this cpu is powered up. 91 * Currently, this involves managing the used stack memory before turning 92 * on the data cache. 93 * ----------------------------------------------------------------------- 94 */ 95func psci_do_pwrup_cache_maintenance 96 push {lr} 97 98 /* --------------------------------------------- 99 * Ensure any inflight stack writes have made it 100 * to main memory. 101 * --------------------------------------------- 102 */ 103 dmb st 104 105 /* --------------------------------------------- 106 * Calculate and store the size of the used 107 * stack memory in r1. Calculate and store the 108 * stack base address in r0. 109 * --------------------------------------------- 110 */ 111 bl plat_get_my_stack 112 mov r1, sp 113 sub r1, r0, r1 114 mov r0, sp 115 bl inv_dcache_range 116 117 /* --------------------------------------------- 118 * Enable the data cache. 119 * --------------------------------------------- 120 */ 121 ldcopr r0, SCTLR 122 orr r0, r0, #SCTLR_C_BIT 123 stcopr r0, SCTLR 124 isb 125 126 pop {pc} 127endfunc psci_do_pwrup_cache_maintenance 128 129 /* --------------------------------------------- 130 * void do_stack_maintenance(void) 131 * Do stack maintenance by flushing the used 132 * stack to the main memory and invalidating the 133 * remainder. 134 * --------------------------------------------- 135 */ 136func do_stack_maintenance 137 push {r4, lr} 138 bl plat_get_my_stack 139 140 /* Turn off the D-cache */ 141 ldcopr r1, SCTLR 142 bic r1, #SCTLR_C_BIT 143 stcopr r1, SCTLR 144 isb 145 146 /* --------------------------------------------- 147 * Calculate and store the size of the used 148 * stack memory in r1. 149 * --------------------------------------------- 150 */ 151 mov r4, r0 152 mov r1, sp 153 sub r1, r0, r1 154 mov r0, sp 155 bl flush_dcache_range 156 157 /* --------------------------------------------- 158 * Calculate and store the size of the unused 159 * stack memory in r1. Calculate and store the 160 * stack base address in r0. 161 * --------------------------------------------- 162 */ 163 sub r0, r4, #PLATFORM_STACK_SIZE 164 sub r1, sp, r0 165 bl inv_dcache_range 166 167 pop {r4, pc} 168endfunc do_stack_maintenance 169 170/* ----------------------------------------------------------------------- 171 * This function is called to indicate to the power controller that it 172 * is safe to power down this cpu. It should not exit the wfi and will 173 * be released from reset upon power up. 174 * ----------------------------------------------------------------------- 175 */ 176func psci_power_down_wfi 177 dsb sy // ensure write buffer empty 178 wfi 179 no_ret plat_panic_handler 180endfunc psci_power_down_wfi 181