1/* 2 * Copyright (c) 2013-2014, 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 dcisw 35 .globl dccisw 36 .globl dccsw 37 .globl dccvac 38 .globl dcivac 39 .globl dccivac 40 .globl dccvau 41 .globl dczva 42 .globl flush_dcache_range 43 .globl inv_dcache_range 44 .globl dcsw_op_louis 45 .globl dcsw_op_all 46 47func dcisw 48 dc isw, x0 49 ret 50 51 52func dccisw 53 dc cisw, x0 54 ret 55 56 57func dccsw 58 dc csw, x0 59 ret 60 61 62func dccvac 63 dc cvac, x0 64 ret 65 66 67func dcivac 68 dc ivac, x0 69 ret 70 71 72func dccivac 73 dc civac, x0 74 ret 75 76 77func dccvau 78 dc cvau, x0 79 ret 80 81 82func dczva 83 dc zva, x0 84 ret 85 86 87 /* ------------------------------------------ 88 * Clean+Invalidate from base address till 89 * size. 'x0' = addr, 'x1' = size 90 * ------------------------------------------ 91 */ 92func flush_dcache_range 93 dcache_line_size x2, x3 94 add x1, x0, x1 95 sub x3, x2, #1 96 bic x0, x0, x3 97flush_loop: 98 dc civac, x0 99 add x0, x0, x2 100 cmp x0, x1 101 b.lo flush_loop 102 dsb sy 103 ret 104 105 106 /* ------------------------------------------ 107 * Invalidate from base address till 108 * size. 'x0' = addr, 'x1' = size 109 * ------------------------------------------ 110 */ 111func inv_dcache_range 112 dcache_line_size x2, x3 113 add x1, x0, x1 114 sub x3, x2, #1 115 bic x0, x0, x3 116inv_loop: 117 dc ivac, x0 118 add x0, x0, x2 119 cmp x0, x1 120 b.lo inv_loop 121 dsb sy 122 ret 123 124 125 /* ------------------------------------------ 126 * Data cache operations by set/way to the 127 * level specified 128 * ------------------------------------------ 129 * ---------------------------------- 130 * Call this func with the clidr in 131 * x0, starting cache level in x10, 132 * last cache level in x3 & cm op in 133 * x14 134 * ---------------------------------- 135 */ 136func dcsw_op 137all_start_at_level: 138 add x2, x10, x10, lsr #1 // work out 3x current cache level 139 lsr x1, x0, x2 // extract cache type bits from clidr 140 and x1, x1, #7 // mask of the bits for current cache only 141 cmp x1, #2 // see what cache we have at this level 142 b.lt skip // skip if no cache, or just i-cache 143 msr csselr_el1, x10 // select current cache level in csselr 144 isb // isb to sych the new cssr&csidr 145 mrs x1, ccsidr_el1 // read the new ccsidr 146 and x2, x1, #7 // extract the length of the cache lines 147 add x2, x2, #4 // add 4 (line length offset) 148 mov x4, #0x3ff 149 and x4, x4, x1, lsr #3 // find maximum number on the way size 150 clz w5, w4 // find bit position of way size increment 151 mov x7, #0x7fff 152 and x7, x7, x1, lsr #13 // extract max number of the index size 153loop2: 154 mov x9, x4 // create working copy of max way size 155loop3: 156 lsl x6, x9, x5 157 orr x11, x10, x6 // factor way and cache number into x11 158 lsl x6, x7, x2 159 orr x11, x11, x6 // factor index number into x11 160 mov x12, x0 161 mov x13, x30 // lr 162 mov x0, x11 163 blr x14 164 mov x0, x12 165 mov x30, x13 // lr 166 subs x9, x9, #1 // decrement the way 167 b.ge loop3 168 subs x7, x7, #1 // decrement the index 169 b.ge loop2 170skip: 171 add x10, x10, #2 // increment cache number 172 cmp x3, x10 173 b.gt all_start_at_level 174finished: 175 mov x10, #0 // swith back to cache level 0 176 msr csselr_el1, x10 // select current cache level in csselr 177 dsb sy 178 isb 179 ret 180 181 182func do_dcsw_op 183 cbz x3, exit 184 cmp x0, #DCISW 185 b.eq dc_isw 186 cmp x0, #DCCISW 187 b.eq dc_cisw 188 cmp x0, #DCCSW 189 b.eq dc_csw 190dc_isw: 191 mov x0, x9 192 adr x14, dcisw 193 b dcsw_op 194dc_cisw: 195 mov x0, x9 196 adr x14, dccisw 197 b dcsw_op 198dc_csw: 199 mov x0, x9 200 adr x14, dccsw 201 b dcsw_op 202exit: 203 ret 204 205 206func dcsw_op_louis 207 dsb sy 208 setup_dcsw_op_args x10, x3, x9, #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT 209 b do_dcsw_op 210 211 212func dcsw_op_all 213 dsb sy 214 setup_dcsw_op_args x10, x3, x9, #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT 215 b do_dcsw_op 216