1/*- 2 * Copyright (C) 2008 MARVELL INTERNATIONAL LTD. 3 * All rights reserved. 4 * 5 * Developed by Semihalf. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of MARVELL nor the names of contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32#include <machine/armreg.h> 33#include <machine/asm.h> 34__FBSDID("$FreeBSD$"); 35 36#include <machine/param.h> 37 38.Lsheeva_cache_line_size: 39 .word _C_LABEL(arm_pdcache_line_size) 40.Lsheeva_asm_page_mask: 41 .word _C_LABEL(PAGE_MASK) 42 43ENTRY(sheeva_setttb) 44 /* Disable irqs */ 45 mrs r2, cpsr 46 orr r3, r2, #PSR_I | PSR_F 47 msr cpsr_c, r3 48 49 mov r1, #0 50 mcr p15, 0, r1, c7, c5, 0 /* Invalidate ICache */ 511: mrc p15, 0, APSR_nzcv, c7, c14, 3 /* Test, clean and invalidate DCache */ 52 bne 1b /* More to do? */ 53 54 mcr p15, 1, r1, c15, c9, 0 /* Clean L2 */ 55 mcr p15, 1, r1, c15, c11, 0 /* Invalidate L2 */ 56 57 /* Reenable irqs */ 58 msr cpsr_c, r2 59 60 mcr p15, 0, r1, c7, c10, 4 /* drain the write buffer */ 61 62 mcr p15, 0, r0, c2, c0, 0 /* load new TTB */ 63 64 mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLBs */ 65 RET 66END(sheeva_setttb) 67 68ENTRY(sheeva_dcache_wbinv_range) 69 str lr, [sp, #-4]! 70 mrs lr, cpsr 71 /* Start with cache line aligned address */ 72 ldr ip, .Lsheeva_cache_line_size 73 ldr ip, [ip] 74 sub ip, ip, #1 75 and r2, r0, ip 76 add r1, r1, r2 77 add r1, r1, ip 78 bics r1, r1, ip 79 bics r0, r0, ip 80 81 ldr ip, .Lsheeva_asm_page_mask 82 and r2, r0, ip 83 rsb r2, r2, #PAGE_SIZE 84 cmp r1, r2 85 movcc ip, r1 86 movcs ip, r2 871: 88 add r3, r0, ip 89 sub r2, r3, #1 90 /* Disable irqs */ 91 orr r3, lr, #PSR_I | PSR_F 92 msr cpsr_c, r3 93 mcr p15, 5, r0, c15, c15, 0 /* Clean and inv zone start address */ 94 mcr p15, 5, r2, c15, c15, 1 /* Clean and inv zone end address */ 95 /* Enable irqs */ 96 msr cpsr_c, lr 97 98 add r0, r0, ip 99 sub r1, r1, ip 100 cmp r1, #PAGE_SIZE 101 movcc ip, r1 102 movcs ip, #PAGE_SIZE 103 cmp r1, #0 104 bne 1b 105 mov r0, #0 106 mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ 107 ldr lr, [sp], #4 108 RET 109END(sheeva_dcache_wbinv_range) 110 111ENTRY(sheeva_idcache_wbinv_range) 112 str lr, [sp, #-4]! 113 mrs lr, cpsr 114 /* Start with cache line aligned address */ 115 ldr ip, .Lsheeva_cache_line_size 116 ldr ip, [ip] 117 sub ip, ip, #1 118 and r2, r0, ip 119 add r1, r1, r2 120 add r1, r1, ip 121 bics r1, r1, ip 122 bics r0, r0, ip 123 124 ldr ip, .Lsheeva_asm_page_mask 125 and r2, r0, ip 126 rsb r2, r2, #PAGE_SIZE 127 cmp r1, r2 128 movcc ip, r1 129 movcs ip, r2 1301: 131 add r3, r0, ip 132 sub r2, r3, #1 133 /* Disable irqs */ 134 orr r3, lr, #PSR_I | PSR_F 135 msr cpsr_c, r3 136 mcr p15, 5, r0, c15, c15, 0 /* Clean and inv zone start address */ 137 mcr p15, 5, r2, c15, c15, 1 /* Clean and inv zone end address */ 138 /* Enable irqs */ 139 msr cpsr_c, lr 140 141 /* Invalidate and clean icache line by line */ 142 ldr r3, .Lsheeva_cache_line_size 143 ldr r3, [r3] 1442: 145 mcr p15, 0, r0, c7, c5, 1 146 add r0, r0, r3 147 cmp r2, r0 148 bhi 2b 149 150 add r0, r2, #1 151 sub r1, r1, ip 152 cmp r1, #PAGE_SIZE 153 movcc ip, r1 154 movcs ip, #PAGE_SIZE 155 cmp r1, #0 156 bne 1b 157 mov r0, #0 158 mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ 159 ldr lr, [sp], #4 160 RET 161END(sheeva_idcache_wbinv_range) 162 163ENTRY(sheeva_dcache_inv_range) 164 str lr, [sp, #-4]! 165 mrs lr, cpsr 166 /* Start with cache line aligned address */ 167 ldr ip, .Lsheeva_cache_line_size 168 ldr ip, [ip] 169 sub ip, ip, #1 170 and r2, r0, ip 171 add r1, r1, r2 172 add r1, r1, ip 173 bics r1, r1, ip 174 bics r0, r0, ip 175 176 ldr ip, .Lsheeva_asm_page_mask 177 and r2, r0, ip 178 rsb r2, r2, #PAGE_SIZE 179 cmp r1, r2 180 movcc ip, r1 181 movcs ip, r2 1821: 183 add r3, r0, ip 184 sub r2, r3, #1 185 /* Disable irqs */ 186 orr r3, lr, #PSR_I | PSR_F 187 msr cpsr_c, r3 188 mcr p15, 5, r0, c15, c14, 0 /* Inv zone start address */ 189 mcr p15, 5, r2, c15, c14, 1 /* Inv zone end address */ 190 /* Enable irqs */ 191 msr cpsr_c, lr 192 193 add r0, r0, ip 194 sub r1, r1, ip 195 cmp r1, #PAGE_SIZE 196 movcc ip, r1 197 movcs ip, #PAGE_SIZE 198 cmp r1, #0 199 bne 1b 200 mov r0, #0 201 mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ 202 ldr lr, [sp], #4 203 RET 204END(sheeva_dcache_inv_range) 205 206ENTRY(sheeva_dcache_wb_range) 207 str lr, [sp, #-4]! 208 mrs lr, cpsr 209 /* Start with cache line aligned address */ 210 ldr ip, .Lsheeva_cache_line_size 211 ldr ip, [ip] 212 sub ip, ip, #1 213 and r2, r0, ip 214 add r1, r1, r2 215 add r1, r1, ip 216 bics r1, r1, ip 217 bics r0, r0, ip 218 219 ldr ip, .Lsheeva_asm_page_mask 220 and r2, r0, ip 221 rsb r2, r2, #PAGE_SIZE 222 cmp r1, r2 223 movcc ip, r1 224 movcs ip, r2 2251: 226 add r3, r0, ip 227 sub r2, r3, #1 228 /* Disable irqs */ 229 orr r3, lr, #PSR_I | PSR_F 230 msr cpsr_c, r3 231 mcr p15, 5, r0, c15, c13, 0 /* Clean zone start address */ 232 mcr p15, 5, r2, c15, c13, 1 /* Clean zone end address */ 233 /* Enable irqs */ 234 msr cpsr_c, lr 235 236 add r0, r0, ip 237 sub r1, r1, ip 238 cmp r1, #PAGE_SIZE 239 movcc ip, r1 240 movcs ip, #PAGE_SIZE 241 cmp r1, #0 242 bne 1b 243 mov r0, #0 244 mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ 245 ldr lr, [sp], #4 246 RET 247END(sheeva_dcache_wb_range) 248 249ENTRY(sheeva_l2cache_wbinv_range) 250 str lr, [sp, #-4]! 251 mrs lr, cpsr 252 /* Start with cache line aligned address */ 253 ldr ip, .Lsheeva_cache_line_size 254 ldr ip, [ip] 255 sub ip, ip, #1 256 and r2, r0, ip 257 add r1, r1, r2 258 add r1, r1, ip 259 bics r1, r1, ip 260 bics r0, r0, ip 261 262 ldr ip, .Lsheeva_asm_page_mask 263 and r2, r0, ip 264 rsb r2, r2, #PAGE_SIZE 265 cmp r1, r2 266 movcc ip, r1 267 movcs ip, r2 2681: 269 add r3, r0, ip 270 sub r2, r3, #1 271 /* Disable irqs */ 272 orr r3, lr, #PSR_I | PSR_F 273 msr cpsr_c, r3 274 mcr p15, 1, r0, c15, c9, 4 /* Clean L2 zone start address */ 275 mcr p15, 1, r2, c15, c9, 5 /* Clean L2 zone end address */ 276 mcr p15, 1, r0, c15, c11, 4 /* Inv L2 zone start address */ 277 mcr p15, 1, r2, c15, c11, 5 /* Inv L2 zone end address */ 278 /* Enable irqs */ 279 msr cpsr_c, lr 280 281 add r0, r0, ip 282 sub r1, r1, ip 283 cmp r1, #PAGE_SIZE 284 movcc ip, r1 285 movcs ip, #PAGE_SIZE 286 cmp r1, #0 287 bne 1b 288 mov r0, #0 289 mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ 290 ldr lr, [sp], #4 291 RET 292END(sheeva_l2cache_wbinv_range) 293 294ENTRY(sheeva_l2cache_inv_range) 295 str lr, [sp, #-4]! 296 mrs lr, cpsr 297 /* Start with cache line aligned address */ 298 ldr ip, .Lsheeva_cache_line_size 299 ldr ip, [ip] 300 sub ip, ip, #1 301 and r2, r0, ip 302 add r1, r1, r2 303 add r1, r1, ip 304 bics r1, r1, ip 305 bics r0, r0, ip 306 307 ldr ip, .Lsheeva_asm_page_mask 308 and r2, r0, ip 309 rsb r2, r2, #PAGE_SIZE 310 cmp r1, r2 311 movcc ip, r1 312 movcs ip, r2 3131: 314 add r3, r0, ip 315 sub r2, r3, #1 316 /* Disable irqs */ 317 orr r3, lr, #PSR_I | PSR_F 318 msr cpsr_c, r3 319 mcr p15, 1, r0, c15, c11, 4 /* Inv L2 zone start address */ 320 mcr p15, 1, r2, c15, c11, 5 /* Inv L2 zone end address */ 321 /* Enable irqs */ 322 msr cpsr_c, lr 323 324 add r0, r0, ip 325 sub r1, r1, ip 326 cmp r1, #PAGE_SIZE 327 movcc ip, r1 328 movcs ip, #PAGE_SIZE 329 cmp r1, #0 330 bne 1b 331 mov r0, #0 332 mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ 333 ldr lr, [sp], #4 334 RET 335END(sheeva_l2cache_inv_range) 336 337ENTRY(sheeva_l2cache_wb_range) 338 str lr, [sp, #-4]! 339 mrs lr, cpsr 340 /* Start with cache line aligned address */ 341 ldr ip, .Lsheeva_cache_line_size 342 ldr ip, [ip] 343 sub ip, ip, #1 344 and r2, r0, ip 345 add r1, r1, r2 346 add r1, r1, ip 347 bics r1, r1, ip 348 bics r0, r0, ip 349 350 ldr ip, .Lsheeva_asm_page_mask 351 and r2, r0, ip 352 rsb r2, r2, #PAGE_SIZE 353 cmp r1, r2 354 movcc ip, r1 355 movcs ip, r2 3561: 357 add r3, r0, ip 358 sub r2, r3, #1 359 /* Disable irqs */ 360 orr r3, lr, #PSR_I | PSR_F 361 msr cpsr_c, r3 362 mcr p15, 1, r0, c15, c9, 4 /* Clean L2 zone start address */ 363 mcr p15, 1, r2, c15, c9, 5 /* Clean L2 zone end address */ 364 /* Enable irqs */ 365 msr cpsr_c, lr 366 367 add r0, r0, ip 368 sub r1, r1, ip 369 cmp r1, #PAGE_SIZE 370 movcc ip, r1 371 movcs ip, #PAGE_SIZE 372 cmp r1, #0 373 bne 1b 374 mov r0, #0 375 mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ 376 ldr lr, [sp], #4 377 RET 378END(sheeva_l2cache_wb_range) 379 380ENTRY(sheeva_l2cache_wbinv_all) 381 /* Disable irqs */ 382 mrs r1, cpsr 383 orr r2, r1, #PSR_I | PSR_F 384 msr cpsr_c, r2 385 386 mov r0, #0 387 mcr p15, 1, r0, c15, c9, 0 /* Clean L2 */ 388 mcr p15, 1, r0, c15, c11, 0 /* Invalidate L2 */ 389 390 msr cpsr_c, r1 /* Reenable irqs */ 391 392 mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ 393 RET 394END(sheeva_l2cache_wbinv_all) 395 396/* This function modifies register value as follows: 397 * 398 * arg1 arg EFFECT (bit value saved into register) 399 * 0 0 not changed 400 * 0 1 negated 401 * 1 0 cleared 402 * 1 1 set 403 */ 404ENTRY(sheeva_control_ext) 405 mrc p15, 1, r3, c15, c1, 0 /* Read the control register */ 406 bic r2, r3, r0 /* Clear bits */ 407 eor r2, r2, r1 /* XOR bits */ 408 409 teq r2, r3 /* Only write if there is a change */ 410 mcrne p15, 1, r2, c15, c1, 0 /* Write new control register */ 411 mov r0, r3 /* Return old value */ 412 RET 413END(sheeva_control_ext) 414 415ENTRY(sheeva_cpu_sleep) 416 mov r0, #0 417 mcr p15, 0, r0, c7, c10, 4 /* Drain write buffer */ 418 mcr p15, 0, r0, c7, c0, 4 /* Wait for interrupt */ 419 mov pc, lr 420END(sheeva_cpu_sleep) 421 422