1129198Scognet/* $NetBSD: cpufunc_asm_xscale.S,v 1.16 2002/08/17 16:36:32 thorpej Exp $ */ 2129198Scognet 3139735Simp/*- 4129198Scognet * Copyright (c) 2001, 2002 Wasabi Systems, Inc. 5129198Scognet * All rights reserved. 6129198Scognet * 7129198Scognet * Written by Allen Briggs and Jason R. Thorpe for Wasabi Systems, Inc. 8129198Scognet * 9129198Scognet * Redistribution and use in source and binary forms, with or without 10129198Scognet * modification, are permitted provided that the following conditions 11129198Scognet * are met: 12129198Scognet * 1. Redistributions of source code must retain the above copyright 13129198Scognet * notice, this list of conditions and the following disclaimer. 14129198Scognet * 2. Redistributions in binary form must reproduce the above copyright 15129198Scognet * notice, this list of conditions and the following disclaimer in the 16129198Scognet * documentation and/or other materials provided with the distribution. 17129198Scognet * 3. All advertising materials mentioning features or use of this software 18129198Scognet * must display the following acknowledgement: 19129198Scognet * This product includes software developed for the NetBSD Project by 20129198Scognet * Wasabi Systems, Inc. 21129198Scognet * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22129198Scognet * or promote products derived from this software without specific prior 23129198Scognet * written permission. 24129198Scognet * 25129198Scognet * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26129198Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27129198Scognet * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28129198Scognet * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29129198Scognet * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30129198Scognet * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31129198Scognet * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32129198Scognet * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33129198Scognet * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34129198Scognet * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35129198Scognet * POSSIBILITY OF SUCH DAMAGE. 36129198Scognet * 37129198Scognet */ 38129198Scognet 39139735Simp/*- 40129198Scognet * Copyright (c) 2001 Matt Thomas. 41129198Scognet * Copyright (c) 1997,1998 Mark Brinicombe. 42129198Scognet * Copyright (c) 1997 Causality Limited 43129198Scognet * All rights reserved. 44129198Scognet * 45129198Scognet * Redistribution and use in source and binary forms, with or without 46129198Scognet * modification, are permitted provided that the following conditions 47129198Scognet * are met: 48129198Scognet * 1. Redistributions of source code must retain the above copyright 49129198Scognet * notice, this list of conditions and the following disclaimer. 50129198Scognet * 2. Redistributions in binary form must reproduce the above copyright 51129198Scognet * notice, this list of conditions and the following disclaimer in the 52129198Scognet * documentation and/or other materials provided with the distribution. 53129198Scognet * 3. All advertising materials mentioning features or use of this software 54129198Scognet * must display the following acknowledgement: 55129198Scognet * This product includes software developed by Causality Limited. 56129198Scognet * 4. The name of Causality Limited may not be used to endorse or promote 57129198Scognet * products derived from this software without specific prior written 58129198Scognet * permission. 59129198Scognet * 60129198Scognet * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS 61129198Scognet * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 62129198Scognet * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 63129198Scognet * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT, 64129198Scognet * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 65129198Scognet * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 66129198Scognet * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 67129198Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 68129198Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 69129198Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 70129198Scognet * SUCH DAMAGE. 71129198Scognet * 72129198Scognet * XScale assembly functions for CPU / MMU / TLB specific operations 73129198Scognet */ 74271398Sandrew#include <machine/armreg.h> 75129198Scognet#include <machine/asm.h> 76129198Scognet__FBSDID("$FreeBSD$"); 77129198Scognet 78129198Scognet/* 79129198Scognet * Size of the XScale core D-cache. 80129198Scognet */ 81129198Scognet#define DCACHE_SIZE 0x00008000 82129198Scognet 83129198Scognet/* 84129198Scognet * CPWAIT -- Canonical method to wait for CP15 update. 85129198Scognet * From: Intel 80200 manual, section 2.3.3. 86129198Scognet * 87129198Scognet * NOTE: Clobbers the specified temp reg. 88129198Scognet */ 89129198Scognet#define CPWAIT_BRANCH \ 90129198Scognet sub pc, pc, #4 91129198Scognet 92129198Scognet#define CPWAIT(tmp) \ 93129198Scognet mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\ 94129198Scognet mov tmp, tmp /* wait for it to complete */ ;\ 95129198Scognet CPWAIT_BRANCH /* branch to next insn */ 96129198Scognet 97129198Scognet#define CPWAIT_AND_RETURN_SHIFTER lsr #32 98129198Scognet 99129198Scognet#define CPWAIT_AND_RETURN(tmp) \ 100129198Scognet mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\ 101129198Scognet /* Wait for it to complete and branch to the return address */ \ 102129198Scognet sub pc, lr, tmp, CPWAIT_AND_RETURN_SHIFTER 103129198Scognet 104129198ScognetENTRY(xscale_cpwait) 105129198Scognet CPWAIT_AND_RETURN(r0) 106248361SandrewEND(xscale_cpwait) 107129198Scognet 108129198Scognet/* 109129198Scognet * We need a separate cpu_control() entry point, since we have to 110129198Scognet * invalidate the Branch Target Buffer in the event the BPRD bit 111129198Scognet * changes in the control register. 112129198Scognet */ 113129198ScognetENTRY(xscale_control) 114300533Sian mrc CP15_SCTLR(r3) /* Read the control register */ 115129198Scognet bic r2, r3, r0 /* Clear bits */ 116129198Scognet eor r2, r2, r1 /* XOR bits */ 117129198Scognet 118129198Scognet teq r2, r3 /* Only write if there was a change */ 119129198Scognet mcrne p15, 0, r0, c7, c5, 6 /* Invalidate the BTB */ 120300534Sian mcrne CP15_SCTLR(r2) /* Write new control register */ 121129198Scognet mov r0, r3 /* Return old value */ 122129198Scognet 123129198Scognet CPWAIT_AND_RETURN(r1) 124248361SandrewEND(xscale_control) 125129198Scognet 126129198Scognet/* 127129198Scognet * Functions to set the MMU Translation Table Base register 128129198Scognet * 129129198Scognet * We need to clean and flush the cache as it uses virtual 130129198Scognet * addresses that are about to change. 131129198Scognet */ 132129198ScognetENTRY(xscale_setttb) 133129198Scognet#ifdef CACHE_CLEAN_BLOCK_INTR 134261393Sian mrs r3, cpsr 135271398Sandrew orr r1, r3, #(PSR_I | PSR_F) 136261393Sian msr cpsr_fsxc, r1 137129198Scognet#endif 138129198Scognet stmfd sp!, {r0-r3, lr} 139129198Scognet bl _C_LABEL(xscale_cache_cleanID) 140129198Scognet mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ and BTB */ 141129198Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write and fill buffer */ 142129198Scognet 143129198Scognet CPWAIT(r0) 144129198Scognet 145129198Scognet ldmfd sp!, {r0-r3, lr} 146129198Scognet 147236991Simp /* Write the TTB */ 148129198Scognet mcr p15, 0, r0, c2, c0, 0 149129198Scognet 150129198Scognet /* If we have updated the TTB we must flush the TLB */ 151129198Scognet mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLB */ 152129198Scognet 153129198Scognet /* The cleanID above means we only need to flush the I cache here */ 154129198Scognet mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ and BTB */ 155129198Scognet 156129198Scognet CPWAIT(r0) 157129198Scognet 158129198Scognet#ifdef CACHE_CLEAN_BLOCK_INTR 159261393Sian msr cpsr_fsxc, r3 160129198Scognet#endif 161137463Scognet RET 162248361SandrewEND(xscale_setttb) 163129198Scognet 164129198Scognet/* 165129198Scognet * TLB functions 166129198Scognet * 167129198Scognet */ 168129198ScognetENTRY(xscale_tlb_flushID_SE) 169129198Scognet mcr p15, 0, r0, c8, c6, 1 /* flush D tlb single entry */ 170129198Scognet mcr p15, 0, r0, c8, c5, 1 /* flush I tlb single entry */ 171140000Scognet CPWAIT_AND_RETURN(r0) 172248361SandrewEND(xscale_tlb_flushID_SE) 173129198Scognet 174129198Scognet/* 175129198Scognet * Cache functions 176129198Scognet */ 177129198ScognetENTRY(xscale_cache_flushID) 178129198Scognet mcr p15, 0, r0, c7, c7, 0 /* flush I+D cache */ 179129198Scognet CPWAIT_AND_RETURN(r0) 180248361SandrewEND(xscale_cache_flushID) 181129198Scognet 182129198ScognetENTRY(xscale_cache_flushI) 183129198Scognet mcr p15, 0, r0, c7, c5, 0 /* flush I cache */ 184129198Scognet CPWAIT_AND_RETURN(r0) 185248361SandrewEND(xscale_cache_flushI) 186129198Scognet 187129198ScognetENTRY(xscale_cache_flushD) 188129198Scognet mcr p15, 0, r0, c7, c6, 0 /* flush D cache */ 189129198Scognet CPWAIT_AND_RETURN(r0) 190248361SandrewEND(xscale_cache_flushD) 191129198Scognet 192129198ScognetENTRY(xscale_cache_flushI_SE) 193129198Scognet mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */ 194129198Scognet CPWAIT_AND_RETURN(r0) 195248361SandrewEND(xscale_cache_flushI_SE) 196129198Scognet 197129198ScognetENTRY(xscale_cache_flushD_SE) 198129198Scognet /* 199129198Scognet * Errata (rev < 2): Must clean-dcache-line to an address 200129198Scognet * before invalidate-dcache-line to an address, or dirty 201129198Scognet * bits will not be cleared in the dcache array. 202129198Scognet */ 203129198Scognet mcr p15, 0, r0, c7, c10, 1 204129198Scognet mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */ 205129198Scognet CPWAIT_AND_RETURN(r0) 206248361SandrewEND(xscale_cache_flushD_SE) 207129198Scognet 208129198ScognetENTRY(xscale_cache_cleanD_E) 209129198Scognet mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ 210129198Scognet CPWAIT_AND_RETURN(r0) 211248361SandrewEND(xscale_cache_cleanD_E) 212129198Scognet 213129198Scognet/* 214129198Scognet * Information for the XScale cache clean/purge functions: 215129198Scognet * 216129198Scognet * * Virtual address of the memory region to use 217129198Scognet * * Size of memory region 218129198Scognet * 219129198Scognet * Note the virtual address for the Data cache clean operation 220129198Scognet * does not need to be backed by physical memory, since no loads 221129198Scognet * will actually be performed by the allocate-line operation. 222129198Scognet * 223129198Scognet * Note that the Mini-Data cache MUST be cleaned by executing 224129198Scognet * loads from memory mapped into a region reserved exclusively 225129198Scognet * for cleaning of the Mini-Data cache. 226129198Scognet */ 227129198Scognet .data 228129198Scognet 229129198Scognet .global _C_LABEL(xscale_cache_clean_addr) 230129198Scognet_C_LABEL(xscale_cache_clean_addr): 231129198Scognet .word 0x00000000 232129198Scognet 233129198Scognet .global _C_LABEL(xscale_cache_clean_size) 234129198Scognet_C_LABEL(xscale_cache_clean_size): 235129198Scognet .word DCACHE_SIZE 236129198Scognet 237129198Scognet .global _C_LABEL(xscale_minidata_clean_addr) 238129198Scognet_C_LABEL(xscale_minidata_clean_addr): 239129198Scognet .word 0x00000000 240129198Scognet 241129198Scognet .global _C_LABEL(xscale_minidata_clean_size) 242129198Scognet_C_LABEL(xscale_minidata_clean_size): 243129198Scognet .word 0x00000800 244129198Scognet 245129198Scognet .text 246129198Scognet 247129198Scognet.Lxscale_cache_clean_addr: 248129198Scognet .word _C_LABEL(xscale_cache_clean_addr) 249129198Scognet.Lxscale_cache_clean_size: 250129198Scognet .word _C_LABEL(xscale_cache_clean_size) 251129198Scognet 252129198Scognet.Lxscale_minidata_clean_addr: 253129198Scognet .word _C_LABEL(xscale_minidata_clean_addr) 254129198Scognet.Lxscale_minidata_clean_size: 255129198Scognet .word _C_LABEL(xscale_minidata_clean_size) 256129198Scognet 257129198Scognet#ifdef CACHE_CLEAN_BLOCK_INTR 258129198Scognet#define XSCALE_CACHE_CLEAN_BLOCK \ 259261393Sian mrs r3, cpsr ; \ 260271398Sandrew orr r0, r3, #(PSR_I | PSR_F) ; \ 261261393Sian msr cpsr_fsxc, r0 262129198Scognet 263129198Scognet#define XSCALE_CACHE_CLEAN_UNBLOCK \ 264261393Sian msr cpsr_fsxc, r3 265129198Scognet#else 266295267Smmel#define XSCALE_CACHE_CLEAN_BLOCK 267129198Scognet 268295267Smmel#define XSCALE_CACHE_CLEAN_UNBLOCK 269129198Scognet#endif /* CACHE_CLEAN_BLOCK_INTR */ 270129198Scognet 271129198Scognet#define XSCALE_CACHE_CLEAN_PROLOGUE \ 272129198Scognet XSCALE_CACHE_CLEAN_BLOCK ; \ 273129198Scognet ldr r2, .Lxscale_cache_clean_addr ; \ 274129198Scognet ldmia r2, {r0, r1} ; \ 275129198Scognet /* \ 276129198Scognet * BUG ALERT! \ 277129198Scognet * \ 278129198Scognet * The XScale core has a strange cache eviction bug, which \ 279129198Scognet * requires us to use 2x the cache size for the cache clean \ 280129198Scognet * and for that area to be aligned to 2 * cache size. \ 281129198Scognet * \ 282129198Scognet * The work-around is to use 2 areas for cache clean, and to \ 283129198Scognet * alternate between them whenever this is done. No one knows \ 284129198Scognet * why the work-around works (mmm!). \ 285129198Scognet */ \ 286129198Scognet eor r0, r0, #(DCACHE_SIZE) ; \ 287129198Scognet str r0, [r2] ; \ 288129198Scognet add r0, r0, r1 289129198Scognet 290129198Scognet#define XSCALE_CACHE_CLEAN_EPILOGUE \ 291129198Scognet XSCALE_CACHE_CLEAN_UNBLOCK 292129198Scognet 293129198ScognetENTRY_NP(xscale_cache_syncI) 294269390Sian 295269390SianEENTRY_NP(xscale_cache_purgeID) 296129198Scognet mcr p15, 0, r0, c7, c5, 0 /* flush I cache (D cleaned below) */ 297269390SianEENTRY_NP(xscale_cache_cleanID) 298269390SianEENTRY_NP(xscale_cache_purgeD) 299269390SianEENTRY(xscale_cache_cleanD) 300129198Scognet XSCALE_CACHE_CLEAN_PROLOGUE 301129198Scognet 302129198Scognet1: subs r0, r0, #32 303129198Scognet mcr p15, 0, r0, c7, c2, 5 /* allocate cache line */ 304129198Scognet subs r1, r1, #32 305129198Scognet bne 1b 306129198Scognet 307129198Scognet CPWAIT(r0) 308129198Scognet 309129198Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 310129198Scognet 311129198Scognet CPWAIT(r0) 312129198Scognet 313129198Scognet XSCALE_CACHE_CLEAN_EPILOGUE 314137463Scognet RET 315269390SianEEND(xscale_cache_cleanD) 316269390SianEEND(xscale_cache_purgeD) 317269390SianEEND(xscale_cache_cleanID) 318269390SianEEND(xscale_cache_purgeID) 319248361SandrewEND(xscale_cache_syncI) 320129198Scognet 321129198Scognet/* 322129198Scognet * Clean the mini-data cache. 323129198Scognet * 324129198Scognet * It's expected that we only use the mini-data cache for 325129198Scognet * kernel addresses, so there is no need to purge it on 326129198Scognet * context switch, and no need to prevent userspace access 327129198Scognet * while we clean it. 328129198Scognet */ 329129198ScognetENTRY(xscale_cache_clean_minidata) 330129198Scognet ldr r2, .Lxscale_minidata_clean_addr 331129198Scognet ldmia r2, {r0, r1} 332129198Scognet1: ldr r3, [r0], #32 333129198Scognet subs r1, r1, #32 334129198Scognet bne 1b 335129198Scognet 336129198Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 337129198Scognet 338129198Scognet CPWAIT_AND_RETURN(r1) 339248361SandrewEND(xscale_cache_clean_minidata) 340129198Scognet 341129198ScognetENTRY(xscale_cache_purgeID_E) 342129198Scognet mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ 343129198Scognet CPWAIT(r1) 344129198Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 345129198Scognet mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */ 346129198Scognet mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */ 347129198Scognet CPWAIT_AND_RETURN(r1) 348248361SandrewEND(xscale_cache_purgeID_E) 349129198Scognet 350129198ScognetENTRY(xscale_cache_purgeD_E) 351129198Scognet mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ 352129198Scognet CPWAIT(r1) 353129198Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 354129198Scognet mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */ 355129198Scognet CPWAIT_AND_RETURN(r1) 356248361SandrewEND(xscale_cache_purgeD_E) 357129198Scognet 358129198Scognet/* 359129198Scognet * Soft functions 360129198Scognet */ 361129198Scognet/* xscale_cache_syncI is identical to xscale_cache_purgeID */ 362129198Scognet 363269390SianEENTRY(xscale_cache_cleanID_rng) 364129198ScognetENTRY(xscale_cache_cleanD_rng) 365129198Scognet cmp r1, #0x4000 366129198Scognet bcs _C_LABEL(xscale_cache_cleanID) 367129198Scognet 368129198Scognet and r2, r0, #0x1f 369129198Scognet add r1, r1, r2 370129198Scognet bic r0, r0, #0x1f 371129198Scognet 372129198Scognet1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ 373129198Scognet add r0, r0, #32 374129198Scognet subs r1, r1, #32 375129198Scognet bhi 1b 376129198Scognet 377129198Scognet CPWAIT(r0) 378129198Scognet 379129198Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 380129198Scognet 381129198Scognet CPWAIT_AND_RETURN(r0) 382269390Sian/*END(xscale_cache_cleanID_rng)*/ 383248361SandrewEND(xscale_cache_cleanD_rng) 384129198Scognet 385129198ScognetENTRY(xscale_cache_purgeID_rng) 386129198Scognet cmp r1, #0x4000 387129198Scognet bcs _C_LABEL(xscale_cache_purgeID) 388129198Scognet 389129198Scognet and r2, r0, #0x1f 390129198Scognet add r1, r1, r2 391129198Scognet bic r0, r0, #0x1f 392129198Scognet 393129198Scognet1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ 394129198Scognet mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */ 395129198Scognet mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */ 396129198Scognet add r0, r0, #32 397129198Scognet subs r1, r1, #32 398129198Scognet bhi 1b 399129198Scognet 400129198Scognet CPWAIT(r0) 401129198Scognet 402129198Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 403129198Scognet 404129198Scognet CPWAIT_AND_RETURN(r0) 405248361SandrewEND(xscale_cache_purgeID_rng) 406129198Scognet 407129198ScognetENTRY(xscale_cache_purgeD_rng) 408129198Scognet cmp r1, #0x4000 409129198Scognet bcs _C_LABEL(xscale_cache_purgeD) 410129198Scognet 411129198Scognet and r2, r0, #0x1f 412129198Scognet add r1, r1, r2 413129198Scognet bic r0, r0, #0x1f 414129198Scognet 415129198Scognet1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ 416129198Scognet mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */ 417129198Scognet add r0, r0, #32 418129198Scognet subs r1, r1, #32 419129198Scognet bhi 1b 420129198Scognet 421129198Scognet CPWAIT(r0) 422129198Scognet 423129198Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 424129198Scognet 425129198Scognet CPWAIT_AND_RETURN(r0) 426248361SandrewEND(xscale_cache_purgeD_rng) 427129198Scognet 428129198ScognetENTRY(xscale_cache_syncI_rng) 429129198Scognet cmp r1, #0x4000 430129198Scognet bcs _C_LABEL(xscale_cache_syncI) 431129198Scognet 432129198Scognet and r2, r0, #0x1f 433129198Scognet add r1, r1, r2 434129198Scognet bic r0, r0, #0x1f 435129198Scognet 436129198Scognet1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ 437129198Scognet mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */ 438129198Scognet add r0, r0, #32 439129198Scognet subs r1, r1, #32 440129198Scognet bhi 1b 441129198Scognet 442129198Scognet CPWAIT(r0) 443129198Scognet 444129198Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 445129198Scognet 446129198Scognet CPWAIT_AND_RETURN(r0) 447248361SandrewEND(xscale_cache_syncI_rng) 448129198Scognet 449129198ScognetENTRY(xscale_cache_flushD_rng) 450129198Scognet and r2, r0, #0x1f 451129198Scognet add r1, r1, r2 452129198Scognet bic r0, r0, #0x1f 453129198Scognet 454129198Scognet1: mcr p15, 0, r0, c7, c6, 1 /* flush D cache single entry */ 455129198Scognet add r0, r0, #32 456129198Scognet subs r1, r1, #32 457129198Scognet bhi 1b 458129198Scognet 459129198Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 460129198Scognet 461129198Scognet CPWAIT_AND_RETURN(r0) 462248361SandrewEND(xscale_cache_flushD_rng) 463129198Scognet 464129198Scognet/* 465129198Scognet * Context switch. 466129198Scognet * 467129198Scognet * These is the CPU-specific parts of the context switcher cpu_switch() 468129198Scognet * These functions actually perform the TTB reload. 469129198Scognet * 470129198Scognet * NOTE: Special calling convention 471129198Scognet * r1, r4-r13 must be preserved 472129198Scognet */ 473129198ScognetENTRY(xscale_context_switch) 474129198Scognet /* 475129198Scognet * CF_CACHE_PURGE_ID will *ALWAYS* be called prior to this. 476129198Scognet * Thus the data cache will contain only kernel data and the 477129198Scognet * instruction cache will contain only kernel code, and all 478129198Scognet * kernel mappings are shared by all processes. 479129198Scognet */ 480129198Scognet 481129198Scognet /* Write the TTB */ 482129198Scognet mcr p15, 0, r0, c2, c0, 0 483129198Scognet 484129198Scognet /* If we have updated the TTB we must flush the TLB */ 485129198Scognet mcr p15, 0, r0, c8, c7, 0 /* flush the I+D tlb */ 486129198Scognet 487129198Scognet CPWAIT_AND_RETURN(r0) 488248361SandrewEND(xscale_context_switch) 489129198Scognet 490129198Scognet/* 491129198Scognet * xscale_cpu_sleep 492129198Scognet * 493129198Scognet * This is called when there is nothing on any of the run queues. 494129198Scognet * We go into IDLE mode so that any IRQ or FIQ will awaken us. 495129198Scognet * 496129198Scognet * If this is called with anything other than ARM_SLEEP_MODE_IDLE, 497129198Scognet * ignore it. 498129198Scognet */ 499129198ScognetENTRY(xscale_cpu_sleep) 500129198Scognet tst r0, #0x00000000 501129198Scognet bne 1f 502129198Scognet mov r0, #0x1 503129198Scognet mcr p14, 0, r0, c7, c0, 0 504129198Scognet 505129198Scognet1: 506137463Scognet RET 507248361SandrewEND(xscale_cpu_sleep) 508248361Sandrew 509