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 /* r12 is pushed to meet the 8 byte stack alignment requirement */ 97 push {r12, lr} 98 99 /* --------------------------------------------- 100 * Ensure any inflight stack writes have made it 101 * to main memory. 102 * --------------------------------------------- 103 */ 104 dmb st 105 106 /* --------------------------------------------- 107 * Calculate and store the size of the used 108 * stack memory in r1. Calculate and store the 109 * stack base address in r0. 110 * --------------------------------------------- 111 */ 112 bl plat_get_my_stack 113 mov r1, sp 114 sub r1, r0, r1 115 mov r0, sp 116 bl inv_dcache_range 117 118 /* --------------------------------------------- 119 * Enable the data cache. 120 * --------------------------------------------- 121 */ 122 ldcopr r0, SCTLR 123 orr r0, r0, #SCTLR_C_BIT 124 stcopr r0, SCTLR 125 isb 126 127 pop {r12, pc} 128endfunc psci_do_pwrup_cache_maintenance 129 130 /* --------------------------------------------- 131 * void do_stack_maintenance(void) 132 * Do stack maintenance by flushing the used 133 * stack to the main memory and invalidating the 134 * remainder. 135 * --------------------------------------------- 136 */ 137func do_stack_maintenance 138 push {r4, lr} 139 bl plat_get_my_stack 140 141 /* Turn off the D-cache */ 142 ldcopr r1, SCTLR 143 bic r1, #SCTLR_C_BIT 144 stcopr r1, SCTLR 145 isb 146 147 /* --------------------------------------------- 148 * Calculate and store the size of the used 149 * stack memory in r1. 150 * --------------------------------------------- 151 */ 152 mov r4, r0 153 mov r1, sp 154 sub r1, r0, r1 155 mov r0, sp 156 bl flush_dcache_range 157 158 /* --------------------------------------------- 159 * Calculate and store the size of the unused 160 * stack memory in r1. Calculate and store the 161 * stack base address in r0. 162 * --------------------------------------------- 163 */ 164 sub r0, r4, #PLATFORM_STACK_SIZE 165 sub r1, sp, r0 166 bl inv_dcache_range 167 168 pop {r4, pc} 169endfunc do_stack_maintenance 170 171/* ----------------------------------------------------------------------- 172 * This function is called to indicate to the power controller that it 173 * is safe to power down this cpu. It should not exit the wfi and will 174 * be released from reset upon power up. 175 * ----------------------------------------------------------------------- 176 */ 177func psci_power_down_wfi 178 dsb sy // ensure write buffer empty 179 wfi 180 bl plat_panic_handler 181endfunc psci_power_down_wfi 182