1239701Sgonzo/* $NetBSD: cpufunc_asm_armv6.S,v 1.4 2010/12/10 02:06:22 bsh Exp $ */ 2239701Sgonzo 3239701Sgonzo/* 4239701Sgonzo * Copyright (c) 2002, 2005 ARM Limited 5239701Sgonzo * Portions Copyright (c) 2007 Microsoft 6239701Sgonzo * All rights reserved. 7239701Sgonzo * 8239701Sgonzo * Redistribution and use in source and binary forms, with or without 9239701Sgonzo * modification, are permitted provided that the following conditions 10239701Sgonzo * are met: 11239701Sgonzo * 1. Redistributions of source code must retain the above copyright 12239701Sgonzo * notice, this list of conditions and the following disclaimer. 13239701Sgonzo * 2. Redistributions in binary form must reproduce the above copyright 14239701Sgonzo * notice, this list of conditions and the following disclaimer in the 15239701Sgonzo * documentation and/or other materials provided with the distribution. 16239701Sgonzo * 3. The name of the company may not be used to endorse or promote 17239701Sgonzo * products derived from this software without specific prior written 18239701Sgonzo * permission. 19239701Sgonzo * 20239701Sgonzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 21239701Sgonzo * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 22239701Sgonzo * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23239701Sgonzo * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24239701Sgonzo * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25239701Sgonzo * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26239701Sgonzo * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27239701Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28239701Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29239701Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30239701Sgonzo * SUCH DAMAGE. 31239701Sgonzo * 32239701Sgonzo * ARMv6 assembly functions for manipulating caches. 33239701Sgonzo * These routines can be used by any core that supports the mcrr address 34239701Sgonzo * range operations. 35239701Sgonzo */ 36239701Sgonzo 37239701Sgonzo/* 38239701Sgonzo * $FreeBSD: releng/10.2/sys/arm/arm/cpufunc_asm_armv6.S 269796 2014-08-11 01:29:28Z ian $ 39239701Sgonzo */ 40239701Sgonzo 41239701Sgonzo#include <machine/asm.h> 42239701Sgonzo 43239701Sgonzo .arch armv6 44239701Sgonzo 45239701Sgonzo/* 46239701Sgonzo * Functions to set the MMU Translation Table Base register 47239701Sgonzo * 48239701Sgonzo * We need to clean and flush the cache as it uses virtual 49239701Sgonzo * addresses that are about to change. 50239701Sgonzo */ 51239701SgonzoENTRY(armv6_setttb) 52239701Sgonzo mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ 53239701Sgonzo 54239701Sgonzo mcr p15, 0, r0, c2, c0, 0 /* load new TTB */ 55239701Sgonzo 56239701Sgonzo mcr p15, 0, r0, c8, c7, 0 /* invalidate I+D TLBs */ 57239701Sgonzo RET 58248361SandrewEND(armv6_setttb) 59239701Sgonzo 60239701Sgonzo/* 61239701Sgonzo * Cache operations. 62239701Sgonzo */ 63239701Sgonzo 64239701Sgonzo/* LINTSTUB: void armv6_icache_sync_range(vaddr_t, vsize_t); */ 65239701SgonzoENTRY_NP(armv6_icache_sync_range) 66239701Sgonzo add r1, r1, r0 67239701Sgonzo sub r1, r1, #1 68239701Sgonzo mcrr p15, 0, r1, r0, c5 /* invalidate I cache range */ 69239701Sgonzo mcrr p15, 0, r1, r0, c12 /* clean D cache range */ 70239701Sgonzo mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ 71239701Sgonzo RET 72248361SandrewEND(armv6_icache_sync_range) 73239701Sgonzo 74239701Sgonzo/* LINTSTUB: void armv6_icache_sync_all(void); */ 75239701SgonzoENTRY_NP(armv6_icache_sync_all) 76239701Sgonzo /* 77239701Sgonzo * We assume that the code here can never be out of sync with the 78239701Sgonzo * dcache, so that we can safely flush the Icache and fall through 79239701Sgonzo * into the Dcache cleaning code. 80239701Sgonzo */ 81239701Sgonzo mcr p15, 0, r0, c7, c5, 0 /* Flush I cache */ 82239701Sgonzo mcr p15, 0, r0, c7, c10, 0 /* Clean D cache */ 83239701Sgonzo mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ 84239701Sgonzo RET 85248361SandrewEND(armv6_icache_sync_all) 86239701Sgonzo 87239701Sgonzo/* LINTSTUB: void armv6_dcache_wb_range(vaddr_t, vsize_t); */ 88239701SgonzoENTRY(armv6_dcache_wb_range) 89239701Sgonzo add r1, r1, r0 90239701Sgonzo sub r1, r1, #1 91239701Sgonzo mcrr p15, 0, r1, r0, c12 /* clean D cache range */ 92239701Sgonzo mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ 93239701Sgonzo RET 94248361SandrewEND(armv6_dcache_wb_range) 95239701Sgonzo 96239701Sgonzo/* LINTSTUB: void armv6_dcache_wbinv_range(vaddr_t, vsize_t); */ 97239701SgonzoENTRY(armv6_dcache_wbinv_range) 98239701Sgonzo add r1, r1, r0 99239701Sgonzo sub r1, r1, #1 100239701Sgonzo mcrr p15, 0, r1, r0, c14 /* clean and invaliate D cache range */ 101239701Sgonzo mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ 102239701Sgonzo RET 103248361SandrewEND(armv6_dcache_wbinv_range) 104239701Sgonzo 105239701Sgonzo/* 106239701Sgonzo * Note, we must not invalidate everything. If the range is too big we 107239701Sgonzo * must use wb-inv of the entire cache. 108239701Sgonzo * 109239701Sgonzo * LINTSTUB: void armv6_dcache_inv_range(vaddr_t, vsize_t); 110239701Sgonzo */ 111239701SgonzoENTRY(armv6_dcache_inv_range) 112239701Sgonzo add r1, r1, r0 113239701Sgonzo sub r1, r1, #1 114239701Sgonzo mcrr p15, 0, r1, r0, c6 /* invaliate D cache range */ 115239701Sgonzo mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ 116239701Sgonzo RET 117248361SandrewEND(armv6_dcache_inv_range) 118239701Sgonzo 119239701Sgonzo/* LINTSTUB: void armv6_idcache_wbinv_range(vaddr_t, vsize_t); */ 120239701SgonzoENTRY(armv6_idcache_wbinv_range) 121239701Sgonzo add r1, r1, r0 122239701Sgonzo sub r1, r1, #1 123239701Sgonzo mcrr p15, 0, r1, r0, c5 /* invaliate I cache range */ 124239701Sgonzo mcrr p15, 0, r1, r0, c14 /* clean & invaliate D cache range */ 125239701Sgonzo mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ 126239701Sgonzo RET 127248361SandrewEND(armv6_idcache_wbinv_range) 128239701Sgonzo 129239701Sgonzo/* LINTSTUB: void armv6_idcache_wbinv_all(void); */ 130239701SgonzoENTRY_NP(armv6_idcache_wbinv_all) 131239701Sgonzo /* 132239701Sgonzo * We assume that the code here can never be out of sync with the 133239701Sgonzo * dcache, so that we can safely flush the Icache and fall through 134239701Sgonzo * into the Dcache purging code. 135239701Sgonzo */ 136239701Sgonzo mcr p15, 0, r0, c7, c5, 0 /* Flush I cache */ 137239701Sgonzo /* Fall through to purge Dcache. */ 138239701Sgonzo 139239701Sgonzo/* LINTSTUB: void armv6_dcache_wbinv_all(void); */ 140269796SianEENTRY(armv6_dcache_wbinv_all) 141239701Sgonzo mcr p15, 0, r0, c7, c14, 0 /* clean & invalidate D cache */ 142239701Sgonzo mcr p15, 0, r0, c7, c10, 4 /* drain the write buffer */ 143239701Sgonzo RET 144269796SianEEND(armv6_dcache_wbinv_all) 145248361SandrewEND(armv6_idcache_wbinv_all) 146248361Sandrew 147266203SianENTRY(armv6_idcache_inv_all) 148266203Sian mov r0, #0 149266203Sian mcr p15, 0, r0, c7, c7, 0 /* invalidate all I+D cache */ 150266203Sian RET 151266203SianEND(armv6_idcache_inv_all) 152266203Sian 153