1f24307deSSoby Mathew/* 2*d0ec1cc4Sjohpow01 * Copyright (c) 2016-2021, Arm Limited and Contributors. All rights reserved. 3f24307deSSoby Mathew * 482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 5f24307deSSoby Mathew */ 6f24307deSSoby Mathew 7f24307deSSoby Mathew#include <arch.h> 8f24307deSSoby Mathew#include <asm_macros.S> 9f24307deSSoby Mathew 10f24307deSSoby Mathew .globl flush_dcache_range 11f24307deSSoby Mathew .globl clean_dcache_range 12f24307deSSoby Mathew .globl inv_dcache_range 13f24307deSSoby Mathew .globl dcsw_op_louis 14f24307deSSoby Mathew .globl dcsw_op_all 15f24307deSSoby Mathew .globl dcsw_op_level1 16f24307deSSoby Mathew .globl dcsw_op_level2 17f24307deSSoby Mathew .globl dcsw_op_level3 18f24307deSSoby Mathew 19f24307deSSoby Mathew/* 20f24307deSSoby Mathew * This macro can be used for implementing various data cache operations `op` 21f24307deSSoby Mathew */ 22f24307deSSoby Mathew.macro do_dcache_maintenance_by_mva op, coproc, opc1, CRn, CRm, opc2 233ec5204cSSoby Mathew /* Exit early if size is zero */ 243ec5204cSSoby Mathew cmp r1, #0 253ec5204cSSoby Mathew beq exit_loop_\op 26f24307deSSoby Mathew dcache_line_size r2, r3 27f24307deSSoby Mathew add r1, r0, r1 28f24307deSSoby Mathew sub r3, r2, #1 29f24307deSSoby Mathew bic r0, r0, r3 30f24307deSSoby Mathewloop_\op: 31f24307deSSoby Mathew stcopr r0, \coproc, \opc1, \CRn, \CRm, \opc2 32f24307deSSoby Mathew add r0, r0, r2 33f24307deSSoby Mathew cmp r0, r1 34f24307deSSoby Mathew blo loop_\op 35f24307deSSoby Mathew dsb sy 363ec5204cSSoby Mathewexit_loop_\op: 37f24307deSSoby Mathew bx lr 38f24307deSSoby Mathew.endm 39f24307deSSoby Mathew 40f24307deSSoby Mathew /* ------------------------------------------ 41f24307deSSoby Mathew * Clean+Invalidate from base address till 42f24307deSSoby Mathew * size. 'r0' = addr, 'r1' = size 43f24307deSSoby Mathew * ------------------------------------------ 44f24307deSSoby Mathew */ 45f24307deSSoby Mathewfunc flush_dcache_range 46f24307deSSoby Mathew do_dcache_maintenance_by_mva cimvac, DCCIMVAC 47f24307deSSoby Mathewendfunc flush_dcache_range 48f24307deSSoby Mathew 49f24307deSSoby Mathew /* ------------------------------------------ 50f24307deSSoby Mathew * Clean from base address till size. 51f24307deSSoby Mathew * 'r0' = addr, 'r1' = size 52f24307deSSoby Mathew * ------------------------------------------ 53f24307deSSoby Mathew */ 54f24307deSSoby Mathewfunc clean_dcache_range 55f24307deSSoby Mathew do_dcache_maintenance_by_mva cmvac, DCCMVAC 56f24307deSSoby Mathewendfunc clean_dcache_range 57f24307deSSoby Mathew 58f24307deSSoby Mathew /* ------------------------------------------ 59f24307deSSoby Mathew * Invalidate from base address till 60f24307deSSoby Mathew * size. 'r0' = addr, 'r1' = size 61f24307deSSoby Mathew * ------------------------------------------ 62f24307deSSoby Mathew */ 63f24307deSSoby Mathewfunc inv_dcache_range 64f24307deSSoby Mathew do_dcache_maintenance_by_mva imvac, DCIMVAC 65f24307deSSoby Mathewendfunc inv_dcache_range 66f24307deSSoby Mathew 67f24307deSSoby Mathew /* ---------------------------------------------------------------- 68f24307deSSoby Mathew * Data cache operations by set/way to the level specified 69f24307deSSoby Mathew * 70f24307deSSoby Mathew * The main function, do_dcsw_op requires: 71f24307deSSoby Mathew * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), 72f24307deSSoby Mathew * as defined in arch.h 73f24307deSSoby Mathew * r1: The cache level to begin operation from 74f24307deSSoby Mathew * r2: clidr_el1 75f24307deSSoby Mathew * r3: The last cache level to operate on 76f24307deSSoby Mathew * and will carry out the operation on each data cache from level 0 77f24307deSSoby Mathew * to the level in r3 in sequence 78f24307deSSoby Mathew * 79f24307deSSoby Mathew * The dcsw_op macro sets up the r2 and r3 parameters based on 80f24307deSSoby Mathew * clidr_el1 cache information before invoking the main function 81f24307deSSoby Mathew * ---------------------------------------------------------------- 82f24307deSSoby Mathew */ 83f24307deSSoby Mathew 84f24307deSSoby Mathew .macro dcsw_op shift, fw, ls 85f24307deSSoby Mathew ldcopr r2, CLIDR 86f24307deSSoby Mathew ubfx r3, r2, \shift, \fw 87f24307deSSoby Mathew lsl r3, r3, \ls 88f24307deSSoby Mathew mov r1, #0 89f24307deSSoby Mathew b do_dcsw_op 90f24307deSSoby Mathew .endm 91f24307deSSoby Mathew 92f24307deSSoby Mathewfunc do_dcsw_op 93f24307deSSoby Mathew push {r4-r12, lr} 94*d0ec1cc4Sjohpow01 ldcopr r8, ID_MMFR4 // stash FEAT_CCIDX identifier in r8 95*d0ec1cc4Sjohpow01 ubfx r8, r8, #ID_MMFR4_CCIDX_SHIFT, #ID_MMFR4_CCIDX_LENGTH 96f24307deSSoby Mathew adr r11, dcsw_loop_table // compute cache op based on the operation type 97f24307deSSoby Mathew add r6, r11, r0, lsl #3 // cache op is 2x32-bit instructions 98f24307deSSoby Mathewloop1: 99f24307deSSoby Mathew add r10, r1, r1, LSR #1 // Work out 3x current cache level 100f24307deSSoby Mathew mov r12, r2, LSR r10 // extract cache type bits from clidr 101f24307deSSoby Mathew and r12, r12, #7 // mask the bits for current cache only 102f24307deSSoby Mathew cmp r12, #2 // see what cache we have at this level 103355a5d03SDouglas Raillard blo level_done // no cache or only instruction cache at this level 104f24307deSSoby Mathew 105f24307deSSoby Mathew stcopr r1, CSSELR // select current cache level in csselr 106f24307deSSoby Mathew isb // isb to sych the new cssr&csidr 107f24307deSSoby Mathew ldcopr r12, CCSIDR // read the new ccsidr 108f24307deSSoby Mathew and r10, r12, #7 // extract the length of the cache lines 109f24307deSSoby Mathew add r10, r10, #4 // add 4 (r10 = line length offset) 110*d0ec1cc4Sjohpow01 111*d0ec1cc4Sjohpow01 cmp r8, #0 // check for FEAT_CCIDX for Associativity 112*d0ec1cc4Sjohpow01 beq 1f 113*d0ec1cc4Sjohpow01 ubfx r4, r12, #3, #21 // r4 = associativity CCSIDR[23:3] 114*d0ec1cc4Sjohpow01 b 2f 115*d0ec1cc4Sjohpow011: 116*d0ec1cc4Sjohpow01 ubfx r4, r12, #3, #10 // r4 = associativity CCSIDR[12:3] 117*d0ec1cc4Sjohpow012: 118f24307deSSoby Mathew clz r5, r4 // r5 = the bit position of the way size increment 119f24307deSSoby Mathew mov r9, r4 // r9 working copy of the aligned max way number 120f24307deSSoby Mathew 121f24307deSSoby Mathewloop2: 122*d0ec1cc4Sjohpow01 cmp r8, #0 // check for FEAT_CCIDX for NumSets 123*d0ec1cc4Sjohpow01 beq 3f 124*d0ec1cc4Sjohpow01 ldcopr r12, CCSIDR2 // FEAT_CCIDX numsets is in CCSIDR2 125*d0ec1cc4Sjohpow01 ubfx r7, r12, #0, #24 // r7 = numsets CCSIDR2[23:0] 126*d0ec1cc4Sjohpow01 b loop3 127*d0ec1cc4Sjohpow013: 128*d0ec1cc4Sjohpow01 ubfx r7, r12, #13, #15 // r7 = numsets CCSIDR[27:13] 129f24307deSSoby Mathewloop3: 130f24307deSSoby Mathew orr r0, r1, r9, LSL r5 // factor in the way number and cache level into r0 131f24307deSSoby Mathew orr r0, r0, r7, LSL r10 // factor in the set number 132f24307deSSoby Mathew 133f24307deSSoby Mathew blx r6 134f24307deSSoby Mathew subs r7, r7, #1 // decrement the set number 135355a5d03SDouglas Raillard bhs loop3 136f24307deSSoby Mathew subs r9, r9, #1 // decrement the way number 137355a5d03SDouglas Raillard bhs loop2 138f24307deSSoby Mathewlevel_done: 139f24307deSSoby Mathew add r1, r1, #2 // increment the cache number 140f24307deSSoby Mathew cmp r3, r1 141f999facaSJoel Hutton // Ensure completion of previous cache maintenance instruction. Note 142f999facaSJoel Hutton // this also mitigates erratum 814220 on Cortex-A7 143f999facaSJoel Hutton dsb sy 144355a5d03SDouglas Raillard bhi loop1 145f24307deSSoby Mathew 146f24307deSSoby Mathew mov r6, #0 147f24307deSSoby Mathew stcopr r6, CSSELR //select cache level 0 in csselr 148f24307deSSoby Mathew dsb sy 149f24307deSSoby Mathew isb 150f24307deSSoby Mathew pop {r4-r12, pc} 151f24307deSSoby Mathew 152f24307deSSoby Mathewdcsw_loop_table: 153f24307deSSoby Mathew stcopr r0, DCISW 154f24307deSSoby Mathew bx lr 155f24307deSSoby Mathew stcopr r0, DCCISW 156f24307deSSoby Mathew bx lr 157f24307deSSoby Mathew stcopr r0, DCCSW 158f24307deSSoby Mathew bx lr 159f24307deSSoby Mathew 160f24307deSSoby Mathewendfunc do_dcsw_op 161f24307deSSoby Mathew 162f24307deSSoby Mathew /* --------------------------------------------------------------- 163f24307deSSoby Mathew * Data cache operations by set/way till PoU. 164f24307deSSoby Mathew * 165f24307deSSoby Mathew * The function requires : 166f24307deSSoby Mathew * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), 167f24307deSSoby Mathew * as defined in arch.h 168f24307deSSoby Mathew * --------------------------------------------------------------- 169f24307deSSoby Mathew */ 170f24307deSSoby Mathewfunc dcsw_op_louis 171f24307deSSoby Mathew dcsw_op #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT 172f24307deSSoby Mathewendfunc dcsw_op_louis 173f24307deSSoby Mathew 174f24307deSSoby Mathew /* --------------------------------------------------------------- 175f24307deSSoby Mathew * Data cache operations by set/way till PoC. 176f24307deSSoby Mathew * 177f24307deSSoby Mathew * The function requires : 178f24307deSSoby Mathew * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), 179f24307deSSoby Mathew * as defined in arch.h 180f24307deSSoby Mathew * --------------------------------------------------------------- 181f24307deSSoby Mathew */ 182f24307deSSoby Mathewfunc dcsw_op_all 183f24307deSSoby Mathew dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT 184f24307deSSoby Mathewendfunc dcsw_op_all 185f24307deSSoby Mathew 186f24307deSSoby Mathew 187f24307deSSoby Mathew /* --------------------------------------------------------------- 188f24307deSSoby Mathew * Helper macro for data cache operations by set/way for the 189f24307deSSoby Mathew * level specified 190f24307deSSoby Mathew * --------------------------------------------------------------- 191f24307deSSoby Mathew */ 192f24307deSSoby Mathew .macro dcsw_op_level level 193f24307deSSoby Mathew ldcopr r2, CLIDR 194f24307deSSoby Mathew mov r3, \level 195f24307deSSoby Mathew sub r1, r3, #2 196f24307deSSoby Mathew b do_dcsw_op 197f24307deSSoby Mathew .endm 198f24307deSSoby Mathew 199f24307deSSoby Mathew /* --------------------------------------------------------------- 200f24307deSSoby Mathew * Data cache operations by set/way for level 1 cache 201f24307deSSoby Mathew * 202f24307deSSoby Mathew * The main function, do_dcsw_op requires: 203f24307deSSoby Mathew * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), 204f24307deSSoby Mathew * as defined in arch.h 205f24307deSSoby Mathew * --------------------------------------------------------------- 206f24307deSSoby Mathew */ 207f24307deSSoby Mathewfunc dcsw_op_level1 208f24307deSSoby Mathew dcsw_op_level #(1 << LEVEL_SHIFT) 209f24307deSSoby Mathewendfunc dcsw_op_level1 210f24307deSSoby Mathew 211f24307deSSoby Mathew /* --------------------------------------------------------------- 212f24307deSSoby Mathew * Data cache operations by set/way for level 2 cache 213f24307deSSoby Mathew * 214f24307deSSoby Mathew * The main function, do_dcsw_op requires: 215f24307deSSoby Mathew * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), 216f24307deSSoby Mathew * as defined in arch.h 217f24307deSSoby Mathew * --------------------------------------------------------------- 218f24307deSSoby Mathew */ 219f24307deSSoby Mathewfunc dcsw_op_level2 220f24307deSSoby Mathew dcsw_op_level #(2 << LEVEL_SHIFT) 221f24307deSSoby Mathewendfunc dcsw_op_level2 222f24307deSSoby Mathew 223f24307deSSoby Mathew /* --------------------------------------------------------------- 224f24307deSSoby Mathew * Data cache operations by set/way for level 3 cache 225f24307deSSoby Mathew * 226f24307deSSoby Mathew * The main function, do_dcsw_op requires: 227f24307deSSoby Mathew * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), 228f24307deSSoby Mathew * as defined in arch.h 229f24307deSSoby Mathew * --------------------------------------------------------------- 230f24307deSSoby Mathew */ 231f24307deSSoby Mathewfunc dcsw_op_level3 232f24307deSSoby Mathew dcsw_op_level #(3 << LEVEL_SHIFT) 233f24307deSSoby Mathewendfunc dcsw_op_level3 234