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