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 <arch.h> 32#include <asm_macros.S> 33 34 .globl flush_dcache_range 35 .globl clean_dcache_range 36 .globl inv_dcache_range 37 .globl dcsw_op_louis 38 .globl dcsw_op_all 39 .globl dcsw_op_level1 40 .globl dcsw_op_level2 41 .globl dcsw_op_level3 42 43/* 44 * This macro can be used for implementing various data cache operations `op` 45 */ 46.macro do_dcache_maintenance_by_mva op, coproc, opc1, CRn, CRm, opc2 47 dcache_line_size r2, r3 48 add r1, r0, r1 49 sub r3, r2, #1 50 bic r0, r0, r3 51loop_\op: 52 stcopr r0, \coproc, \opc1, \CRn, \CRm, \opc2 53 add r0, r0, r2 54 cmp r0, r1 55 blo loop_\op 56 dsb sy 57 bx lr 58.endm 59 60 /* ------------------------------------------ 61 * Clean+Invalidate from base address till 62 * size. 'r0' = addr, 'r1' = size 63 * ------------------------------------------ 64 */ 65func flush_dcache_range 66 do_dcache_maintenance_by_mva cimvac, DCCIMVAC 67endfunc flush_dcache_range 68 69 /* ------------------------------------------ 70 * Clean from base address till size. 71 * 'r0' = addr, 'r1' = size 72 * ------------------------------------------ 73 */ 74func clean_dcache_range 75 do_dcache_maintenance_by_mva cmvac, DCCMVAC 76endfunc clean_dcache_range 77 78 /* ------------------------------------------ 79 * Invalidate from base address till 80 * size. 'r0' = addr, 'r1' = size 81 * ------------------------------------------ 82 */ 83func inv_dcache_range 84 do_dcache_maintenance_by_mva imvac, DCIMVAC 85endfunc inv_dcache_range 86 87 /* ---------------------------------------------------------------- 88 * Data cache operations by set/way to the level specified 89 * 90 * The main function, do_dcsw_op requires: 91 * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), 92 * as defined in arch.h 93 * r1: The cache level to begin operation from 94 * r2: clidr_el1 95 * r3: The last cache level to operate on 96 * and will carry out the operation on each data cache from level 0 97 * to the level in r3 in sequence 98 * 99 * The dcsw_op macro sets up the r2 and r3 parameters based on 100 * clidr_el1 cache information before invoking the main function 101 * ---------------------------------------------------------------- 102 */ 103 104 .macro dcsw_op shift, fw, ls 105 ldcopr r2, CLIDR 106 ubfx r3, r2, \shift, \fw 107 lsl r3, r3, \ls 108 mov r1, #0 109 b do_dcsw_op 110 .endm 111 112func do_dcsw_op 113 push {r4-r12,lr} 114 adr r11, dcsw_loop_table // compute cache op based on the operation type 115 add r6, r11, r0, lsl #3 // cache op is 2x32-bit instructions 116loop1: 117 add r10, r1, r1, LSR #1 // Work out 3x current cache level 118 mov r12, r2, LSR r10 // extract cache type bits from clidr 119 and r12, r12, #7 // mask the bits for current cache only 120 cmp r12, #2 // see what cache we have at this level 121 blt level_done // no cache or only instruction cache at this level 122 123 stcopr r1, CSSELR // select current cache level in csselr 124 isb // isb to sych the new cssr&csidr 125 ldcopr r12, CCSIDR // read the new ccsidr 126 and r10, r12, #7 // extract the length of the cache lines 127 add r10, r10, #4 // add 4 (r10 = line length offset) 128 ubfx r4, r12, #3, #10 // r4 = maximum way number (right aligned) 129 clz r5, r4 // r5 = the bit position of the way size increment 130 mov r9, r4 // r9 working copy of the aligned max way number 131 132loop2: 133 ubfx r7, r12, #13, #15 // r7 = max set number (right aligned) 134 135loop3: 136 orr r0, r1, r9, LSL r5 // factor in the way number and cache level into r0 137 orr r0, r0, r7, LSL r10 // factor in the set number 138 139 blx r6 140 subs r7, r7, #1 // decrement the set number 141 bge loop3 142 subs r9, r9, #1 // decrement the way number 143 bge loop2 144level_done: 145 add r1, r1, #2 // increment the cache number 146 cmp r3, r1 147 dsb sy // ensure completion of previous cache maintenance instruction 148 bgt loop1 149 150 mov r6, #0 151 stcopr r6, CSSELR //select cache level 0 in csselr 152 dsb sy 153 isb 154 pop {r4-r12,pc} 155 156dcsw_loop_table: 157 stcopr r0, DCISW 158 bx lr 159 stcopr r0, DCCISW 160 bx lr 161 stcopr r0, DCCSW 162 bx lr 163 164endfunc do_dcsw_op 165 166 /* --------------------------------------------------------------- 167 * Data cache operations by set/way till PoU. 168 * 169 * The function requires : 170 * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), 171 * as defined in arch.h 172 * --------------------------------------------------------------- 173 */ 174func dcsw_op_louis 175 dcsw_op #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT 176endfunc dcsw_op_louis 177 178 /* --------------------------------------------------------------- 179 * Data cache operations by set/way till PoC. 180 * 181 * The function requires : 182 * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), 183 * as defined in arch.h 184 * --------------------------------------------------------------- 185 */ 186func dcsw_op_all 187 dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT 188endfunc dcsw_op_all 189 190 191 /* --------------------------------------------------------------- 192 * Helper macro for data cache operations by set/way for the 193 * level specified 194 * --------------------------------------------------------------- 195 */ 196 .macro dcsw_op_level level 197 ldcopr r2, CLIDR 198 mov r3, \level 199 sub r1, r3, #2 200 b do_dcsw_op 201 .endm 202 203 /* --------------------------------------------------------------- 204 * Data cache operations by set/way for level 1 cache 205 * 206 * The main function, do_dcsw_op requires: 207 * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), 208 * as defined in arch.h 209 * --------------------------------------------------------------- 210 */ 211func dcsw_op_level1 212 dcsw_op_level #(1 << LEVEL_SHIFT) 213endfunc dcsw_op_level1 214 215 /* --------------------------------------------------------------- 216 * Data cache operations by set/way for level 2 cache 217 * 218 * The main function, do_dcsw_op requires: 219 * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), 220 * as defined in arch.h 221 * --------------------------------------------------------------- 222 */ 223func dcsw_op_level2 224 dcsw_op_level #(2 << LEVEL_SHIFT) 225endfunc dcsw_op_level2 226 227 /* --------------------------------------------------------------- 228 * Data cache operations by set/way for level 3 cache 229 * 230 * The main function, do_dcsw_op requires: 231 * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), 232 * as defined in arch.h 233 * --------------------------------------------------------------- 234 */ 235func dcsw_op_level3 236 dcsw_op_level #(3 << LEVEL_SHIFT) 237endfunc dcsw_op_level3 238