1/* MN10300 CPU core caching routines, using indirect regs on cache controller 2 * 3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public Licence 8 * as published by the Free Software Foundation; either version 9 * 2 of the Licence, or (at your option) any later version. 10 */ 11 12#include <linux/sys.h> 13#include <linux/linkage.h> 14#include <asm/smp.h> 15#include <asm/page.h> 16#include <asm/cache.h> 17#include <asm/irqflags.h> 18 19 .am33_2 20 21#ifndef CONFIG_SMP 22 .globl mn10300_dcache_flush 23 .globl mn10300_dcache_flush_page 24 .globl mn10300_dcache_flush_range 25 .globl mn10300_dcache_flush_range2 26 .globl mn10300_dcache_flush_inv 27 .globl mn10300_dcache_flush_inv_page 28 .globl mn10300_dcache_flush_inv_range 29 .globl mn10300_dcache_flush_inv_range2 30 31mn10300_dcache_flush = mn10300_local_dcache_flush 32mn10300_dcache_flush_page = mn10300_local_dcache_flush_page 33mn10300_dcache_flush_range = mn10300_local_dcache_flush_range 34mn10300_dcache_flush_range2 = mn10300_local_dcache_flush_range2 35mn10300_dcache_flush_inv = mn10300_local_dcache_flush_inv 36mn10300_dcache_flush_inv_page = mn10300_local_dcache_flush_inv_page 37mn10300_dcache_flush_inv_range = mn10300_local_dcache_flush_inv_range 38mn10300_dcache_flush_inv_range2 = mn10300_local_dcache_flush_inv_range2 39 40#endif /* !CONFIG_SMP */ 41 42############################################################################### 43# 44# void mn10300_local_dcache_flush(void) 45# Flush the entire data cache back to RAM 46# 47############################################################################### 48 ALIGN 49 .globl mn10300_local_dcache_flush 50 .type mn10300_local_dcache_flush,@function 51mn10300_local_dcache_flush: 52 movhu (CHCTR),d0 53 btst CHCTR_DCEN,d0 54 beq mn10300_local_dcache_flush_end 55 56 mov DCPGCR,a0 57 58 LOCAL_CLI_SAVE(d1) 59 60 # wait for busy bit of area purge 61 setlb 62 mov (a0),d0 63 btst DCPGCR_DCPGBSY,d0 64 lne 65 66 # set mask 67 clr d0 68 mov d0,(DCPGMR) 69 70 # area purge 71 # 72 # DCPGCR = DCPGCR_DCP 73 # 74 mov DCPGCR_DCP,d0 75 mov d0,(a0) 76 77 # wait for busy bit of area purge 78 setlb 79 mov (a0),d0 80 btst DCPGCR_DCPGBSY,d0 81 lne 82 83 LOCAL_IRQ_RESTORE(d1) 84 85mn10300_local_dcache_flush_end: 86 ret [],0 87 .size mn10300_local_dcache_flush,.-mn10300_local_dcache_flush 88 89############################################################################### 90# 91# void mn10300_local_dcache_flush_page(unsigned long start) 92# void mn10300_local_dcache_flush_range(unsigned long start, unsigned long end) 93# void mn10300_local_dcache_flush_range2(unsigned long start, unsigned long size) 94# Flush a range of addresses on a page in the dcache 95# 96############################################################################### 97 ALIGN 98 .globl mn10300_local_dcache_flush_page 99 .globl mn10300_local_dcache_flush_range 100 .globl mn10300_local_dcache_flush_range2 101 .type mn10300_local_dcache_flush_page,@function 102 .type mn10300_local_dcache_flush_range,@function 103 .type mn10300_local_dcache_flush_range2,@function 104mn10300_local_dcache_flush_page: 105 and ~(PAGE_SIZE-1),d0 106 mov PAGE_SIZE,d1 107mn10300_local_dcache_flush_range2: 108 add d0,d1 109mn10300_local_dcache_flush_range: 110 movm [d2,d3,a2],(sp) 111 112 movhu (CHCTR),d2 113 btst CHCTR_DCEN,d2 114 beq mn10300_local_dcache_flush_range_end 115 116 # calculate alignsize 117 # 118 # alignsize = L1_CACHE_BYTES; 119 # for (i = (end - start - 1) / L1_CACHE_BYTES ; i > 0; i >>= 1) 120 # alignsize <<= 1; 121 # d2 = alignsize; 122 # 123 mov L1_CACHE_BYTES,d2 124 sub d0,d1,d3 125 add -1,d3 126 lsr L1_CACHE_SHIFT,d3 127 beq 2f 1281: 129 add d2,d2 130 lsr 1,d3 131 bne 1b 1322: 133 mov d1,a1 # a1 = end 134 135 LOCAL_CLI_SAVE(d3) 136 mov DCPGCR,a0 137 138 # wait for busy bit of area purge 139 setlb 140 mov (a0),d1 141 btst DCPGCR_DCPGBSY,d1 142 lne 143 144 # determine the mask 145 mov d2,d1 146 add -1,d1 147 not d1 # d1 = mask = ~(alignsize-1) 148 mov d1,(DCPGMR) 149 150 and d1,d0,a2 # a2 = mask & start 151 152dcpgloop: 153 # area purge 154 mov a2,d0 155 or DCPGCR_DCP,d0 156 mov d0,(a0) # DCPGCR = (mask & start) | DCPGCR_DCP 157 158 # wait for busy bit of area purge 159 setlb 160 mov (a0),d1 161 btst DCPGCR_DCPGBSY,d1 162 lne 163 164 # check purge of end address 165 add d2,a2 # a2 += alignsize 166 cmp a1,a2 # if (a2 < end) goto dcpgloop 167 bns dcpgloop 168 169 LOCAL_IRQ_RESTORE(d3) 170 171mn10300_local_dcache_flush_range_end: 172 ret [d2,d3,a2],12 173 174 .size mn10300_local_dcache_flush_page,.-mn10300_local_dcache_flush_page 175 .size mn10300_local_dcache_flush_range,.-mn10300_local_dcache_flush_range 176 .size mn10300_local_dcache_flush_range2,.-mn10300_local_dcache_flush_range2 177 178############################################################################### 179# 180# void mn10300_local_dcache_flush_inv(void) 181# Flush the entire data cache and invalidate all entries 182# 183############################################################################### 184 ALIGN 185 .globl mn10300_local_dcache_flush_inv 186 .type mn10300_local_dcache_flush_inv,@function 187mn10300_local_dcache_flush_inv: 188 movhu (CHCTR),d0 189 btst CHCTR_DCEN,d0 190 beq mn10300_local_dcache_flush_inv_end 191 192 mov DCPGCR,a0 193 194 LOCAL_CLI_SAVE(d1) 195 196 # wait for busy bit of area purge & invalidate 197 setlb 198 mov (a0),d0 199 btst DCPGCR_DCPGBSY,d0 200 lne 201 202 # set the mask to cover everything 203 clr d0 204 mov d0,(DCPGMR) 205 206 # area purge & invalidate 207 mov DCPGCR_DCP|DCPGCR_DCI,d0 208 mov d0,(a0) 209 210 # wait for busy bit of area purge & invalidate 211 setlb 212 mov (a0),d0 213 btst DCPGCR_DCPGBSY,d0 214 lne 215 216 LOCAL_IRQ_RESTORE(d1) 217 218mn10300_local_dcache_flush_inv_end: 219 ret [],0 220 .size mn10300_local_dcache_flush_inv,.-mn10300_local_dcache_flush_inv 221 222############################################################################### 223# 224# void mn10300_local_dcache_flush_inv_page(unsigned long start) 225# void mn10300_local_dcache_flush_inv_range(unsigned long start, unsigned long end) 226# void mn10300_local_dcache_flush_inv_range2(unsigned long start, unsigned long size) 227# Flush and invalidate a range of addresses on a page in the dcache 228# 229############################################################################### 230 ALIGN 231 .globl mn10300_local_dcache_flush_inv_page 232 .globl mn10300_local_dcache_flush_inv_range 233 .globl mn10300_local_dcache_flush_inv_range2 234 .type mn10300_local_dcache_flush_inv_page,@function 235 .type mn10300_local_dcache_flush_inv_range,@function 236 .type mn10300_local_dcache_flush_inv_range2,@function 237mn10300_local_dcache_flush_inv_page: 238 and ~(PAGE_SIZE-1),d0 239 mov PAGE_SIZE,d1 240mn10300_local_dcache_flush_inv_range2: 241 add d0,d1 242mn10300_local_dcache_flush_inv_range: 243 movm [d2,d3,a2],(sp) 244 245 movhu (CHCTR),d2 246 btst CHCTR_DCEN,d2 247 beq mn10300_local_dcache_flush_inv_range_end 248 249 # calculate alignsize 250 # 251 # alignsize = L1_CACHE_BYTES; 252 # for (i = (end - start - 1) / L1_CACHE_BYTES; i > 0; i >>= 1) 253 # alignsize <<= 1; 254 # d2 = alignsize 255 # 256 mov L1_CACHE_BYTES,d2 257 sub d0,d1,d3 258 add -1,d3 259 lsr L1_CACHE_SHIFT,d3 260 beq 2f 2611: 262 add d2,d2 263 lsr 1,d3 264 bne 1b 2652: 266 mov d1,a1 # a1 = end 267 268 LOCAL_CLI_SAVE(d3) 269 mov DCPGCR,a0 270 271 # wait for busy bit of area purge & invalidate 272 setlb 273 mov (a0),d1 274 btst DCPGCR_DCPGBSY,d1 275 lne 276 277 # set the mask 278 mov d2,d1 279 add -1,d1 280 not d1 # d1 = mask = ~(alignsize-1) 281 mov d1,(DCPGMR) 282 283 and d1,d0,a2 # a2 = mask & start 284 285dcpgivloop: 286 # area purge & invalidate 287 mov a2,d0 288 or DCPGCR_DCP|DCPGCR_DCI,d0 289 mov d0,(a0) # DCPGCR = (mask & start)|DCPGCR_DCP|DCPGCR_DCI 290 291 # wait for busy bit of area purge & invalidate 292 setlb 293 mov (a0),d1 294 btst DCPGCR_DCPGBSY,d1 295 lne 296 297 # check purge & invalidate of end address 298 add d2,a2 # a2 += alignsize 299 cmp a1,a2 # if (a2 < end) goto dcpgivloop 300 bns dcpgivloop 301 302 LOCAL_IRQ_RESTORE(d3) 303 304mn10300_local_dcache_flush_inv_range_end: 305 ret [d2,d3,a2],12 306 .size mn10300_local_dcache_flush_inv_page,.-mn10300_local_dcache_flush_inv_page 307 .size mn10300_local_dcache_flush_inv_range,.-mn10300_local_dcache_flush_inv_range 308 .size mn10300_local_dcache_flush_inv_range2,.-mn10300_local_dcache_flush_inv_range2 309