cpu_asm-v6.S revision 276394
1276336Sian/*- 2276336Sian * Copyright 2014 Svatopluk Kraus <onwahe@gmail.com> 3276336Sian * Copyright 2014 Michal Meloun <meloun@miracle.cz> 4276336Sian * All rights reserved. 5276336Sian * 6276336Sian * Redistribution and use in source and binary forms, with or without 7276336Sian * modification, are permitted provided that the following conditions 8276336Sian * are met: 9276336Sian * 1. Redistributions of source code must retain the above copyright 10276336Sian * notice, this list of conditions and the following disclaimer. 11276336Sian * 2. Redistributions in binary form must reproduce the above copyright 12276336Sian * notice, this list of conditions and the following disclaimer in the 13276336Sian * documentation and/or other materials provided with the distribution. 14276336Sian * 15276336Sian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16276336Sian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17276336Sian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18276336Sian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19276336Sian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20276336Sian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21276336Sian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22276336Sian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23276336Sian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24276336Sian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25276336Sian * SUCH DAMAGE. 26276336Sian * 27276336Sian * $FreeBSD: head/sys/arm/arm/cpu_asm-v6.S 276394 2014-12-30 02:56:31Z ian $ 28276336Sian */ 29276336Sian 30276336Sian#include <machine/acle-compat.h> 31276336Sian#include <machine/asm.h> 32276336Sian#include <machine/asmacros.h> 33276336Sian#include <machine/armreg.h> 34276336Sian#include <machine/sysreg.h> 35276336Sian 36276336Sian/* 37276336Sian * Define cache functions used by startup code, which counts on the fact that 38276350Sian * only r0-r3,r12 (ip) are modified and no stack space is used. These functions 39276350Sian * must be called with interrupts disabled. Moreover, these work only with 40276350Sian * caches integrated to CPU (accessible via CP15); systems with an external L2 41276350Sian * cache controller such as a PL310 need separate calls to that device driver 42276350Sian * to affect L2 caches. This is not a factor during early kernel startup, as 43276350Sian * any external L2 cache controller has not been enabled yet. 44276336Sian */ 45276336Sian 46276336Sian/* Invalidate D cache to PoC. (aka all cache levels)*/ 47276350SianASENTRY_NP(dcache_inv_poc_all) 48276394Sian#if __ARM_ARCH == 6 49276394Sian mcr CP15_DCIALL 50276394Sian DSB 51276394Sian bx lr 52276394Sian#else 53276336Sian mrc CP15_CLIDR(r0) 54276336Sian ands r0, r0, #0x07000000 55276394Sian mov r0, r0, lsr #23 /* Get LoC 'naturally' aligned for */ 56276394Sian beq 4f /* use in the CSSELR register below */ 57276336Sian 58276394Sian1: sub r0, #2 59276394Sian mcr CP15_CSSELR(r0) /* set cache level */ 60276336Sian isb 61276336Sian mrc CP15_CCSIDR(r0) /* read CCSIDR */ 62276336Sian 63276336Sian ubfx r2, r0, #13, #15 /* get num sets - 1 from CCSIDR */ 64276336Sian ubfx r3, r0, #3, #10 /* get num ways - 1 from CCSIDR */ 65276336Sian clz r1, r3 /* number of bits to MSB of way */ 66276336Sian lsl r3, r3, r1 /* shift into position */ 67276336Sian mov ip, #1 68276336Sian lsl ip, ip, r1 /* ip now contains the way decr */ 69276336Sian 70276336Sian ubfx r0, r0, #0, #3 /* get linesize from CCSIDR */ 71276336Sian add r0, r0, #4 /* apply bias */ 72276336Sian lsl r2, r2, r0 /* shift sets by log2(linesize) */ 73276336Sian add r3, r3, r2 /* merge numsets - 1 with numways - 1 */ 74276336Sian sub ip, ip, r2 /* subtract numsets - 1 from way decr */ 75276336Sian mov r1, #1 76276336Sian lsl r1, r1, r0 /* r1 now contains the set decr */ 77276336Sian mov r2, ip /* r2 now contains set way decr */ 78276336Sian 79276336Sian /* r3 = ways/sets, r2 = way decr, r1 = set decr, r0 and ip are free */ 80276336Sian2: mcr CP15_DCISW(r3) /* invalidate line */ 81276336Sian movs r0, r3 /* get current way/set */ 82276336Sian beq 3f /* at 0 means we are done */ 83276336Sian movs r0, r0, lsl #10 /* clear way bits leaving only set bits*/ 84276336Sian subne r3, r3, r1 /* non-zero?, decrement set */ 85276336Sian subeq r3, r3, r2 /* zero?, decrement way and restore set count */ 86276336Sian b 2b 87276336Sian 88276336Sian3: 89276336Sian mrc CP15_CSSELR(r0) /* get cache level */ 90276394Sian teq r0, #0 91276394Sian bne 1b 92276336Sian 93276336Sian4: dsb /* wait for stores to finish */ 94276336Sian mov r0, #0 95276336Sian mcr CP15_CSSELR(r0) 96276336Sian isb 97276336Sian bx lr 98276394Sian#endif /* __ARM_ARCH == 6 */ 99276336SianEND(dcache_inv_poc_all) 100276336Sian 101276336Sian/* Invalidate D cache to PoU. (aka L1 cache only)*/ 102276350SianASENTRY_NP(dcache_inv_pou_all) 103276394Sian#if __ARM_ARCH == 6 104276394Sian mcr CP15_DCIALL 105276394Sian DSB 106276394Sian bx lr 107276394Sian#else 108276336Sian mrc CP15_CLIDR(r0) 109276336Sian ands r0, r0, #0x07000000 110276336Sian mov r0, r0, lsr #26 /* Get LoUU (naturally aligned) */ 111276336Sian beq 4f 112276336Sian 113276394Sian1: sub r0, #2 114276394Sian mcr CP15_CSSELR(r0) /* set cache level */ 115276336Sian isb 116276336Sian mrc CP15_CCSIDR(r0) /* read CCSIDR */ 117276336Sian 118276336Sian ubfx r2, r0, #13, #15 /* get num sets - 1 from CCSIDR */ 119276336Sian ubfx r3, r0, #3, #10 /* get num ways - 1 from CCSIDR */ 120276336Sian clz r1, r3 /* number of bits to MSB of way */ 121276336Sian lsl r3, r3, r1 /* shift into position */ 122276336Sian mov ip, #1 123276336Sian lsl ip, ip, r1 /* ip now contains the way decr */ 124276336Sian 125276336Sian ubfx r0, r0, #0, #3 /* get linesize from CCSIDR */ 126276336Sian add r0, r0, #4 /* apply bias */ 127276336Sian lsl r2, r2, r0 /* shift sets by log2(linesize) */ 128276336Sian add r3, r3, r2 /* merge numsets - 1 with numways - 1 */ 129276336Sian sub ip, ip, r2 /* subtract numsets - 1 from way decr */ 130276336Sian mov r1, #1 131276336Sian lsl r1, r1, r0 /* r1 now contains the set decr */ 132276336Sian mov r2, ip /* r2 now contains set way decr */ 133276336Sian 134276336Sian /* r3 = ways/sets, r2 = way decr, r1 = set decr, r0 and ip are free */ 135276394Sian2: mcr CP15_DCISW(r3) /* invalidate line */ 136276336Sian movs r0, r3 /* get current way/set */ 137276336Sian beq 3f /* at 0 means we are done */ 138276336Sian movs r0, r0, lsl #10 /* clear way bits leaving only set bits*/ 139276336Sian subne r3, r3, r1 /* non-zero?, decrement set */ 140276336Sian subeq r3, r3, r2 /* zero?, decrement way and restore set count */ 141276336Sian b 2b 142276336Sian 143276336Sian3: 144276336Sian mrc CP15_CSSELR(r0) /* get cache level */ 145276394Sian teq r0, #0 146276394Sian bne 1b 147276336Sian 148276336Sian4: dsb /* wait for stores to finish */ 149276336Sian mov r0, #0 150276336Sian mcr CP15_CSSELR(r0) 151276336Sian bx lr 152276394Sian#endif 153276336SianEND(dcache_inv_pou_all) 154276336Sian 155276336Sian/* Write back and Invalidate D cache to PoC. */ 156276350SianASENTRY_NP(dcache_wbinv_poc_all) 157276394Sian#if __ARM_ARCH == 6 158276394Sian mcr CP15_DCCIALL 159276394Sian DSB 160276394Sian bx lr 161276394Sian#else 162276336Sian mrc CP15_CLIDR(r0) 163276336Sian ands r0, r0, #0x07000000 164276336Sian beq 4f 165276394Sian mov r0, #0 /* Clean from inner to outer levels */ 166276336Sian 167276336Sian1: mcr CP15_CSSELR(r0) /* set cache level */ 168276336Sian isb 169276336Sian mrc CP15_CCSIDR(r0) /* read CCSIDR */ 170276336Sian 171276336Sian ubfx r2, r0, #13, #15 /* get num sets - 1 from CCSIDR */ 172276336Sian ubfx r3, r0, #3, #10 /* get num ways - 1 from CCSIDR */ 173276336Sian clz r1, r3 /* number of bits to MSB of way */ 174276336Sian lsl r3, r3, r1 /* shift into position */ 175276336Sian mov ip, #1 176276336Sian lsl ip, ip, r1 /* ip now contains the way decr */ 177276336Sian 178276336Sian ubfx r0, r0, #0, #3 /* get linesize from CCSIDR */ 179276336Sian add r0, r0, #4 /* apply bias */ 180276336Sian lsl r2, r2, r0 /* shift sets by log2(linesize) */ 181276336Sian add r3, r3, r2 /* merge numsets - 1 with numways - 1 */ 182276336Sian sub ip, ip, r2 /* subtract numsets - 1 from way decr */ 183276336Sian mov r1, #1 184276336Sian lsl r1, r1, r0 /* r1 now contains the set decr */ 185276336Sian mov r2, ip /* r2 now contains set way decr */ 186276336Sian 187276336Sian /* r3 = ways/sets, r2 = way decr, r1 = set decr, r0 and ip are free */ 188276394Sian2: mcr CP15_DCCISW(r3) /* clean and invalidate line */ 189276336Sian movs r0, r3 /* get current way/set */ 190276336Sian beq 3f /* at 0 means we are done */ 191276336Sian movs r0, r0, lsl #10 /* clear way bits leaving only set bits*/ 192276336Sian subne r3, r3, r1 /* non-zero?, decrement set */ 193276336Sian subeq r3, r3, r2 /* zero?, decrement way and restore set count */ 194276336Sian b 2b 195276336Sian 196276336Sian3: 197276336Sian mrc CP15_CSSELR(r0) /* get cache level */ 198276336Sian add r0, r0, #2 /* next level */ 199276336Sian mrc CP15_CLIDR(r1) 200276336Sian ands r1, r1, #0x07000000 201276336Sian mov r1, r1, lsr #23 /* Get LoC (naturally aligned) */ 202276336Sian cmp r1, r0 203276394Sian bne 1b 204276336Sian 205276336Sian4: dsb /* wait for stores to finish */ 206276336Sian mov r0, #0 207276336Sian mcr CP15_CSSELR(r0) 208276336Sian bx lr 209276394Sian#endif /* __ARM_ARCH == 6 */ 210276336SianEND(dcache_wbinv_poc_all) 211