1*54fd6939SJiyong Park/* 2*54fd6939SJiyong Park * Copyright (c) 2013-2020, 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 23*54fd6939SJiyong Park /* Exit early if size is zero */ 24*54fd6939SJiyong Park cbz x1, exit_loop_\op 25*54fd6939SJiyong Park dcache_line_size x2, x3 26*54fd6939SJiyong Park add x1, x0, x1 27*54fd6939SJiyong Park sub x3, x2, #1 28*54fd6939SJiyong Park bic x0, x0, x3 29*54fd6939SJiyong Parkloop_\op: 30*54fd6939SJiyong Park dc \op, x0 31*54fd6939SJiyong Park add x0, x0, x2 32*54fd6939SJiyong Park cmp x0, x1 33*54fd6939SJiyong Park b.lo loop_\op 34*54fd6939SJiyong Park dsb sy 35*54fd6939SJiyong Parkexit_loop_\op: 36*54fd6939SJiyong Park ret 37*54fd6939SJiyong Park.endm 38*54fd6939SJiyong Park /* ------------------------------------------ 39*54fd6939SJiyong Park * Clean+Invalidate from base address till 40*54fd6939SJiyong Park * size. 'x0' = addr, 'x1' = size 41*54fd6939SJiyong Park * ------------------------------------------ 42*54fd6939SJiyong Park */ 43*54fd6939SJiyong Parkfunc flush_dcache_range 44*54fd6939SJiyong Park do_dcache_maintenance_by_mva civac 45*54fd6939SJiyong Parkendfunc flush_dcache_range 46*54fd6939SJiyong Park 47*54fd6939SJiyong Park /* ------------------------------------------ 48*54fd6939SJiyong Park * Clean from base address till size. 49*54fd6939SJiyong Park * 'x0' = addr, 'x1' = size 50*54fd6939SJiyong Park * ------------------------------------------ 51*54fd6939SJiyong Park */ 52*54fd6939SJiyong Parkfunc clean_dcache_range 53*54fd6939SJiyong Park do_dcache_maintenance_by_mva cvac 54*54fd6939SJiyong Parkendfunc clean_dcache_range 55*54fd6939SJiyong Park 56*54fd6939SJiyong Park /* ------------------------------------------ 57*54fd6939SJiyong Park * Invalidate from base address till 58*54fd6939SJiyong Park * size. 'x0' = addr, 'x1' = size 59*54fd6939SJiyong Park * ------------------------------------------ 60*54fd6939SJiyong Park */ 61*54fd6939SJiyong Parkfunc inv_dcache_range 62*54fd6939SJiyong Park do_dcache_maintenance_by_mva ivac 63*54fd6939SJiyong Parkendfunc inv_dcache_range 64*54fd6939SJiyong Park 65*54fd6939SJiyong Park 66*54fd6939SJiyong Park /* --------------------------------------------------------------- 67*54fd6939SJiyong Park * Data cache operations by set/way to the level specified 68*54fd6939SJiyong Park * 69*54fd6939SJiyong Park * The main function, do_dcsw_op requires: 70*54fd6939SJiyong Park * x0: The operation type (0-2), as defined in arch.h 71*54fd6939SJiyong Park * x3: The last cache level to operate on 72*54fd6939SJiyong Park * x9: clidr_el1 73*54fd6939SJiyong Park * x10: The cache level to begin operation from 74*54fd6939SJiyong Park * and will carry out the operation on each data cache from level 0 75*54fd6939SJiyong Park * to the level in x3 in sequence 76*54fd6939SJiyong Park * 77*54fd6939SJiyong Park * The dcsw_op macro sets up the x3 and x9 parameters based on 78*54fd6939SJiyong Park * clidr_el1 cache information before invoking the main function 79*54fd6939SJiyong Park * --------------------------------------------------------------- 80*54fd6939SJiyong Park */ 81*54fd6939SJiyong Park 82*54fd6939SJiyong Park .macro dcsw_op shift, fw, ls 83*54fd6939SJiyong Park mrs x9, clidr_el1 84*54fd6939SJiyong Park ubfx x3, x9, \shift, \fw 85*54fd6939SJiyong Park lsl x3, x3, \ls 86*54fd6939SJiyong Park mov x10, xzr 87*54fd6939SJiyong Park b do_dcsw_op 88*54fd6939SJiyong Park .endm 89*54fd6939SJiyong Park 90*54fd6939SJiyong Parkfunc do_dcsw_op 91*54fd6939SJiyong Park cbz x3, exit 92*54fd6939SJiyong Park adr x14, dcsw_loop_table // compute inner loop address 93*54fd6939SJiyong Park add x14, x14, x0, lsl #5 // inner loop is 8x32-bit instructions 94*54fd6939SJiyong Park#if ENABLE_BTI 95*54fd6939SJiyong Park add x14, x14, x0, lsl #2 // inner loop is + "bti j" instruction 96*54fd6939SJiyong Park#endif 97*54fd6939SJiyong Park mov x0, x9 98*54fd6939SJiyong Park mov w8, #1 99*54fd6939SJiyong Parkloop1: 100*54fd6939SJiyong Park add x2, x10, x10, lsr #1 // work out 3x current cache level 101*54fd6939SJiyong Park lsr x1, x0, x2 // extract cache type bits from clidr 102*54fd6939SJiyong Park and x1, x1, #7 // mask the bits for current cache only 103*54fd6939SJiyong Park cmp x1, #2 // see what cache we have at this level 104*54fd6939SJiyong Park b.lo level_done // nothing to do if no cache or icache 105*54fd6939SJiyong Park 106*54fd6939SJiyong Park msr csselr_el1, x10 // select current cache level in csselr 107*54fd6939SJiyong Park isb // isb to sych the new cssr&csidr 108*54fd6939SJiyong Park mrs x1, ccsidr_el1 // read the new ccsidr 109*54fd6939SJiyong Park and x2, x1, #7 // extract the length of the cache lines 110*54fd6939SJiyong Park add x2, x2, #4 // add 4 (line length offset) 111*54fd6939SJiyong Park ubfx x4, x1, #3, #10 // maximum way number 112*54fd6939SJiyong Park clz w5, w4 // bit position of way size increment 113*54fd6939SJiyong Park lsl w9, w4, w5 // w9 = aligned max way number 114*54fd6939SJiyong Park lsl w16, w8, w5 // w16 = way number loop decrement 115*54fd6939SJiyong Park orr w9, w10, w9 // w9 = combine way and cache number 116*54fd6939SJiyong Park ubfx w6, w1, #13, #15 // w6 = max set number 117*54fd6939SJiyong Park lsl w17, w8, w2 // w17 = set number loop decrement 118*54fd6939SJiyong Park dsb sy // barrier before we start this level 119*54fd6939SJiyong Park br x14 // jump to DC operation specific loop 120*54fd6939SJiyong Park 121*54fd6939SJiyong Park .macro dcsw_loop _op 122*54fd6939SJiyong Park#if ENABLE_BTI 123*54fd6939SJiyong Park bti j 124*54fd6939SJiyong Park#endif 125*54fd6939SJiyong Parkloop2_\_op: 126*54fd6939SJiyong Park lsl w7, w6, w2 // w7 = aligned max set number 127*54fd6939SJiyong Park 128*54fd6939SJiyong Parkloop3_\_op: 129*54fd6939SJiyong Park orr w11, w9, w7 // combine cache, way and set number 130*54fd6939SJiyong Park dc \_op, x11 131*54fd6939SJiyong Park subs w7, w7, w17 // decrement set number 132*54fd6939SJiyong Park b.hs loop3_\_op 133*54fd6939SJiyong Park 134*54fd6939SJiyong Park subs x9, x9, x16 // decrement way number 135*54fd6939SJiyong Park b.hs loop2_\_op 136*54fd6939SJiyong Park 137*54fd6939SJiyong Park b level_done 138*54fd6939SJiyong Park .endm 139*54fd6939SJiyong Park 140*54fd6939SJiyong Parklevel_done: 141*54fd6939SJiyong Park add x10, x10, #2 // increment cache number 142*54fd6939SJiyong Park cmp x3, x10 143*54fd6939SJiyong Park b.hi loop1 144*54fd6939SJiyong Park msr csselr_el1, xzr // select cache level 0 in csselr 145*54fd6939SJiyong Park dsb sy // barrier to complete final cache operation 146*54fd6939SJiyong Park isb 147*54fd6939SJiyong Parkexit: 148*54fd6939SJiyong Park ret 149*54fd6939SJiyong Parkendfunc do_dcsw_op 150*54fd6939SJiyong Park 151*54fd6939SJiyong Parkdcsw_loop_table: 152*54fd6939SJiyong Park dcsw_loop isw 153*54fd6939SJiyong Park dcsw_loop cisw 154*54fd6939SJiyong Park dcsw_loop csw 155*54fd6939SJiyong Park 156*54fd6939SJiyong Park 157*54fd6939SJiyong Parkfunc dcsw_op_louis 158*54fd6939SJiyong Park dcsw_op #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT 159*54fd6939SJiyong Parkendfunc dcsw_op_louis 160*54fd6939SJiyong Park 161*54fd6939SJiyong Park 162*54fd6939SJiyong Parkfunc dcsw_op_all 163*54fd6939SJiyong Park dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT 164*54fd6939SJiyong Parkendfunc dcsw_op_all 165*54fd6939SJiyong Park 166*54fd6939SJiyong Park /* --------------------------------------------------------------- 167*54fd6939SJiyong Park * Helper macro for data cache operations by set/way for the 168*54fd6939SJiyong Park * level specified 169*54fd6939SJiyong Park * --------------------------------------------------------------- 170*54fd6939SJiyong Park */ 171*54fd6939SJiyong Park .macro dcsw_op_level level 172*54fd6939SJiyong Park mrs x9, clidr_el1 173*54fd6939SJiyong Park mov x3, \level 174*54fd6939SJiyong Park sub x10, x3, #2 175*54fd6939SJiyong Park b do_dcsw_op 176*54fd6939SJiyong Park .endm 177*54fd6939SJiyong Park 178*54fd6939SJiyong Park /* --------------------------------------------------------------- 179*54fd6939SJiyong Park * Data cache operations by set/way for level 1 cache 180*54fd6939SJiyong Park * 181*54fd6939SJiyong Park * The main function, do_dcsw_op requires: 182*54fd6939SJiyong Park * x0: The operation type (0-2), as defined in arch.h 183*54fd6939SJiyong Park * --------------------------------------------------------------- 184*54fd6939SJiyong Park */ 185*54fd6939SJiyong Parkfunc dcsw_op_level1 186*54fd6939SJiyong Park dcsw_op_level #(1 << LEVEL_SHIFT) 187*54fd6939SJiyong Parkendfunc dcsw_op_level1 188*54fd6939SJiyong Park 189*54fd6939SJiyong Park /* --------------------------------------------------------------- 190*54fd6939SJiyong Park * Data cache operations by set/way for level 2 cache 191*54fd6939SJiyong Park * 192*54fd6939SJiyong Park * The main function, do_dcsw_op requires: 193*54fd6939SJiyong Park * x0: The operation type (0-2), as defined in arch.h 194*54fd6939SJiyong Park * --------------------------------------------------------------- 195*54fd6939SJiyong Park */ 196*54fd6939SJiyong Parkfunc dcsw_op_level2 197*54fd6939SJiyong Park dcsw_op_level #(2 << LEVEL_SHIFT) 198*54fd6939SJiyong Parkendfunc dcsw_op_level2 199*54fd6939SJiyong Park 200*54fd6939SJiyong Park /* --------------------------------------------------------------- 201*54fd6939SJiyong Park * Data cache operations by set/way for level 3 cache 202*54fd6939SJiyong Park * 203*54fd6939SJiyong Park * The main function, do_dcsw_op requires: 204*54fd6939SJiyong Park * x0: The operation type (0-2), as defined in arch.h 205*54fd6939SJiyong Park * --------------------------------------------------------------- 206*54fd6939SJiyong Park */ 207*54fd6939SJiyong Parkfunc dcsw_op_level3 208*54fd6939SJiyong Park dcsw_op_level #(3 << LEVEL_SHIFT) 209*54fd6939SJiyong Parkendfunc dcsw_op_level3 210