1129198Scognet/* $NetBSD: cpufunc.c,v 1.65 2003/11/05 12:53:15 scw Exp $ */ 2129198Scognet 3139735Simp/*- 4129198Scognet * arm9 support code Copyright (C) 2001 ARM Ltd 5129198Scognet * Copyright (c) 1997 Mark Brinicombe. 6129198Scognet * Copyright (c) 1997 Causality Limited 7129198Scognet * All rights reserved. 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 by Causality Limited. 20129198Scognet * 4. The name of Causality Limited may not be used to endorse or promote 21129198Scognet * products derived from this software without specific prior written 22129198Scognet * permission. 23129198Scognet * 24129198Scognet * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS 25129198Scognet * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26129198Scognet * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27129198Scognet * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT, 28129198Scognet * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29129198Scognet * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30129198Scognet * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31129198Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32129198Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33129198Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34129198Scognet * SUCH DAMAGE. 35129198Scognet * 36129198Scognet * RiscBSD kernel project 37129198Scognet * 38129198Scognet * cpufuncs.c 39129198Scognet * 40129198Scognet * C functions for supporting CPU / MMU / TLB specific operations. 41129198Scognet * 42129198Scognet * Created : 30/01/97 43129198Scognet */ 44129198Scognet#include <sys/cdefs.h> 45129198Scognet__FBSDID("$FreeBSD: stable/11/sys/arm/arm/cpufunc.c 317003 2017-04-16 06:51:06Z mmel $"); 46129198Scognet 47129198Scognet#include <sys/param.h> 48129198Scognet#include <sys/systm.h> 49129198Scognet#include <sys/lock.h> 50129198Scognet#include <sys/mutex.h> 51132472Scognet#include <sys/bus.h> 52132472Scognet#include <machine/bus.h> 53129198Scognet#include <machine/cpu.h> 54129198Scognet#include <machine/disassem.h> 55129198Scognet 56129198Scognet#include <vm/vm.h> 57129198Scognet#include <vm/pmap.h> 58166655Scognet#include <vm/uma.h> 59129198Scognet 60129198Scognet#include <machine/cpufunc.h> 61129198Scognet 62295200Smmel#if defined(CPU_XSCALE_81342) 63164080Scognet#include <arm/xscale/i8134x/i81342reg.h> 64164080Scognet#endif 65164080Scognet 66129198Scognet#ifdef CPU_XSCALE_IXP425 67135646Scognet#include <arm/xscale/ixp425/ixp425reg.h> 68135646Scognet#include <arm/xscale/ixp425/ixp425var.h> 69129198Scognet#endif 70129198Scognet 71129198Scognet/* PRIMARY CACHE VARIABLES */ 72129198Scognetint arm_picache_size; 73129198Scognetint arm_picache_line_size; 74129198Scognetint arm_picache_ways; 75129198Scognet 76129198Scognetint arm_pdcache_size; /* and unified */ 77129198Scognetint arm_pdcache_line_size; 78129198Scognetint arm_pdcache_ways; 79129198Scognet 80129198Scognetint arm_pcache_type; 81129198Scognetint arm_pcache_unified; 82129198Scognet 83129198Scognetint arm_dcache_align; 84129198Scognetint arm_dcache_align_mask; 85129198Scognet 86239268Sgonzou_int arm_cache_level; 87239268Sgonzou_int arm_cache_type[14]; 88239268Sgonzou_int arm_cache_loc; 89239268Sgonzo 90129198Scognet#ifdef CPU_ARM9 91129198Scognetstruct cpu_functions arm9_cpufuncs = { 92129198Scognet /* CPU functions */ 93129198Scognet 94129198Scognet cpufunc_nullop, /* cpwait */ 95129198Scognet 96129198Scognet /* MMU functions */ 97129198Scognet 98129198Scognet cpufunc_control, /* control */ 99129198Scognet arm9_setttb, /* Setttb */ 100129198Scognet 101129198Scognet /* TLB functions */ 102129198Scognet 103129198Scognet armv4_tlb_flushID, /* tlb_flushID */ 104129198Scognet arm9_tlb_flushID_SE, /* tlb_flushID_SE */ 105129198Scognet armv4_tlb_flushD, /* tlb_flushD */ 106129198Scognet armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 107129198Scognet 108129198Scognet /* Cache operations */ 109129198Scognet 110146605Scognet arm9_icache_sync_range, /* icache_sync_range */ 111129198Scognet 112146605Scognet arm9_dcache_wbinv_all, /* dcache_wbinv_all */ 113146605Scognet arm9_dcache_wbinv_range, /* dcache_wbinv_range */ 114195798Sraj arm9_dcache_inv_range, /* dcache_inv_range */ 115146605Scognet arm9_dcache_wb_range, /* dcache_wb_range */ 116129198Scognet 117262420Sian armv4_idcache_inv_all, /* idcache_inv_all */ 118146605Scognet arm9_idcache_wbinv_all, /* idcache_wbinv_all */ 119146605Scognet arm9_idcache_wbinv_range, /* idcache_wbinv_range */ 120171618Scognet cpufunc_nullop, /* l2cache_wbinv_all */ 121171781Scognet (void *)cpufunc_nullop, /* l2cache_wbinv_range */ 122171781Scognet (void *)cpufunc_nullop, /* l2cache_inv_range */ 123171781Scognet (void *)cpufunc_nullop, /* l2cache_wb_range */ 124265870Sian (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 125129198Scognet 126129198Scognet /* Other functions */ 127129198Scognet 128129198Scognet armv4_drain_writebuf, /* drain_writebuf */ 129129198Scognet 130129198Scognet (void *)cpufunc_nullop, /* sleep */ 131129198Scognet 132129198Scognet /* Soft functions */ 133129198Scognet 134129198Scognet arm9_context_switch, /* context_switch */ 135129198Scognet 136129198Scognet arm9_setup /* cpu setup */ 137129198Scognet 138129198Scognet}; 139129198Scognet#endif /* CPU_ARM9 */ 140129198Scognet 141280809Sandrew#if defined(CPU_ARM9E) 142172738Simpstruct cpu_functions armv5_ec_cpufuncs = { 143172738Simp /* CPU functions */ 144172738Simp 145172738Simp cpufunc_nullop, /* cpwait */ 146172738Simp 147172738Simp /* MMU functions */ 148172738Simp 149172738Simp cpufunc_control, /* control */ 150172738Simp armv5_ec_setttb, /* Setttb */ 151172738Simp 152172738Simp /* TLB functions */ 153172738Simp 154172738Simp armv4_tlb_flushID, /* tlb_flushID */ 155295149Smmel arm9_tlb_flushID_SE, /* tlb_flushID_SE */ 156172738Simp armv4_tlb_flushD, /* tlb_flushD */ 157172738Simp armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 158172738Simp 159172738Simp /* Cache operations */ 160172738Simp 161172738Simp armv5_ec_icache_sync_range, /* icache_sync_range */ 162172738Simp 163172738Simp armv5_ec_dcache_wbinv_all, /* dcache_wbinv_all */ 164172738Simp armv5_ec_dcache_wbinv_range, /* dcache_wbinv_range */ 165195798Sraj armv5_ec_dcache_inv_range, /* dcache_inv_range */ 166172738Simp armv5_ec_dcache_wb_range, /* dcache_wb_range */ 167172738Simp 168262420Sian armv4_idcache_inv_all, /* idcache_inv_all */ 169172738Simp armv5_ec_idcache_wbinv_all, /* idcache_wbinv_all */ 170172738Simp armv5_ec_idcache_wbinv_range, /* idcache_wbinv_range */ 171172738Simp 172173442Scognet cpufunc_nullop, /* l2cache_wbinv_all */ 173173442Scognet (void *)cpufunc_nullop, /* l2cache_wbinv_range */ 174173442Scognet (void *)cpufunc_nullop, /* l2cache_inv_range */ 175173442Scognet (void *)cpufunc_nullop, /* l2cache_wb_range */ 176265870Sian (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 177236991Simp 178172738Simp /* Other functions */ 179172738Simp 180172738Simp armv4_drain_writebuf, /* drain_writebuf */ 181172738Simp 182172738Simp (void *)cpufunc_nullop, /* sleep */ 183172738Simp 184172738Simp /* Soft functions */ 185172738Simp 186295149Smmel arm9_context_switch, /* context_switch */ 187172738Simp 188172738Simp arm10_setup /* cpu setup */ 189172738Simp 190172738Simp}; 191183835Sraj 192186933Srajstruct cpu_functions sheeva_cpufuncs = { 193183835Sraj /* CPU functions */ 194183835Sraj 195183835Sraj cpufunc_nullop, /* cpwait */ 196183835Sraj 197183835Sraj /* MMU functions */ 198183835Sraj 199183835Sraj cpufunc_control, /* control */ 200186933Sraj sheeva_setttb, /* Setttb */ 201183835Sraj 202183835Sraj /* TLB functions */ 203183835Sraj 204183835Sraj armv4_tlb_flushID, /* tlb_flushID */ 205295149Smmel arm9_tlb_flushID_SE, /* tlb_flushID_SE */ 206183835Sraj armv4_tlb_flushD, /* tlb_flushD */ 207183835Sraj armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 208183835Sraj 209183835Sraj /* Cache operations */ 210183835Sraj 211183835Sraj armv5_ec_icache_sync_range, /* icache_sync_range */ 212183835Sraj 213183835Sraj armv5_ec_dcache_wbinv_all, /* dcache_wbinv_all */ 214186933Sraj sheeva_dcache_wbinv_range, /* dcache_wbinv_range */ 215186933Sraj sheeva_dcache_inv_range, /* dcache_inv_range */ 216186933Sraj sheeva_dcache_wb_range, /* dcache_wb_range */ 217183835Sraj 218262420Sian armv4_idcache_inv_all, /* idcache_inv_all */ 219183835Sraj armv5_ec_idcache_wbinv_all, /* idcache_wbinv_all */ 220186933Sraj sheeva_idcache_wbinv_range, /* idcache_wbinv_all */ 221183835Sraj 222186933Sraj sheeva_l2cache_wbinv_all, /* l2cache_wbinv_all */ 223186933Sraj sheeva_l2cache_wbinv_range, /* l2cache_wbinv_range */ 224186933Sraj sheeva_l2cache_inv_range, /* l2cache_inv_range */ 225186933Sraj sheeva_l2cache_wb_range, /* l2cache_wb_range */ 226265870Sian (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 227183835Sraj 228183835Sraj /* Other functions */ 229183835Sraj 230183835Sraj armv4_drain_writebuf, /* drain_writebuf */ 231183835Sraj 232212825Smav sheeva_cpu_sleep, /* sleep */ 233183835Sraj 234183835Sraj /* Soft functions */ 235183835Sraj 236295149Smmel arm9_context_switch, /* context_switch */ 237183835Sraj 238183835Sraj arm10_setup /* cpu setup */ 239183835Sraj}; 240280809Sandrew#endif /* CPU_ARM9E */ 241172738Simp 242239268Sgonzo#ifdef CPU_MV_PJ4B 243239268Sgonzostruct cpu_functions pj4bv7_cpufuncs = { 244239268Sgonzo 245239268Sgonzo /* Cache operations */ 246317002Smmel .cf_l2cache_wbinv_all = (void *)cpufunc_nullop, 247317002Smmel .cf_l2cache_wbinv_range = (void *)cpufunc_nullop, 248317002Smmel .cf_l2cache_inv_range = (void *)cpufunc_nullop, 249317002Smmel .cf_l2cache_wb_range = (void *)cpufunc_nullop, 250317002Smmel .cf_l2cache_drain_writebuf = (void *)cpufunc_nullop, 251239268Sgonzo 252239268Sgonzo /* Other functions */ 253317002Smmel .cf_sleep = (void *)cpufunc_nullop, 254239268Sgonzo 255239268Sgonzo /* Soft functions */ 256317002Smmel .cf_setup = pj4bv7_setup 257239268Sgonzo}; 258239268Sgonzo#endif /* CPU_MV_PJ4B */ 259239268Sgonzo 260295200Smmel#if defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) 261161592Scognet 262129198Scognetstruct cpu_functions xscale_cpufuncs = { 263129198Scognet /* CPU functions */ 264283366Sandrew 265129198Scognet xscale_cpwait, /* cpwait */ 266129198Scognet 267129198Scognet /* MMU functions */ 268129198Scognet 269129198Scognet xscale_control, /* control */ 270129198Scognet xscale_setttb, /* setttb */ 271129198Scognet 272129198Scognet /* TLB functions */ 273129198Scognet 274129198Scognet armv4_tlb_flushID, /* tlb_flushID */ 275129198Scognet xscale_tlb_flushID_SE, /* tlb_flushID_SE */ 276129198Scognet armv4_tlb_flushD, /* tlb_flushD */ 277129198Scognet armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 278129198Scognet 279129198Scognet /* Cache operations */ 280129198Scognet 281129198Scognet xscale_cache_syncI_rng, /* icache_sync_range */ 282129198Scognet 283129198Scognet xscale_cache_purgeD, /* dcache_wbinv_all */ 284129198Scognet xscale_cache_purgeD_rng, /* dcache_wbinv_range */ 285129198Scognet xscale_cache_flushD_rng, /* dcache_inv_range */ 286129198Scognet xscale_cache_cleanD_rng, /* dcache_wb_range */ 287129198Scognet 288262420Sian xscale_cache_flushID, /* idcache_inv_all */ 289129198Scognet xscale_cache_purgeID, /* idcache_wbinv_all */ 290129198Scognet xscale_cache_purgeID_rng, /* idcache_wbinv_range */ 291171618Scognet cpufunc_nullop, /* l2cache_wbinv_all */ 292171781Scognet (void *)cpufunc_nullop, /* l2cache_wbinv_range */ 293171781Scognet (void *)cpufunc_nullop, /* l2cache_inv_range */ 294171781Scognet (void *)cpufunc_nullop, /* l2cache_wb_range */ 295265870Sian (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 296129198Scognet 297129198Scognet /* Other functions */ 298129198Scognet 299129198Scognet armv4_drain_writebuf, /* drain_writebuf */ 300129198Scognet 301129198Scognet xscale_cpu_sleep, /* sleep */ 302129198Scognet 303129198Scognet /* Soft functions */ 304129198Scognet 305129198Scognet xscale_context_switch, /* context_switch */ 306129198Scognet 307129198Scognet xscale_setup /* cpu setup */ 308129198Scognet}; 309129198Scognet#endif 310295200Smmel/* CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */ 311129198Scognet 312164080Scognet#ifdef CPU_XSCALE_81342 313164080Scognetstruct cpu_functions xscalec3_cpufuncs = { 314164080Scognet /* CPU functions */ 315283366Sandrew 316164080Scognet xscale_cpwait, /* cpwait */ 317164080Scognet 318164080Scognet /* MMU functions */ 319164080Scognet 320164080Scognet xscale_control, /* control */ 321164080Scognet xscalec3_setttb, /* setttb */ 322164080Scognet 323164080Scognet /* TLB functions */ 324164080Scognet 325164080Scognet armv4_tlb_flushID, /* tlb_flushID */ 326164080Scognet xscale_tlb_flushID_SE, /* tlb_flushID_SE */ 327164080Scognet armv4_tlb_flushD, /* tlb_flushD */ 328164080Scognet armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 329164080Scognet 330164080Scognet /* Cache operations */ 331164080Scognet 332171618Scognet xscalec3_cache_syncI_rng, /* icache_sync_range */ 333164080Scognet 334164080Scognet xscalec3_cache_purgeD, /* dcache_wbinv_all */ 335164080Scognet xscalec3_cache_purgeD_rng, /* dcache_wbinv_range */ 336164080Scognet xscale_cache_flushD_rng, /* dcache_inv_range */ 337164080Scognet xscalec3_cache_cleanD_rng, /* dcache_wb_range */ 338164080Scognet 339262420Sian xscale_cache_flushID, /* idcache_inv_all */ 340171618Scognet xscalec3_cache_purgeID, /* idcache_wbinv_all */ 341164080Scognet xscalec3_cache_purgeID_rng, /* idcache_wbinv_range */ 342171618Scognet xscalec3_l2cache_purge, /* l2cache_wbinv_all */ 343171618Scognet xscalec3_l2cache_purge_rng, /* l2cache_wbinv_range */ 344171618Scognet xscalec3_l2cache_flush_rng, /* l2cache_inv_range */ 345171618Scognet xscalec3_l2cache_clean_rng, /* l2cache_wb_range */ 346265870Sian (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 347164080Scognet 348164080Scognet /* Other functions */ 349164080Scognet 350164080Scognet armv4_drain_writebuf, /* drain_writebuf */ 351164080Scognet 352164080Scognet xscale_cpu_sleep, /* sleep */ 353164080Scognet 354164080Scognet /* Soft functions */ 355164080Scognet 356164080Scognet xscalec3_context_switch, /* context_switch */ 357164080Scognet 358164080Scognet xscale_setup /* cpu setup */ 359164080Scognet}; 360164080Scognet#endif /* CPU_XSCALE_81342 */ 361201468Srpaulo 362201468Srpaulo 363280842Sandrew#if defined(CPU_FA526) 364201468Srpaulostruct cpu_functions fa526_cpufuncs = { 365201468Srpaulo /* CPU functions */ 366201468Srpaulo 367207611Skevlo cpufunc_nullop, /* cpwait */ 368201468Srpaulo 369201468Srpaulo /* MMU functions */ 370201468Srpaulo 371207611Skevlo cpufunc_control, /* control */ 372207611Skevlo fa526_setttb, /* setttb */ 373201468Srpaulo 374201468Srpaulo /* TLB functions */ 375201468Srpaulo 376207611Skevlo armv4_tlb_flushID, /* tlb_flushID */ 377207611Skevlo fa526_tlb_flushID_SE, /* tlb_flushID_SE */ 378207611Skevlo armv4_tlb_flushD, /* tlb_flushD */ 379207611Skevlo armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 380201468Srpaulo 381201468Srpaulo /* Cache operations */ 382201468Srpaulo 383207611Skevlo fa526_icache_sync_range, /* icache_sync_range */ 384201468Srpaulo 385207611Skevlo fa526_dcache_wbinv_all, /* dcache_wbinv_all */ 386207611Skevlo fa526_dcache_wbinv_range, /* dcache_wbinv_range */ 387207611Skevlo fa526_dcache_inv_range, /* dcache_inv_range */ 388207611Skevlo fa526_dcache_wb_range, /* dcache_wb_range */ 389201468Srpaulo 390262420Sian armv4_idcache_inv_all, /* idcache_inv_all */ 391207611Skevlo fa526_idcache_wbinv_all, /* idcache_wbinv_all */ 392207611Skevlo fa526_idcache_wbinv_range, /* idcache_wbinv_range */ 393207611Skevlo cpufunc_nullop, /* l2cache_wbinv_all */ 394207611Skevlo (void *)cpufunc_nullop, /* l2cache_wbinv_range */ 395207611Skevlo (void *)cpufunc_nullop, /* l2cache_inv_range */ 396207611Skevlo (void *)cpufunc_nullop, /* l2cache_wb_range */ 397265870Sian (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ 398201468Srpaulo 399201468Srpaulo /* Other functions */ 400201468Srpaulo 401207611Skevlo armv4_drain_writebuf, /* drain_writebuf */ 402201468Srpaulo 403207611Skevlo fa526_cpu_sleep, /* sleep */ 404201468Srpaulo 405201468Srpaulo /* Soft functions */ 406201468Srpaulo 407201468Srpaulo 408207611Skevlo fa526_context_switch, /* context_switch */ 409201468Srpaulo 410207611Skevlo fa526_setup /* cpu setup */ 411236991Simp}; 412280842Sandrew#endif /* CPU_FA526 */ 413201468Srpaulo 414244480Sgonzo#if defined(CPU_ARM1176) 415244480Sgonzostruct cpu_functions arm1176_cpufuncs = { 416283366Sandrew 417244480Sgonzo /* Cache operations */ 418317002Smmel .cf_l2cache_wbinv_all = (void *)cpufunc_nullop, 419317002Smmel .cf_l2cache_wbinv_range = (void *)cpufunc_nullop, 420317002Smmel .cf_l2cache_inv_range = (void *)cpufunc_nullop, 421317002Smmel .cf_l2cache_wb_range = (void *)cpufunc_nullop, 422317002Smmel .cf_l2cache_drain_writebuf = (void *)cpufunc_nullop, 423283366Sandrew 424244480Sgonzo /* Other functions */ 425317002Smmel .cf_sleep = arm11x6_sleep, 426283366Sandrew 427244480Sgonzo /* Soft functions */ 428317002Smmel .cf_setup = arm11x6_setup 429244480Sgonzo}; 430244480Sgonzo#endif /*CPU_ARM1176 */ 431239701Sgonzo 432259640Sganbold#if defined(CPU_CORTEXA) || defined(CPU_KRAIT) 433239268Sgonzostruct cpu_functions cortexa_cpufuncs = { 434283366Sandrew 435239268Sgonzo /* Cache operations */ 436283366Sandrew 437283366Sandrew /* 438243026Scognet * Note: For CPUs using the PL310 the L2 ops are filled in when the 439239268Sgonzo * L2 cache controller is actually enabled. 440239268Sgonzo */ 441317002Smmel .cf_l2cache_wbinv_all = cpufunc_nullop, 442317002Smmel .cf_l2cache_wbinv_range = (void *)cpufunc_nullop, 443317002Smmel .cf_l2cache_inv_range = (void *)cpufunc_nullop, 444317002Smmel .cf_l2cache_wb_range = (void *)cpufunc_nullop, 445317002Smmel .cf_l2cache_drain_writebuf = (void *)cpufunc_nullop, 446283366Sandrew 447239268Sgonzo /* Other functions */ 448317002Smmel .cf_sleep = armv7_cpu_sleep, 449283366Sandrew 450239268Sgonzo /* Soft functions */ 451317002Smmel .cf_setup = cortexa_setup 452239268Sgonzo}; 453239268Sgonzo#endif /* CPU_CORTEXA */ 454201468Srpaulo 455129198Scognet/* 456129198Scognet * Global constants also used by locore.s 457129198Scognet */ 458129198Scognet 459129198Scognetstruct cpu_functions cpufuncs; 460129198Scognetu_int cputype; 461296313Sandrew#if __ARM_ARCH <= 5 462296313Sandrewu_int cpu_reset_needs_v4_MMU_disable; /* flag used in locore-v4.s */ 463296313Sandrew#endif 464129198Scognet 465262958Sian#if defined(CPU_ARM9) || \ 466280824Sandrew defined (CPU_ARM9E) || \ 467295200Smmel defined(CPU_ARM1176) || \ 468207611Skevlo defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ 469280842Sandrew defined(CPU_FA526) || defined(CPU_MV_PJ4B) || \ 470295200Smmel defined(CPU_XSCALE_81342) || \ 471259640Sganbold defined(CPU_CORTEXA) || defined(CPU_KRAIT) 472161592Scognet 473278518Szbb/* Global cache line sizes, use 32 as default */ 474278518Szbbint arm_dcache_min_line_size = 32; 475278518Szbbint arm_icache_min_line_size = 32; 476278518Szbbint arm_idcache_min_line_size = 32; 477278518Szbb 478137498Strhodesstatic void get_cachetype_cp15(void); 479129198Scognet 480129198Scognet/* Additional cache information local to this file. Log2 of some of the 481129198Scognet above numbers. */ 482129198Scognetstatic int arm_dcache_l2_nsets; 483129198Scognetstatic int arm_dcache_l2_assoc; 484129198Scognetstatic int arm_dcache_l2_linesize; 485129198Scognet 486129198Scognetstatic void 487314506Sianget_cachetype_cp15(void) 488129198Scognet{ 489239268Sgonzo u_int ctype, isize, dsize, cpuid; 490239268Sgonzo u_int clevel, csize, i, sel; 491129198Scognet u_int multiplier; 492239268Sgonzo u_char type; 493129198Scognet 494129198Scognet __asm __volatile("mrc p15, 0, %0, c0, c0, 1" 495129198Scognet : "=r" (ctype)); 496129198Scognet 497295096Smmel cpuid = cpu_ident(); 498129198Scognet /* 499129198Scognet * ...and thus spake the ARM ARM: 500129198Scognet * 501129198Scognet * If an <opcode2> value corresponding to an unimplemented or 502129198Scognet * reserved ID register is encountered, the System Control 503129198Scognet * processor returns the value of the main ID register. 504129198Scognet */ 505239268Sgonzo if (ctype == cpuid) 506129198Scognet goto out; 507129198Scognet 508239268Sgonzo if (CPU_CT_FORMAT(ctype) == CPU_CT_ARMV7) { 509278518Szbb /* Resolve minimal cache line sizes */ 510278518Szbb arm_dcache_min_line_size = 1 << (CPU_CT_DMINLINE(ctype) + 2); 511278518Szbb arm_icache_min_line_size = 1 << (CPU_CT_IMINLINE(ctype) + 2); 512278518Szbb arm_idcache_min_line_size = 513278518Szbb min(arm_icache_min_line_size, arm_dcache_min_line_size); 514278518Szbb 515239268Sgonzo __asm __volatile("mrc p15, 1, %0, c0, c0, 1" 516239268Sgonzo : "=r" (clevel)); 517239268Sgonzo arm_cache_level = clevel; 518239268Sgonzo arm_cache_loc = CPU_CLIDR_LOC(arm_cache_level); 519239268Sgonzo i = 0; 520239268Sgonzo while ((type = (clevel & 0x7)) && i < 7) { 521239268Sgonzo if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE || 522239268Sgonzo type == CACHE_SEP_CACHE) { 523239268Sgonzo sel = i << 1; 524239268Sgonzo __asm __volatile("mcr p15, 2, %0, c0, c0, 0" 525239268Sgonzo : : "r" (sel)); 526239268Sgonzo __asm __volatile("mrc p15, 1, %0, c0, c0, 0" 527239268Sgonzo : "=r" (csize)); 528239268Sgonzo arm_cache_type[sel] = csize; 529283366Sandrew arm_dcache_align = 1 << 530239268Sgonzo (CPUV7_CT_xSIZE_LEN(csize) + 4); 531239268Sgonzo arm_dcache_align_mask = arm_dcache_align - 1; 532239268Sgonzo } 533239268Sgonzo if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) { 534239268Sgonzo sel = (i << 1) | 1; 535239268Sgonzo __asm __volatile("mcr p15, 2, %0, c0, c0, 0" 536239268Sgonzo : : "r" (sel)); 537239268Sgonzo __asm __volatile("mrc p15, 1, %0, c0, c0, 0" 538239268Sgonzo : "=r" (csize)); 539239268Sgonzo arm_cache_type[sel] = csize; 540239268Sgonzo } 541239268Sgonzo i++; 542239268Sgonzo clevel >>= 3; 543239268Sgonzo } 544239268Sgonzo } else { 545239268Sgonzo if ((ctype & CPU_CT_S) == 0) 546239268Sgonzo arm_pcache_unified = 1; 547129198Scognet 548239268Sgonzo /* 549239268Sgonzo * If you want to know how this code works, go read the ARM ARM. 550239268Sgonzo */ 551129198Scognet 552239268Sgonzo arm_pcache_type = CPU_CT_CTYPE(ctype); 553129198Scognet 554239268Sgonzo if (arm_pcache_unified == 0) { 555239268Sgonzo isize = CPU_CT_ISIZE(ctype); 556239268Sgonzo multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2; 557239268Sgonzo arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3); 558239268Sgonzo if (CPU_CT_xSIZE_ASSOC(isize) == 0) { 559239268Sgonzo if (isize & CPU_CT_xSIZE_M) 560239268Sgonzo arm_picache_line_size = 0; /* not present */ 561239268Sgonzo else 562239268Sgonzo arm_picache_ways = 1; 563239268Sgonzo } else { 564239268Sgonzo arm_picache_ways = multiplier << 565239268Sgonzo (CPU_CT_xSIZE_ASSOC(isize) - 1); 566239268Sgonzo } 567239268Sgonzo arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8); 568239268Sgonzo } 569239268Sgonzo 570239268Sgonzo dsize = CPU_CT_DSIZE(ctype); 571239268Sgonzo multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2; 572239268Sgonzo arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3); 573239268Sgonzo if (CPU_CT_xSIZE_ASSOC(dsize) == 0) { 574239268Sgonzo if (dsize & CPU_CT_xSIZE_M) 575239268Sgonzo arm_pdcache_line_size = 0; /* not present */ 576129198Scognet else 577239268Sgonzo arm_pdcache_ways = 1; 578129198Scognet } else { 579239268Sgonzo arm_pdcache_ways = multiplier << 580239268Sgonzo (CPU_CT_xSIZE_ASSOC(dsize) - 1); 581129198Scognet } 582239268Sgonzo arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8); 583129198Scognet 584239268Sgonzo arm_dcache_align = arm_pdcache_line_size; 585129198Scognet 586239268Sgonzo arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2; 587239268Sgonzo arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3; 588239268Sgonzo arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) - 589239268Sgonzo CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize); 590129198Scognet 591239268Sgonzo out: 592239268Sgonzo arm_dcache_align_mask = arm_dcache_align - 1; 593239268Sgonzo } 594129198Scognet} 595262958Sian#endif /* ARM9 || XSCALE */ 596129198Scognet 597129198Scognet/* 598129198Scognet * Cannot panic here as we may not have a console yet ... 599129198Scognet */ 600129198Scognet 601129198Scognetint 602314506Sianset_cpufuncs(void) 603129198Scognet{ 604295096Smmel cputype = cpu_ident(); 605129198Scognet cputype &= CPU_ID_CPU_MASK; 606129198Scognet 607129198Scognet#ifdef CPU_ARM9 608129198Scognet if (((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD || 609129198Scognet (cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_TI) && 610129198Scognet (cputype & 0x0000f000) == 0x00009000) { 611129198Scognet cpufuncs = arm9_cpufuncs; 612129198Scognet cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */ 613129198Scognet get_cachetype_cp15(); 614146605Scognet arm9_dcache_sets_inc = 1U << arm_dcache_l2_linesize; 615146605Scognet arm9_dcache_sets_max = (1U << (arm_dcache_l2_linesize + 616146605Scognet arm_dcache_l2_nsets)) - arm9_dcache_sets_inc; 617146605Scognet arm9_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc); 618146605Scognet arm9_dcache_index_max = 0U - arm9_dcache_index_inc; 619137270Scognet pmap_pte_init_generic(); 620166655Scognet goto out; 621129198Scognet } 622129198Scognet#endif /* CPU_ARM9 */ 623280809Sandrew#if defined(CPU_ARM9E) 624239268Sgonzo if (cputype == CPU_ID_MV88FR131 || cputype == CPU_ID_MV88FR571_VD || 625183835Sraj cputype == CPU_ID_MV88FR571_41) { 626239268Sgonzo uint32_t sheeva_ctrl; 627183835Sraj 628239268Sgonzo sheeva_ctrl = (MV_DC_STREAM_ENABLE | MV_BTB_DISABLE | 629239268Sgonzo MV_L2_ENABLE); 630239268Sgonzo /* 631239268Sgonzo * Workaround for Marvell MV78100 CPU: Cache prefetch 632239268Sgonzo * mechanism may affect the cache coherency validity, 633239268Sgonzo * so it needs to be disabled. 634239268Sgonzo * 635239268Sgonzo * Refer to errata document MV-S501058-00C.pdf (p. 3.1 636239268Sgonzo * L2 Prefetching Mechanism) for details. 637239268Sgonzo */ 638239268Sgonzo if (cputype == CPU_ID_MV88FR571_VD || 639239268Sgonzo cputype == CPU_ID_MV88FR571_41) 640239268Sgonzo sheeva_ctrl |= MV_L2_PREFETCH_DISABLE; 641212825Smav 642239268Sgonzo sheeva_control_ext(0xffffffff & ~MV_WA_ENABLE, sheeva_ctrl); 643183835Sraj 644239268Sgonzo cpufuncs = sheeva_cpufuncs; 645172738Simp get_cachetype_cp15(); 646172738Simp pmap_pte_init_generic(); 647174058Scognet goto out; 648280809Sandrew } else if (cputype == CPU_ID_ARM926EJS) { 649239268Sgonzo cpufuncs = armv5_ec_cpufuncs; 650239268Sgonzo get_cachetype_cp15(); 651239268Sgonzo pmap_pte_init_generic(); 652239268Sgonzo goto out; 653172738Simp } 654280809Sandrew#endif /* CPU_ARM9E */ 655280824Sandrew#if defined(CPU_ARM1176) 656280824Sandrew if (cputype == CPU_ID_ARM1176JZS) { 657280868Sandrew cpufuncs = arm1176_cpufuncs; 658244480Sgonzo get_cachetype_cp15(); 659244480Sgonzo goto out; 660244480Sgonzo } 661280824Sandrew#endif /* CPU_ARM1176 */ 662259640Sganbold#if defined(CPU_CORTEXA) || defined(CPU_KRAIT) 663301561Sandrew switch(cputype & CPU_ID_SCHEME_MASK) { 664301561Sandrew case CPU_ID_CORTEXA5: 665301561Sandrew case CPU_ID_CORTEXA7: 666301561Sandrew case CPU_ID_CORTEXA8: 667301561Sandrew case CPU_ID_CORTEXA9: 668301561Sandrew case CPU_ID_CORTEXA12: 669301561Sandrew case CPU_ID_CORTEXA15: 670317002Smmel case CPU_ID_CORTEXA53: 671317002Smmel case CPU_ID_CORTEXA57: 672317002Smmel case CPU_ID_CORTEXA72: 673301561Sandrew case CPU_ID_KRAIT300: 674239268Sgonzo cpufuncs = cortexa_cpufuncs; 675239268Sgonzo get_cachetype_cp15(); 676239268Sgonzo goto out; 677301561Sandrew default: 678301561Sandrew break; 679239268Sgonzo } 680239268Sgonzo#endif /* CPU_CORTEXA */ 681283366Sandrew 682239268Sgonzo#if defined(CPU_MV_PJ4B) 683257281Szbb if (cputype == CPU_ID_MV88SV581X_V7 || 684240486Sgber cputype == CPU_ID_MV88SV584X_V7 || 685239268Sgonzo cputype == CPU_ID_ARM_88SV581X_V7) { 686257281Szbb cpufuncs = pj4bv7_cpufuncs; 687239268Sgonzo get_cachetype_cp15(); 688239268Sgonzo goto out; 689239268Sgonzo } 690239268Sgonzo#endif /* CPU_MV_PJ4B */ 691129198Scognet 692280842Sandrew#if defined(CPU_FA526) 693207611Skevlo if (cputype == CPU_ID_FA526 || cputype == CPU_ID_FA626TE) { 694201468Srpaulo cpufuncs = fa526_cpufuncs; 695201468Srpaulo cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */ 696201468Srpaulo get_cachetype_cp15(); 697201468Srpaulo pmap_pte_init_generic(); 698201468Srpaulo 699201468Srpaulo goto out; 700201468Srpaulo } 701280842Sandrew#endif /* CPU_FA526 */ 702262958Sian 703164080Scognet#if defined(CPU_XSCALE_81342) 704164080Scognet if (cputype == CPU_ID_81342) { 705164080Scognet cpufuncs = xscalec3_cpufuncs; 706164080Scognet cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ 707164080Scognet get_cachetype_cp15(); 708164080Scognet pmap_pte_init_xscale(); 709166655Scognet goto out; 710164080Scognet } 711164080Scognet#endif /* CPU_XSCALE_81342 */ 712129198Scognet#ifdef CPU_XSCALE_PXA2X0 713129198Scognet /* ignore core revision to test PXA2xx CPUs */ 714129198Scognet if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA250 || 715191817Sstas (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X || 716129198Scognet (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA210) { 717129198Scognet 718129198Scognet cpufuncs = xscale_cpufuncs; 719129198Scognet cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ 720129198Scognet get_cachetype_cp15(); 721129198Scognet pmap_pte_init_xscale(); 722129198Scognet 723166655Scognet goto out; 724129198Scognet } 725129198Scognet#endif /* CPU_XSCALE_PXA2X0 */ 726129198Scognet#ifdef CPU_XSCALE_IXP425 727129198Scognet if (cputype == CPU_ID_IXP425_533 || cputype == CPU_ID_IXP425_400 || 728186352Ssam cputype == CPU_ID_IXP425_266 || cputype == CPU_ID_IXP435) { 729129198Scognet 730129198Scognet cpufuncs = xscale_cpufuncs; 731129198Scognet cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ 732129198Scognet get_cachetype_cp15(); 733129198Scognet pmap_pte_init_xscale(); 734129198Scognet 735166655Scognet goto out; 736129198Scognet } 737129198Scognet#endif /* CPU_XSCALE_IXP425 */ 738129198Scognet /* 739129198Scognet * Bzzzz. And the answer was ... 740129198Scognet */ 741129198Scognet panic("No support for this CPU type (%08x) in kernel", cputype); 742129198Scognet return(ARCHITECTURE_NOT_PRESENT); 743166655Scognetout: 744166655Scognet uma_set_align(arm_dcache_align_mask); 745166655Scognet return (0); 746129198Scognet} 747129198Scognet 748129198Scognet/* 749129198Scognet * CPU Setup code 750129198Scognet */ 751129198Scognet 752129198Scognet#ifdef CPU_ARM9 753129198Scognetvoid 754280823Sandrewarm9_setup(void) 755129198Scognet{ 756129198Scognet int cpuctrl, cpuctrlmask; 757129198Scognet 758129198Scognet cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 759129198Scognet | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 760129198Scognet | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 761157618Scognet | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE | 762157618Scognet CPU_CONTROL_ROUNDROBIN; 763129198Scognet cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 764129198Scognet | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 765129198Scognet | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 766129198Scognet | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 767129198Scognet | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 768146605Scognet | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_VECRELOC 769146605Scognet | CPU_CONTROL_ROUNDROBIN; 770129198Scognet 771129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 772129198Scognet cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 773129198Scognet#endif 774129198Scognet 775129198Scognet#ifdef __ARMEB__ 776129198Scognet cpuctrl |= CPU_CONTROL_BEND_ENABLE; 777129198Scognet#endif 778142050Scognet if (vector_page == ARM_VECTORS_HIGH) 779142050Scognet cpuctrl |= CPU_CONTROL_VECRELOC; 780129198Scognet 781129198Scognet /* Clear out the cache */ 782129198Scognet cpu_idcache_wbinv_all(); 783129198Scognet 784300533Sian /* Set the control register (SCTLR) */ 785146605Scognet cpu_control(cpuctrlmask, cpuctrl); 786129198Scognet 787129198Scognet} 788129198Scognet#endif /* CPU_ARM9 */ 789129198Scognet 790280809Sandrew#if defined(CPU_ARM9E) 791129198Scognetvoid 792280823Sandrewarm10_setup(void) 793129198Scognet{ 794129198Scognet int cpuctrl, cpuctrlmask; 795129198Scognet 796129198Scognet cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE 797236991Simp | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 798129198Scognet | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_BPRD_ENABLE; 799129198Scognet cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE 800129198Scognet | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 801129198Scognet | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 802129198Scognet | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 803129198Scognet | CPU_CONTROL_BPRD_ENABLE 804129198Scognet | CPU_CONTROL_ROUNDROBIN | CPU_CONTROL_CPCLK; 805129198Scognet 806129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 807129198Scognet cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 808129198Scognet#endif 809129198Scognet 810129198Scognet#ifdef __ARMEB__ 811129198Scognet cpuctrl |= CPU_CONTROL_BEND_ENABLE; 812129198Scognet#endif 813129198Scognet 814129198Scognet /* Clear out the cache */ 815129198Scognet cpu_idcache_wbinv_all(); 816129198Scognet 817129198Scognet /* Now really make sure they are clean. */ 818172738Simp __asm __volatile ("mcr\tp15, 0, r0, c7, c7, 0" : : ); 819129198Scognet 820174058Scognet if (vector_page == ARM_VECTORS_HIGH) 821174058Scognet cpuctrl |= CPU_CONTROL_VECRELOC; 822174058Scognet 823129198Scognet /* Set the control register */ 824129198Scognet cpu_control(0xffffffff, cpuctrl); 825129198Scognet 826129198Scognet /* And again. */ 827129198Scognet cpu_idcache_wbinv_all(); 828129198Scognet} 829172738Simp#endif /* CPU_ARM9E || CPU_ARM10 */ 830129198Scognet 831280824Sandrew#if defined(CPU_ARM1176) \ 832266083Smarkm || defined(CPU_MV_PJ4B) \ 833266083Smarkm || defined(CPU_CORTEXA) || defined(CPU_KRAIT) 834266083Smarkmstatic __inline void 835266083Smarkmcpu_scc_setup_ccnt(void) 836266083Smarkm{ 837266083Smarkm/* This is how you give userland access to the CCNT and PMCn 838266083Smarkm * registers. 839266083Smarkm * BEWARE! This gives write access also, which may not be what 840266083Smarkm * you want! 841266083Smarkm */ 842266083Smarkm#ifdef _PMC_USER_READ_WRITE_ 843266083Smarkm /* Set PMUSERENR[0] to allow userland access */ 844283365Sandrew cp15_pmuserenr_set(1); 845266083Smarkm#endif 846280824Sandrew#if defined(CPU_ARM1176) 847267597Stuexen /* Set PMCR[2,0] to enable counters and reset CCNT */ 848283365Sandrew cp15_pmcr_set(5); 849267597Stuexen#else 850267597Stuexen /* Set up the PMCCNTR register as a cyclecounter: 851266083Smarkm * Set PMINTENCLR to 0xFFFFFFFF to block interrupts 852266083Smarkm * Set PMCR[2,0] to enable counters and reset CCNT 853266083Smarkm * Set PMCNTENSET to 0x80000000 to enable CCNT */ 854283365Sandrew cp15_pminten_clr(0xFFFFFFFF); 855283365Sandrew cp15_pmcr_set(5); 856283365Sandrew cp15_pmcnten_set(0x80000000); 857267597Stuexen#endif 858266083Smarkm} 859266083Smarkm#endif 860266083Smarkm 861280824Sandrew#if defined(CPU_ARM1176) 862172738Simpvoid 863280823Sandrewarm11x6_setup(void) 864172738Simp{ 865244480Sgonzo uint32_t auxctrl, auxctrl_wax; 866244480Sgonzo uint32_t tmp, tmp2; 867244480Sgonzo uint32_t cpuid; 868172738Simp 869295096Smmel cpuid = cpu_ident(); 870244480Sgonzo 871244480Sgonzo auxctrl = 0; 872244480Sgonzo auxctrl_wax = ~0; 873244480Sgonzo 874244480Sgonzo /* 875244480Sgonzo * Enable an errata workaround 876244480Sgonzo */ 877244480Sgonzo if ((cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM1176JZS) { /* ARM1176JZSr0 */ 878244480Sgonzo auxctrl = ARM1176_AUXCTL_PHD; 879244480Sgonzo auxctrl_wax = ~ARM1176_AUXCTL_PHD; 880244480Sgonzo } 881244480Sgonzo 882283365Sandrew tmp = cp15_actlr_get(); 883283365Sandrew tmp2 = tmp; 884283365Sandrew tmp &= auxctrl_wax; 885283365Sandrew tmp |= auxctrl; 886283365Sandrew if (tmp != tmp2) 887283365Sandrew cp15_actlr_set(tmp); 888244480Sgonzo 889266083Smarkm cpu_scc_setup_ccnt(); 890172738Simp} 891280824Sandrew#endif /* CPU_ARM1176 */ 892172738Simp 893239268Sgonzo#ifdef CPU_MV_PJ4B 894239268Sgonzovoid 895280823Sandrewpj4bv7_setup(void) 896239268Sgonzo{ 897239268Sgonzo 898239268Sgonzo pj4b_config(); 899266083Smarkm cpu_scc_setup_ccnt(); 900239268Sgonzo} 901239268Sgonzo#endif /* CPU_MV_PJ4B */ 902239268Sgonzo 903259640Sganbold#if defined(CPU_CORTEXA) || defined(CPU_KRAIT) 904239268Sgonzo 905239268Sgonzovoid 906280823Sandrewcortexa_setup(void) 907239268Sgonzo{ 908283366Sandrew 909266083Smarkm cpu_scc_setup_ccnt(); 910239268Sgonzo} 911239268Sgonzo#endif /* CPU_CORTEXA */ 912239268Sgonzo 913280842Sandrew#if defined(CPU_FA526) 914201468Srpaulovoid 915280823Sandrewfa526_setup(void) 916201468Srpaulo{ 917201468Srpaulo int cpuctrl, cpuctrlmask; 918201468Srpaulo 919201468Srpaulo cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 920201468Srpaulo | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 921201468Srpaulo | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 922204122Skevlo | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE 923204122Skevlo | CPU_CONTROL_BPRD_ENABLE; 924201468Srpaulo cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 925201468Srpaulo | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 926201468Srpaulo | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 927201468Srpaulo | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 928201468Srpaulo | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 929201468Srpaulo | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE 930201468Srpaulo | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC; 931201468Srpaulo 932201468Srpaulo#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 933201468Srpaulo cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 934201468Srpaulo#endif 935201468Srpaulo 936201468Srpaulo#ifdef __ARMEB__ 937201468Srpaulo cpuctrl |= CPU_CONTROL_BEND_ENABLE; 938201468Srpaulo#endif 939201468Srpaulo 940201468Srpaulo if (vector_page == ARM_VECTORS_HIGH) 941201468Srpaulo cpuctrl |= CPU_CONTROL_VECRELOC; 942201468Srpaulo 943201468Srpaulo /* Clear out the cache */ 944201468Srpaulo cpu_idcache_wbinv_all(); 945201468Srpaulo 946201468Srpaulo /* Set the control register */ 947201468Srpaulo cpu_control(0xffffffff, cpuctrl); 948201468Srpaulo} 949280842Sandrew#endif /* CPU_FA526 */ 950201468Srpaulo 951295200Smmel#if defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ 952295200Smmel defined(CPU_XSCALE_81342) 953129198Scognetvoid 954280823Sandrewxscale_setup(void) 955129198Scognet{ 956129198Scognet uint32_t auxctl; 957129198Scognet int cpuctrl, cpuctrlmask; 958129198Scognet 959129198Scognet /* 960129198Scognet * The XScale Write Buffer is always enabled. Our option 961129198Scognet * is to enable/disable coalescing. Note that bits 6:3 962129198Scognet * must always be enabled. 963129198Scognet */ 964129198Scognet 965129198Scognet cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 966129198Scognet | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 967129198Scognet | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 968129198Scognet | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE 969129198Scognet | CPU_CONTROL_BPRD_ENABLE; 970129198Scognet cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 971129198Scognet | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 972129198Scognet | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 973129198Scognet | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 974129198Scognet | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 975129198Scognet | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE 976171618Scognet | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC | \ 977171618Scognet CPU_CONTROL_L2_ENABLE; 978129198Scognet 979129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 980129198Scognet cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 981129198Scognet#endif 982129198Scognet 983129198Scognet#ifdef __ARMEB__ 984129198Scognet cpuctrl |= CPU_CONTROL_BEND_ENABLE; 985129198Scognet#endif 986129198Scognet 987129198Scognet if (vector_page == ARM_VECTORS_HIGH) 988129198Scognet cpuctrl |= CPU_CONTROL_VECRELOC; 989171618Scognet#ifdef CPU_XSCALE_CORE3 990171618Scognet cpuctrl |= CPU_CONTROL_L2_ENABLE; 991171618Scognet#endif 992129198Scognet 993129198Scognet /* Clear out the cache */ 994129198Scognet cpu_idcache_wbinv_all(); 995129198Scognet 996129198Scognet /* 997129198Scognet * Set the control register. Note that bits 6:3 must always 998129198Scognet * be set to 1. 999129198Scognet */ 1000129198Scognet/* cpu_control(cpuctrlmask, cpuctrl);*/ 1001129198Scognet cpu_control(0xffffffff, cpuctrl); 1002129198Scognet 1003129198Scognet /* Make sure write coalescing is turned on */ 1004129198Scognet __asm __volatile("mrc p15, 0, %0, c1, c0, 1" 1005129198Scognet : "=r" (auxctl)); 1006129198Scognet#ifdef XSCALE_NO_COALESCE_WRITES 1007129198Scognet auxctl |= XSCALE_AUXCTL_K; 1008129198Scognet#else 1009129198Scognet auxctl &= ~XSCALE_AUXCTL_K; 1010129198Scognet#endif 1011171618Scognet#ifdef CPU_XSCALE_CORE3 1012171618Scognet auxctl |= XSCALE_AUXCTL_LLR; 1013171618Scognet auxctl |= XSCALE_AUXCTL_MD_MASK; 1014171618Scognet#endif 1015129198Scognet __asm __volatile("mcr p15, 0, %0, c1, c0, 1" 1016129198Scognet : : "r" (auxctl)); 1017129198Scognet} 1018295200Smmel#endif /* CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */ 1019