1171617Scognet/* $NetBSD: cpufunc_asm_xscale.S,v 1.16 2002/08/17 16:36:32 thorpej Exp $ */ 2171617Scognet 3171617Scognet/*- 4171617Scognet * Copyright (c) 2007 Olivier Houchard 5171617Scognet * Copyright (c) 2001, 2002 Wasabi Systems, Inc. 6171617Scognet * All rights reserved. 7171617Scognet * 8171617Scognet * Written by Allen Briggs and Jason R. Thorpe for Wasabi Systems, Inc. 9171617Scognet * 10171617Scognet * Redistribution and use in source and binary forms, with or without 11171617Scognet * modification, are permitted provided that the following conditions 12171617Scognet * are met: 13171617Scognet * 1. Redistributions of source code must retain the above copyright 14171617Scognet * notice, this list of conditions and the following disclaimer. 15171617Scognet * 2. Redistributions in binary form must reproduce the above copyright 16171617Scognet * notice, this list of conditions and the following disclaimer in the 17171617Scognet * documentation and/or other materials provided with the distribution. 18171617Scognet * 3. All advertising materials mentioning features or use of this software 19171617Scognet * must display the following acknowledgement: 20171617Scognet * This product includes software developed for the NetBSD Project by 21171617Scognet * Wasabi Systems, Inc. 22171617Scognet * 4. The name of Wasabi Systems, Inc. may not be used to endorse 23171617Scognet * or promote products derived from this software without specific prior 24171617Scognet * written permission. 25171617Scognet * 26171617Scognet * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 27171617Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28171617Scognet * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29171617Scognet * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 30171617Scognet * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31171617Scognet * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32171617Scognet * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33171617Scognet * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34171617Scognet * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35171617Scognet * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36171617Scognet * POSSIBILITY OF SUCH DAMAGE. 37171617Scognet * 38171617Scognet */ 39171617Scognet 40171617Scognet/*- 41171617Scognet * Copyright (c) 2001 Matt Thomas. 42171617Scognet * Copyright (c) 1997,1998 Mark Brinicombe. 43171617Scognet * Copyright (c) 1997 Causality Limited 44171617Scognet * All rights reserved. 45171617Scognet * 46171617Scognet * Redistribution and use in source and binary forms, with or without 47171617Scognet * modification, are permitted provided that the following conditions 48171617Scognet * are met: 49171617Scognet * 1. Redistributions of source code must retain the above copyright 50171617Scognet * notice, this list of conditions and the following disclaimer. 51171617Scognet * 2. Redistributions in binary form must reproduce the above copyright 52171617Scognet * notice, this list of conditions and the following disclaimer in the 53171617Scognet * documentation and/or other materials provided with the distribution. 54171617Scognet * 3. All advertising materials mentioning features or use of this software 55171617Scognet * must display the following acknowledgement: 56171617Scognet * This product includes software developed by Causality Limited. 57171617Scognet * 4. The name of Causality Limited may not be used to endorse or promote 58171617Scognet * products derived from this software without specific prior written 59171617Scognet * permission. 60171617Scognet * 61171617Scognet * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS 62171617Scognet * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 63171617Scognet * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 64171617Scognet * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT, 65171617Scognet * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 66171617Scognet * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 67171617Scognet * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 68171617Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 69171617Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 70171617Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 71171617Scognet * SUCH DAMAGE. 72171617Scognet * 73171617Scognet * XScale core 3 assembly functions for CPU / MMU / TLB specific operations 74171617Scognet */ 75236991Simp 76271398Sandrew#include <machine/armreg.h> 77171617Scognet#include <machine/asm.h> 78171617Scognet__FBSDID("$FreeBSD: stable/11/sys/arm/arm/cpufunc_asm_xscale_c3.S 331890 2018-04-02 22:02:49Z gonzo $"); 79171617Scognet 80171617Scognet/* 81171617Scognet * Size of the XScale core D-cache. 82171617Scognet */ 83171617Scognet#define DCACHE_SIZE 0x00008000 84171617Scognet 85171617Scognet/* 86171617Scognet * CPWAIT -- Canonical method to wait for CP15 update. 87171617Scognet * From: Intel 80200 manual, section 2.3.3. 88171617Scognet * 89171617Scognet * NOTE: Clobbers the specified temp reg. 90171617Scognet */ 91171617Scognet#define CPWAIT_BRANCH \ 92171617Scognet sub pc, pc, #4 93171617Scognet 94171617Scognet#define CPWAIT(tmp) \ 95171617Scognet mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\ 96171617Scognet mov tmp, tmp /* wait for it to complete */ ;\ 97171617Scognet CPWAIT_BRANCH /* branch to next insn */ 98171617Scognet 99171617Scognet#define CPWAIT_AND_RETURN_SHIFTER lsr #32 100171617Scognet 101171617Scognet#define CPWAIT_AND_RETURN(tmp) \ 102171617Scognet mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\ 103171617Scognet /* Wait for it to complete and branch to the return address */ \ 104171617Scognet sub pc, lr, tmp, CPWAIT_AND_RETURN_SHIFTER 105171617Scognet 106171617Scognet#define ARM_USE_L2_CACHE 107171617Scognet 108171617Scognet#define L2_CACHE_SIZE 0x80000 109171617Scognet#define L2_CACHE_WAYS 8 110171617Scognet#define L2_CACHE_LINE_SIZE 32 111171617Scognet#define L2_CACHE_SETS (L2_CACHE_SIZE / \ 112171617Scognet (L2_CACHE_WAYS * L2_CACHE_LINE_SIZE)) 113171617Scognet 114171617Scognet#define L1_DCACHE_SIZE 32 * 1024 115171617Scognet#define L1_DCACHE_WAYS 4 116171617Scognet#define L1_DCACHE_LINE_SIZE 32 117171617Scognet#define L1_DCACHE_SETS (L1_DCACHE_SIZE / \ 118171617Scognet (L1_DCACHE_WAYS * L1_DCACHE_LINE_SIZE)) 119171617Scognet#ifdef CACHE_CLEAN_BLOCK_INTR 120171617Scognet#define XSCALE_CACHE_CLEAN_BLOCK \ 121171617Scognet stmfd sp!, {r4} ; \ 122261393Sian mrs r4, cpsr ; \ 123271398Sandrew orr r0, r4, #(PSR_I | PSR_F) ; \ 124261393Sian msr cpsr_fsxc, r0 125171617Scognet 126171617Scognet#define XSCALE_CACHE_CLEAN_UNBLOCK \ 127261393Sian msr cpsr_fsxc, r4 ; \ 128171617Scognet ldmfd sp!, {r4} 129171617Scognet#else 130295267Smmel#define XSCALE_CACHE_CLEAN_BLOCK 131295267Smmel#define XSCALE_CACHE_CLEAN_UNBLOCK 132171617Scognet#endif /* CACHE_CLEAN_BLOCK_INTR */ 133171617Scognet 134171617Scognet 135171617ScognetENTRY_NP(xscalec3_cache_syncI) 136269390SianEENTRY_NP(xscalec3_cache_purgeID) 137171617Scognet mcr p15, 0, r0, c7, c5, 0 /* flush I cache (D cleaned below) */ 138269390SianEENTRY_NP(xscalec3_cache_cleanID) 139269390SianEENTRY_NP(xscalec3_cache_purgeD) 140269390SianEENTRY(xscalec3_cache_cleanD) 141171617Scognet 142171617Scognet XSCALE_CACHE_CLEAN_BLOCK 143171617Scognet mov r0, #0 144171617Scognet1: 145171617Scognet mov r1, r0, asl #30 146171617Scognet mov r2, #0 147171617Scognet2: 148171617Scognet orr r3, r1, r2, asl #5 149171617Scognet mcr p15, 0, r3, c7, c14, 2 /* clean and invalidate */ 150171617Scognet add r2, r2, #1 151171617Scognet cmp r2, #L1_DCACHE_SETS 152171617Scognet bne 2b 153171617Scognet add r0, r0, #1 154171617Scognet cmp r0, #4 155171617Scognet bne 1b 156171617Scognet CPWAIT(r0) 157171617Scognet XSCALE_CACHE_CLEAN_UNBLOCK 158171617Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 159171617Scognet 160171617Scognet RET 161269390SianEEND(xscalec3_cache_purgeID) 162269390SianEEND(xscalec3_cache_cleanID) 163269390SianEEND(xscalec3_cache_purgeD) 164269390SianEEND(xscalec3_cache_cleanD) 165248361SandrewEND(xscalec3_cache_syncI) 166171617Scognet 167171617ScognetENTRY(xscalec3_cache_purgeID_rng) 168171617Scognet 169171617Scognet cmp r1, #0x4000 170171617Scognet bcs _C_LABEL(xscalec3_cache_cleanID) 171171617Scognet and r2, r0, #0x1f 172171617Scognet add r1, r1, r2 173171617Scognet bic r0, r0, #0x1f 174171617Scognet 175171617Scognet1: mcr p15, 0, r0, c7, c14, 1 /* clean/invalidate L1 D cache entry */ 176171617Scognet nop 177171617Scognet mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */ 178171617Scognet add r0, r0, #32 179171617Scognet subs r1, r1, #32 180171617Scognet bhi 1b 181171617Scognet 182171617Scognet CPWAIT(r0) 183171617Scognet 184171617Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 185171617Scognet 186171617Scognet CPWAIT_AND_RETURN(r0) 187248361SandrewEND(xscalec3_cache_purgeID_rng) 188171617Scognet 189171617ScognetENTRY(xscalec3_cache_syncI_rng) 190171617Scognet cmp r1, #0x4000 191171617Scognet bcs _C_LABEL(xscalec3_cache_syncI) 192171617Scognet 193171617Scognet and r2, r0, #0x1f 194171617Scognet add r1, r1, r2 195171617Scognet bic r0, r0, #0x1f 196171617Scognet 197171617Scognet1: mcr p15, 0, r0, c7, c10, 1 /* clean D cache entry */ 198171617Scognet mcr p15, 0, r0, c7, c5, 1 /* flush I cache single entry */ 199171617Scognet add r0, r0, #32 200171617Scognet subs r1, r1, #32 201171617Scognet bhi 1b 202171617Scognet 203171617Scognet CPWAIT(r0) 204171617Scognet 205171617Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 206171617Scognet 207171617Scognet CPWAIT_AND_RETURN(r0) 208248361SandrewEND(xscalec3_cache_syncI_rng) 209283366Sandrew 210171617ScognetENTRY(xscalec3_cache_purgeD_rng) 211171617Scognet 212171617Scognet cmp r1, #0x4000 213171617Scognet bcs _C_LABEL(xscalec3_cache_cleanID) 214171617Scognet and r2, r0, #0x1f 215171617Scognet add r1, r1, r2 216171617Scognet bic r0, r0, #0x1f 217171617Scognet 218171617Scognet1: mcr p15, 0, r0, c7, c14, 1 /* Clean and invalidate D cache entry */ 219171617Scognet add r0, r0, #32 220171617Scognet subs r1, r1, #32 221171617Scognet bhi 1b 222171617Scognet 223171617Scognet CPWAIT(r0) 224171617Scognet 225171617Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 226171617Scognet 227171617Scognet CPWAIT_AND_RETURN(r0) 228248361SandrewEND(xscalec3_cache_purgeD_rng) 229248361Sandrew 230171617ScognetENTRY(xscalec3_cache_cleanID_rng) 231269390SianEENTRY(xscalec3_cache_cleanD_rng) 232171617Scognet 233171617Scognet cmp r1, #0x4000 234171617Scognet bcs _C_LABEL(xscalec3_cache_cleanID) 235171617Scognet and r2, r0, #0x1f 236171617Scognet add r1, r1, r2 237171617Scognet bic r0, r0, #0x1f 238171617Scognet 239171617Scognet1: mcr p15, 0, r0, c7, c10, 1 /* clean L1 D cache entry */ 240171617Scognet nop 241171617Scognet add r0, r0, #32 242171617Scognet subs r1, r1, #32 243171617Scognet bhi 1b 244171617Scognet 245171617Scognet CPWAIT(r0) 246171617Scognet 247171617Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ 248171617Scognet 249171617Scognet CPWAIT_AND_RETURN(r0) 250269390SianEEND(xscalec3_cache_cleanD_rng) 251248361SandrewEND(xscalec3_cache_cleanID_rng) 252171617Scognet 253171617ScognetENTRY(xscalec3_l2cache_purge) 254171617Scognet /* Clean-up the L2 cache */ 255171617Scognet mcr p15, 0, r0, c7, c10, 5 /* Data memory barrier */ 256171617Scognet mov r0, #0 257171617Scognet1: 258171617Scognet mov r1, r0, asl #29 259171617Scognet mov r2, #0 260171617Scognet2: 261171617Scognet orr r3, r1, r2, asl #5 262171617Scognet mcr p15, 1, r3, c7, c15, 2 263171617Scognet add r2, r2, #1 264171617Scognet cmp r2, #L2_CACHE_SETS 265171617Scognet bne 2b 266171617Scognet add r0, r0, #1 267171617Scognet cmp r0, #8 268171617Scognet bne 1b 269171617Scognet mcr p15, 0, r0, c7, c10, 4 @ data write barrier 270171617Scognet 271171617Scognet CPWAIT(r0) 272171617Scognet mcr p15, 0, r0, c7, c10, 5 /* Data memory barrier */ 273171617Scognet RET 274248361SandrewEND(xscalec3_l2cache_purge) 275171617Scognet 276171617ScognetENTRY(xscalec3_l2cache_clean_rng) 277171617Scognet mcr p15, 0, r0, c7, c10, 5 /* Data memory barrier */ 278171617Scognet 279171617Scognet and r2, r0, #0x1f 280171617Scognet add r1, r1, r2 281171617Scognet bic r0, r0, #0x1f 282171617Scognet 283171617Scognet1: mcr p15, 1, r0, c7, c11, 1 /* Clean L2 D cache entry */ 284171617Scognet add r0, r0, #32 285171617Scognet subs r1, r1, #32 286171617Scognet bhi 1b 287171617Scognet 288171617Scognet 289171617Scognet CPWAIT(r0) 290171617Scognet 291171617Scognet mcr p15, 0, r0, c7, c10, 4 @ data write barrier 292171617Scognet mcr p15, 0, r0, c7, c10, 5 293171617Scognet 294171617Scognet CPWAIT_AND_RETURN(r0) 295248361SandrewEND(xscalec3_l2cache_clean_rng) 296171617Scognet 297171617ScognetENTRY(xscalec3_l2cache_purge_rng) 298171617Scognet 299171617Scognet mcr p15, 0, r0, c7, c10, 5 /* Data memory barrier */ 300171617Scognet 301171617Scognet and r2, r0, #0x1f 302171617Scognet add r1, r1, r2 303171617Scognet bic r0, r0, #0x1f 304171617Scognet 305171617Scognet1: mcr p15, 1, r0, c7, c11, 1 /* Clean L2 D cache entry */ 306171617Scognet mcr p15, 1, r0, c7, c7, 1 /* Invalidate L2 D cache entry */ 307171617Scognet add r0, r0, #32 308171617Scognet subs r1, r1, #32 309171617Scognet bhi 1b 310171617Scognet 311171617Scognet mcr p15, 0, r0, c7, c10, 4 @ data write barrier 312171617Scognet mcr p15, 0, r0, c7, c10, 5 313171617Scognet 314171617Scognet CPWAIT_AND_RETURN(r0) 315248361SandrewEND(xscalec3_l2cache_purge_rng) 316171617Scognet 317171617ScognetENTRY(xscalec3_l2cache_flush_rng) 318171617Scognet mcr p15, 0, r0, c7, c10, 5 /* Data memory barrier */ 319171617Scognet 320171617Scognet and r2, r0, #0x1f 321171617Scognet add r1, r1, r2 322171617Scognet bic r0, r0, #0x1f 323171617Scognet 324171617Scognet1: mcr p15, 1, r0, c7, c7, 1 /* Invalidate L2 cache line */ 325171617Scognet add r0, r0, #32 326171617Scognet subs r1, r1, #32 327171617Scognet bhi 1b 328171617Scognet mcr p15, 0, r0, c7, c10, 4 @ data write barrier 329171617Scognet mcr p15, 0, r0, c7, c10, 5 330171617Scognet CPWAIT_AND_RETURN(r0) 331248361SandrewEND(xscalec3_l2cache_flush_rng) 332248361Sandrew 333171617Scognet/* 334171617Scognet * Functions to set the MMU Translation Table Base register 335171617Scognet * 336171617Scognet * We need to clean and flush the cache as it uses virtual 337171617Scognet * addresses that are about to change. 338171617Scognet */ 339171617ScognetENTRY(xscalec3_setttb) 340171617Scognet#ifdef CACHE_CLEAN_BLOCK_INTR 341261393Sian mrs r3, cpsr 342271398Sandrew orr r1, r3, #(PSR_I | PSR_F) 343261393Sian msr cpsr_fsxc, r1 344171617Scognet#endif 345171617Scognet stmfd sp!, {r0-r3, lr} 346171617Scognet bl _C_LABEL(xscalec3_cache_cleanID) 347171617Scognet mcr p15, 0, r0, c7, c5, 0 /* invalidate I$ and BTB */ 348171617Scognet mcr p15, 0, r0, c7, c10, 4 /* drain write and fill buffer */ 349171617Scognet 350171617Scognet CPWAIT(r0) 351171617Scognet 352171617Scognet ldmfd sp!, {r0-r3, lr} 353171617Scognet 354171617Scognet#ifdef ARM_USE_L2_CACHE 355171617Scognet orr r0, r0, #0x18 /* cache the page table in L2 */ 356171617Scognet#endif 357236991Simp /* Write the TTB */ 358171617Scognet mcr p15, 0, r0, c2, c0, 0 359171617Scognet 360171617Scognet /* If we have updated the TTB we must flush the TLB */ 361171617Scognet mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLB */ 362171617Scognet 363171617Scognet CPWAIT(r0) 364171617Scognet 365171617Scognet#ifdef CACHE_CLEAN_BLOCK_INTR 366261393Sian msr cpsr_fsxc, r3 367171617Scognet#endif 368171617Scognet RET 369248361SandrewEND(xscalec3_setttb) 370171617Scognet 371171617Scognet/* 372171617Scognet * Context switch. 373171617Scognet * 374171617Scognet * These is the CPU-specific parts of the context switcher cpu_switch() 375171617Scognet * These functions actually perform the TTB reload. 376171617Scognet * 377171617Scognet * NOTE: Special calling convention 378171617Scognet * r1, r4-r13 must be preserved 379171617Scognet */ 380171617ScognetENTRY(xscalec3_context_switch) 381171617Scognet /* 382171617Scognet * CF_CACHE_PURGE_ID will *ALWAYS* be called prior to this. 383171617Scognet * Thus the data cache will contain only kernel data and the 384171617Scognet * instruction cache will contain only kernel code, and all 385171617Scognet * kernel mappings are shared by all processes. 386171617Scognet */ 387171617Scognet#ifdef ARM_USE_L2_CACHE 388171617Scognet orr r0, r0, #0x18 /* Cache the page table in L2 */ 389171617Scognet#endif 390171617Scognet /* Write the TTB */ 391171617Scognet mcr p15, 0, r0, c2, c0, 0 392171617Scognet 393171617Scognet /* If we have updated the TTB we must flush the TLB */ 394171617Scognet mcr p15, 0, r0, c8, c7, 0 /* flush the I+D tlb */ 395171617Scognet 396171617Scognet CPWAIT_AND_RETURN(r0) 397248361SandrewEND(xscalec3_context_switch) 398248361Sandrew 399