cpufunc.c revision 280824
1132718Skan/* $NetBSD: cpufunc.c,v 1.65 2003/11/05 12:53:15 scw Exp $ */ 290075Sobrien 3169689Skan/*- 490075Sobrien * arm9 support code Copyright (C) 2001 ARM Ltd 5169689Skan * Copyright (c) 1997 Mark Brinicombe. 690075Sobrien * Copyright (c) 1997 Causality Limited 7132718Skan * All rights reserved. 890075Sobrien * 990075Sobrien * Redistribution and use in source and binary forms, with or without 1090075Sobrien * modification, are permitted provided that the following conditions 1190075Sobrien * are met: 1290075Sobrien * 1. Redistributions of source code must retain the above copyright 1390075Sobrien * notice, this list of conditions and the following disclaimer. 1490075Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1590075Sobrien * notice, this list of conditions and the following disclaimer in the 1690075Sobrien * documentation and/or other materials provided with the distribution. 1790075Sobrien * 3. All advertising materials mentioning features or use of this software 1890075Sobrien * must display the following acknowledgement: 1990075Sobrien * This product includes software developed by Causality Limited. 2090075Sobrien * 4. The name of Causality Limited may not be used to endorse or promote 21169689Skan * products derived from this software without specific prior written 22169689Skan * permission. 2390075Sobrien * 2490075Sobrien * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS 25132718Skan * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26132718Skan * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27132718Skan * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT, 2890075Sobrien * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2990075Sobrien * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 3090075Sobrien * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3290075Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3390075Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3490075Sobrien * SUCH DAMAGE. 3590075Sobrien * 3690075Sobrien * RiscBSD kernel project 3790075Sobrien * 38117395Skan * cpufuncs.c 39132718Skan * 4090075Sobrien * C functions for supporting CPU / MMU / TLB specific operations. 4190075Sobrien * 4290075Sobrien * Created : 30/01/97 4390075Sobrien */ 4490075Sobrien#include <sys/cdefs.h> 4590075Sobrien__FBSDID("$FreeBSD: head/sys/arm/arm/cpufunc.c 280824 2015-03-29 21:12:59Z andrew $"); 4690075Sobrien 4790075Sobrien#include <sys/param.h> 4890075Sobrien#include <sys/systm.h> 4990075Sobrien#include <sys/lock.h> 5090075Sobrien#include <sys/mutex.h> 5190075Sobrien#include <sys/bus.h> 5290075Sobrien#include <machine/bus.h> 5390075Sobrien#include <machine/cpu.h> 5490075Sobrien#include <machine/disassem.h> 5590075Sobrien 5690075Sobrien#include <vm/vm.h> 5790075Sobrien#include <vm/pmap.h> 5890075Sobrien#include <vm/uma.h> 5990075Sobrien 6090075Sobrien#include <machine/cpuconf.h> 6190075Sobrien#include <machine/cpufunc.h> 6290075Sobrien 6390075Sobrien#ifdef CPU_XSCALE_80200 6490075Sobrien#include <arm/xscale/i80200/i80200reg.h> 6590075Sobrien#include <arm/xscale/i80200/i80200var.h> 6690075Sobrien#endif 6790075Sobrien 6890075Sobrien#if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219) 6990075Sobrien#include <arm/xscale/i80321/i80321reg.h> 7090075Sobrien#include <arm/xscale/i80321/i80321var.h> 7190075Sobrien#endif 7290075Sobrien 7390075Sobrien/* 7490075Sobrien * Some definitions in i81342reg.h clash with i80321reg.h. 7590075Sobrien * This only happens for the LINT kernel. As it happens, 7690075Sobrien * we don't need anything from i81342reg.h that we already 7790075Sobrien * got from somewhere else during a LINT compile. 7890075Sobrien */ 7990075Sobrien#if defined(CPU_XSCALE_81342) && !defined(COMPILING_LINT) 8090075Sobrien#include <arm/xscale/i8134x/i81342reg.h> 8190075Sobrien#endif 8290075Sobrien 8390075Sobrien#ifdef CPU_XSCALE_IXP425 8490075Sobrien#include <arm/xscale/ixp425/ixp425reg.h> 8590075Sobrien#include <arm/xscale/ixp425/ixp425var.h> 8690075Sobrien#endif 8790075Sobrien 8890075Sobrien/* PRIMARY CACHE VARIABLES */ 8990075Sobrienint arm_picache_size; 9090075Sobrienint arm_picache_line_size; 9190075Sobrienint arm_picache_ways; 92117395Skan 9390075Sobrienint arm_pdcache_size; /* and unified */ 9490075Sobrienint arm_pdcache_line_size; 9590075Sobrienint arm_pdcache_ways; 9690075Sobrien 9790075Sobrienint arm_pcache_type; 9890075Sobrienint arm_pcache_unified; 9990075Sobrien 10090075Sobrienint arm_dcache_align; 10190075Sobrienint arm_dcache_align_mask; 10290075Sobrien 10390075Sobrienu_int arm_cache_level; 10490075Sobrienu_int arm_cache_type[14]; 10590075Sobrienu_int arm_cache_loc; 10690075Sobrien 107169689Skan/* 1 == use cpu_sleep(), 0 == don't */ 108169689Skanint cpu_do_powersave; 109169689Skanint ctrl; 110169689Skan 111169689Skan#ifdef CPU_ARM9 112169689Skanstruct cpu_functions arm9_cpufuncs = { 113169689Skan /* CPU functions */ 114169689Skan 115169689Skan cpufunc_id, /* id */ 116169689Skan cpufunc_nullop, /* cpwait */ 117169689Skan 118169689Skan /* MMU functions */ 11990075Sobrien 12090075Sobrien cpufunc_control, /* control */ 12190075Sobrien cpufunc_domains, /* Domain */ 12290075Sobrien arm9_setttb, /* Setttb */ 123169689Skan cpufunc_faultstatus, /* Faultstatus */ 124169689Skan cpufunc_faultaddress, /* Faultaddress */ 125169689Skan 126169689Skan /* TLB functions */ 12790075Sobrien 12890075Sobrien armv4_tlb_flushID, /* tlb_flushID */ 12990075Sobrien arm9_tlb_flushID_SE, /* tlb_flushID_SE */ 13090075Sobrien armv4_tlb_flushI, /* tlb_flushI */ 13190075Sobrien (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ 13290075Sobrien armv4_tlb_flushD, /* tlb_flushD */ 13390075Sobrien armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 13490075Sobrien 13590075Sobrien /* Cache operations */ 13690075Sobrien 13790075Sobrien arm9_icache_sync_all, /* icache_sync_all */ 13890075Sobrien arm9_icache_sync_range, /* icache_sync_range */ 13990075Sobrien 14090075Sobrien arm9_dcache_wbinv_all, /* dcache_wbinv_all */ 14190075Sobrien arm9_dcache_wbinv_range, /* dcache_wbinv_range */ 14290075Sobrien arm9_dcache_inv_range, /* dcache_inv_range */ 14390075Sobrien arm9_dcache_wb_range, /* dcache_wb_range */ 14490075Sobrien 14590075Sobrien armv4_idcache_inv_all, /* idcache_inv_all */ 14690075Sobrien arm9_idcache_wbinv_all, /* idcache_wbinv_all */ 14790075Sobrien arm9_idcache_wbinv_range, /* idcache_wbinv_range */ 148132718Skan cpufunc_nullop, /* l2cache_wbinv_all */ 149132718Skan (void *)cpufunc_nullop, /* l2cache_wbinv_range */ 150132718Skan (void *)cpufunc_nullop, /* l2cache_inv_range */ 151132718Skan (void *)cpufunc_nullop, /* l2cache_wb_range */ 152132718Skan (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 153132718Skan 154132718Skan /* Other functions */ 155132718Skan 156132718Skan cpufunc_nullop, /* flush_prefetchbuf */ 157132718Skan armv4_drain_writebuf, /* drain_writebuf */ 158132718Skan cpufunc_nullop, /* flush_brnchtgt_C */ 159132718Skan (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 160132718Skan 161132718Skan (void *)cpufunc_nullop, /* sleep */ 162132718Skan 163132718Skan /* Soft functions */ 164132718Skan 165132718Skan cpufunc_null_fixup, /* dataabt_fixup */ 16690075Sobrien cpufunc_null_fixup, /* prefetchabt_fixup */ 167132718Skan 168132718Skan arm9_context_switch, /* context_switch */ 169132718Skan 170132718Skan arm9_setup /* cpu setup */ 171132718Skan 172132718Skan}; 173132718Skan#endif /* CPU_ARM9 */ 174132718Skan 175132718Skan#if defined(CPU_ARM9E) 176132718Skanstruct cpu_functions armv5_ec_cpufuncs = { 177132718Skan /* CPU functions */ 178132718Skan 179132718Skan cpufunc_id, /* id */ 180132718Skan cpufunc_nullop, /* cpwait */ 181132718Skan 182132718Skan /* MMU functions */ 183132718Skan 184132718Skan cpufunc_control, /* control */ 18590075Sobrien cpufunc_domains, /* Domain */ 18690075Sobrien armv5_ec_setttb, /* Setttb */ 18790075Sobrien cpufunc_faultstatus, /* Faultstatus */ 188117395Skan cpufunc_faultaddress, /* Faultaddress */ 18990075Sobrien 19090075Sobrien /* TLB functions */ 19190075Sobrien 19290075Sobrien armv4_tlb_flushID, /* tlb_flushID */ 19390075Sobrien arm10_tlb_flushID_SE, /* tlb_flushID_SE */ 19490075Sobrien armv4_tlb_flushI, /* tlb_flushI */ 19590075Sobrien arm10_tlb_flushI_SE, /* tlb_flushI_SE */ 19690075Sobrien armv4_tlb_flushD, /* tlb_flushD */ 19790075Sobrien armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 19890075Sobrien 19990075Sobrien /* Cache operations */ 200117395Skan 201117395Skan armv5_ec_icache_sync_all, /* icache_sync_all */ 202117395Skan armv5_ec_icache_sync_range, /* icache_sync_range */ 203117395Skan 20490075Sobrien armv5_ec_dcache_wbinv_all, /* dcache_wbinv_all */ 20590075Sobrien armv5_ec_dcache_wbinv_range, /* dcache_wbinv_range */ 206169689Skan armv5_ec_dcache_inv_range, /* dcache_inv_range */ 207169689Skan armv5_ec_dcache_wb_range, /* dcache_wb_range */ 208169689Skan 20990075Sobrien armv4_idcache_inv_all, /* idcache_inv_all */ 210169689Skan armv5_ec_idcache_wbinv_all, /* idcache_wbinv_all */ 211169689Skan armv5_ec_idcache_wbinv_range, /* idcache_wbinv_range */ 212169689Skan 213169689Skan cpufunc_nullop, /* l2cache_wbinv_all */ 214169689Skan (void *)cpufunc_nullop, /* l2cache_wbinv_range */ 21590075Sobrien (void *)cpufunc_nullop, /* l2cache_inv_range */ 21690075Sobrien (void *)cpufunc_nullop, /* l2cache_wb_range */ 21790075Sobrien (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 21890075Sobrien 21990075Sobrien /* Other functions */ 22090075Sobrien 22190075Sobrien cpufunc_nullop, /* flush_prefetchbuf */ 22290075Sobrien armv4_drain_writebuf, /* drain_writebuf */ 22390075Sobrien cpufunc_nullop, /* flush_brnchtgt_C */ 22490075Sobrien (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 22590075Sobrien 22690075Sobrien (void *)cpufunc_nullop, /* sleep */ 22790075Sobrien 22890075Sobrien /* Soft functions */ 22990075Sobrien 23090075Sobrien cpufunc_null_fixup, /* dataabt_fixup */ 23190075Sobrien cpufunc_null_fixup, /* prefetchabt_fixup */ 23290075Sobrien 23390075Sobrien arm10_context_switch, /* context_switch */ 23490075Sobrien 23590075Sobrien arm10_setup /* cpu setup */ 23690075Sobrien 23790075Sobrien}; 23890075Sobrien 23990075Sobrienstruct cpu_functions sheeva_cpufuncs = { 24090075Sobrien /* CPU functions */ 24190075Sobrien 24290075Sobrien cpufunc_id, /* id */ 24390075Sobrien cpufunc_nullop, /* cpwait */ 24490075Sobrien 24590075Sobrien /* MMU functions */ 24690075Sobrien 24790075Sobrien cpufunc_control, /* control */ 24890075Sobrien cpufunc_domains, /* Domain */ 24990075Sobrien sheeva_setttb, /* Setttb */ 25090075Sobrien cpufunc_faultstatus, /* Faultstatus */ 25190075Sobrien cpufunc_faultaddress, /* Faultaddress */ 25290075Sobrien 25390075Sobrien /* TLB functions */ 25490075Sobrien 25590075Sobrien armv4_tlb_flushID, /* tlb_flushID */ 25690075Sobrien arm10_tlb_flushID_SE, /* tlb_flushID_SE */ 25790075Sobrien armv4_tlb_flushI, /* tlb_flushI */ 25890075Sobrien arm10_tlb_flushI_SE, /* tlb_flushI_SE */ 25990075Sobrien armv4_tlb_flushD, /* tlb_flushD */ 26090075Sobrien armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 26190075Sobrien 26290075Sobrien /* Cache operations */ 26390075Sobrien 26490075Sobrien armv5_ec_icache_sync_all, /* icache_sync_all */ 26590075Sobrien armv5_ec_icache_sync_range, /* icache_sync_range */ 26690075Sobrien 26790075Sobrien armv5_ec_dcache_wbinv_all, /* dcache_wbinv_all */ 26890075Sobrien sheeva_dcache_wbinv_range, /* dcache_wbinv_range */ 26990075Sobrien sheeva_dcache_inv_range, /* dcache_inv_range */ 27090075Sobrien sheeva_dcache_wb_range, /* dcache_wb_range */ 27190075Sobrien 27290075Sobrien armv4_idcache_inv_all, /* idcache_inv_all */ 27390075Sobrien armv5_ec_idcache_wbinv_all, /* idcache_wbinv_all */ 27490075Sobrien sheeva_idcache_wbinv_range, /* idcache_wbinv_all */ 27590075Sobrien 27690075Sobrien sheeva_l2cache_wbinv_all, /* l2cache_wbinv_all */ 27790075Sobrien sheeva_l2cache_wbinv_range, /* l2cache_wbinv_range */ 27890075Sobrien sheeva_l2cache_inv_range, /* l2cache_inv_range */ 27990075Sobrien sheeva_l2cache_wb_range, /* l2cache_wb_range */ 28090075Sobrien (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 28190075Sobrien 28290075Sobrien /* Other functions */ 28390075Sobrien 28490075Sobrien cpufunc_nullop, /* flush_prefetchbuf */ 28590075Sobrien armv4_drain_writebuf, /* drain_writebuf */ 28690075Sobrien cpufunc_nullop, /* flush_brnchtgt_C */ 28790075Sobrien (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 28890075Sobrien 28990075Sobrien sheeva_cpu_sleep, /* sleep */ 29090075Sobrien 29190075Sobrien /* Soft functions */ 29290075Sobrien 29390075Sobrien cpufunc_null_fixup, /* dataabt_fixup */ 29490075Sobrien cpufunc_null_fixup, /* prefetchabt_fixup */ 29590075Sobrien 29690075Sobrien arm10_context_switch, /* context_switch */ 29790075Sobrien 29890075Sobrien arm10_setup /* cpu setup */ 29990075Sobrien}; 30090075Sobrien#endif /* CPU_ARM9E */ 30190075Sobrien 30290075Sobrien#ifdef CPU_MV_PJ4B 30390075Sobrienstruct cpu_functions pj4bv7_cpufuncs = { 30490075Sobrien /* CPU functions */ 30590075Sobrien 30690075Sobrien cpufunc_id, /* id */ 30790075Sobrien armv7_drain_writebuf, /* cpwait */ 30890075Sobrien 30990075Sobrien /* MMU functions */ 31090075Sobrien 31190075Sobrien cpufunc_control, /* control */ 31290075Sobrien cpufunc_domains, /* Domain */ 31390075Sobrien armv7_setttb, /* Setttb */ 31490075Sobrien cpufunc_faultstatus, /* Faultstatus */ 31590075Sobrien cpufunc_faultaddress, /* Faultaddress */ 31690075Sobrien 31790075Sobrien /* TLB functions */ 31890075Sobrien 31990075Sobrien armv7_tlb_flushID, /* tlb_flushID */ 32090075Sobrien armv7_tlb_flushID_SE, /* tlb_flushID_SE */ 32190075Sobrien armv7_tlb_flushID, /* tlb_flushI */ 32290075Sobrien armv7_tlb_flushID_SE, /* tlb_flushI_SE */ 32390075Sobrien armv7_tlb_flushID, /* tlb_flushD */ 32490075Sobrien armv7_tlb_flushID_SE, /* tlb_flushD_SE */ 32590075Sobrien 32690075Sobrien /* Cache operations */ 32790075Sobrien armv7_idcache_wbinv_all, /* icache_sync_all */ 32890075Sobrien armv7_icache_sync_range, /* icache_sync_range */ 32990075Sobrien 33090075Sobrien armv7_dcache_wbinv_all, /* dcache_wbinv_all */ 33190075Sobrien armv7_dcache_wbinv_range, /* dcache_wbinv_range */ 33290075Sobrien armv7_dcache_inv_range, /* dcache_inv_range */ 33390075Sobrien armv7_dcache_wb_range, /* dcache_wb_range */ 33490075Sobrien 33590075Sobrien armv7_idcache_inv_all, /* idcache_inv_all */ 33690075Sobrien armv7_idcache_wbinv_all, /* idcache_wbinv_all */ 33790075Sobrien armv7_idcache_wbinv_range, /* idcache_wbinv_all */ 33890075Sobrien 33990075Sobrien (void *)cpufunc_nullop, /* l2cache_wbinv_all */ 34090075Sobrien (void *)cpufunc_nullop, /* l2cache_wbinv_range */ 34190075Sobrien (void *)cpufunc_nullop, /* l2cache_inv_range */ 34290075Sobrien (void *)cpufunc_nullop, /* l2cache_wb_range */ 34390075Sobrien (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 34490075Sobrien 34590075Sobrien /* Other functions */ 34690075Sobrien 34790075Sobrien cpufunc_nullop, /* flush_prefetchbuf */ 34890075Sobrien armv7_drain_writebuf, /* drain_writebuf */ 34990075Sobrien cpufunc_nullop, /* flush_brnchtgt_C */ 35090075Sobrien (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 35190075Sobrien 35290075Sobrien (void *)cpufunc_nullop, /* sleep */ 35390075Sobrien 35490075Sobrien /* Soft functions */ 35590075Sobrien 35690075Sobrien cpufunc_null_fixup, /* dataabt_fixup */ 35790075Sobrien cpufunc_null_fixup, /* prefetchabt_fixup */ 35890075Sobrien 35990075Sobrien armv7_context_switch, /* context_switch */ 36090075Sobrien 36190075Sobrien pj4bv7_setup /* cpu setup */ 36290075Sobrien}; 36390075Sobrien#endif /* CPU_MV_PJ4B */ 36490075Sobrien 36590075Sobrien#if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ 36690075Sobrien defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ 36790075Sobrien defined(CPU_XSCALE_80219) 36890075Sobrien 36990075Sobrienstruct cpu_functions xscale_cpufuncs = { 37090075Sobrien /* CPU functions */ 37190075Sobrien 37290075Sobrien cpufunc_id, /* id */ 37390075Sobrien xscale_cpwait, /* cpwait */ 37490075Sobrien 37590075Sobrien /* MMU functions */ 37690075Sobrien 377132718Skan xscale_control, /* control */ 37890075Sobrien cpufunc_domains, /* domain */ 37990075Sobrien xscale_setttb, /* setttb */ 38090075Sobrien cpufunc_faultstatus, /* faultstatus */ 38190075Sobrien cpufunc_faultaddress, /* faultaddress */ 38290075Sobrien 38390075Sobrien /* TLB functions */ 38490075Sobrien 38590075Sobrien armv4_tlb_flushID, /* tlb_flushID */ 38690075Sobrien xscale_tlb_flushID_SE, /* tlb_flushID_SE */ 38790075Sobrien armv4_tlb_flushI, /* tlb_flushI */ 38890075Sobrien (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ 38990075Sobrien armv4_tlb_flushD, /* tlb_flushD */ 39090075Sobrien armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 39190075Sobrien 39290075Sobrien /* Cache operations */ 39390075Sobrien 39490075Sobrien xscale_cache_syncI, /* icache_sync_all */ 39590075Sobrien xscale_cache_syncI_rng, /* icache_sync_range */ 39690075Sobrien 39790075Sobrien xscale_cache_purgeD, /* dcache_wbinv_all */ 39890075Sobrien xscale_cache_purgeD_rng, /* dcache_wbinv_range */ 39990075Sobrien xscale_cache_flushD_rng, /* dcache_inv_range */ 40090075Sobrien xscale_cache_cleanD_rng, /* dcache_wb_range */ 40190075Sobrien 40290075Sobrien xscale_cache_flushID, /* idcache_inv_all */ 40390075Sobrien xscale_cache_purgeID, /* idcache_wbinv_all */ 40490075Sobrien xscale_cache_purgeID_rng, /* idcache_wbinv_range */ 40590075Sobrien cpufunc_nullop, /* l2cache_wbinv_all */ 406132718Skan (void *)cpufunc_nullop, /* l2cache_wbinv_range */ 40790075Sobrien (void *)cpufunc_nullop, /* l2cache_inv_range */ 40890075Sobrien (void *)cpufunc_nullop, /* l2cache_wb_range */ 40990075Sobrien (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 41090075Sobrien 41190075Sobrien /* Other functions */ 41290075Sobrien 41390075Sobrien cpufunc_nullop, /* flush_prefetchbuf */ 41490075Sobrien armv4_drain_writebuf, /* drain_writebuf */ 41590075Sobrien cpufunc_nullop, /* flush_brnchtgt_C */ 41690075Sobrien (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 41790075Sobrien 41890075Sobrien xscale_cpu_sleep, /* sleep */ 41990075Sobrien 42090075Sobrien /* Soft functions */ 42190075Sobrien 42290075Sobrien cpufunc_null_fixup, /* dataabt_fixup */ 42390075Sobrien cpufunc_null_fixup, /* prefetchabt_fixup */ 42490075Sobrien 42590075Sobrien xscale_context_switch, /* context_switch */ 42690075Sobrien 427132718Skan xscale_setup /* cpu setup */ 42890075Sobrien}; 42990075Sobrien#endif 43090075Sobrien/* CPU_XSCALE_80200 || CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 43190075Sobrien CPU_XSCALE_80219 */ 432169689Skan 43390075Sobrien#ifdef CPU_XSCALE_81342 43490075Sobrienstruct cpu_functions xscalec3_cpufuncs = { 43590075Sobrien /* CPU functions */ 43690075Sobrien 437169689Skan cpufunc_id, /* id */ 438169689Skan xscale_cpwait, /* cpwait */ 43990075Sobrien 44090075Sobrien /* MMU functions */ 44190075Sobrien 44290075Sobrien xscale_control, /* control */ 44390075Sobrien cpufunc_domains, /* domain */ 44490075Sobrien xscalec3_setttb, /* setttb */ 44590075Sobrien cpufunc_faultstatus, /* faultstatus */ 44690075Sobrien cpufunc_faultaddress, /* faultaddress */ 44790075Sobrien 44890075Sobrien /* TLB functions */ 44990075Sobrien 45090075Sobrien armv4_tlb_flushID, /* tlb_flushID */ 45190075Sobrien xscale_tlb_flushID_SE, /* tlb_flushID_SE */ 45290075Sobrien armv4_tlb_flushI, /* tlb_flushI */ 45390075Sobrien (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ 45490075Sobrien armv4_tlb_flushD, /* tlb_flushD */ 45590075Sobrien armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 45690075Sobrien 45790075Sobrien /* Cache operations */ 45890075Sobrien 45990075Sobrien xscalec3_cache_syncI, /* icache_sync_all */ 46090075Sobrien xscalec3_cache_syncI_rng, /* icache_sync_range */ 46190075Sobrien 46290075Sobrien xscalec3_cache_purgeD, /* dcache_wbinv_all */ 46390075Sobrien xscalec3_cache_purgeD_rng, /* dcache_wbinv_range */ 464117395Skan xscale_cache_flushD_rng, /* dcache_inv_range */ 46590075Sobrien xscalec3_cache_cleanD_rng, /* dcache_wb_range */ 46690075Sobrien 46790075Sobrien xscale_cache_flushID, /* idcache_inv_all */ 46890075Sobrien xscalec3_cache_purgeID, /* idcache_wbinv_all */ 46990075Sobrien xscalec3_cache_purgeID_rng, /* idcache_wbinv_range */ 47090075Sobrien xscalec3_l2cache_purge, /* l2cache_wbinv_all */ 47190075Sobrien xscalec3_l2cache_purge_rng, /* l2cache_wbinv_range */ 47290075Sobrien xscalec3_l2cache_flush_rng, /* l2cache_inv_range */ 47390075Sobrien xscalec3_l2cache_clean_rng, /* l2cache_wb_range */ 47490075Sobrien (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 47590075Sobrien 47690075Sobrien /* Other functions */ 47790075Sobrien 47890075Sobrien cpufunc_nullop, /* flush_prefetchbuf */ 47990075Sobrien armv4_drain_writebuf, /* drain_writebuf */ 48090075Sobrien cpufunc_nullop, /* flush_brnchtgt_C */ 48190075Sobrien (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 48290075Sobrien 48390075Sobrien xscale_cpu_sleep, /* sleep */ 48490075Sobrien 48590075Sobrien /* Soft functions */ 48690075Sobrien 48790075Sobrien cpufunc_null_fixup, /* dataabt_fixup */ 48890075Sobrien cpufunc_null_fixup, /* prefetchabt_fixup */ 48990075Sobrien 49090075Sobrien xscalec3_context_switch, /* context_switch */ 49190075Sobrien 49290075Sobrien xscale_setup /* cpu setup */ 49390075Sobrien}; 49490075Sobrien#endif /* CPU_XSCALE_81342 */ 49590075Sobrien 49690075Sobrien 49790075Sobrien#if defined(CPU_FA526) || defined(CPU_FA626TE) 49890075Sobrienstruct cpu_functions fa526_cpufuncs = { 49990075Sobrien /* CPU functions */ 50090075Sobrien 50190075Sobrien cpufunc_id, /* id */ 50290075Sobrien cpufunc_nullop, /* cpwait */ 50390075Sobrien 50490075Sobrien /* MMU functions */ 50590075Sobrien 50690075Sobrien cpufunc_control, /* control */ 50790075Sobrien cpufunc_domains, /* domain */ 50890075Sobrien fa526_setttb, /* setttb */ 50990075Sobrien cpufunc_faultstatus, /* faultstatus */ 51090075Sobrien cpufunc_faultaddress, /* faultaddress */ 51190075Sobrien 51290075Sobrien /* TLB functions */ 51390075Sobrien 51490075Sobrien armv4_tlb_flushID, /* tlb_flushID */ 51590075Sobrien fa526_tlb_flushID_SE, /* tlb_flushID_SE */ 51690075Sobrien armv4_tlb_flushI, /* tlb_flushI */ 51790075Sobrien fa526_tlb_flushI_SE, /* tlb_flushI_SE */ 51890075Sobrien armv4_tlb_flushD, /* tlb_flushD */ 51990075Sobrien armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 52090075Sobrien 52190075Sobrien /* Cache operations */ 52290075Sobrien 52390075Sobrien fa526_icache_sync_all, /* icache_sync_all */ 52490075Sobrien fa526_icache_sync_range, /* icache_sync_range */ 52590075Sobrien 52690075Sobrien fa526_dcache_wbinv_all, /* dcache_wbinv_all */ 52790075Sobrien fa526_dcache_wbinv_range, /* dcache_wbinv_range */ 52890075Sobrien fa526_dcache_inv_range, /* dcache_inv_range */ 52990075Sobrien fa526_dcache_wb_range, /* dcache_wb_range */ 53090075Sobrien 53190075Sobrien armv4_idcache_inv_all, /* idcache_inv_all */ 53290075Sobrien fa526_idcache_wbinv_all, /* idcache_wbinv_all */ 53390075Sobrien fa526_idcache_wbinv_range, /* idcache_wbinv_range */ 53490075Sobrien cpufunc_nullop, /* l2cache_wbinv_all */ 53590075Sobrien (void *)cpufunc_nullop, /* l2cache_wbinv_range */ 53690075Sobrien (void *)cpufunc_nullop, /* l2cache_inv_range */ 53790075Sobrien (void *)cpufunc_nullop, /* l2cache_wb_range */ 53890075Sobrien (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 53990075Sobrien 54090075Sobrien /* Other functions */ 54190075Sobrien 54290075Sobrien fa526_flush_prefetchbuf, /* flush_prefetchbuf */ 54390075Sobrien armv4_drain_writebuf, /* drain_writebuf */ 54490075Sobrien cpufunc_nullop, /* flush_brnchtgt_C */ 54590075Sobrien fa526_flush_brnchtgt_E, /* flush_brnchtgt_E */ 54690075Sobrien 54790075Sobrien fa526_cpu_sleep, /* sleep */ 54890075Sobrien 54990075Sobrien /* Soft functions */ 550117395Skan 55190075Sobrien cpufunc_null_fixup, /* dataabt_fixup */ 55290075Sobrien cpufunc_null_fixup, /* prefetchabt_fixup */ 553132718Skan 55490075Sobrien fa526_context_switch, /* context_switch */ 55590075Sobrien 55690075Sobrien fa526_setup /* cpu setup */ 55790075Sobrien}; 55890075Sobrien#endif /* CPU_FA526 || CPU_FA626TE */ 55990075Sobrien 56090075Sobrien#if defined(CPU_ARM1176) 56190075Sobrienstruct cpu_functions arm1176_cpufuncs = { 56290075Sobrien /* CPU functions */ 56390075Sobrien 56490075Sobrien cpufunc_id, /* id */ 56590075Sobrien cpufunc_nullop, /* cpwait */ 56690075Sobrien 56790075Sobrien /* MMU functions */ 56890075Sobrien 56990075Sobrien cpufunc_control, /* control */ 57090075Sobrien cpufunc_domains, /* Domain */ 57190075Sobrien arm11x6_setttb, /* Setttb */ 57290075Sobrien cpufunc_faultstatus, /* Faultstatus */ 57390075Sobrien cpufunc_faultaddress, /* Faultaddress */ 57490075Sobrien 57590075Sobrien /* TLB functions */ 57690075Sobrien 57790075Sobrien arm11_tlb_flushID, /* tlb_flushID */ 57890075Sobrien arm11_tlb_flushID_SE, /* tlb_flushID_SE */ 579117395Skan arm11_tlb_flushI, /* tlb_flushI */ 58090075Sobrien arm11_tlb_flushI_SE, /* tlb_flushI_SE */ 58190075Sobrien arm11_tlb_flushD, /* tlb_flushD */ 582132718Skan arm11_tlb_flushD_SE, /* tlb_flushD_SE */ 58390075Sobrien 58490075Sobrien /* Cache operations */ 58590075Sobrien 58690075Sobrien arm11x6_icache_sync_all, /* icache_sync_all */ 58790075Sobrien arm11x6_icache_sync_range, /* icache_sync_range */ 58890075Sobrien 58990075Sobrien arm11x6_dcache_wbinv_all, /* dcache_wbinv_all */ 59090075Sobrien armv6_dcache_wbinv_range, /* dcache_wbinv_range */ 59190075Sobrien armv6_dcache_inv_range, /* dcache_inv_range */ 59290075Sobrien armv6_dcache_wb_range, /* dcache_wb_range */ 59390075Sobrien 59490075Sobrien armv6_idcache_inv_all, /* idcache_inv_all */ 59590075Sobrien arm11x6_idcache_wbinv_all, /* idcache_wbinv_all */ 59690075Sobrien arm11x6_idcache_wbinv_range, /* idcache_wbinv_range */ 597117395Skan 59890075Sobrien (void *)cpufunc_nullop, /* l2cache_wbinv_all */ 59990075Sobrien (void *)cpufunc_nullop, /* l2cache_wbinv_range */ 600132718Skan (void *)cpufunc_nullop, /* l2cache_inv_range */ 60190075Sobrien (void *)cpufunc_nullop, /* l2cache_wb_range */ 60290075Sobrien (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 60390075Sobrien 60490075Sobrien /* Other functions */ 60590075Sobrien 60690075Sobrien arm11x6_flush_prefetchbuf, /* flush_prefetchbuf */ 60790075Sobrien arm11_drain_writebuf, /* drain_writebuf */ 60890075Sobrien cpufunc_nullop, /* flush_brnchtgt_C */ 60990075Sobrien (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 61090075Sobrien 61190075Sobrien arm11x6_sleep, /* sleep */ 61290075Sobrien 61390075Sobrien /* Soft functions */ 61490075Sobrien 615117395Skan cpufunc_null_fixup, /* dataabt_fixup */ 61690075Sobrien cpufunc_null_fixup, /* prefetchabt_fixup */ 61790075Sobrien 618132718Skan arm11_context_switch, /* context_switch */ 61990075Sobrien 62090075Sobrien arm11x6_setup /* cpu setup */ 62190075Sobrien}; 62290075Sobrien#endif /*CPU_ARM1176 */ 62390075Sobrien 62490075Sobrien#if defined(CPU_CORTEXA) || defined(CPU_KRAIT) 62590075Sobrienstruct cpu_functions cortexa_cpufuncs = { 62690075Sobrien /* CPU functions */ 62790075Sobrien 62890075Sobrien cpufunc_id, /* id */ 62990075Sobrien cpufunc_nullop, /* cpwait */ 63090075Sobrien 63190075Sobrien /* MMU functions */ 632117395Skan 63390075Sobrien cpufunc_control, /* control */ 63490075Sobrien cpufunc_domains, /* Domain */ 635132718Skan armv7_setttb, /* Setttb */ 63690075Sobrien cpufunc_faultstatus, /* Faultstatus */ 63790075Sobrien cpufunc_faultaddress, /* Faultaddress */ 63890075Sobrien 63990075Sobrien /* 64090075Sobrien * TLB functions. ARMv7 does all TLB ops based on a unified TLB model 64190075Sobrien * whether the hardware implements separate I+D or not, so we use the 64290075Sobrien * same 'ID' functions for all 3 variations. 64390075Sobrien */ 644117395Skan 64590075Sobrien armv7_tlb_flushID, /* tlb_flushID */ 64690075Sobrien armv7_tlb_flushID_SE, /* tlb_flushID_SE */ 64790075Sobrien armv7_tlb_flushID, /* tlb_flushI */ 64890075Sobrien armv7_tlb_flushID_SE, /* tlb_flushI_SE */ 649117395Skan armv7_tlb_flushID, /* tlb_flushD */ 65090075Sobrien armv7_tlb_flushID_SE, /* tlb_flushD_SE */ 65190075Sobrien 652132718Skan /* Cache operations */ 653132718Skan 65490075Sobrien armv7_icache_sync_all, /* icache_sync_all */ 65590075Sobrien armv7_icache_sync_range, /* icache_sync_range */ 65690075Sobrien 65790075Sobrien armv7_dcache_wbinv_all, /* dcache_wbinv_all */ 65890075Sobrien armv7_dcache_wbinv_range, /* dcache_wbinv_range */ 65990075Sobrien armv7_dcache_inv_range, /* dcache_inv_range */ 66090075Sobrien armv7_dcache_wb_range, /* dcache_wb_range */ 66190075Sobrien 66290075Sobrien armv7_idcache_inv_all, /* idcache_inv_all */ 66390075Sobrien armv7_idcache_wbinv_all, /* idcache_wbinv_all */ 66490075Sobrien armv7_idcache_wbinv_range, /* idcache_wbinv_range */ 66590075Sobrien 66690075Sobrien /* 66790075Sobrien * Note: For CPUs using the PL310 the L2 ops are filled in when the 668117395Skan * L2 cache controller is actually enabled. 66990075Sobrien */ 67090075Sobrien cpufunc_nullop, /* l2cache_wbinv_all */ 671132718Skan (void *)cpufunc_nullop, /* l2cache_wbinv_range */ 672132718Skan (void *)cpufunc_nullop, /* l2cache_inv_range */ 67390075Sobrien (void *)cpufunc_nullop, /* l2cache_wb_range */ 67490075Sobrien (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 67590075Sobrien 67690075Sobrien /* Other functions */ 67790075Sobrien 67890075Sobrien cpufunc_nullop, /* flush_prefetchbuf */ 67990075Sobrien armv7_drain_writebuf, /* drain_writebuf */ 68090075Sobrien cpufunc_nullop, /* flush_brnchtgt_C */ 68190075Sobrien (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 68290075Sobrien 68390075Sobrien armv7_sleep, /* sleep */ 68490075Sobrien 68590075Sobrien /* Soft functions */ 68690075Sobrien 687117395Skan cpufunc_null_fixup, /* dataabt_fixup */ 68890075Sobrien cpufunc_null_fixup, /* prefetchabt_fixup */ 68990075Sobrien 690132718Skan armv7_context_switch, /* context_switch */ 69190075Sobrien 69290075Sobrien cortexa_setup /* cpu setup */ 69390075Sobrien}; 69490075Sobrien#endif /* CPU_CORTEXA */ 69590075Sobrien 69690075Sobrien/* 69790075Sobrien * Global constants also used by locore.s 69890075Sobrien */ 699117395Skan 70090075Sobrienstruct cpu_functions cpufuncs; 70190075Sobrienu_int cputype; 70290075Sobrienu_int cpu_reset_needs_v4_MMU_disable; /* flag used in locore.s */ 70390075Sobrien 704117395Skan#if defined(CPU_ARM9) || \ 70590075Sobrien defined (CPU_ARM9E) || \ 70690075Sobrien defined(CPU_ARM1176) || defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ 707132718Skan defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ 70890075Sobrien defined(CPU_FA526) || defined(CPU_FA626TE) || defined(CPU_MV_PJ4B) || \ 70990075Sobrien defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \ 71090075Sobrien defined(CPU_CORTEXA) || defined(CPU_KRAIT) 71190075Sobrien 71290075Sobrien/* Global cache line sizes, use 32 as default */ 71390075Sobrienint arm_dcache_min_line_size = 32; 71490075Sobrienint arm_icache_min_line_size = 32; 71590075Sobrienint arm_idcache_min_line_size = 32; 71690075Sobrien 71790075Sobrienstatic void get_cachetype_cp15(void); 71890075Sobrien 71990075Sobrien/* Additional cache information local to this file. Log2 of some of the 72090075Sobrien above numbers. */ 72190075Sobrienstatic int arm_dcache_l2_nsets; 72290075Sobrienstatic int arm_dcache_l2_assoc; 72390075Sobrienstatic int arm_dcache_l2_linesize; 72490075Sobrien 72590075Sobrienstatic void 72690075Sobrienget_cachetype_cp15() 72790075Sobrien{ 72890075Sobrien u_int ctype, isize, dsize, cpuid; 72990075Sobrien u_int clevel, csize, i, sel; 73090075Sobrien u_int multiplier; 73190075Sobrien u_char type; 73290075Sobrien 73390075Sobrien __asm __volatile("mrc p15, 0, %0, c0, c0, 1" 73490075Sobrien : "=r" (ctype)); 73590075Sobrien 73690075Sobrien cpuid = cpufunc_id(); 73790075Sobrien /* 73890075Sobrien * ...and thus spake the ARM ARM: 73990075Sobrien * 74090075Sobrien * If an <opcode2> value corresponding to an unimplemented or 74190075Sobrien * reserved ID register is encountered, the System Control 74290075Sobrien * processor returns the value of the main ID register. 74390075Sobrien */ 74490075Sobrien if (ctype == cpuid) 74590075Sobrien goto out; 74690075Sobrien 74790075Sobrien if (CPU_CT_FORMAT(ctype) == CPU_CT_ARMV7) { 74890075Sobrien /* Resolve minimal cache line sizes */ 74990075Sobrien arm_dcache_min_line_size = 1 << (CPU_CT_DMINLINE(ctype) + 2); 75090075Sobrien arm_icache_min_line_size = 1 << (CPU_CT_IMINLINE(ctype) + 2); 75190075Sobrien arm_idcache_min_line_size = 75290075Sobrien min(arm_icache_min_line_size, arm_dcache_min_line_size); 75390075Sobrien 75490075Sobrien __asm __volatile("mrc p15, 1, %0, c0, c0, 1" 75590075Sobrien : "=r" (clevel)); 75690075Sobrien arm_cache_level = clevel; 75790075Sobrien arm_cache_loc = CPU_CLIDR_LOC(arm_cache_level); 75890075Sobrien i = 0; 75990075Sobrien while ((type = (clevel & 0x7)) && i < 7) { 76090075Sobrien if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE || 76190075Sobrien type == CACHE_SEP_CACHE) { 76290075Sobrien sel = i << 1; 76390075Sobrien __asm __volatile("mcr p15, 2, %0, c0, c0, 0" 76490075Sobrien : : "r" (sel)); 76590075Sobrien __asm __volatile("mrc p15, 1, %0, c0, c0, 0" 76690075Sobrien : "=r" (csize)); 767117395Skan arm_cache_type[sel] = csize; 76890075Sobrien arm_dcache_align = 1 << 76990075Sobrien (CPUV7_CT_xSIZE_LEN(csize) + 4); 770132718Skan arm_dcache_align_mask = arm_dcache_align - 1; 77190075Sobrien } 77290075Sobrien if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) { 77390075Sobrien sel = (i << 1) | 1; 77490075Sobrien __asm __volatile("mcr p15, 2, %0, c0, c0, 0" 77590075Sobrien : : "r" (sel)); 77690075Sobrien __asm __volatile("mrc p15, 1, %0, c0, c0, 0" 77790075Sobrien : "=r" (csize)); 77890075Sobrien arm_cache_type[sel] = csize; 77990075Sobrien } 78090075Sobrien i++; 78190075Sobrien clevel >>= 3; 78290075Sobrien } 78390075Sobrien } else { 78490075Sobrien if ((ctype & CPU_CT_S) == 0) 78590075Sobrien arm_pcache_unified = 1; 786117395Skan 78790075Sobrien /* 78890075Sobrien * If you want to know how this code works, go read the ARM ARM. 789132718Skan */ 79090075Sobrien 79190075Sobrien arm_pcache_type = CPU_CT_CTYPE(ctype); 792117395Skan 79390075Sobrien if (arm_pcache_unified == 0) { 79490075Sobrien isize = CPU_CT_ISIZE(ctype); 79590075Sobrien multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2; 79690075Sobrien arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3); 79790075Sobrien if (CPU_CT_xSIZE_ASSOC(isize) == 0) { 798169689Skan if (isize & CPU_CT_xSIZE_M) 79990075Sobrien arm_picache_line_size = 0; /* not present */ 800169689Skan else 80190075Sobrien arm_picache_ways = 1; 802117395Skan } else { 80390075Sobrien arm_picache_ways = multiplier << 80490075Sobrien (CPU_CT_xSIZE_ASSOC(isize) - 1); 80590075Sobrien } 80690075Sobrien arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8); 80790075Sobrien } 80890075Sobrien 80990075Sobrien dsize = CPU_CT_DSIZE(ctype); 81090075Sobrien multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2; 81190075Sobrien arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3); 81290075Sobrien if (CPU_CT_xSIZE_ASSOC(dsize) == 0) { 81390075Sobrien if (dsize & CPU_CT_xSIZE_M) 81490075Sobrien arm_pdcache_line_size = 0; /* not present */ 815117395Skan else 81690075Sobrien arm_pdcache_ways = 1; 81790075Sobrien } else { 81890075Sobrien arm_pdcache_ways = multiplier << 81990075Sobrien (CPU_CT_xSIZE_ASSOC(dsize) - 1); 82090075Sobrien } 82190075Sobrien arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8); 82290075Sobrien 82390075Sobrien arm_dcache_align = arm_pdcache_line_size; 82490075Sobrien 82590075Sobrien arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2; 82690075Sobrien arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3; 82790075Sobrien arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) - 82890075Sobrien CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize); 82990075Sobrien 83090075Sobrien out: 831132718Skan arm_dcache_align_mask = arm_dcache_align - 1; 83290075Sobrien } 83390075Sobrien} 83490075Sobrien#endif /* ARM9 || XSCALE */ 83590075Sobrien 83690075Sobrien/* 83790075Sobrien * Cannot panic here as we may not have a console yet ... 83890075Sobrien */ 83990075Sobrien 84090075Sobrienint 84190075Sobrienset_cpufuncs() 84290075Sobrien{ 84390075Sobrien cputype = cpufunc_id(); 84490075Sobrien cputype &= CPU_ID_CPU_MASK; 84590075Sobrien 84690075Sobrien /* 84790075Sobrien * NOTE: cpu_do_powersave defaults to off. If we encounter a 84890075Sobrien * CPU type where we want to use it by default, then we set it. 84990075Sobrien */ 85090075Sobrien 85190075Sobrien#ifdef CPU_ARM9 85290075Sobrien if (((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD || 85390075Sobrien (cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_TI) && 85490075Sobrien (cputype & 0x0000f000) == 0x00009000) { 85590075Sobrien cpufuncs = arm9_cpufuncs; 85690075Sobrien cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */ 85790075Sobrien get_cachetype_cp15(); 85890075Sobrien arm9_dcache_sets_inc = 1U << arm_dcache_l2_linesize; 85990075Sobrien arm9_dcache_sets_max = (1U << (arm_dcache_l2_linesize + 86090075Sobrien arm_dcache_l2_nsets)) - arm9_dcache_sets_inc; 86190075Sobrien arm9_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc); 86290075Sobrien arm9_dcache_index_max = 0U - arm9_dcache_index_inc; 86390075Sobrien pmap_pte_init_generic(); 86490075Sobrien goto out; 86590075Sobrien } 86690075Sobrien#endif /* CPU_ARM9 */ 86790075Sobrien#if defined(CPU_ARM9E) 86890075Sobrien if (cputype == CPU_ID_MV88FR131 || cputype == CPU_ID_MV88FR571_VD || 86990075Sobrien cputype == CPU_ID_MV88FR571_41) { 87090075Sobrien uint32_t sheeva_ctrl; 871169689Skan 87290075Sobrien sheeva_ctrl = (MV_DC_STREAM_ENABLE | MV_BTB_DISABLE | 87390075Sobrien MV_L2_ENABLE); 87490075Sobrien /* 87590075Sobrien * Workaround for Marvell MV78100 CPU: Cache prefetch 87690075Sobrien * mechanism may affect the cache coherency validity, 87790075Sobrien * so it needs to be disabled. 87890075Sobrien * 87990075Sobrien * Refer to errata document MV-S501058-00C.pdf (p. 3.1 880117395Skan * L2 Prefetching Mechanism) for details. 88190075Sobrien */ 88290075Sobrien if (cputype == CPU_ID_MV88FR571_VD || 883132718Skan cputype == CPU_ID_MV88FR571_41) 88490075Sobrien sheeva_ctrl |= MV_L2_PREFETCH_DISABLE; 88590075Sobrien 88690075Sobrien sheeva_control_ext(0xffffffff & ~MV_WA_ENABLE, sheeva_ctrl); 88790075Sobrien 88890075Sobrien cpufuncs = sheeva_cpufuncs; 889169689Skan get_cachetype_cp15(); 890169689Skan pmap_pte_init_generic(); 89190075Sobrien goto out; 89290075Sobrien } else if (cputype == CPU_ID_ARM926EJS) { 89390075Sobrien cpufuncs = armv5_ec_cpufuncs; 89490075Sobrien get_cachetype_cp15(); 89590075Sobrien pmap_pte_init_generic(); 89690075Sobrien goto out; 89790075Sobrien } 89890075Sobrien#endif /* CPU_ARM9E */ 89990075Sobrien#if defined(CPU_ARM1176) 90090075Sobrien if (cputype == CPU_ID_ARM1176JZS) { 90190075Sobrien cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */ 90290075Sobrien get_cachetype_cp15(); 90390075Sobrien 90490075Sobrien pmap_pte_init_mmu_v6(); 905169689Skan 906169689Skan goto out; 90790075Sobrien } 90890075Sobrien#endif /* CPU_ARM1176 */ 90990075Sobrien#if defined(CPU_CORTEXA) || defined(CPU_KRAIT) 91090075Sobrien if (cputype == CPU_ID_CORTEXA5 || 91190075Sobrien cputype == CPU_ID_CORTEXA7 || 91290075Sobrien cputype == CPU_ID_CORTEXA8R1 || 91390075Sobrien cputype == CPU_ID_CORTEXA8R2 || 91490075Sobrien cputype == CPU_ID_CORTEXA8R3 || 91590075Sobrien cputype == CPU_ID_CORTEXA9R1 || 91690075Sobrien cputype == CPU_ID_CORTEXA9R2 || 91790075Sobrien cputype == CPU_ID_CORTEXA9R3 || 91890075Sobrien cputype == CPU_ID_CORTEXA12R0 || 91990075Sobrien cputype == CPU_ID_CORTEXA15R0 || 92090075Sobrien cputype == CPU_ID_CORTEXA15R1 || 92190075Sobrien cputype == CPU_ID_CORTEXA15R2 || 92290075Sobrien cputype == CPU_ID_CORTEXA15R3 || 92390075Sobrien cputype == CPU_ID_KRAIT ) { 924117395Skan cpufuncs = cortexa_cpufuncs; 92590075Sobrien cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */ 92690075Sobrien get_cachetype_cp15(); 927132718Skan 92890075Sobrien pmap_pte_init_mmu_v6(); 92990075Sobrien /* Use powersave on this CPU. */ 93090075Sobrien cpu_do_powersave = 1; 93190075Sobrien goto out; 93290075Sobrien } 93390075Sobrien#endif /* CPU_CORTEXA */ 93490075Sobrien 93590075Sobrien#if defined(CPU_MV_PJ4B) 93690075Sobrien if (cputype == CPU_ID_MV88SV581X_V7 || 93790075Sobrien cputype == CPU_ID_MV88SV584X_V7 || 93890075Sobrien cputype == CPU_ID_ARM_88SV581X_V7) { 93990075Sobrien cpufuncs = pj4bv7_cpufuncs; 94090075Sobrien get_cachetype_cp15(); 94190075Sobrien pmap_pte_init_mmu_v6(); 94290075Sobrien goto out; 94390075Sobrien } 94490075Sobrien#endif /* CPU_MV_PJ4B */ 94590075Sobrien 94690075Sobrien#if defined(CPU_FA526) || defined(CPU_FA626TE) 94790075Sobrien if (cputype == CPU_ID_FA526 || cputype == CPU_ID_FA626TE) { 94890075Sobrien cpufuncs = fa526_cpufuncs; 94990075Sobrien cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */ 95090075Sobrien get_cachetype_cp15(); 95190075Sobrien pmap_pte_init_generic(); 952132718Skan 95390075Sobrien /* Use powersave on this CPU. */ 95490075Sobrien cpu_do_powersave = 1; 95590075Sobrien 95690075Sobrien goto out; 95790075Sobrien } 95890075Sobrien#endif /* CPU_FA526 || CPU_FA626TE */ 95990075Sobrien 96090075Sobrien#ifdef CPU_XSCALE_80200 96190075Sobrien if (cputype == CPU_ID_80200) { 96290075Sobrien int rev = cpufunc_id() & CPU_ID_REVISION_MASK; 96390075Sobrien 96490075Sobrien i80200_icu_init(); 96590075Sobrien 96690075Sobrien#if defined(XSCALE_CCLKCFG) 96790075Sobrien /* 96890075Sobrien * Crank CCLKCFG to maximum legal value. 96990075Sobrien */ 97090075Sobrien __asm __volatile ("mcr p14, 0, %0, c6, c0, 0" 97190075Sobrien : 97290075Sobrien : "r" (XSCALE_CCLKCFG)); 97390075Sobrien#endif 97490075Sobrien 97590075Sobrien /* 97690075Sobrien * XXX Disable ECC in the Bus Controller Unit; we 97790075Sobrien * don't really support it, yet. Clear any pending 97890075Sobrien * error indications. 97990075Sobrien */ 98090075Sobrien __asm __volatile("mcr p13, 0, %0, c0, c1, 0" 98190075Sobrien : 98290075Sobrien : "r" (BCUCTL_E0|BCUCTL_E1|BCUCTL_EV)); 983117395Skan 984117395Skan cpufuncs = xscale_cpufuncs; 98590075Sobrien /* 98690075Sobrien * i80200 errata: Step-A0 and A1 have a bug where 98790075Sobrien * D$ dirty bits are not cleared on "invalidate by 98890075Sobrien * address". 98990075Sobrien * 99090075Sobrien * Workaround: Clean cache line before invalidating. 99190075Sobrien */ 99290075Sobrien if (rev == 0 || rev == 1) 99390075Sobrien cpufuncs.cf_dcache_inv_range = xscale_cache_purgeD_rng; 99490075Sobrien 99590075Sobrien cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ 99690075Sobrien get_cachetype_cp15(); 99790075Sobrien pmap_pte_init_xscale(); 99890075Sobrien goto out; 99990075Sobrien } 100090075Sobrien#endif /* CPU_XSCALE_80200 */ 100190075Sobrien#if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219) 100290075Sobrien if (cputype == CPU_ID_80321_400 || cputype == CPU_ID_80321_600 || 100390075Sobrien cputype == CPU_ID_80321_400_B0 || cputype == CPU_ID_80321_600_B0 || 100490075Sobrien cputype == CPU_ID_80219_400 || cputype == CPU_ID_80219_600) { 100590075Sobrien cpufuncs = xscale_cpufuncs; 100690075Sobrien cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ 100790075Sobrien get_cachetype_cp15(); 100890075Sobrien pmap_pte_init_xscale(); 100990075Sobrien goto out; 101090075Sobrien } 101190075Sobrien#endif /* CPU_XSCALE_80321 */ 101290075Sobrien 101390075Sobrien#if defined(CPU_XSCALE_81342) 101490075Sobrien if (cputype == CPU_ID_81342) { 101590075Sobrien cpufuncs = xscalec3_cpufuncs; 101690075Sobrien cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ 101790075Sobrien get_cachetype_cp15(); 101890075Sobrien pmap_pte_init_xscale(); 101990075Sobrien goto out; 102090075Sobrien } 102190075Sobrien#endif /* CPU_XSCALE_81342 */ 102290075Sobrien#ifdef CPU_XSCALE_PXA2X0 102390075Sobrien /* ignore core revision to test PXA2xx CPUs */ 102490075Sobrien if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA250 || 102590075Sobrien (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X || 102690075Sobrien (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA210) { 102790075Sobrien 102890075Sobrien cpufuncs = xscale_cpufuncs; 102990075Sobrien cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ 103090075Sobrien get_cachetype_cp15(); 103190075Sobrien pmap_pte_init_xscale(); 103290075Sobrien 103390075Sobrien /* Use powersave on this CPU. */ 103490075Sobrien cpu_do_powersave = 1; 103590075Sobrien 103690075Sobrien goto out; 103790075Sobrien } 103890075Sobrien#endif /* CPU_XSCALE_PXA2X0 */ 103990075Sobrien#ifdef CPU_XSCALE_IXP425 104090075Sobrien if (cputype == CPU_ID_IXP425_533 || cputype == CPU_ID_IXP425_400 || 104190075Sobrien cputype == CPU_ID_IXP425_266 || cputype == CPU_ID_IXP435) { 104290075Sobrien 104390075Sobrien cpufuncs = xscale_cpufuncs; 104490075Sobrien cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ 104590075Sobrien get_cachetype_cp15(); 104690075Sobrien pmap_pte_init_xscale(); 104790075Sobrien 104890075Sobrien goto out; 104990075Sobrien } 105090075Sobrien#endif /* CPU_XSCALE_IXP425 */ 105190075Sobrien /* 105290075Sobrien * Bzzzz. And the answer was ... 105390075Sobrien */ 1054117395Skan panic("No support for this CPU type (%08x) in kernel", cputype); 105590075Sobrien return(ARCHITECTURE_NOT_PRESENT); 105690075Sobrienout: 1057132718Skan uma_set_align(arm_dcache_align_mask); 1058132718Skan return (0); 105990075Sobrien} 106090075Sobrien 106190075Sobrien/* 106290075Sobrien * Fixup routines for data and prefetch aborts. 106390075Sobrien * 106490075Sobrien * Several compile time symbols are used 106590075Sobrien * 106690075Sobrien * DEBUG_FAULT_CORRECTION - Print debugging information during the 106790075Sobrien * correction of registers after a fault. 106890075Sobrien */ 106990075Sobrien 107090075Sobrien 107190075Sobrien/* 107290075Sobrien * Null abort fixup routine. 107390075Sobrien * For use when no fixup is required. 107490075Sobrien */ 107590075Sobrienint 107690075Sobriencpufunc_null_fixup(arg) 107790075Sobrien void *arg; 107890075Sobrien{ 107990075Sobrien return(ABORT_FIXUP_OK); 108090075Sobrien} 108190075Sobrien 108290075Sobrien/* 108390075Sobrien * CPU Setup code 108490075Sobrien */ 108590075Sobrien 108690075Sobrien#ifdef CPU_ARM9 108790075Sobrienvoid 108890075Sobrienarm9_setup(void) 108990075Sobrien{ 109090075Sobrien int cpuctrl, cpuctrlmask; 109190075Sobrien 109290075Sobrien cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 109390075Sobrien | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 109490075Sobrien | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 109590075Sobrien | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE | 109690075Sobrien CPU_CONTROL_ROUNDROBIN; 109790075Sobrien cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 109890075Sobrien | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 109990075Sobrien | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 110090075Sobrien | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 110190075Sobrien | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 110290075Sobrien | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_VECRELOC 110390075Sobrien | CPU_CONTROL_ROUNDROBIN; 110490075Sobrien 110590075Sobrien#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 110690075Sobrien cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 110790075Sobrien#endif 110890075Sobrien 110990075Sobrien#ifdef __ARMEB__ 111090075Sobrien cpuctrl |= CPU_CONTROL_BEND_ENABLE; 111190075Sobrien#endif 111290075Sobrien if (vector_page == ARM_VECTORS_HIGH) 111390075Sobrien cpuctrl |= CPU_CONTROL_VECRELOC; 111490075Sobrien 111590075Sobrien /* Clear out the cache */ 1116117395Skan cpu_idcache_wbinv_all(); 111790075Sobrien 111890075Sobrien /* Set the control register */ 111990075Sobrien cpu_control(cpuctrlmask, cpuctrl); 112090075Sobrien ctrl = cpuctrl; 112190075Sobrien 112290075Sobrien} 112390075Sobrien#endif /* CPU_ARM9 */ 112490075Sobrien 112590075Sobrien#if defined(CPU_ARM9E) 112690075Sobrienvoid 112790075Sobrienarm10_setup(void) 112890075Sobrien{ 112990075Sobrien int cpuctrl, cpuctrlmask; 113090075Sobrien 113190075Sobrien cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE 113290075Sobrien | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 113390075Sobrien | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_BPRD_ENABLE; 113490075Sobrien cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE 113590075Sobrien | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1136117395Skan | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 113790075Sobrien | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 113890075Sobrien | CPU_CONTROL_BPRD_ENABLE 113990075Sobrien | CPU_CONTROL_ROUNDROBIN | CPU_CONTROL_CPCLK; 114090075Sobrien 114190075Sobrien#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 114290075Sobrien cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 114390075Sobrien#endif 114490075Sobrien 114590075Sobrien#ifdef __ARMEB__ 114690075Sobrien cpuctrl |= CPU_CONTROL_BEND_ENABLE; 114790075Sobrien#endif 114890075Sobrien 114990075Sobrien /* Clear out the cache */ 115090075Sobrien cpu_idcache_wbinv_all(); 115190075Sobrien 115290075Sobrien /* Now really make sure they are clean. */ 115390075Sobrien __asm __volatile ("mcr\tp15, 0, r0, c7, c7, 0" : : ); 115490075Sobrien 115590075Sobrien if (vector_page == ARM_VECTORS_HIGH) 115690075Sobrien cpuctrl |= CPU_CONTROL_VECRELOC; 115790075Sobrien 115890075Sobrien /* Set the control register */ 115990075Sobrien ctrl = cpuctrl; 116090075Sobrien cpu_control(0xffffffff, cpuctrl); 116190075Sobrien 116290075Sobrien /* And again. */ 116390075Sobrien cpu_idcache_wbinv_all(); 116490075Sobrien} 116590075Sobrien#endif /* CPU_ARM9E || CPU_ARM10 */ 116690075Sobrien 116790075Sobrien#if defined(CPU_ARM1176) \ 116890075Sobrien || defined(CPU_MV_PJ4B) \ 116990075Sobrien || defined(CPU_CORTEXA) || defined(CPU_KRAIT) 117090075Sobrienstatic __inline void 117190075Sobriencpu_scc_setup_ccnt(void) 117290075Sobrien{ 117390075Sobrien/* This is how you give userland access to the CCNT and PMCn 117490075Sobrien * registers. 117590075Sobrien * BEWARE! This gives write access also, which may not be what 117690075Sobrien * you want! 117790075Sobrien */ 117890075Sobrien#ifdef _PMC_USER_READ_WRITE_ 117990075Sobrien#if defined(CPU_ARM1176) 118090075Sobrien /* Use the Secure User and Non-secure Access Validation Control Register 1181117395Skan * to allow userland access 1182117395Skan */ 1183117395Skan __asm volatile ("mcr p15, 0, %0, c15, c9, 0\n\t" 1184117395Skan : 118590075Sobrien : "r"(0x00000001)); 1186117395Skan#else 1187117395Skan /* Set PMUSERENR[0] to allow userland access */ 118890075Sobrien __asm volatile ("mcr p15, 0, %0, c9, c14, 0\n\t" 1189117395Skan : 1190117395Skan : "r"(0x00000001)); 1191117395Skan#endif 119290075Sobrien#endif 1193117395Skan#if defined(CPU_ARM1176) 1194117395Skan /* Set PMCR[2,0] to enable counters and reset CCNT */ 119590075Sobrien __asm volatile ("mcr p15, 0, %0, c15, c12, 0\n\t" 1196117395Skan : 1197117395Skan : "r"(0x00000005)); 1198117395Skan#else 119990075Sobrien /* Set up the PMCCNTR register as a cyclecounter: 1200117395Skan * Set PMINTENCLR to 0xFFFFFFFF to block interrupts 1201117395Skan * Set PMCR[2,0] to enable counters and reset CCNT 120290075Sobrien * Set PMCNTENSET to 0x80000000 to enable CCNT */ 1203117395Skan __asm volatile ("mcr p15, 0, %0, c9, c14, 2\n\t" 1204117395Skan "mcr p15, 0, %1, c9, c12, 0\n\t" 1205117395Skan "mcr p15, 0, %2, c9, c12, 1\n\t" 120690075Sobrien : 120790075Sobrien : "r"(0xFFFFFFFF), 120890075Sobrien "r"(0x00000005), 1209117395Skan "r"(0x80000000)); 121090075Sobrien#endif 121190075Sobrien} 121290075Sobrien#endif 121390075Sobrien 121490075Sobrien#if defined(CPU_ARM1176) 1215117395Skanvoid 1216117395Skanarm11x6_setup(void) 1217117395Skan{ 1218117395Skan int cpuctrl, cpuctrl_wax; 1219117395Skan uint32_t auxctrl, auxctrl_wax; 1220117395Skan uint32_t tmp, tmp2; 1221117395Skan uint32_t sbz=0; 1222117395Skan uint32_t cpuid; 1223117395Skan 1224117395Skan cpuid = cpufunc_id(); 1225117395Skan 1226117395Skan cpuctrl = 1227117395Skan CPU_CONTROL_MMU_ENABLE | 1228117395Skan CPU_CONTROL_DC_ENABLE | 1229117395Skan CPU_CONTROL_WBUF_ENABLE | 1230117395Skan CPU_CONTROL_32BP_ENABLE | 1231117395Skan CPU_CONTROL_32BD_ENABLE | 1232117395Skan CPU_CONTROL_LABT_ENABLE | 1233117395Skan CPU_CONTROL_SYST_ENABLE | 1234117395Skan CPU_CONTROL_IC_ENABLE; 1235117395Skan 1236117395Skan /* 1237117395Skan * "write as existing" bits 1238117395Skan * inverse of this is mask 1239117395Skan */ 1240117395Skan cpuctrl_wax = 124190075Sobrien (3 << 30) | /* SBZ */ 124290075Sobrien (1 << 29) | /* FA */ 124390075Sobrien (1 << 28) | /* TR */ 124490075Sobrien (3 << 26) | /* SBZ */ 124590075Sobrien (3 << 19) | /* SBZ */ 124690075Sobrien (1 << 17); /* SBZ */ 1247117395Skan 124890075Sobrien cpuctrl |= CPU_CONTROL_BPRD_ENABLE; 124990075Sobrien cpuctrl |= CPU_CONTROL_V6_EXTPAGE; 1250132718Skan 125190075Sobrien#ifdef __ARMEB__ 125290075Sobrien cpuctrl |= CPU_CONTROL_BEND_ENABLE; 125390075Sobrien#endif 125490075Sobrien 125590075Sobrien if (vector_page == ARM_VECTORS_HIGH) 125690075Sobrien cpuctrl |= CPU_CONTROL_VECRELOC; 125790075Sobrien 125890075Sobrien auxctrl = 0; 1259117395Skan auxctrl_wax = ~0; 126090075Sobrien 126190075Sobrien /* 126290075Sobrien * Enable an errata workaround 126390075Sobrien */ 126490075Sobrien if ((cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM1176JZS) { /* ARM1176JZSr0 */ 1265132718Skan auxctrl = ARM1176_AUXCTL_PHD; 126690075Sobrien auxctrl_wax = ~ARM1176_AUXCTL_PHD; 126790075Sobrien } 126890075Sobrien 126990075Sobrien /* Clear out the cache */ 127090075Sobrien cpu_idcache_wbinv_all(); 127190075Sobrien 127290075Sobrien /* Now really make sure they are clean. */ 127390075Sobrien __asm volatile ("mcr\tp15, 0, %0, c7, c7, 0" : : "r"(sbz)); 127490075Sobrien 1275117395Skan /* Allow detection code to find the VFP if it's fitted. */ 127690075Sobrien __asm volatile ("mcr\tp15, 0, %0, c1, c0, 2" : : "r" (0x0fffffff)); 127790075Sobrien 127890075Sobrien /* Set the control register */ 127990075Sobrien ctrl = cpuctrl; 128090075Sobrien cpu_control(~cpuctrl_wax, cpuctrl); 128190075Sobrien 128290075Sobrien __asm volatile ("mrc p15, 0, %0, c1, c0, 1\n\t" 1283117395Skan "and %1, %0, %2\n\t" 1284132718Skan "orr %1, %1, %3\n\t" 128590075Sobrien "teq %0, %1\n\t" 128690075Sobrien "mcrne p15, 0, %1, c1, c0, 1\n\t" 128790075Sobrien : "=r"(tmp), "=r"(tmp2) : 1288117395Skan "r"(auxctrl_wax), "r"(auxctrl)); 1289117395Skan 1290117395Skan /* And again. */ 129190075Sobrien cpu_idcache_wbinv_all(); 129290075Sobrien 129390075Sobrien cpu_scc_setup_ccnt(); 1294117395Skan} 129590075Sobrien#endif /* CPU_ARM1176 */ 1296117395Skan 1297132718Skan#ifdef CPU_MV_PJ4B 1298117395Skanvoid 129990075Sobrienpj4bv7_setup(void) 130090075Sobrien{ 130190075Sobrien int cpuctrl; 1302117395Skan 1303117395Skan pj4b_config(); 1304117395Skan 1305132718Skan cpuctrl = CPU_CONTROL_MMU_ENABLE; 1306117395Skan#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 1307117395Skan cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 1308117395Skan#endif 1309117395Skan cpuctrl |= CPU_CONTROL_DC_ENABLE; 1310117395Skan cpuctrl |= (0xf << 3); 131190075Sobrien cpuctrl |= CPU_CONTROL_BPRD_ENABLE; 131290075Sobrien cpuctrl |= CPU_CONTROL_IC_ENABLE; 131390075Sobrien if (vector_page == ARM_VECTORS_HIGH) 131490075Sobrien cpuctrl |= CPU_CONTROL_VECRELOC; 131590075Sobrien cpuctrl |= (0x5 << 16) | (1 < 22); 1316132718Skan cpuctrl |= CPU_CONTROL_V6_EXTPAGE; 131790075Sobrien 131890075Sobrien /* Clear out the cache */ 131990075Sobrien cpu_idcache_wbinv_all(); 132090075Sobrien 1321117395Skan /* Set the control register */ 132290075Sobrien ctrl = cpuctrl; 132390075Sobrien cpu_control(0xFFFFFFFF, cpuctrl); 132490075Sobrien 132590075Sobrien /* And again. */ 132690075Sobrien cpu_idcache_wbinv_all(); 132790075Sobrien 1328117395Skan cpu_scc_setup_ccnt(); 132990075Sobrien} 1330117395Skan#endif /* CPU_MV_PJ4B */ 1331132718Skan 1332117395Skan#if defined(CPU_CORTEXA) || defined(CPU_KRAIT) 133390075Sobrien 133490075Sobrienvoid 133590075Sobriencortexa_setup(void) 133690075Sobrien{ 133790075Sobrien int cpuctrl, cpuctrlmask; 133890075Sobrien 133990075Sobrien cpuctrlmask = CPU_CONTROL_MMU_ENABLE | /* MMU enable [0] */ 1340132718Skan CPU_CONTROL_AFLT_ENABLE | /* Alignment fault [1] */ 134190075Sobrien CPU_CONTROL_DC_ENABLE | /* DCache enable [2] */ 134290075Sobrien CPU_CONTROL_BPRD_ENABLE | /* Branch prediction [11] */ 134390075Sobrien CPU_CONTROL_IC_ENABLE | /* ICache enable [12] */ 134490075Sobrien CPU_CONTROL_VECRELOC; /* Vector relocation [13] */ 134590075Sobrien 1346169689Skan cpuctrl = CPU_CONTROL_MMU_ENABLE | 134790075Sobrien CPU_CONTROL_IC_ENABLE | 134890075Sobrien CPU_CONTROL_DC_ENABLE | 134990075Sobrien CPU_CONTROL_BPRD_ENABLE; 135090075Sobrien 135190075Sobrien#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 135290075Sobrien cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 1353132718Skan#endif 135490075Sobrien 135590075Sobrien /* Switch to big endian */ 135690075Sobrien#ifdef __ARMEB__ 135790075Sobrien cpuctrl |= CPU_CONTROL_BEND_ENABLE; 135890075Sobrien#endif 1359169689Skan 136090075Sobrien /* Check if the vector page is at the high address (0xffff0000) */ 136190075Sobrien if (vector_page == ARM_VECTORS_HIGH) 136290075Sobrien cpuctrl |= CPU_CONTROL_VECRELOC; 136390075Sobrien 136490075Sobrien /* Clear out the cache */ 1365132718Skan cpu_idcache_wbinv_all(); 136690075Sobrien 136790075Sobrien /* Set the control register */ 136890075Sobrien ctrl = cpuctrl; 136990075Sobrien cpu_control(cpuctrlmask, cpuctrl); 137090075Sobrien 137190075Sobrien /* And again. */ 137290075Sobrien cpu_idcache_wbinv_all(); 137390075Sobrien#ifdef SMP 137490075Sobrien armv7_auxctrl((1 << 6) | (1 << 0), (1 << 6) | (1 << 0)); /* Enable SMP + TLB broadcasting */ 137590075Sobrien#endif 137690075Sobrien 137790075Sobrien cpu_scc_setup_ccnt(); 1378132718Skan} 137990075Sobrien#endif /* CPU_CORTEXA */ 138090075Sobrien 1381169689Skan#if defined(CPU_FA526) || defined(CPU_FA626TE) 138290075Sobrienvoid 138390075Sobrienfa526_setup(void) 138490075Sobrien{ 138590075Sobrien int cpuctrl, cpuctrlmask; 138690075Sobrien 138790075Sobrien cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 138890075Sobrien | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1389169689Skan | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1390169689Skan | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE 1391169689Skan | CPU_CONTROL_BPRD_ENABLE; 139290075Sobrien cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 139390075Sobrien | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 139490075Sobrien | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1395169689Skan | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 1396169689Skan | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 1397169689Skan | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE 1398169689Skan | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC; 139990075Sobrien 140090075Sobrien#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 140190075Sobrien cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 140290075Sobrien#endif 140390075Sobrien 140490075Sobrien#ifdef __ARMEB__ 140590075Sobrien cpuctrl |= CPU_CONTROL_BEND_ENABLE; 140690075Sobrien#endif 1407132718Skan 140890075Sobrien if (vector_page == ARM_VECTORS_HIGH) 140990075Sobrien cpuctrl |= CPU_CONTROL_VECRELOC; 141090075Sobrien 141190075Sobrien /* Clear out the cache */ 141290075Sobrien cpu_idcache_wbinv_all(); 141390075Sobrien 141490075Sobrien /* Set the control register */ 141590075Sobrien ctrl = cpuctrl; 141690075Sobrien cpu_control(0xffffffff, cpuctrl); 141790075Sobrien} 141890075Sobrien#endif /* CPU_FA526 || CPU_FA626TE */ 141990075Sobrien 142090075Sobrien#if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ 142190075Sobrien defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ 142290075Sobrien defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) 142390075Sobrienvoid 142490075Sobrienxscale_setup(void) 142590075Sobrien{ 142690075Sobrien uint32_t auxctl; 142790075Sobrien int cpuctrl, cpuctrlmask; 142890075Sobrien 142990075Sobrien /* 143090075Sobrien * The XScale Write Buffer is always enabled. Our option 143190075Sobrien * is to enable/disable coalescing. Note that bits 6:3 143290075Sobrien * must always be enabled. 143390075Sobrien */ 143490075Sobrien 143590075Sobrien cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 143690075Sobrien | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 143790075Sobrien | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1438132718Skan | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE 143990075Sobrien | CPU_CONTROL_BPRD_ENABLE; 144090075Sobrien cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 144190075Sobrien | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 144290075Sobrien | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 144390075Sobrien | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 144490075Sobrien | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 144590075Sobrien | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE 144690075Sobrien | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC | \ 144790075Sobrien CPU_CONTROL_L2_ENABLE; 144890075Sobrien 144990075Sobrien#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 145090075Sobrien cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 145190075Sobrien#endif 145290075Sobrien 145396263Sobrien#ifdef __ARMEB__ 145490075Sobrien cpuctrl |= CPU_CONTROL_BEND_ENABLE; 145596263Sobrien#endif 145696263Sobrien 1457132718Skan if (vector_page == ARM_VECTORS_HIGH) 145896263Sobrien cpuctrl |= CPU_CONTROL_VECRELOC; 145996263Sobrien#ifdef CPU_XSCALE_CORE3 146096263Sobrien cpuctrl |= CPU_CONTROL_L2_ENABLE; 1461132718Skan#endif 146290075Sobrien 146390075Sobrien /* Clear out the cache */ 146496263Sobrien cpu_idcache_wbinv_all(); 146596263Sobrien 146696263Sobrien /* 1467132718Skan * Set the control register. Note that bits 6:3 must always 146890075Sobrien * be set to 1. 146990075Sobrien */ 147096263Sobrien ctrl = cpuctrl; 147196263Sobrien/* cpu_control(cpuctrlmask, cpuctrl);*/ 147296263Sobrien cpu_control(0xffffffff, cpuctrl); 147390075Sobrien 147490075Sobrien /* Make sure write coalescing is turned on */ 147590075Sobrien __asm __volatile("mrc p15, 0, %0, c1, c0, 1" 147690075Sobrien : "=r" (auxctl)); 147790075Sobrien#ifdef XSCALE_NO_COALESCE_WRITES 147890075Sobrien auxctl |= XSCALE_AUXCTL_K; 147990075Sobrien#else 148090075Sobrien auxctl &= ~XSCALE_AUXCTL_K; 148190075Sobrien#endif 148290075Sobrien#ifdef CPU_XSCALE_CORE3 148390075Sobrien auxctl |= XSCALE_AUXCTL_LLR; 148490075Sobrien auxctl |= XSCALE_AUXCTL_MD_MASK; 148590075Sobrien#endif 148690075Sobrien __asm __volatile("mcr p15, 0, %0, c1, c0, 1" 148790075Sobrien : : "r" (auxctl)); 148890075Sobrien} 148990075Sobrien#endif /* CPU_XSCALE_80200 || CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 149090075Sobrien CPU_XSCALE_80219 */ 149190075Sobrien