Hans de Goede | 076e841 | 2016-04-09 13:53:48 +0200 | [diff] [blame] | 1 | /* |
| 2 | * SPDX-License-Identifier: GPL-2.0+ |
| 3 | */ |
| 4 | |
| 5 | #include <config.h> |
| 6 | #include <linux/linkage.h> |
| 7 | #include <linux/sizes.h> |
| 8 | #include <asm/system.h> |
| 9 | |
Tom Rini | 1c640a6 | 2017-03-18 09:01:44 -0400 | [diff] [blame] | 10 | #if CONFIG_IS_ENABLED(SYS_THUMB_BUILD) |
Hans de Goede | 076e841 | 2016-04-09 13:53:48 +0200 | [diff] [blame] | 11 | #define ARM(x...) |
| 12 | #define THUMB(x...) x |
| 13 | #else |
| 14 | #define ARM(x...) x |
| 15 | #define THUMB(x...) |
| 16 | #endif |
| 17 | |
| 18 | /* |
| 19 | * v7_flush_dcache_all() |
| 20 | * |
| 21 | * Flush the whole D-cache. |
| 22 | * |
| 23 | * Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode) |
| 24 | * |
| 25 | * Note: copied from arch/arm/mm/cache-v7.S of Linux 4.4 |
| 26 | */ |
| 27 | ENTRY(__v7_flush_dcache_all) |
| 28 | dmb @ ensure ordering with previous memory accesses |
| 29 | mrc p15, 1, r0, c0, c0, 1 @ read clidr |
| 30 | mov r3, r0, lsr #23 @ move LoC into position |
| 31 | ands r3, r3, #7 << 1 @ extract LoC*2 from clidr |
| 32 | beq finished @ if loc is 0, then no need to clean |
| 33 | start_flush_levels: |
| 34 | mov r10, #0 @ start clean at cache level 0 |
| 35 | flush_levels: |
| 36 | add r2, r10, r10, lsr #1 @ work out 3x current cache level |
| 37 | mov r1, r0, lsr r2 @ extract cache type bits from clidr |
| 38 | and r1, r1, #7 @ mask of the bits for current cache only |
| 39 | cmp r1, #2 @ see what cache we have at this level |
| 40 | blt skip @ skip if no cache, or just i-cache |
| 41 | mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr |
| 42 | isb @ isb to sych the new cssr&csidr |
| 43 | mrc p15, 1, r1, c0, c0, 0 @ read the new csidr |
| 44 | and r2, r1, #7 @ extract the length of the cache lines |
| 45 | add r2, r2, #4 @ add 4 (line length offset) |
| 46 | movw r4, #0x3ff |
| 47 | ands r4, r4, r1, lsr #3 @ find maximum number on the way size |
| 48 | clz r5, r4 @ find bit position of way size increment |
| 49 | movw r7, #0x7fff |
| 50 | ands r7, r7, r1, lsr #13 @ extract max number of the index size |
| 51 | loop1: |
| 52 | mov r9, r7 @ create working copy of max index |
| 53 | loop2: |
| 54 | ARM( orr r11, r10, r4, lsl r5 ) @ factor way and cache number into r11 |
| 55 | THUMB( lsl r6, r4, r5 ) |
| 56 | THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11 |
| 57 | ARM( orr r11, r11, r9, lsl r2 ) @ factor index number into r11 |
| 58 | THUMB( lsl r6, r9, r2 ) |
| 59 | THUMB( orr r11, r11, r6 ) @ factor index number into r11 |
| 60 | mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way |
| 61 | subs r9, r9, #1 @ decrement the index |
| 62 | bge loop2 |
| 63 | subs r4, r4, #1 @ decrement the way |
| 64 | bge loop1 |
| 65 | skip: |
| 66 | add r10, r10, #2 @ increment cache number |
| 67 | cmp r3, r10 |
| 68 | bgt flush_levels |
| 69 | finished: |
| 70 | mov r10, #0 @ swith back to cache level 0 |
| 71 | mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr |
| 72 | dsb st |
| 73 | isb |
| 74 | bx lr |
| 75 | ENDPROC(__v7_flush_dcache_all) |
| 76 | |
| 77 | ENTRY(v7_flush_dcache_all) |
| 78 | ARM( stmfd sp!, {r4-r5, r7, r9-r11, lr} ) |
| 79 | THUMB( stmfd sp!, {r4-r7, r9-r11, lr} ) |
| 80 | bl __v7_flush_dcache_all |
| 81 | ARM( ldmfd sp!, {r4-r5, r7, r9-r11, lr} ) |
| 82 | THUMB( ldmfd sp!, {r4-r7, r9-r11, lr} ) |
| 83 | bx lr |
| 84 | ENDPROC(v7_flush_dcache_all) |
Hans de Goede | ba3bf9b | 2016-04-09 13:53:49 +0200 | [diff] [blame] | 85 | |
| 86 | /* |
| 87 | * v7_invalidate_dcache_all() |
| 88 | * |
| 89 | * Invalidate the whole D-cache. |
| 90 | * |
| 91 | * Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode) |
| 92 | * |
| 93 | * Note: copied from __v7_flush_dcache_all above with |
| 94 | * mcr p15, 0, r11, c7, c14, 2 |
| 95 | * Replaced with: |
| 96 | * mcr p15, 0, r11, c7, c6, 2 |
| 97 | */ |
| 98 | ENTRY(__v7_invalidate_dcache_all) |
| 99 | dmb @ ensure ordering with previous memory accesses |
| 100 | mrc p15, 1, r0, c0, c0, 1 @ read clidr |
| 101 | mov r3, r0, lsr #23 @ move LoC into position |
| 102 | ands r3, r3, #7 << 1 @ extract LoC*2 from clidr |
| 103 | beq inval_finished @ if loc is 0, then no need to clean |
| 104 | mov r10, #0 @ start clean at cache level 0 |
| 105 | inval_levels: |
| 106 | add r2, r10, r10, lsr #1 @ work out 3x current cache level |
| 107 | mov r1, r0, lsr r2 @ extract cache type bits from clidr |
| 108 | and r1, r1, #7 @ mask of the bits for current cache only |
| 109 | cmp r1, #2 @ see what cache we have at this level |
| 110 | blt inval_skip @ skip if no cache, or just i-cache |
| 111 | mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr |
| 112 | isb @ isb to sych the new cssr&csidr |
| 113 | mrc p15, 1, r1, c0, c0, 0 @ read the new csidr |
| 114 | and r2, r1, #7 @ extract the length of the cache lines |
| 115 | add r2, r2, #4 @ add 4 (line length offset) |
| 116 | movw r4, #0x3ff |
| 117 | ands r4, r4, r1, lsr #3 @ find maximum number on the way size |
| 118 | clz r5, r4 @ find bit position of way size increment |
| 119 | movw r7, #0x7fff |
| 120 | ands r7, r7, r1, lsr #13 @ extract max number of the index size |
| 121 | inval_loop1: |
| 122 | mov r9, r7 @ create working copy of max index |
| 123 | inval_loop2: |
| 124 | ARM( orr r11, r10, r4, lsl r5 ) @ factor way and cache number into r11 |
| 125 | THUMB( lsl r6, r4, r5 ) |
| 126 | THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11 |
| 127 | ARM( orr r11, r11, r9, lsl r2 ) @ factor index number into r11 |
| 128 | THUMB( lsl r6, r9, r2 ) |
| 129 | THUMB( orr r11, r11, r6 ) @ factor index number into r11 |
| 130 | mcr p15, 0, r11, c7, c6, 2 @ invalidate by set/way |
| 131 | subs r9, r9, #1 @ decrement the index |
| 132 | bge inval_loop2 |
| 133 | subs r4, r4, #1 @ decrement the way |
| 134 | bge inval_loop1 |
| 135 | inval_skip: |
| 136 | add r10, r10, #2 @ increment cache number |
| 137 | cmp r3, r10 |
| 138 | bgt inval_levels |
| 139 | inval_finished: |
| 140 | mov r10, #0 @ swith back to cache level 0 |
| 141 | mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr |
| 142 | dsb st |
| 143 | isb |
| 144 | bx lr |
| 145 | ENDPROC(__v7_invalidate_dcache_all) |
| 146 | |
| 147 | ENTRY(v7_invalidate_dcache_all) |
| 148 | ARM( stmfd sp!, {r4-r5, r7, r9-r11, lr} ) |
| 149 | THUMB( stmfd sp!, {r4-r7, r9-r11, lr} ) |
| 150 | bl __v7_invalidate_dcache_all |
| 151 | ARM( ldmfd sp!, {r4-r5, r7, r9-r11, lr} ) |
| 152 | THUMB( ldmfd sp!, {r4-r7, r9-r11, lr} ) |
| 153 | bx lr |
| 154 | ENDPROC(v7_invalidate_dcache_all) |