cpufunc.c revision 146605
1129198Scognet/* $NetBSD: cpufunc.c,v 1.65 2003/11/05 12:53:15 scw Exp $ */ 2129198Scognet 3139735Simp/*- 4129198Scognet * arm7tdmi support code Copyright (c) 2001 John Fremlin 5129198Scognet * arm8 support code Copyright (c) 1997 ARM Limited 6129198Scognet * arm8 support code Copyright (c) 1997 Causality Limited 7129198Scognet * arm9 support code Copyright (C) 2001 ARM Ltd 8129198Scognet * Copyright (c) 1997 Mark Brinicombe. 9129198Scognet * Copyright (c) 1997 Causality Limited 10129198Scognet * All rights reserved. 11129198Scognet * 12129198Scognet * Redistribution and use in source and binary forms, with or without 13129198Scognet * modification, are permitted provided that the following conditions 14129198Scognet * are met: 15129198Scognet * 1. Redistributions of source code must retain the above copyright 16129198Scognet * notice, this list of conditions and the following disclaimer. 17129198Scognet * 2. Redistributions in binary form must reproduce the above copyright 18129198Scognet * notice, this list of conditions and the following disclaimer in the 19129198Scognet * documentation and/or other materials provided with the distribution. 20129198Scognet * 3. All advertising materials mentioning features or use of this software 21129198Scognet * must display the following acknowledgement: 22129198Scognet * This product includes software developed by Causality Limited. 23129198Scognet * 4. The name of Causality Limited may not be used to endorse or promote 24129198Scognet * products derived from this software without specific prior written 25129198Scognet * permission. 26129198Scognet * 27129198Scognet * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS 28129198Scognet * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 29129198Scognet * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 30129198Scognet * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT, 31129198Scognet * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 32129198Scognet * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 33129198Scognet * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34129198Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35129198Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36129198Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37129198Scognet * SUCH DAMAGE. 38129198Scognet * 39129198Scognet * RiscBSD kernel project 40129198Scognet * 41129198Scognet * cpufuncs.c 42129198Scognet * 43129198Scognet * C functions for supporting CPU / MMU / TLB specific operations. 44129198Scognet * 45129198Scognet * Created : 30/01/97 46129198Scognet */ 47129198Scognet#include <sys/cdefs.h> 48129198Scognet__FBSDID("$FreeBSD: head/sys/arm/arm/cpufunc.c 146605 2005-05-24 23:57:22Z cognet $"); 49129198Scognet 50129198Scognet#include <sys/cdefs.h> 51129198Scognet 52129198Scognet#include <sys/types.h> 53129198Scognet#include <sys/param.h> 54129198Scognet#include <sys/systm.h> 55129198Scognet#include <sys/lock.h> 56129198Scognet#include <sys/mutex.h> 57132472Scognet#include <sys/bus.h> 58132472Scognet#include <machine/bus.h> 59129198Scognet#include <machine/cpu.h> 60129198Scognet#include <machine/disassem.h> 61129198Scognet 62129198Scognet#include <vm/vm.h> 63129198Scognet#include <vm/pmap.h> 64129198Scognet 65129198Scognet#include <machine/cpuconf.h> 66129198Scognet#include <machine/cpufunc.h> 67129198Scognet#include <machine/bootconfig.h> 68129198Scognet 69129198Scognet#ifdef CPU_XSCALE_80200 70135646Scognet#include <arm/xscale/i80200/i80200reg.h> 71135646Scognet#include <arm/xscale/i80200/i80200var.h> 72129198Scognet#endif 73129198Scognet 74129198Scognet#ifdef CPU_XSCALE_80321 75135646Scognet#include <arm/xscale/i80321/i80321reg.h> 76135646Scognet#include <arm/xscale/i80321/i80321var.h> 77129198Scognet#endif 78129198Scognet 79129198Scognet#ifdef CPU_XSCALE_IXP425 80135646Scognet#include <arm/xscale/ixp425/ixp425reg.h> 81135646Scognet#include <arm/xscale/ixp425/ixp425var.h> 82129198Scognet#endif 83129198Scognet 84129198Scognet#if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) 85129198Scognet#include <arm/xscale/xscalereg.h> 86129198Scognet#endif 87129198Scognet 88129198Scognet#if defined(PERFCTRS) 89129198Scognetstruct arm_pmc_funcs *arm_pmc; 90129198Scognet#endif 91129198Scognet 92129198Scognet/* PRIMARY CACHE VARIABLES */ 93129198Scognetint arm_picache_size; 94129198Scognetint arm_picache_line_size; 95129198Scognetint arm_picache_ways; 96129198Scognet 97129198Scognetint arm_pdcache_size; /* and unified */ 98129198Scognetint arm_pdcache_line_size; 99129198Scognetint arm_pdcache_ways; 100129198Scognet 101129198Scognetint arm_pcache_type; 102129198Scognetint arm_pcache_unified; 103129198Scognet 104129198Scognetint arm_dcache_align; 105129198Scognetint arm_dcache_align_mask; 106129198Scognet 107129198Scognet/* 1 == use cpu_sleep(), 0 == don't */ 108129198Scognetint cpu_do_powersave; 109129198Scognetint ctrl; 110129198Scognet#ifdef CPU_ARM3 111129198Scognetstruct cpu_functions arm3_cpufuncs = { 112129198Scognet /* CPU functions */ 113129198Scognet 114129198Scognet cpufunc_id, /* id */ 115129198Scognet cpufunc_nullop, /* cpwait */ 116129198Scognet 117129198Scognet /* MMU functions */ 118129198Scognet 119129198Scognet arm3_control, /* control */ 120129198Scognet NULL, /* domain */ 121129198Scognet NULL, /* setttb */ 122129198Scognet NULL, /* faultstatus */ 123129198Scognet NULL, /* faultaddress */ 124129198Scognet 125129198Scognet /* TLB functions */ 126129198Scognet 127129198Scognet cpufunc_nullop, /* tlb_flushID */ 128129198Scognet (void *)cpufunc_nullop, /* tlb_flushID_SE */ 129129198Scognet cpufunc_nullop, /* tlb_flushI */ 130129198Scognet (void *)cpufunc_nullop, /* tlb_flushI_SE */ 131129198Scognet cpufunc_nullop, /* tlb_flushD */ 132129198Scognet (void *)cpufunc_nullop, /* tlb_flushD_SE */ 133129198Scognet 134129198Scognet /* Cache operations */ 135129198Scognet 136129198Scognet cpufunc_nullop, /* icache_sync_all */ 137129198Scognet (void *) cpufunc_nullop, /* icache_sync_range */ 138129198Scognet 139129198Scognet arm3_cache_flush, /* dcache_wbinv_all */ 140129198Scognet (void *)arm3_cache_flush, /* dcache_wbinv_range */ 141129198Scognet (void *)arm3_cache_flush, /* dcache_inv_range */ 142129198Scognet (void *)cpufunc_nullop, /* dcache_wb_range */ 143129198Scognet 144129198Scognet arm3_cache_flush, /* idcache_wbinv_all */ 145129198Scognet (void *)arm3_cache_flush, /* idcache_wbinv_range */ 146129198Scognet 147129198Scognet /* Other functions */ 148129198Scognet 149129198Scognet cpufunc_nullop, /* flush_prefetchbuf */ 150129198Scognet cpufunc_nullop, /* drain_writebuf */ 151129198Scognet cpufunc_nullop, /* flush_brnchtgt_C */ 152129198Scognet (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 153129198Scognet 154129198Scognet (void *)cpufunc_nullop, /* sleep */ 155129198Scognet 156129198Scognet /* Soft functions */ 157129198Scognet 158129198Scognet early_abort_fixup, /* dataabt_fixup */ 159129198Scognet cpufunc_null_fixup, /* prefetchabt_fixup */ 160129198Scognet 161129198Scognet NULL, /* context_switch */ 162129198Scognet 163129198Scognet (void *)cpufunc_nullop /* cpu setup */ 164129198Scognet 165129198Scognet}; 166129198Scognet#endif /* CPU_ARM3 */ 167129198Scognet 168129198Scognet#ifdef CPU_ARM6 169129198Scognetstruct cpu_functions arm6_cpufuncs = { 170129198Scognet /* CPU functions */ 171129198Scognet 172129198Scognet cpufunc_id, /* id */ 173129198Scognet cpufunc_nullop, /* cpwait */ 174129198Scognet 175129198Scognet /* MMU functions */ 176129198Scognet 177129198Scognet cpufunc_control, /* control */ 178129198Scognet cpufunc_domains, /* domain */ 179129198Scognet arm67_setttb, /* setttb */ 180129198Scognet cpufunc_faultstatus, /* faultstatus */ 181129198Scognet cpufunc_faultaddress, /* faultaddress */ 182129198Scognet 183129198Scognet /* TLB functions */ 184129198Scognet 185129198Scognet arm67_tlb_flush, /* tlb_flushID */ 186129198Scognet arm67_tlb_purge, /* tlb_flushID_SE */ 187129198Scognet arm67_tlb_flush, /* tlb_flushI */ 188129198Scognet arm67_tlb_purge, /* tlb_flushI_SE */ 189129198Scognet arm67_tlb_flush, /* tlb_flushD */ 190129198Scognet arm67_tlb_purge, /* tlb_flushD_SE */ 191129198Scognet 192129198Scognet /* Cache operations */ 193129198Scognet 194129198Scognet cpufunc_nullop, /* icache_sync_all */ 195129198Scognet (void *) cpufunc_nullop, /* icache_sync_range */ 196129198Scognet 197129198Scognet arm67_cache_flush, /* dcache_wbinv_all */ 198129198Scognet (void *)arm67_cache_flush, /* dcache_wbinv_range */ 199129198Scognet (void *)arm67_cache_flush, /* dcache_inv_range */ 200129198Scognet (void *)cpufunc_nullop, /* dcache_wb_range */ 201129198Scognet 202129198Scognet arm67_cache_flush, /* idcache_wbinv_all */ 203129198Scognet (void *)arm67_cache_flush, /* idcache_wbinv_range */ 204129198Scognet 205129198Scognet /* Other functions */ 206129198Scognet 207129198Scognet cpufunc_nullop, /* flush_prefetchbuf */ 208129198Scognet cpufunc_nullop, /* drain_writebuf */ 209129198Scognet cpufunc_nullop, /* flush_brnchtgt_C */ 210129198Scognet (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 211129198Scognet 212129198Scognet (void *)cpufunc_nullop, /* sleep */ 213129198Scognet 214129198Scognet /* Soft functions */ 215129198Scognet 216129198Scognet#ifdef ARM6_LATE_ABORT 217129198Scognet late_abort_fixup, /* dataabt_fixup */ 218129198Scognet#else 219129198Scognet early_abort_fixup, /* dataabt_fixup */ 220129198Scognet#endif 221129198Scognet cpufunc_null_fixup, /* prefetchabt_fixup */ 222129198Scognet 223129198Scognet arm67_context_switch, /* context_switch */ 224129198Scognet 225129198Scognet arm6_setup /* cpu setup */ 226129198Scognet 227129198Scognet}; 228129198Scognet#endif /* CPU_ARM6 */ 229129198Scognet 230129198Scognet#ifdef CPU_ARM7 231129198Scognetstruct cpu_functions arm7_cpufuncs = { 232129198Scognet /* CPU functions */ 233129198Scognet 234129198Scognet cpufunc_id, /* id */ 235129198Scognet cpufunc_nullop, /* cpwait */ 236129198Scognet 237129198Scognet /* MMU functions */ 238129198Scognet 239129198Scognet cpufunc_control, /* control */ 240129198Scognet cpufunc_domains, /* domain */ 241129198Scognet arm67_setttb, /* setttb */ 242129198Scognet cpufunc_faultstatus, /* faultstatus */ 243129198Scognet cpufunc_faultaddress, /* faultaddress */ 244129198Scognet 245129198Scognet /* TLB functions */ 246129198Scognet 247129198Scognet arm67_tlb_flush, /* tlb_flushID */ 248129198Scognet arm67_tlb_purge, /* tlb_flushID_SE */ 249129198Scognet arm67_tlb_flush, /* tlb_flushI */ 250129198Scognet arm67_tlb_purge, /* tlb_flushI_SE */ 251129198Scognet arm67_tlb_flush, /* tlb_flushD */ 252129198Scognet arm67_tlb_purge, /* tlb_flushD_SE */ 253129198Scognet 254129198Scognet /* Cache operations */ 255129198Scognet 256129198Scognet cpufunc_nullop, /* icache_sync_all */ 257129198Scognet (void *)cpufunc_nullop, /* icache_sync_range */ 258129198Scognet 259129198Scognet arm67_cache_flush, /* dcache_wbinv_all */ 260129198Scognet (void *)arm67_cache_flush, /* dcache_wbinv_range */ 261129198Scognet (void *)arm67_cache_flush, /* dcache_inv_range */ 262129198Scognet (void *)cpufunc_nullop, /* dcache_wb_range */ 263129198Scognet 264129198Scognet arm67_cache_flush, /* idcache_wbinv_all */ 265129198Scognet (void *)arm67_cache_flush, /* idcache_wbinv_range */ 266129198Scognet 267129198Scognet /* Other functions */ 268129198Scognet 269129198Scognet cpufunc_nullop, /* flush_prefetchbuf */ 270129198Scognet cpufunc_nullop, /* drain_writebuf */ 271129198Scognet cpufunc_nullop, /* flush_brnchtgt_C */ 272129198Scognet (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 273129198Scognet 274129198Scognet (void *)cpufunc_nullop, /* sleep */ 275129198Scognet 276129198Scognet /* Soft functions */ 277129198Scognet 278129198Scognet late_abort_fixup, /* dataabt_fixup */ 279129198Scognet cpufunc_null_fixup, /* prefetchabt_fixup */ 280129198Scognet 281129198Scognet arm67_context_switch, /* context_switch */ 282129198Scognet 283129198Scognet arm7_setup /* cpu setup */ 284129198Scognet 285129198Scognet}; 286129198Scognet#endif /* CPU_ARM7 */ 287129198Scognet 288129198Scognet#ifdef CPU_ARM7TDMI 289129198Scognetstruct cpu_functions arm7tdmi_cpufuncs = { 290129198Scognet /* CPU functions */ 291129198Scognet 292129198Scognet cpufunc_id, /* id */ 293129198Scognet cpufunc_nullop, /* cpwait */ 294129198Scognet 295129198Scognet /* MMU functions */ 296129198Scognet 297129198Scognet cpufunc_control, /* control */ 298129198Scognet cpufunc_domains, /* domain */ 299129198Scognet arm7tdmi_setttb, /* setttb */ 300129198Scognet cpufunc_faultstatus, /* faultstatus */ 301129198Scognet cpufunc_faultaddress, /* faultaddress */ 302129198Scognet 303129198Scognet /* TLB functions */ 304129198Scognet 305129198Scognet arm7tdmi_tlb_flushID, /* tlb_flushID */ 306129198Scognet arm7tdmi_tlb_flushID_SE, /* tlb_flushID_SE */ 307129198Scognet arm7tdmi_tlb_flushID, /* tlb_flushI */ 308129198Scognet arm7tdmi_tlb_flushID_SE, /* tlb_flushI_SE */ 309129198Scognet arm7tdmi_tlb_flushID, /* tlb_flushD */ 310129198Scognet arm7tdmi_tlb_flushID_SE, /* tlb_flushD_SE */ 311129198Scognet 312129198Scognet /* Cache operations */ 313129198Scognet 314129198Scognet cpufunc_nullop, /* icache_sync_all */ 315129198Scognet (void *)cpufunc_nullop, /* icache_sync_range */ 316129198Scognet 317129198Scognet arm7tdmi_cache_flushID, /* dcache_wbinv_all */ 318129198Scognet (void *)arm7tdmi_cache_flushID, /* dcache_wbinv_range */ 319129198Scognet (void *)arm7tdmi_cache_flushID, /* dcache_inv_range */ 320129198Scognet (void *)cpufunc_nullop, /* dcache_wb_range */ 321129198Scognet 322129198Scognet arm7tdmi_cache_flushID, /* idcache_wbinv_all */ 323129198Scognet (void *)arm7tdmi_cache_flushID, /* idcache_wbinv_range */ 324129198Scognet 325129198Scognet /* Other functions */ 326129198Scognet 327129198Scognet cpufunc_nullop, /* flush_prefetchbuf */ 328129198Scognet cpufunc_nullop, /* drain_writebuf */ 329129198Scognet cpufunc_nullop, /* flush_brnchtgt_C */ 330129198Scognet (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 331129198Scognet 332129198Scognet (void *)cpufunc_nullop, /* sleep */ 333129198Scognet 334129198Scognet /* Soft functions */ 335129198Scognet 336129198Scognet late_abort_fixup, /* dataabt_fixup */ 337129198Scognet cpufunc_null_fixup, /* prefetchabt_fixup */ 338129198Scognet 339129198Scognet arm7tdmi_context_switch, /* context_switch */ 340129198Scognet 341129198Scognet arm7tdmi_setup /* cpu setup */ 342129198Scognet 343129198Scognet}; 344129198Scognet#endif /* CPU_ARM7TDMI */ 345129198Scognet 346129198Scognet#ifdef CPU_ARM8 347129198Scognetstruct cpu_functions arm8_cpufuncs = { 348129198Scognet /* CPU functions */ 349129198Scognet 350129198Scognet cpufunc_id, /* id */ 351129198Scognet cpufunc_nullop, /* cpwait */ 352129198Scognet 353129198Scognet /* MMU functions */ 354129198Scognet 355129198Scognet cpufunc_control, /* control */ 356129198Scognet cpufunc_domains, /* domain */ 357129198Scognet arm8_setttb, /* setttb */ 358129198Scognet cpufunc_faultstatus, /* faultstatus */ 359129198Scognet cpufunc_faultaddress, /* faultaddress */ 360129198Scognet 361129198Scognet /* TLB functions */ 362129198Scognet 363129198Scognet arm8_tlb_flushID, /* tlb_flushID */ 364129198Scognet arm8_tlb_flushID_SE, /* tlb_flushID_SE */ 365129198Scognet arm8_tlb_flushID, /* tlb_flushI */ 366129198Scognet arm8_tlb_flushID_SE, /* tlb_flushI_SE */ 367129198Scognet arm8_tlb_flushID, /* tlb_flushD */ 368129198Scognet arm8_tlb_flushID_SE, /* tlb_flushD_SE */ 369129198Scognet 370129198Scognet /* Cache operations */ 371129198Scognet 372129198Scognet cpufunc_nullop, /* icache_sync_all */ 373129198Scognet (void *)cpufunc_nullop, /* icache_sync_range */ 374129198Scognet 375129198Scognet arm8_cache_purgeID, /* dcache_wbinv_all */ 376129198Scognet (void *)arm8_cache_purgeID, /* dcache_wbinv_range */ 377129198Scognet/*XXX*/ (void *)arm8_cache_purgeID, /* dcache_inv_range */ 378129198Scognet (void *)arm8_cache_cleanID, /* dcache_wb_range */ 379129198Scognet 380129198Scognet arm8_cache_purgeID, /* idcache_wbinv_all */ 381129198Scognet (void *)arm8_cache_purgeID, /* idcache_wbinv_range */ 382129198Scognet 383129198Scognet /* Other functions */ 384129198Scognet 385129198Scognet cpufunc_nullop, /* flush_prefetchbuf */ 386129198Scognet cpufunc_nullop, /* drain_writebuf */ 387129198Scognet cpufunc_nullop, /* flush_brnchtgt_C */ 388129198Scognet (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 389129198Scognet 390129198Scognet (void *)cpufunc_nullop, /* sleep */ 391129198Scognet 392129198Scognet /* Soft functions */ 393129198Scognet 394129198Scognet cpufunc_null_fixup, /* dataabt_fixup */ 395129198Scognet cpufunc_null_fixup, /* prefetchabt_fixup */ 396129198Scognet 397129198Scognet arm8_context_switch, /* context_switch */ 398129198Scognet 399129198Scognet arm8_setup /* cpu setup */ 400129198Scognet}; 401129198Scognet#endif /* CPU_ARM8 */ 402129198Scognet 403129198Scognet#ifdef CPU_ARM9 404129198Scognetstruct cpu_functions arm9_cpufuncs = { 405129198Scognet /* CPU functions */ 406129198Scognet 407129198Scognet cpufunc_id, /* id */ 408129198Scognet cpufunc_nullop, /* cpwait */ 409129198Scognet 410129198Scognet /* MMU functions */ 411129198Scognet 412129198Scognet cpufunc_control, /* control */ 413129198Scognet cpufunc_domains, /* Domain */ 414129198Scognet arm9_setttb, /* Setttb */ 415129198Scognet cpufunc_faultstatus, /* Faultstatus */ 416129198Scognet cpufunc_faultaddress, /* Faultaddress */ 417129198Scognet 418129198Scognet /* TLB functions */ 419129198Scognet 420129198Scognet armv4_tlb_flushID, /* tlb_flushID */ 421129198Scognet arm9_tlb_flushID_SE, /* tlb_flushID_SE */ 422129198Scognet armv4_tlb_flushI, /* tlb_flushI */ 423129198Scognet (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ 424129198Scognet armv4_tlb_flushD, /* tlb_flushD */ 425129198Scognet armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 426129198Scognet 427129198Scognet /* Cache operations */ 428129198Scognet 429146605Scognet arm9_icache_sync_all, /* icache_sync_all */ 430146605Scognet arm9_icache_sync_range, /* icache_sync_range */ 431129198Scognet 432146605Scognet arm9_dcache_wbinv_all, /* dcache_wbinv_all */ 433146605Scognet arm9_dcache_wbinv_range, /* dcache_wbinv_range */ 434146605Scognet/*XXX*/ arm9_dcache_wbinv_range, /* dcache_inv_range */ 435146605Scognet arm9_dcache_wb_range, /* dcache_wb_range */ 436129198Scognet 437146605Scognet arm9_idcache_wbinv_all, /* idcache_wbinv_all */ 438146605Scognet arm9_idcache_wbinv_range, /* idcache_wbinv_range */ 439129198Scognet 440129198Scognet /* Other functions */ 441129198Scognet 442129198Scognet cpufunc_nullop, /* flush_prefetchbuf */ 443129198Scognet armv4_drain_writebuf, /* drain_writebuf */ 444129198Scognet cpufunc_nullop, /* flush_brnchtgt_C */ 445129198Scognet (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 446129198Scognet 447129198Scognet (void *)cpufunc_nullop, /* sleep */ 448129198Scognet 449129198Scognet /* Soft functions */ 450129198Scognet 451129198Scognet cpufunc_null_fixup, /* dataabt_fixup */ 452129198Scognet cpufunc_null_fixup, /* prefetchabt_fixup */ 453129198Scognet 454129198Scognet arm9_context_switch, /* context_switch */ 455129198Scognet 456129198Scognet arm9_setup /* cpu setup */ 457129198Scognet 458129198Scognet}; 459129198Scognet#endif /* CPU_ARM9 */ 460129198Scognet 461129198Scognet#ifdef CPU_ARM10 462129198Scognetstruct cpu_functions arm10_cpufuncs = { 463129198Scognet /* CPU functions */ 464129198Scognet 465129198Scognet cpufunc_id, /* id */ 466129198Scognet cpufunc_nullop, /* cpwait */ 467129198Scognet 468129198Scognet /* MMU functions */ 469129198Scognet 470129198Scognet cpufunc_control, /* control */ 471129198Scognet cpufunc_domains, /* Domain */ 472129198Scognet arm10_setttb, /* Setttb */ 473129198Scognet cpufunc_faultstatus, /* Faultstatus */ 474129198Scognet cpufunc_faultaddress, /* Faultaddress */ 475129198Scognet 476129198Scognet /* TLB functions */ 477129198Scognet 478129198Scognet armv4_tlb_flushID, /* tlb_flushID */ 479129198Scognet arm10_tlb_flushID_SE, /* tlb_flushID_SE */ 480129198Scognet armv4_tlb_flushI, /* tlb_flushI */ 481129198Scognet arm10_tlb_flushI_SE, /* tlb_flushI_SE */ 482129198Scognet armv4_tlb_flushD, /* tlb_flushD */ 483129198Scognet armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 484129198Scognet 485129198Scognet /* Cache operations */ 486129198Scognet 487129198Scognet arm10_icache_sync_all, /* icache_sync_all */ 488129198Scognet arm10_icache_sync_range, /* icache_sync_range */ 489129198Scognet 490129198Scognet arm10_dcache_wbinv_all, /* dcache_wbinv_all */ 491129198Scognet arm10_dcache_wbinv_range, /* dcache_wbinv_range */ 492129198Scognet arm10_dcache_inv_range, /* dcache_inv_range */ 493129198Scognet arm10_dcache_wb_range, /* dcache_wb_range */ 494129198Scognet 495129198Scognet arm10_idcache_wbinv_all, /* idcache_wbinv_all */ 496129198Scognet arm10_idcache_wbinv_range, /* idcache_wbinv_range */ 497129198Scognet 498129198Scognet /* Other functions */ 499129198Scognet 500129198Scognet cpufunc_nullop, /* flush_prefetchbuf */ 501129198Scognet armv4_drain_writebuf, /* drain_writebuf */ 502129198Scognet cpufunc_nullop, /* flush_brnchtgt_C */ 503129198Scognet (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 504129198Scognet 505129198Scognet (void *)cpufunc_nullop, /* sleep */ 506129198Scognet 507129198Scognet /* Soft functions */ 508129198Scognet 509129198Scognet cpufunc_null_fixup, /* dataabt_fixup */ 510129198Scognet cpufunc_null_fixup, /* prefetchabt_fixup */ 511129198Scognet 512129198Scognet arm10_context_switch, /* context_switch */ 513129198Scognet 514129198Scognet arm10_setup /* cpu setup */ 515129198Scognet 516129198Scognet}; 517129198Scognet#endif /* CPU_ARM10 */ 518129198Scognet 519129198Scognet#ifdef CPU_SA110 520129198Scognetstruct cpu_functions sa110_cpufuncs = { 521129198Scognet /* CPU functions */ 522129198Scognet 523129198Scognet cpufunc_id, /* id */ 524129198Scognet cpufunc_nullop, /* cpwait */ 525129198Scognet 526129198Scognet /* MMU functions */ 527129198Scognet 528129198Scognet cpufunc_control, /* control */ 529129198Scognet cpufunc_domains, /* domain */ 530129198Scognet sa1_setttb, /* setttb */ 531129198Scognet cpufunc_faultstatus, /* faultstatus */ 532129198Scognet cpufunc_faultaddress, /* faultaddress */ 533129198Scognet 534129198Scognet /* TLB functions */ 535129198Scognet 536129198Scognet armv4_tlb_flushID, /* tlb_flushID */ 537129198Scognet sa1_tlb_flushID_SE, /* tlb_flushID_SE */ 538129198Scognet armv4_tlb_flushI, /* tlb_flushI */ 539129198Scognet (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ 540129198Scognet armv4_tlb_flushD, /* tlb_flushD */ 541129198Scognet armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 542129198Scognet 543129198Scognet /* Cache operations */ 544129198Scognet 545129198Scognet sa1_cache_syncI, /* icache_sync_all */ 546129198Scognet sa1_cache_syncI_rng, /* icache_sync_range */ 547129198Scognet 548129198Scognet sa1_cache_purgeD, /* dcache_wbinv_all */ 549129198Scognet sa1_cache_purgeD_rng, /* dcache_wbinv_range */ 550129198Scognet/*XXX*/ sa1_cache_purgeD_rng, /* dcache_inv_range */ 551129198Scognet sa1_cache_cleanD_rng, /* dcache_wb_range */ 552129198Scognet 553129198Scognet sa1_cache_purgeID, /* idcache_wbinv_all */ 554129198Scognet sa1_cache_purgeID_rng, /* idcache_wbinv_range */ 555129198Scognet 556129198Scognet /* Other functions */ 557129198Scognet 558129198Scognet cpufunc_nullop, /* flush_prefetchbuf */ 559129198Scognet armv4_drain_writebuf, /* drain_writebuf */ 560129198Scognet cpufunc_nullop, /* flush_brnchtgt_C */ 561129198Scognet (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 562129198Scognet 563129198Scognet (void *)cpufunc_nullop, /* sleep */ 564129198Scognet 565129198Scognet /* Soft functions */ 566129198Scognet 567129198Scognet cpufunc_null_fixup, /* dataabt_fixup */ 568129198Scognet cpufunc_null_fixup, /* prefetchabt_fixup */ 569129198Scognet 570129198Scognet sa110_context_switch, /* context_switch */ 571129198Scognet 572129198Scognet sa110_setup /* cpu setup */ 573129198Scognet}; 574129198Scognet#endif /* CPU_SA110 */ 575129198Scognet 576129198Scognet#if defined(CPU_SA1100) || defined(CPU_SA1110) 577129198Scognetstruct cpu_functions sa11x0_cpufuncs = { 578129198Scognet /* CPU functions */ 579129198Scognet 580129198Scognet cpufunc_id, /* id */ 581129198Scognet cpufunc_nullop, /* cpwait */ 582129198Scognet 583129198Scognet /* MMU functions */ 584129198Scognet 585129198Scognet cpufunc_control, /* control */ 586129198Scognet cpufunc_domains, /* domain */ 587129198Scognet sa1_setttb, /* setttb */ 588129198Scognet cpufunc_faultstatus, /* faultstatus */ 589129198Scognet cpufunc_faultaddress, /* faultaddress */ 590129198Scognet 591129198Scognet /* TLB functions */ 592129198Scognet 593129198Scognet armv4_tlb_flushID, /* tlb_flushID */ 594129198Scognet sa1_tlb_flushID_SE, /* tlb_flushID_SE */ 595129198Scognet armv4_tlb_flushI, /* tlb_flushI */ 596129198Scognet (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ 597129198Scognet armv4_tlb_flushD, /* tlb_flushD */ 598129198Scognet armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 599129198Scognet 600129198Scognet /* Cache operations */ 601129198Scognet 602129198Scognet sa1_cache_syncI, /* icache_sync_all */ 603129198Scognet sa1_cache_syncI_rng, /* icache_sync_range */ 604129198Scognet 605129198Scognet sa1_cache_purgeD, /* dcache_wbinv_all */ 606129198Scognet sa1_cache_purgeD_rng, /* dcache_wbinv_range */ 607129198Scognet/*XXX*/ sa1_cache_purgeD_rng, /* dcache_inv_range */ 608129198Scognet sa1_cache_cleanD_rng, /* dcache_wb_range */ 609129198Scognet 610129198Scognet sa1_cache_purgeID, /* idcache_wbinv_all */ 611129198Scognet sa1_cache_purgeID_rng, /* idcache_wbinv_range */ 612129198Scognet 613129198Scognet /* Other functions */ 614129198Scognet 615129198Scognet sa11x0_drain_readbuf, /* flush_prefetchbuf */ 616129198Scognet armv4_drain_writebuf, /* drain_writebuf */ 617129198Scognet cpufunc_nullop, /* flush_brnchtgt_C */ 618129198Scognet (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 619129198Scognet 620129198Scognet sa11x0_cpu_sleep, /* sleep */ 621129198Scognet 622129198Scognet /* Soft functions */ 623129198Scognet 624129198Scognet cpufunc_null_fixup, /* dataabt_fixup */ 625129198Scognet cpufunc_null_fixup, /* prefetchabt_fixup */ 626129198Scognet 627129198Scognet sa11x0_context_switch, /* context_switch */ 628129198Scognet 629129198Scognet sa11x0_setup /* cpu setup */ 630129198Scognet}; 631129198Scognet#endif /* CPU_SA1100 || CPU_SA1110 */ 632129198Scognet 633129198Scognet#ifdef CPU_IXP12X0 634129198Scognetstruct cpu_functions ixp12x0_cpufuncs = { 635129198Scognet /* CPU functions */ 636129198Scognet 637129198Scognet cpufunc_id, /* id */ 638129198Scognet cpufunc_nullop, /* cpwait */ 639129198Scognet 640129198Scognet /* MMU functions */ 641129198Scognet 642129198Scognet cpufunc_control, /* control */ 643129198Scognet cpufunc_domains, /* domain */ 644129198Scognet sa1_setttb, /* setttb */ 645129198Scognet cpufunc_faultstatus, /* faultstatus */ 646129198Scognet cpufunc_faultaddress, /* faultaddress */ 647129198Scognet 648129198Scognet /* TLB functions */ 649129198Scognet 650129198Scognet armv4_tlb_flushID, /* tlb_flushID */ 651129198Scognet sa1_tlb_flushID_SE, /* tlb_flushID_SE */ 652129198Scognet armv4_tlb_flushI, /* tlb_flushI */ 653129198Scognet (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ 654129198Scognet armv4_tlb_flushD, /* tlb_flushD */ 655129198Scognet armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 656129198Scognet 657129198Scognet /* Cache operations */ 658129198Scognet 659129198Scognet sa1_cache_syncI, /* icache_sync_all */ 660129198Scognet sa1_cache_syncI_rng, /* icache_sync_range */ 661129198Scognet 662129198Scognet sa1_cache_purgeD, /* dcache_wbinv_all */ 663129198Scognet sa1_cache_purgeD_rng, /* dcache_wbinv_range */ 664129198Scognet/*XXX*/ sa1_cache_purgeD_rng, /* dcache_inv_range */ 665129198Scognet sa1_cache_cleanD_rng, /* dcache_wb_range */ 666129198Scognet 667129198Scognet sa1_cache_purgeID, /* idcache_wbinv_all */ 668129198Scognet sa1_cache_purgeID_rng, /* idcache_wbinv_range */ 669129198Scognet 670129198Scognet /* Other functions */ 671129198Scognet 672129198Scognet ixp12x0_drain_readbuf, /* flush_prefetchbuf */ 673129198Scognet armv4_drain_writebuf, /* drain_writebuf */ 674129198Scognet cpufunc_nullop, /* flush_brnchtgt_C */ 675129198Scognet (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 676129198Scognet 677129198Scognet (void *)cpufunc_nullop, /* sleep */ 678129198Scognet 679129198Scognet /* Soft functions */ 680129198Scognet 681129198Scognet cpufunc_null_fixup, /* dataabt_fixup */ 682129198Scognet cpufunc_null_fixup, /* prefetchabt_fixup */ 683129198Scognet 684129198Scognet ixp12x0_context_switch, /* context_switch */ 685129198Scognet 686129198Scognet ixp12x0_setup /* cpu setup */ 687129198Scognet}; 688129198Scognet#endif /* CPU_IXP12X0 */ 689129198Scognet 690129198Scognet#if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ 691129198Scognet defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) 692129198Scognetstruct cpu_functions xscale_cpufuncs = { 693129198Scognet /* CPU functions */ 694129198Scognet 695129198Scognet cpufunc_id, /* id */ 696129198Scognet xscale_cpwait, /* cpwait */ 697129198Scognet 698129198Scognet /* MMU functions */ 699129198Scognet 700129198Scognet xscale_control, /* control */ 701129198Scognet cpufunc_domains, /* domain */ 702129198Scognet xscale_setttb, /* setttb */ 703129198Scognet cpufunc_faultstatus, /* faultstatus */ 704129198Scognet cpufunc_faultaddress, /* faultaddress */ 705129198Scognet 706129198Scognet /* TLB functions */ 707129198Scognet 708129198Scognet armv4_tlb_flushID, /* tlb_flushID */ 709129198Scognet xscale_tlb_flushID_SE, /* tlb_flushID_SE */ 710129198Scognet armv4_tlb_flushI, /* tlb_flushI */ 711129198Scognet (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ 712129198Scognet armv4_tlb_flushD, /* tlb_flushD */ 713129198Scognet armv4_tlb_flushD_SE, /* tlb_flushD_SE */ 714129198Scognet 715129198Scognet /* Cache operations */ 716129198Scognet 717129198Scognet xscale_cache_syncI, /* icache_sync_all */ 718129198Scognet xscale_cache_syncI_rng, /* icache_sync_range */ 719129198Scognet 720129198Scognet xscale_cache_purgeD, /* dcache_wbinv_all */ 721129198Scognet xscale_cache_purgeD_rng, /* dcache_wbinv_range */ 722129198Scognet xscale_cache_flushD_rng, /* dcache_inv_range */ 723129198Scognet xscale_cache_cleanD_rng, /* dcache_wb_range */ 724129198Scognet 725129198Scognet xscale_cache_purgeID, /* idcache_wbinv_all */ 726129198Scognet xscale_cache_purgeID_rng, /* idcache_wbinv_range */ 727129198Scognet 728129198Scognet /* Other functions */ 729129198Scognet 730129198Scognet cpufunc_nullop, /* flush_prefetchbuf */ 731129198Scognet armv4_drain_writebuf, /* drain_writebuf */ 732129198Scognet cpufunc_nullop, /* flush_brnchtgt_C */ 733129198Scognet (void *)cpufunc_nullop, /* flush_brnchtgt_E */ 734129198Scognet 735129198Scognet xscale_cpu_sleep, /* sleep */ 736129198Scognet 737129198Scognet /* Soft functions */ 738129198Scognet 739129198Scognet cpufunc_null_fixup, /* dataabt_fixup */ 740129198Scognet cpufunc_null_fixup, /* prefetchabt_fixup */ 741129198Scognet 742129198Scognet xscale_context_switch, /* context_switch */ 743129198Scognet 744129198Scognet xscale_setup /* cpu setup */ 745129198Scognet}; 746129198Scognet#endif 747129198Scognet/* CPU_XSCALE_80200 || CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */ 748129198Scognet 749129198Scognet/* 750129198Scognet * Global constants also used by locore.s 751129198Scognet */ 752129198Scognet 753129198Scognetstruct cpu_functions cpufuncs; 754129198Scognetu_int cputype; 755129198Scognetu_int cpu_reset_needs_v4_MMU_disable; /* flag used in locore.s */ 756129198Scognet 757129198Scognet#if defined(CPU_ARM7TDMI) || defined(CPU_ARM8) || defined(CPU_ARM9) || \ 758129198Scognet defined (CPU_ARM10) || \ 759129198Scognet defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ 760129198Scognet defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) 761137498Strhodesstatic void get_cachetype_cp15(void); 762129198Scognet 763129198Scognet/* Additional cache information local to this file. Log2 of some of the 764129198Scognet above numbers. */ 765129198Scognetstatic int arm_dcache_l2_nsets; 766129198Scognetstatic int arm_dcache_l2_assoc; 767129198Scognetstatic int arm_dcache_l2_linesize; 768129198Scognet 769129198Scognetstatic void 770129198Scognetget_cachetype_cp15() 771129198Scognet{ 772129198Scognet u_int ctype, isize, dsize; 773129198Scognet u_int multiplier; 774129198Scognet 775129198Scognet __asm __volatile("mrc p15, 0, %0, c0, c0, 1" 776129198Scognet : "=r" (ctype)); 777129198Scognet 778129198Scognet /* 779129198Scognet * ...and thus spake the ARM ARM: 780129198Scognet * 781129198Scognet * If an <opcode2> value corresponding to an unimplemented or 782129198Scognet * reserved ID register is encountered, the System Control 783129198Scognet * processor returns the value of the main ID register. 784129198Scognet */ 785129198Scognet if (ctype == cpufunc_id()) 786129198Scognet goto out; 787129198Scognet 788129198Scognet if ((ctype & CPU_CT_S) == 0) 789129198Scognet arm_pcache_unified = 1; 790129198Scognet 791129198Scognet /* 792129198Scognet * If you want to know how this code works, go read the ARM ARM. 793129198Scognet */ 794129198Scognet 795129198Scognet arm_pcache_type = CPU_CT_CTYPE(ctype); 796129198Scognet 797129198Scognet if (arm_pcache_unified == 0) { 798129198Scognet isize = CPU_CT_ISIZE(ctype); 799129198Scognet multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2; 800129198Scognet arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3); 801129198Scognet if (CPU_CT_xSIZE_ASSOC(isize) == 0) { 802129198Scognet if (isize & CPU_CT_xSIZE_M) 803129198Scognet arm_picache_line_size = 0; /* not present */ 804129198Scognet else 805129198Scognet arm_picache_ways = 1; 806129198Scognet } else { 807129198Scognet arm_picache_ways = multiplier << 808129198Scognet (CPU_CT_xSIZE_ASSOC(isize) - 1); 809129198Scognet } 810129198Scognet arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8); 811129198Scognet } 812129198Scognet 813129198Scognet dsize = CPU_CT_DSIZE(ctype); 814129198Scognet multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2; 815129198Scognet arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3); 816129198Scognet if (CPU_CT_xSIZE_ASSOC(dsize) == 0) { 817129198Scognet if (dsize & CPU_CT_xSIZE_M) 818129198Scognet arm_pdcache_line_size = 0; /* not present */ 819129198Scognet else 820129198Scognet arm_pdcache_ways = 1; 821129198Scognet } else { 822129198Scognet arm_pdcache_ways = multiplier << 823129198Scognet (CPU_CT_xSIZE_ASSOC(dsize) - 1); 824129198Scognet } 825129198Scognet arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8); 826129198Scognet 827129198Scognet arm_dcache_align = arm_pdcache_line_size; 828129198Scognet 829129198Scognet arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2; 830129198Scognet arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3; 831129198Scognet arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) - 832129198Scognet CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize); 833129198Scognet 834129198Scognet out: 835129198Scognet arm_dcache_align_mask = arm_dcache_align - 1; 836129198Scognet} 837129198Scognet#endif /* ARM7TDMI || ARM8 || ARM9 || XSCALE */ 838129198Scognet 839129198Scognet#if defined(CPU_ARM2) || defined(CPU_ARM250) || defined(CPU_ARM3) || \ 840129198Scognet defined(CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_SA110) || \ 841129198Scognet defined(CPU_SA1100) || defined(CPU_SA1110) || defined(CPU_IXP12X0) 842129198Scognet/* Cache information for CPUs without cache type registers. */ 843129198Scognetstruct cachetab { 844129198Scognet u_int32_t ct_cpuid; 845129198Scognet int ct_pcache_type; 846129198Scognet int ct_pcache_unified; 847129198Scognet int ct_pdcache_size; 848129198Scognet int ct_pdcache_line_size; 849129198Scognet int ct_pdcache_ways; 850129198Scognet int ct_picache_size; 851129198Scognet int ct_picache_line_size; 852129198Scognet int ct_picache_ways; 853129198Scognet}; 854129198Scognet 855129198Scognetstruct cachetab cachetab[] = { 856129198Scognet /* cpuid, cache type, u, dsiz, ls, wy, isiz, ls, wy */ 857129198Scognet { CPU_ID_ARM2, 0, 1, 0, 0, 0, 0, 0, 0 }, 858129198Scognet { CPU_ID_ARM250, 0, 1, 0, 0, 0, 0, 0, 0 }, 859129198Scognet { CPU_ID_ARM3, CPU_CT_CTYPE_WT, 1, 4096, 16, 64, 0, 0, 0 }, 860129198Scognet { CPU_ID_ARM610, CPU_CT_CTYPE_WT, 1, 4096, 16, 64, 0, 0, 0 }, 861129198Scognet { CPU_ID_ARM710, CPU_CT_CTYPE_WT, 1, 8192, 32, 4, 0, 0, 0 }, 862129198Scognet { CPU_ID_ARM7500, CPU_CT_CTYPE_WT, 1, 4096, 16, 4, 0, 0, 0 }, 863129198Scognet { CPU_ID_ARM710A, CPU_CT_CTYPE_WT, 1, 8192, 16, 4, 0, 0, 0 }, 864129198Scognet { CPU_ID_ARM7500FE, CPU_CT_CTYPE_WT, 1, 4096, 16, 4, 0, 0, 0 }, 865129198Scognet /* XXX is this type right for SA-1? */ 866129198Scognet { CPU_ID_SA110, CPU_CT_CTYPE_WB1, 0, 16384, 32, 32, 16384, 32, 32 }, 867129198Scognet { CPU_ID_SA1100, CPU_CT_CTYPE_WB1, 0, 8192, 32, 32, 16384, 32, 32 }, 868129198Scognet { CPU_ID_SA1110, CPU_CT_CTYPE_WB1, 0, 8192, 32, 32, 16384, 32, 32 }, 869129198Scognet { CPU_ID_IXP1200, CPU_CT_CTYPE_WB1, 0, 16384, 32, 32, 16384, 32, 32 }, /* XXX */ 870129198Scognet { 0, 0, 0, 0, 0, 0, 0, 0} 871129198Scognet}; 872129198Scognet 873137498Strhodesstatic void get_cachetype_table(void); 874129198Scognet 875129198Scognetstatic void 876129198Scognetget_cachetype_table() 877129198Scognet{ 878129198Scognet int i; 879129198Scognet u_int32_t cpuid = cpufunc_id(); 880129198Scognet 881129198Scognet for (i = 0; cachetab[i].ct_cpuid != 0; i++) { 882129198Scognet if (cachetab[i].ct_cpuid == (cpuid & CPU_ID_CPU_MASK)) { 883129198Scognet arm_pcache_type = cachetab[i].ct_pcache_type; 884129198Scognet arm_pcache_unified = cachetab[i].ct_pcache_unified; 885129198Scognet arm_pdcache_size = cachetab[i].ct_pdcache_size; 886129198Scognet arm_pdcache_line_size = 887129198Scognet cachetab[i].ct_pdcache_line_size; 888129198Scognet arm_pdcache_ways = cachetab[i].ct_pdcache_ways; 889129198Scognet arm_picache_size = cachetab[i].ct_picache_size; 890129198Scognet arm_picache_line_size = 891129198Scognet cachetab[i].ct_picache_line_size; 892129198Scognet arm_picache_ways = cachetab[i].ct_picache_ways; 893129198Scognet } 894129198Scognet } 895129198Scognet arm_dcache_align = arm_pdcache_line_size; 896129198Scognet 897129198Scognet arm_dcache_align_mask = arm_dcache_align - 1; 898129198Scognet} 899129198Scognet 900129198Scognet#endif /* ARM2 || ARM250 || ARM3 || ARM6 || ARM7 || SA110 || SA1100 || SA1111 || IXP12X0 */ 901129198Scognet 902129198Scognet/* 903129198Scognet * Cannot panic here as we may not have a console yet ... 904129198Scognet */ 905129198Scognet 906129198Scognetint 907129198Scognetset_cpufuncs() 908129198Scognet{ 909129198Scognet cputype = cpufunc_id(); 910129198Scognet cputype &= CPU_ID_CPU_MASK; 911129198Scognet 912129198Scognet /* 913129198Scognet * NOTE: cpu_do_powersave defaults to off. If we encounter a 914129198Scognet * CPU type where we want to use it by default, then we set it. 915129198Scognet */ 916129198Scognet 917129198Scognet#ifdef CPU_ARM3 918129198Scognet if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD && 919129198Scognet (cputype & 0x00000f00) == 0x00000300) { 920129198Scognet cpufuncs = arm3_cpufuncs; 921129198Scognet cpu_reset_needs_v4_MMU_disable = 0; 922129198Scognet get_cachetype_table(); 923129198Scognet return 0; 924129198Scognet } 925129198Scognet#endif /* CPU_ARM3 */ 926129198Scognet#ifdef CPU_ARM6 927129198Scognet if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD && 928129198Scognet (cputype & 0x00000f00) == 0x00000600) { 929129198Scognet cpufuncs = arm6_cpufuncs; 930129198Scognet cpu_reset_needs_v4_MMU_disable = 0; 931129198Scognet get_cachetype_table(); 932129198Scognet pmap_pte_init_generic(); 933129198Scognet return 0; 934129198Scognet } 935129198Scognet#endif /* CPU_ARM6 */ 936129198Scognet#ifdef CPU_ARM7 937129198Scognet if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD && 938129198Scognet CPU_ID_IS7(cputype) && 939129198Scognet (cputype & CPU_ID_7ARCH_MASK) == CPU_ID_7ARCH_V3) { 940129198Scognet cpufuncs = arm7_cpufuncs; 941129198Scognet cpu_reset_needs_v4_MMU_disable = 0; 942129198Scognet get_cachetype_table(); 943129198Scognet pmap_pte_init_generic(); 944129198Scognet return 0; 945129198Scognet } 946129198Scognet#endif /* CPU_ARM7 */ 947129198Scognet#ifdef CPU_ARM7TDMI 948129198Scognet if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD && 949129198Scognet CPU_ID_IS7(cputype) && 950129198Scognet (cputype & CPU_ID_7ARCH_MASK) == CPU_ID_7ARCH_V4T) { 951129198Scognet cpufuncs = arm7tdmi_cpufuncs; 952129198Scognet cpu_reset_needs_v4_MMU_disable = 0; 953129198Scognet get_cachetype_cp15(); 954129198Scognet pmap_pte_init_generic(); 955129198Scognet return 0; 956129198Scognet } 957129198Scognet#endif 958129198Scognet#ifdef CPU_ARM8 959129198Scognet if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD && 960129198Scognet (cputype & 0x0000f000) == 0x00008000) { 961129198Scognet cpufuncs = arm8_cpufuncs; 962129198Scognet cpu_reset_needs_v4_MMU_disable = 0; /* XXX correct? */ 963129198Scognet get_cachetype_cp15(); 964129198Scognet pmap_pte_init_arm8(); 965129198Scognet return 0; 966129198Scognet } 967129198Scognet#endif /* CPU_ARM8 */ 968129198Scognet#ifdef CPU_ARM9 969129198Scognet if (((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD || 970129198Scognet (cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_TI) && 971129198Scognet (cputype & 0x0000f000) == 0x00009000) { 972129198Scognet cpufuncs = arm9_cpufuncs; 973129198Scognet cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */ 974129198Scognet get_cachetype_cp15(); 975146605Scognet arm9_dcache_sets_inc = 1U << arm_dcache_l2_linesize; 976146605Scognet arm9_dcache_sets_max = (1U << (arm_dcache_l2_linesize + 977146605Scognet arm_dcache_l2_nsets)) - arm9_dcache_sets_inc; 978146605Scognet arm9_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc); 979146605Scognet arm9_dcache_index_max = 0U - arm9_dcache_index_inc; 980137270Scognet#ifdef ARM9_CACHE_WRITE_THROUGH 981129198Scognet pmap_pte_init_arm9(); 982137270Scognet#else 983137270Scognet pmap_pte_init_generic(); 984137270Scognet#endif 985129198Scognet return 0; 986129198Scognet } 987129198Scognet#endif /* CPU_ARM9 */ 988129198Scognet#ifdef CPU_ARM10 989129198Scognet if (/* cputype == CPU_ID_ARM1020T || */ 990129198Scognet cputype == CPU_ID_ARM1020E) { 991129198Scognet /* 992129198Scognet * Select write-through cacheing (this isn't really an 993129198Scognet * option on ARM1020T). 994129198Scognet */ 995129198Scognet cpufuncs = arm10_cpufuncs; 996129198Scognet cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */ 997129198Scognet get_cachetype_cp15(); 998129198Scognet arm10_dcache_sets_inc = 1U << arm_dcache_l2_linesize; 999129198Scognet arm10_dcache_sets_max = 1000129198Scognet (1U << (arm_dcache_l2_linesize + arm_dcache_l2_nsets)) - 1001129198Scognet arm10_dcache_sets_inc; 1002129198Scognet arm10_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc); 1003129198Scognet arm10_dcache_index_max = 0U - arm10_dcache_index_inc; 1004129198Scognet pmap_pte_init_generic(); 1005129198Scognet return 0; 1006129198Scognet } 1007129198Scognet#endif /* CPU_ARM10 */ 1008129198Scognet#ifdef CPU_SA110 1009129198Scognet if (cputype == CPU_ID_SA110) { 1010129198Scognet cpufuncs = sa110_cpufuncs; 1011129198Scognet cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */ 1012129198Scognet get_cachetype_table(); 1013129198Scognet pmap_pte_init_sa1(); 1014129198Scognet return 0; 1015129198Scognet } 1016129198Scognet#endif /* CPU_SA110 */ 1017129198Scognet#ifdef CPU_SA1100 1018129198Scognet if (cputype == CPU_ID_SA1100) { 1019129198Scognet cpufuncs = sa11x0_cpufuncs; 1020129198Scognet cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */ 1021129198Scognet get_cachetype_table(); 1022129198Scognet pmap_pte_init_sa1(); 1023129198Scognet /* Use powersave on this CPU. */ 1024129198Scognet cpu_do_powersave = 1; 1025129198Scognet 1026129198Scognet return 0; 1027129198Scognet } 1028129198Scognet#endif /* CPU_SA1100 */ 1029129198Scognet#ifdef CPU_SA1110 1030129198Scognet if (cputype == CPU_ID_SA1110) { 1031129198Scognet cpufuncs = sa11x0_cpufuncs; 1032129198Scognet cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */ 1033129198Scognet get_cachetype_table(); 1034129198Scognet pmap_pte_init_sa1(); 1035129198Scognet /* Use powersave on this CPU. */ 1036129198Scognet cpu_do_powersave = 1; 1037129198Scognet 1038129198Scognet return 0; 1039129198Scognet } 1040129198Scognet#endif /* CPU_SA1110 */ 1041129198Scognet#ifdef CPU_IXP12X0 1042129198Scognet if (cputype == CPU_ID_IXP1200) { 1043129198Scognet cpufuncs = ixp12x0_cpufuncs; 1044129198Scognet cpu_reset_needs_v4_MMU_disable = 1; 1045129198Scognet get_cachetype_table(); 1046129198Scognet pmap_pte_init_sa1(); 1047129198Scognet return 0; 1048129198Scognet } 1049129198Scognet#endif /* CPU_IXP12X0 */ 1050129198Scognet#ifdef CPU_XSCALE_80200 1051129198Scognet if (cputype == CPU_ID_80200) { 1052129198Scognet int rev = cpufunc_id() & CPU_ID_REVISION_MASK; 1053129198Scognet 1054129198Scognet i80200_icu_init(); 1055129198Scognet 1056129198Scognet /* 1057129198Scognet * Reset the Performance Monitoring Unit to a 1058129198Scognet * pristine state: 1059129198Scognet * - CCNT, PMN0, PMN1 reset to 0 1060129198Scognet * - overflow indications cleared 1061129198Scognet * - all counters disabled 1062129198Scognet */ 1063129198Scognet __asm __volatile("mcr p14, 0, %0, c0, c0, 0" 1064129198Scognet : 1065129198Scognet : "r" (PMNC_P|PMNC_C|PMNC_PMN0_IF|PMNC_PMN1_IF| 1066129198Scognet PMNC_CC_IF)); 1067129198Scognet 1068129198Scognet#if defined(XSCALE_CCLKCFG) 1069129198Scognet /* 1070129198Scognet * Crank CCLKCFG to maximum legal value. 1071129198Scognet */ 1072129198Scognet __asm __volatile ("mcr p14, 0, %0, c6, c0, 0" 1073129198Scognet : 1074129198Scognet : "r" (XSCALE_CCLKCFG)); 1075129198Scognet#endif 1076129198Scognet 1077129198Scognet /* 1078129198Scognet * XXX Disable ECC in the Bus Controller Unit; we 1079129198Scognet * don't really support it, yet. Clear any pending 1080129198Scognet * error indications. 1081129198Scognet */ 1082129198Scognet __asm __volatile("mcr p13, 0, %0, c0, c1, 0" 1083129198Scognet : 1084129198Scognet : "r" (BCUCTL_E0|BCUCTL_E1|BCUCTL_EV)); 1085129198Scognet 1086129198Scognet cpufuncs = xscale_cpufuncs; 1087129198Scognet#if defined(PERFCTRS) 1088129198Scognet xscale_pmu_init(); 1089129198Scognet#endif 1090129198Scognet 1091129198Scognet /* 1092129198Scognet * i80200 errata: Step-A0 and A1 have a bug where 1093129198Scognet * D$ dirty bits are not cleared on "invalidate by 1094129198Scognet * address". 1095129198Scognet * 1096129198Scognet * Workaround: Clean cache line before invalidating. 1097129198Scognet */ 1098129198Scognet if (rev == 0 || rev == 1) 1099129198Scognet cpufuncs.cf_dcache_inv_range = xscale_cache_purgeD_rng; 1100129198Scognet 1101129198Scognet cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ 1102129198Scognet get_cachetype_cp15(); 1103129198Scognet pmap_pte_init_xscale(); 1104129198Scognet return 0; 1105129198Scognet } 1106129198Scognet#endif /* CPU_XSCALE_80200 */ 1107129198Scognet#ifdef CPU_XSCALE_80321 1108129198Scognet if (cputype == CPU_ID_80321_400 || cputype == CPU_ID_80321_600 || 1109129198Scognet cputype == CPU_ID_80321_400_B0 || cputype == CPU_ID_80321_600_B0) { 1110129198Scognet 1111129198Scognet /* 1112129198Scognet * Reset the Performance Monitoring Unit to a 1113129198Scognet * pristine state: 1114129198Scognet * - CCNT, PMN0, PMN1 reset to 0 1115129198Scognet * - overflow indications cleared 1116129198Scognet * - all counters disabled 1117129198Scognet */ 1118129198Scognet __asm __volatile("mcr p14, 0, %0, c0, c0, 0" 1119129198Scognet : 1120129198Scognet : "r" (PMNC_P|PMNC_C|PMNC_PMN0_IF|PMNC_PMN1_IF| 1121129198Scognet PMNC_CC_IF)); 1122129198Scognet 1123129198Scognet cpufuncs = xscale_cpufuncs; 1124129198Scognet#if defined(PERFCTRS) 1125129198Scognet xscale_pmu_init(); 1126129198Scognet#endif 1127129198Scognet 1128129198Scognet cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ 1129129198Scognet get_cachetype_cp15(); 1130129198Scognet pmap_pte_init_xscale(); 1131129198Scognet return 0; 1132129198Scognet } 1133129198Scognet#endif /* CPU_XSCALE_80321 */ 1134129198Scognet#ifdef CPU_XSCALE_PXA2X0 1135129198Scognet /* ignore core revision to test PXA2xx CPUs */ 1136129198Scognet if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA250 || 1137129198Scognet (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA210) { 1138129198Scognet 1139129198Scognet cpufuncs = xscale_cpufuncs; 1140129198Scognet#if defined(PERFCTRS) 1141129198Scognet xscale_pmu_init(); 1142129198Scognet#endif 1143129198Scognet 1144129198Scognet cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ 1145129198Scognet get_cachetype_cp15(); 1146129198Scognet pmap_pte_init_xscale(); 1147129198Scognet 1148129198Scognet /* Use powersave on this CPU. */ 1149129198Scognet cpu_do_powersave = 1; 1150129198Scognet 1151129198Scognet return 0; 1152129198Scognet } 1153129198Scognet#endif /* CPU_XSCALE_PXA2X0 */ 1154129198Scognet#ifdef CPU_XSCALE_IXP425 1155129198Scognet if (cputype == CPU_ID_IXP425_533 || cputype == CPU_ID_IXP425_400 || 1156129198Scognet cputype == CPU_ID_IXP425_266) { 1157129198Scognet ixp425_icu_init(); 1158129198Scognet 1159129198Scognet cpufuncs = xscale_cpufuncs; 1160129198Scognet#if defined(PERFCTRS) 1161129198Scognet xscale_pmu_init(); 1162129198Scognet#endif 1163129198Scognet 1164129198Scognet cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ 1165129198Scognet get_cachetype_cp15(); 1166129198Scognet pmap_pte_init_xscale(); 1167129198Scognet 1168129198Scognet return 0; 1169129198Scognet } 1170129198Scognet#endif /* CPU_XSCALE_IXP425 */ 1171129198Scognet /* 1172129198Scognet * Bzzzz. And the answer was ... 1173129198Scognet */ 1174129198Scognet panic("No support for this CPU type (%08x) in kernel", cputype); 1175129198Scognet return(ARCHITECTURE_NOT_PRESENT); 1176129198Scognet} 1177129198Scognet 1178129198Scognet/* 1179129198Scognet * Fixup routines for data and prefetch aborts. 1180129198Scognet * 1181129198Scognet * Several compile time symbols are used 1182129198Scognet * 1183129198Scognet * DEBUG_FAULT_CORRECTION - Print debugging information during the 1184129198Scognet * correction of registers after a fault. 1185129198Scognet * ARM6_LATE_ABORT - ARM6 supports both early and late aborts 1186129198Scognet * when defined should use late aborts 1187129198Scognet */ 1188129198Scognet 1189129198Scognet 1190129198Scognet/* 1191129198Scognet * Null abort fixup routine. 1192129198Scognet * For use when no fixup is required. 1193129198Scognet */ 1194129198Scognetint 1195129198Scognetcpufunc_null_fixup(arg) 1196129198Scognet void *arg; 1197129198Scognet{ 1198129198Scognet return(ABORT_FIXUP_OK); 1199129198Scognet} 1200129198Scognet 1201129198Scognet 1202129198Scognet#if defined(CPU_ARM2) || defined(CPU_ARM250) || defined(CPU_ARM3) || \ 1203129198Scognet defined(CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM7TDMI) 1204129198Scognet 1205129198Scognet#ifdef DEBUG_FAULT_CORRECTION 1206129198Scognet#define DFC_PRINTF(x) printf x 1207129198Scognet#define DFC_DISASSEMBLE(x) disassemble(x) 1208129198Scognet#else 1209129198Scognet#define DFC_PRINTF(x) /* nothing */ 1210129198Scognet#define DFC_DISASSEMBLE(x) /* nothing */ 1211129198Scognet#endif 1212129198Scognet 1213129198Scognet/* 1214129198Scognet * "Early" data abort fixup. 1215129198Scognet * 1216129198Scognet * For ARM2, ARM2as, ARM3 and ARM6 (in early-abort mode). Also used 1217129198Scognet * indirectly by ARM6 (in late-abort mode) and ARM7[TDMI]. 1218129198Scognet * 1219129198Scognet * In early aborts, we may have to fix up LDM, STM, LDC and STC. 1220129198Scognet */ 1221129198Scognetint 1222129198Scognetearly_abort_fixup(arg) 1223129198Scognet void *arg; 1224129198Scognet{ 1225129198Scognet trapframe_t *frame = arg; 1226129198Scognet u_int fault_pc; 1227129198Scognet u_int fault_instruction; 1228129198Scognet int saved_lr = 0; 1229129198Scognet 1230129198Scognet if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) { 1231129198Scognet 1232129198Scognet /* Ok an abort in SVC mode */ 1233129198Scognet 1234129198Scognet /* 1235129198Scognet * Copy the SVC r14 into the usr r14 - The usr r14 is garbage 1236129198Scognet * as the fault happened in svc mode but we need it in the 1237129198Scognet * usr slot so we can treat the registers as an array of ints 1238129198Scognet * during fixing. 1239129198Scognet * NOTE: This PC is in the position but writeback is not 1240129198Scognet * allowed on r15. 1241129198Scognet * Doing it like this is more efficient than trapping this 1242129198Scognet * case in all possible locations in the following fixup code. 1243129198Scognet */ 1244129198Scognet 1245129198Scognet saved_lr = frame->tf_usr_lr; 1246129198Scognet frame->tf_usr_lr = frame->tf_svc_lr; 1247129198Scognet 1248129198Scognet /* 1249129198Scognet * Note the trapframe does not have the SVC r13 so a fault 1250129198Scognet * from an instruction with writeback to r13 in SVC mode is 1251129198Scognet * not allowed. This should not happen as the kstack is 1252129198Scognet * always valid. 1253129198Scognet */ 1254129198Scognet } 1255129198Scognet 1256129198Scognet /* Get fault address and status from the CPU */ 1257129198Scognet 1258129198Scognet fault_pc = frame->tf_pc; 1259129198Scognet fault_instruction = *((volatile unsigned int *)fault_pc); 1260129198Scognet 1261129198Scognet /* Decode the fault instruction and fix the registers as needed */ 1262129198Scognet 1263129198Scognet if ((fault_instruction & 0x0e000000) == 0x08000000) { 1264129198Scognet int base; 1265129198Scognet int loop; 1266129198Scognet int count; 1267129198Scognet int *registers = &frame->tf_r0; 1268129198Scognet 1269129198Scognet DFC_PRINTF(("LDM/STM\n")); 1270129198Scognet DFC_DISASSEMBLE(fault_pc); 1271129198Scognet if (fault_instruction & (1 << 21)) { 1272129198Scognet DFC_PRINTF(("This instruction must be corrected\n")); 1273129198Scognet base = (fault_instruction >> 16) & 0x0f; 1274129198Scognet if (base == 15) 1275129198Scognet return ABORT_FIXUP_FAILED; 1276129198Scognet /* Count registers transferred */ 1277129198Scognet count = 0; 1278129198Scognet for (loop = 0; loop < 16; ++loop) { 1279129198Scognet if (fault_instruction & (1<<loop)) 1280129198Scognet ++count; 1281129198Scognet } 1282129198Scognet DFC_PRINTF(("%d registers used\n", count)); 1283129198Scognet DFC_PRINTF(("Corrected r%d by %d bytes ", 1284129198Scognet base, count * 4)); 1285129198Scognet if (fault_instruction & (1 << 23)) { 1286129198Scognet DFC_PRINTF(("down\n")); 1287129198Scognet registers[base] -= count * 4; 1288129198Scognet } else { 1289129198Scognet DFC_PRINTF(("up\n")); 1290129198Scognet registers[base] += count * 4; 1291129198Scognet } 1292129198Scognet } 1293129198Scognet } else if ((fault_instruction & 0x0e000000) == 0x0c000000) { 1294129198Scognet int base; 1295129198Scognet int offset; 1296129198Scognet int *registers = &frame->tf_r0; 1297129198Scognet 1298129198Scognet /* REGISTER CORRECTION IS REQUIRED FOR THESE INSTRUCTIONS */ 1299129198Scognet 1300129198Scognet DFC_DISASSEMBLE(fault_pc); 1301129198Scognet 1302129198Scognet /* Only need to fix registers if write back is turned on */ 1303129198Scognet 1304129198Scognet if ((fault_instruction & (1 << 21)) != 0) { 1305129198Scognet base = (fault_instruction >> 16) & 0x0f; 1306129198Scognet if (base == 13 && 1307129198Scognet (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) 1308129198Scognet return ABORT_FIXUP_FAILED; 1309129198Scognet if (base == 15) 1310129198Scognet return ABORT_FIXUP_FAILED; 1311129198Scognet 1312129198Scognet offset = (fault_instruction & 0xff) << 2; 1313129198Scognet DFC_PRINTF(("r%d=%08x\n", base, registers[base])); 1314129198Scognet if ((fault_instruction & (1 << 23)) != 0) 1315129198Scognet offset = -offset; 1316129198Scognet registers[base] += offset; 1317129198Scognet DFC_PRINTF(("r%d=%08x\n", base, registers[base])); 1318129198Scognet } 1319129198Scognet } else if ((fault_instruction & 0x0e000000) == 0x0c000000) 1320129198Scognet return ABORT_FIXUP_FAILED; 1321129198Scognet 1322129198Scognet if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) { 1323129198Scognet 1324129198Scognet /* Ok an abort in SVC mode */ 1325129198Scognet 1326129198Scognet /* 1327129198Scognet * Copy the SVC r14 into the usr r14 - The usr r14 is garbage 1328129198Scognet * as the fault happened in svc mode but we need it in the 1329129198Scognet * usr slot so we can treat the registers as an array of ints 1330129198Scognet * during fixing. 1331129198Scognet * NOTE: This PC is in the position but writeback is not 1332129198Scognet * allowed on r15. 1333129198Scognet * Doing it like this is more efficient than trapping this 1334129198Scognet * case in all possible locations in the prior fixup code. 1335129198Scognet */ 1336129198Scognet 1337129198Scognet frame->tf_svc_lr = frame->tf_usr_lr; 1338129198Scognet frame->tf_usr_lr = saved_lr; 1339129198Scognet 1340129198Scognet /* 1341129198Scognet * Note the trapframe does not have the SVC r13 so a fault 1342129198Scognet * from an instruction with writeback to r13 in SVC mode is 1343129198Scognet * not allowed. This should not happen as the kstack is 1344129198Scognet * always valid. 1345129198Scognet */ 1346129198Scognet } 1347129198Scognet 1348129198Scognet return(ABORT_FIXUP_OK); 1349129198Scognet} 1350129198Scognet#endif /* CPU_ARM2/250/3/6/7 */ 1351129198Scognet 1352129198Scognet 1353129198Scognet#if (defined(CPU_ARM6) && defined(ARM6_LATE_ABORT)) || defined(CPU_ARM7) || \ 1354129198Scognet defined(CPU_ARM7TDMI) 1355129198Scognet/* 1356129198Scognet * "Late" (base updated) data abort fixup 1357129198Scognet * 1358129198Scognet * For ARM6 (in late-abort mode) and ARM7. 1359129198Scognet * 1360129198Scognet * In this model, all data-transfer instructions need fixing up. We defer 1361129198Scognet * LDM, STM, LDC and STC fixup to the early-abort handler. 1362129198Scognet */ 1363129198Scognetint 1364129198Scognetlate_abort_fixup(arg) 1365129198Scognet void *arg; 1366129198Scognet{ 1367129198Scognet trapframe_t *frame = arg; 1368129198Scognet u_int fault_pc; 1369129198Scognet u_int fault_instruction; 1370129198Scognet int saved_lr = 0; 1371129198Scognet 1372129198Scognet if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) { 1373129198Scognet 1374129198Scognet /* Ok an abort in SVC mode */ 1375129198Scognet 1376129198Scognet /* 1377129198Scognet * Copy the SVC r14 into the usr r14 - The usr r14 is garbage 1378129198Scognet * as the fault happened in svc mode but we need it in the 1379129198Scognet * usr slot so we can treat the registers as an array of ints 1380129198Scognet * during fixing. 1381129198Scognet * NOTE: This PC is in the position but writeback is not 1382129198Scognet * allowed on r15. 1383129198Scognet * Doing it like this is more efficient than trapping this 1384129198Scognet * case in all possible locations in the following fixup code. 1385129198Scognet */ 1386129198Scognet 1387129198Scognet saved_lr = frame->tf_usr_lr; 1388129198Scognet frame->tf_usr_lr = frame->tf_svc_lr; 1389129198Scognet 1390129198Scognet /* 1391129198Scognet * Note the trapframe does not have the SVC r13 so a fault 1392129198Scognet * from an instruction with writeback to r13 in SVC mode is 1393129198Scognet * not allowed. This should not happen as the kstack is 1394129198Scognet * always valid. 1395129198Scognet */ 1396129198Scognet } 1397129198Scognet 1398129198Scognet /* Get fault address and status from the CPU */ 1399129198Scognet 1400129198Scognet fault_pc = frame->tf_pc; 1401129198Scognet fault_instruction = *((volatile unsigned int *)fault_pc); 1402129198Scognet 1403129198Scognet /* Decode the fault instruction and fix the registers as needed */ 1404129198Scognet 1405129198Scognet /* Was is a swap instruction ? */ 1406129198Scognet 1407129198Scognet if ((fault_instruction & 0x0fb00ff0) == 0x01000090) { 1408129198Scognet DFC_DISASSEMBLE(fault_pc); 1409129198Scognet } else if ((fault_instruction & 0x0c000000) == 0x04000000) { 1410129198Scognet 1411129198Scognet /* Was is a ldr/str instruction */ 1412129198Scognet /* This is for late abort only */ 1413129198Scognet 1414129198Scognet int base; 1415129198Scognet int offset; 1416129198Scognet int *registers = &frame->tf_r0; 1417129198Scognet 1418129198Scognet DFC_DISASSEMBLE(fault_pc); 1419129198Scognet 1420129198Scognet /* This is for late abort only */ 1421129198Scognet 1422129198Scognet if ((fault_instruction & (1 << 24)) == 0 1423129198Scognet || (fault_instruction & (1 << 21)) != 0) { 1424129198Scognet /* postindexed ldr/str with no writeback */ 1425129198Scognet 1426129198Scognet base = (fault_instruction >> 16) & 0x0f; 1427129198Scognet if (base == 13 && 1428129198Scognet (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) 1429129198Scognet return ABORT_FIXUP_FAILED; 1430129198Scognet if (base == 15) 1431129198Scognet return ABORT_FIXUP_FAILED; 1432129198Scognet DFC_PRINTF(("late abt fix: r%d=%08x : ", 1433129198Scognet base, registers[base])); 1434129198Scognet if ((fault_instruction & (1 << 25)) == 0) { 1435129198Scognet /* Immediate offset - easy */ 1436129198Scognet 1437129198Scognet offset = fault_instruction & 0xfff; 1438129198Scognet if ((fault_instruction & (1 << 23))) 1439129198Scognet offset = -offset; 1440129198Scognet registers[base] += offset; 1441129198Scognet DFC_PRINTF(("imm=%08x ", offset)); 1442129198Scognet } else { 1443129198Scognet /* offset is a shifted register */ 1444129198Scognet int shift; 1445129198Scognet 1446129198Scognet offset = fault_instruction & 0x0f; 1447129198Scognet if (offset == base) 1448129198Scognet return ABORT_FIXUP_FAILED; 1449129198Scognet 1450129198Scognet /* 1451129198Scognet * Register offset - hard we have to 1452129198Scognet * cope with shifts ! 1453129198Scognet */ 1454129198Scognet offset = registers[offset]; 1455129198Scognet 1456129198Scognet if ((fault_instruction & (1 << 4)) == 0) 1457129198Scognet /* shift with amount */ 1458129198Scognet shift = (fault_instruction >> 7) & 0x1f; 1459129198Scognet else { 1460129198Scognet /* shift with register */ 1461129198Scognet if ((fault_instruction & (1 << 7)) != 0) 1462129198Scognet /* undefined for now so bail out */ 1463129198Scognet return ABORT_FIXUP_FAILED; 1464129198Scognet shift = ((fault_instruction >> 8) & 0xf); 1465129198Scognet if (base == shift) 1466129198Scognet return ABORT_FIXUP_FAILED; 1467129198Scognet DFC_PRINTF(("shift reg=%d ", shift)); 1468129198Scognet shift = registers[shift]; 1469129198Scognet } 1470129198Scognet DFC_PRINTF(("shift=%08x ", shift)); 1471129198Scognet switch (((fault_instruction >> 5) & 0x3)) { 1472129198Scognet case 0 : /* Logical left */ 1473129198Scognet offset = (int)(((u_int)offset) << shift); 1474129198Scognet break; 1475129198Scognet case 1 : /* Logical Right */ 1476129198Scognet if (shift == 0) shift = 32; 1477129198Scognet offset = (int)(((u_int)offset) >> shift); 1478129198Scognet break; 1479129198Scognet case 2 : /* Arithmetic Right */ 1480129198Scognet if (shift == 0) shift = 32; 1481129198Scognet offset = (int)(((int)offset) >> shift); 1482129198Scognet break; 1483129198Scognet case 3 : /* Rotate right (rol or rxx) */ 1484129198Scognet return ABORT_FIXUP_FAILED; 1485129198Scognet break; 1486129198Scognet } 1487129198Scognet 1488129198Scognet DFC_PRINTF(("abt: fixed LDR/STR with " 1489129198Scognet "register offset\n")); 1490129198Scognet if ((fault_instruction & (1 << 23))) 1491129198Scognet offset = -offset; 1492129198Scognet DFC_PRINTF(("offset=%08x ", offset)); 1493129198Scognet registers[base] += offset; 1494129198Scognet } 1495129198Scognet DFC_PRINTF(("r%d=%08x\n", base, registers[base])); 1496129198Scognet } 1497129198Scognet } 1498129198Scognet 1499129198Scognet if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) { 1500129198Scognet 1501129198Scognet /* Ok an abort in SVC mode */ 1502129198Scognet 1503129198Scognet /* 1504129198Scognet * Copy the SVC r14 into the usr r14 - The usr r14 is garbage 1505129198Scognet * as the fault happened in svc mode but we need it in the 1506129198Scognet * usr slot so we can treat the registers as an array of ints 1507129198Scognet * during fixing. 1508129198Scognet * NOTE: This PC is in the position but writeback is not 1509129198Scognet * allowed on r15. 1510129198Scognet * Doing it like this is more efficient than trapping this 1511129198Scognet * case in all possible locations in the prior fixup code. 1512129198Scognet */ 1513129198Scognet 1514129198Scognet frame->tf_svc_lr = frame->tf_usr_lr; 1515129198Scognet frame->tf_usr_lr = saved_lr; 1516129198Scognet 1517129198Scognet /* 1518129198Scognet * Note the trapframe does not have the SVC r13 so a fault 1519129198Scognet * from an instruction with writeback to r13 in SVC mode is 1520129198Scognet * not allowed. This should not happen as the kstack is 1521129198Scognet * always valid. 1522129198Scognet */ 1523129198Scognet } 1524129198Scognet 1525129198Scognet /* 1526129198Scognet * Now let the early-abort fixup routine have a go, in case it 1527129198Scognet * was an LDM, STM, LDC or STC that faulted. 1528129198Scognet */ 1529129198Scognet 1530129198Scognet return early_abort_fixup(arg); 1531129198Scognet} 1532129198Scognet#endif /* CPU_ARM6(LATE)/7/7TDMI */ 1533129198Scognet 1534129198Scognet/* 1535129198Scognet * CPU Setup code 1536129198Scognet */ 1537129198Scognet 1538129198Scognet#if defined(CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM7TDMI) || \ 1539129198Scognet defined(CPU_ARM8) || defined (CPU_ARM9) || defined(CPU_SA110) || \ 1540129198Scognet defined(CPU_SA1100) || defined(CPU_SA1110) || \ 1541129198Scognet defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ 1542129198Scognet defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) 1543129198Scognet 1544129198Scognet#define IGN 0 1545129198Scognet#define OR 1 1546129198Scognet#define BIC 2 1547129198Scognet 1548129198Scognetstruct cpu_option { 1549129198Scognet char *co_name; 1550129198Scognet int co_falseop; 1551129198Scognet int co_trueop; 1552129198Scognet int co_value; 1553129198Scognet}; 1554129198Scognet 1555137498Strhodesstatic u_int parse_cpu_options(char *, struct cpu_option *, u_int); 1556129198Scognet 1557129198Scognetstatic u_int 1558129198Scognetparse_cpu_options(args, optlist, cpuctrl) 1559129198Scognet char *args; 1560129198Scognet struct cpu_option *optlist; 1561129198Scognet u_int cpuctrl; 1562129198Scognet{ 1563129198Scognet int integer; 1564129198Scognet 1565129198Scognet if (args == NULL) 1566129198Scognet return(cpuctrl); 1567129198Scognet 1568129198Scognet while (optlist->co_name) { 1569129198Scognet if (get_bootconf_option(args, optlist->co_name, 1570129198Scognet BOOTOPT_TYPE_BOOLEAN, &integer)) { 1571129198Scognet if (integer) { 1572129198Scognet if (optlist->co_trueop == OR) 1573129198Scognet cpuctrl |= optlist->co_value; 1574129198Scognet else if (optlist->co_trueop == BIC) 1575129198Scognet cpuctrl &= ~optlist->co_value; 1576129198Scognet } else { 1577129198Scognet if (optlist->co_falseop == OR) 1578129198Scognet cpuctrl |= optlist->co_value; 1579129198Scognet else if (optlist->co_falseop == BIC) 1580129198Scognet cpuctrl &= ~optlist->co_value; 1581129198Scognet } 1582129198Scognet } 1583129198Scognet ++optlist; 1584129198Scognet } 1585129198Scognet return(cpuctrl); 1586129198Scognet} 1587129198Scognet#endif /* CPU_ARM6 || CPU_ARM7 || CPU_ARM7TDMI || CPU_ARM8 || CPU_SA110 */ 1588129198Scognet 1589129198Scognet#if defined (CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM7TDMI) \ 1590129198Scognet || defined(CPU_ARM8) 1591129198Scognetstruct cpu_option arm678_options[] = { 1592129198Scognet#ifdef COMPAT_12 1593129198Scognet { "nocache", IGN, BIC, CPU_CONTROL_IDC_ENABLE }, 1594129198Scognet { "nowritebuf", IGN, BIC, CPU_CONTROL_WBUF_ENABLE }, 1595129198Scognet#endif /* COMPAT_12 */ 1596129198Scognet { "cpu.cache", BIC, OR, CPU_CONTROL_IDC_ENABLE }, 1597129198Scognet { "cpu.nocache", OR, BIC, CPU_CONTROL_IDC_ENABLE }, 1598129198Scognet { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1599129198Scognet { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1600129198Scognet { NULL, IGN, IGN, 0 } 1601129198Scognet}; 1602129198Scognet 1603129198Scognet#endif /* CPU_ARM6 || CPU_ARM7 || CPU_ARM7TDMI || CPU_ARM8 */ 1604129198Scognet 1605129198Scognet#ifdef CPU_ARM6 1606129198Scognetstruct cpu_option arm6_options[] = { 1607129198Scognet { "arm6.cache", BIC, OR, CPU_CONTROL_IDC_ENABLE }, 1608129198Scognet { "arm6.nocache", OR, BIC, CPU_CONTROL_IDC_ENABLE }, 1609129198Scognet { "arm6.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1610129198Scognet { "arm6.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1611129198Scognet { NULL, IGN, IGN, 0 } 1612129198Scognet}; 1613129198Scognet 1614129198Scognetvoid 1615129198Scognetarm6_setup(args) 1616129198Scognet char *args; 1617129198Scognet{ 1618129198Scognet int cpuctrl, cpuctrlmask; 1619129198Scognet 1620129198Scognet /* Set up default control registers bits */ 1621129198Scognet cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1622129198Scognet | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1623129198Scognet | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE; 1624129198Scognet cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1625129198Scognet | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1626129198Scognet | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE 1627129198Scognet | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_BEND_ENABLE 1628129198Scognet | CPU_CONTROL_AFLT_ENABLE; 1629129198Scognet 1630129198Scognet#ifdef ARM6_LATE_ABORT 1631129198Scognet cpuctrl |= CPU_CONTROL_LABT_ENABLE; 1632129198Scognet#endif /* ARM6_LATE_ABORT */ 1633129198Scognet 1634129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 1635129198Scognet cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 1636129198Scognet#endif 1637129198Scognet 1638129198Scognet cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl); 1639129198Scognet cpuctrl = parse_cpu_options(args, arm6_options, cpuctrl); 1640129198Scognet 1641129198Scognet#ifdef __ARMEB__ 1642129198Scognet cpuctrl |= CPU_CONTROL_BEND_ENABLE; 1643129198Scognet#endif 1644129198Scognet 1645129198Scognet /* Clear out the cache */ 1646129198Scognet cpu_idcache_wbinv_all(); 1647129198Scognet 1648129198Scognet /* Set the control register */ 1649129198Scognet ctrl = cpuctrl; 1650129198Scognet cpu_control(0xffffffff, cpuctrl); 1651129198Scognet} 1652129198Scognet#endif /* CPU_ARM6 */ 1653129198Scognet 1654129198Scognet#ifdef CPU_ARM7 1655129198Scognetstruct cpu_option arm7_options[] = { 1656129198Scognet { "arm7.cache", BIC, OR, CPU_CONTROL_IDC_ENABLE }, 1657129198Scognet { "arm7.nocache", OR, BIC, CPU_CONTROL_IDC_ENABLE }, 1658129198Scognet { "arm7.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1659129198Scognet { "arm7.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1660129198Scognet#ifdef COMPAT_12 1661129198Scognet { "fpaclk2", BIC, OR, CPU_CONTROL_CPCLK }, 1662129198Scognet#endif /* COMPAT_12 */ 1663129198Scognet { "arm700.fpaclk", BIC, OR, CPU_CONTROL_CPCLK }, 1664129198Scognet { NULL, IGN, IGN, 0 } 1665129198Scognet}; 1666129198Scognet 1667129198Scognetvoid 1668129198Scognetarm7_setup(args) 1669129198Scognet char *args; 1670129198Scognet{ 1671129198Scognet int cpuctrl, cpuctrlmask; 1672129198Scognet 1673129198Scognet cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1674129198Scognet | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1675129198Scognet | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE; 1676129198Scognet cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1677129198Scognet | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1678129198Scognet | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE 1679129198Scognet | CPU_CONTROL_CPCLK | CPU_CONTROL_LABT_ENABLE 1680129198Scognet | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_BEND_ENABLE 1681129198Scognet | CPU_CONTROL_AFLT_ENABLE; 1682129198Scognet 1683129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 1684129198Scognet cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 1685129198Scognet#endif 1686129198Scognet 1687129198Scognet cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl); 1688129198Scognet cpuctrl = parse_cpu_options(args, arm7_options, cpuctrl); 1689129198Scognet 1690129198Scognet#ifdef __ARMEB__ 1691129198Scognet cpuctrl |= CPU_CONTROL_BEND_ENABLE; 1692129198Scognet#endif 1693129198Scognet 1694129198Scognet /* Clear out the cache */ 1695129198Scognet cpu_idcache_wbinv_all(); 1696129198Scognet 1697129198Scognet /* Set the control register */ 1698129198Scognet ctrl = cpuctrl; 1699129198Scognet cpu_control(0xffffffff, cpuctrl); 1700129198Scognet} 1701129198Scognet#endif /* CPU_ARM7 */ 1702129198Scognet 1703129198Scognet#ifdef CPU_ARM7TDMI 1704129198Scognetstruct cpu_option arm7tdmi_options[] = { 1705129198Scognet { "arm7.cache", BIC, OR, CPU_CONTROL_IDC_ENABLE }, 1706129198Scognet { "arm7.nocache", OR, BIC, CPU_CONTROL_IDC_ENABLE }, 1707129198Scognet { "arm7.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1708129198Scognet { "arm7.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1709129198Scognet#ifdef COMPAT_12 1710129198Scognet { "fpaclk2", BIC, OR, CPU_CONTROL_CPCLK }, 1711129198Scognet#endif /* COMPAT_12 */ 1712129198Scognet { "arm700.fpaclk", BIC, OR, CPU_CONTROL_CPCLK }, 1713129198Scognet { NULL, IGN, IGN, 0 } 1714129198Scognet}; 1715129198Scognet 1716129198Scognetvoid 1717129198Scognetarm7tdmi_setup(args) 1718129198Scognet char *args; 1719129198Scognet{ 1720129198Scognet int cpuctrl; 1721129198Scognet 1722129198Scognet cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1723129198Scognet | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1724129198Scognet | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE; 1725129198Scognet 1726129198Scognet cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl); 1727129198Scognet cpuctrl = parse_cpu_options(args, arm7tdmi_options, cpuctrl); 1728129198Scognet 1729129198Scognet#ifdef __ARMEB__ 1730129198Scognet cpuctrl |= CPU_CONTROL_BEND_ENABLE; 1731129198Scognet#endif 1732129198Scognet 1733129198Scognet /* Clear out the cache */ 1734129198Scognet cpu_idcache_wbinv_all(); 1735129198Scognet 1736129198Scognet /* Set the control register */ 1737129198Scognet ctrl = cpuctrl; 1738129198Scognet cpu_control(0xffffffff, cpuctrl); 1739129198Scognet} 1740129198Scognet#endif /* CPU_ARM7TDMI */ 1741129198Scognet 1742129198Scognet#ifdef CPU_ARM8 1743129198Scognetstruct cpu_option arm8_options[] = { 1744129198Scognet { "arm8.cache", BIC, OR, CPU_CONTROL_IDC_ENABLE }, 1745129198Scognet { "arm8.nocache", OR, BIC, CPU_CONTROL_IDC_ENABLE }, 1746129198Scognet { "arm8.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1747129198Scognet { "arm8.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1748129198Scognet#ifdef COMPAT_12 1749129198Scognet { "branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, 1750129198Scognet#endif /* COMPAT_12 */ 1751129198Scognet { "cpu.branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, 1752129198Scognet { "arm8.branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, 1753129198Scognet { NULL, IGN, IGN, 0 } 1754129198Scognet}; 1755129198Scognet 1756129198Scognetvoid 1757129198Scognetarm8_setup(args) 1758129198Scognet char *args; 1759129198Scognet{ 1760129198Scognet int integer; 1761129198Scognet int cpuctrl, cpuctrlmask; 1762129198Scognet int clocktest; 1763129198Scognet int setclock = 0; 1764129198Scognet 1765129198Scognet cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1766129198Scognet | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1767129198Scognet | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE; 1768129198Scognet cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1769129198Scognet | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1770129198Scognet | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE 1771129198Scognet | CPU_CONTROL_BPRD_ENABLE | CPU_CONTROL_ROM_ENABLE 1772129198Scognet | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE; 1773129198Scognet 1774129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 1775129198Scognet cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 1776129198Scognet#endif 1777129198Scognet 1778129198Scognet cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl); 1779129198Scognet cpuctrl = parse_cpu_options(args, arm8_options, cpuctrl); 1780129198Scognet 1781129198Scognet#ifdef __ARMEB__ 1782129198Scognet cpuctrl |= CPU_CONTROL_BEND_ENABLE; 1783129198Scognet#endif 1784129198Scognet 1785129198Scognet /* Get clock configuration */ 1786129198Scognet clocktest = arm8_clock_config(0, 0) & 0x0f; 1787129198Scognet 1788129198Scognet /* Special ARM8 clock and test configuration */ 1789129198Scognet if (get_bootconf_option(args, "arm8.clock.reset", BOOTOPT_TYPE_BOOLEAN, &integer)) { 1790129198Scognet clocktest = 0; 1791129198Scognet setclock = 1; 1792129198Scognet } 1793129198Scognet if (get_bootconf_option(args, "arm8.clock.dynamic", BOOTOPT_TYPE_BOOLEAN, &integer)) { 1794129198Scognet if (integer) 1795129198Scognet clocktest |= 0x01; 1796129198Scognet else 1797129198Scognet clocktest &= ~(0x01); 1798129198Scognet setclock = 1; 1799129198Scognet } 1800129198Scognet if (get_bootconf_option(args, "arm8.clock.sync", BOOTOPT_TYPE_BOOLEAN, &integer)) { 1801129198Scognet if (integer) 1802129198Scognet clocktest |= 0x02; 1803129198Scognet else 1804129198Scognet clocktest &= ~(0x02); 1805129198Scognet setclock = 1; 1806129198Scognet } 1807129198Scognet if (get_bootconf_option(args, "arm8.clock.fast", BOOTOPT_TYPE_BININT, &integer)) { 1808129198Scognet clocktest = (clocktest & ~0xc0) | (integer & 3) << 2; 1809129198Scognet setclock = 1; 1810129198Scognet } 1811129198Scognet if (get_bootconf_option(args, "arm8.test", BOOTOPT_TYPE_BININT, &integer)) { 1812129198Scognet clocktest |= (integer & 7) << 5; 1813129198Scognet setclock = 1; 1814129198Scognet } 1815129198Scognet 1816129198Scognet /* Clear out the cache */ 1817129198Scognet cpu_idcache_wbinv_all(); 1818129198Scognet 1819129198Scognet /* Set the control register */ 1820129198Scognet ctrl = cpuctrl; 1821129198Scognet cpu_control(0xffffffff, cpuctrl); 1822129198Scognet 1823129198Scognet /* Set the clock/test register */ 1824129198Scognet if (setclock) 1825129198Scognet arm8_clock_config(0x7f, clocktest); 1826129198Scognet} 1827129198Scognet#endif /* CPU_ARM8 */ 1828129198Scognet 1829129198Scognet#ifdef CPU_ARM9 1830129198Scognetstruct cpu_option arm9_options[] = { 1831129198Scognet { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1832129198Scognet { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1833129198Scognet { "arm9.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1834129198Scognet { "arm9.icache", BIC, OR, CPU_CONTROL_IC_ENABLE }, 1835129198Scognet { "arm9.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE }, 1836129198Scognet { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1837129198Scognet { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1838129198Scognet { "arm9.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1839129198Scognet { NULL, IGN, IGN, 0 } 1840129198Scognet}; 1841129198Scognet 1842129198Scognetvoid 1843129198Scognetarm9_setup(args) 1844129198Scognet char *args; 1845129198Scognet{ 1846129198Scognet int cpuctrl, cpuctrlmask; 1847129198Scognet 1848129198Scognet cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1849129198Scognet | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1850129198Scognet | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1851146605Scognet | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE; 1852129198Scognet cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1853129198Scognet | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1854129198Scognet | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1855129198Scognet | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 1856129198Scognet | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 1857146605Scognet | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_VECRELOC 1858146605Scognet | CPU_CONTROL_ROUNDROBIN; 1859129198Scognet 1860129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 1861129198Scognet cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 1862129198Scognet#endif 1863129198Scognet 1864129198Scognet cpuctrl = parse_cpu_options(args, arm9_options, cpuctrl); 1865129198Scognet 1866129198Scognet#ifdef __ARMEB__ 1867129198Scognet cpuctrl |= CPU_CONTROL_BEND_ENABLE; 1868129198Scognet#endif 1869142050Scognet if (vector_page == ARM_VECTORS_HIGH) 1870142050Scognet cpuctrl |= CPU_CONTROL_VECRELOC; 1871129198Scognet 1872129198Scognet /* Clear out the cache */ 1873129198Scognet cpu_idcache_wbinv_all(); 1874129198Scognet 1875129198Scognet /* Set the control register */ 1876146605Scognet cpu_control(cpuctrlmask, cpuctrl); 1877129198Scognet ctrl = cpuctrl; 1878129198Scognet 1879129198Scognet} 1880129198Scognet#endif /* CPU_ARM9 */ 1881129198Scognet 1882129198Scognet#ifdef CPU_ARM10 1883129198Scognetstruct cpu_option arm10_options[] = { 1884129198Scognet { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1885129198Scognet { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1886129198Scognet { "arm10.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1887129198Scognet { "arm10.icache", BIC, OR, CPU_CONTROL_IC_ENABLE }, 1888129198Scognet { "arm10.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE }, 1889129198Scognet { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1890129198Scognet { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1891129198Scognet { "arm10.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1892129198Scognet { NULL, IGN, IGN, 0 } 1893129198Scognet}; 1894129198Scognet 1895129198Scognetvoid 1896129198Scognetarm10_setup(args) 1897129198Scognet char *args; 1898129198Scognet{ 1899129198Scognet int cpuctrl, cpuctrlmask; 1900129198Scognet 1901129198Scognet cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE 1902129198Scognet | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1903129198Scognet | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_BPRD_ENABLE; 1904129198Scognet cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE 1905129198Scognet | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1906129198Scognet | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 1907129198Scognet | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 1908129198Scognet | CPU_CONTROL_BPRD_ENABLE 1909129198Scognet | CPU_CONTROL_ROUNDROBIN | CPU_CONTROL_CPCLK; 1910129198Scognet 1911129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 1912129198Scognet cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 1913129198Scognet#endif 1914129198Scognet 1915129198Scognet cpuctrl = parse_cpu_options(args, arm10_options, cpuctrl); 1916129198Scognet 1917129198Scognet#ifdef __ARMEB__ 1918129198Scognet cpuctrl |= CPU_CONTROL_BEND_ENABLE; 1919129198Scognet#endif 1920129198Scognet 1921129198Scognet /* Clear out the cache */ 1922129198Scognet cpu_idcache_wbinv_all(); 1923129198Scognet 1924129198Scognet /* Now really make sure they are clean. */ 1925129198Scognet asm volatile ("mcr\tp15, 0, r0, c7, c7, 0" : : ); 1926129198Scognet 1927129198Scognet /* Set the control register */ 1928129198Scognet ctrl = cpuctrl; 1929129198Scognet cpu_control(0xffffffff, cpuctrl); 1930129198Scognet 1931129198Scognet /* And again. */ 1932129198Scognet cpu_idcache_wbinv_all(); 1933129198Scognet} 1934129198Scognet#endif /* CPU_ARM10 */ 1935129198Scognet 1936129198Scognet#ifdef CPU_SA110 1937129198Scognetstruct cpu_option sa110_options[] = { 1938129198Scognet#ifdef COMPAT_12 1939129198Scognet { "nocache", IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1940129198Scognet { "nowritebuf", IGN, BIC, CPU_CONTROL_WBUF_ENABLE }, 1941129198Scognet#endif /* COMPAT_12 */ 1942129198Scognet { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1943129198Scognet { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1944129198Scognet { "sa110.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 1945129198Scognet { "sa110.icache", BIC, OR, CPU_CONTROL_IC_ENABLE }, 1946129198Scognet { "sa110.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE }, 1947129198Scognet { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1948129198Scognet { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 1949129198Scognet { "sa110.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 1950129198Scognet { NULL, IGN, IGN, 0 } 1951129198Scognet}; 1952129198Scognet 1953129198Scognetvoid 1954129198Scognetsa110_setup(args) 1955129198Scognet char *args; 1956129198Scognet{ 1957129198Scognet int cpuctrl, cpuctrlmask; 1958129198Scognet 1959129198Scognet cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1960129198Scognet | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1961129198Scognet | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1962129198Scognet | CPU_CONTROL_WBUF_ENABLE; 1963129198Scognet cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 1964129198Scognet | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 1965129198Scognet | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 1966129198Scognet | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 1967129198Scognet | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 1968129198Scognet | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE 1969129198Scognet | CPU_CONTROL_CPCLK; 1970129198Scognet 1971129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 1972129198Scognet cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 1973129198Scognet#endif 1974129198Scognet 1975129198Scognet cpuctrl = parse_cpu_options(args, sa110_options, cpuctrl); 1976129198Scognet 1977129198Scognet#ifdef __ARMEB__ 1978129198Scognet cpuctrl |= CPU_CONTROL_BEND_ENABLE; 1979129198Scognet#endif 1980129198Scognet 1981129198Scognet /* Clear out the cache */ 1982129198Scognet cpu_idcache_wbinv_all(); 1983129198Scognet 1984129198Scognet /* Set the control register */ 1985129198Scognet ctrl = cpuctrl; 1986129198Scognet/* cpu_control(cpuctrlmask, cpuctrl);*/ 1987129198Scognet cpu_control(0xffffffff, cpuctrl); 1988129198Scognet 1989129198Scognet /* 1990129198Scognet * enable clockswitching, note that this doesn't read or write to r0, 1991129198Scognet * r0 is just to make it valid asm 1992129198Scognet */ 1993129198Scognet __asm ("mcr 15, 0, r0, c15, c1, 2"); 1994129198Scognet} 1995129198Scognet#endif /* CPU_SA110 */ 1996129198Scognet 1997129198Scognet#if defined(CPU_SA1100) || defined(CPU_SA1110) 1998129198Scognetstruct cpu_option sa11x0_options[] = { 1999129198Scognet#ifdef COMPAT_12 2000129198Scognet { "nocache", IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 2001129198Scognet { "nowritebuf", IGN, BIC, CPU_CONTROL_WBUF_ENABLE }, 2002129198Scognet#endif /* COMPAT_12 */ 2003129198Scognet { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 2004129198Scognet { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 2005129198Scognet { "sa11x0.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 2006129198Scognet { "sa11x0.icache", BIC, OR, CPU_CONTROL_IC_ENABLE }, 2007129198Scognet { "sa11x0.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE }, 2008129198Scognet { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 2009129198Scognet { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 2010129198Scognet { "sa11x0.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 2011129198Scognet { NULL, IGN, IGN, 0 } 2012129198Scognet}; 2013129198Scognet 2014129198Scognetvoid 2015129198Scognetsa11x0_setup(args) 2016129198Scognet char *args; 2017129198Scognet{ 2018129198Scognet int cpuctrl, cpuctrlmask; 2019129198Scognet 2020129198Scognet cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 2021129198Scognet | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 2022129198Scognet | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 2023129198Scognet | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE; 2024129198Scognet cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 2025129198Scognet | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 2026129198Scognet | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 2027129198Scognet | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 2028129198Scognet | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 2029129198Scognet | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE 2030129198Scognet | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC; 2031129198Scognet 2032129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 2033129198Scognet cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 2034129198Scognet#endif 2035129198Scognet 2036129198Scognet 2037129198Scognet cpuctrl = parse_cpu_options(args, sa11x0_options, cpuctrl); 2038129198Scognet 2039129198Scognet#ifdef __ARMEB__ 2040129198Scognet cpuctrl |= CPU_CONTROL_BEND_ENABLE; 2041129198Scognet#endif 2042129198Scognet 2043129198Scognet if (vector_page == ARM_VECTORS_HIGH) 2044129198Scognet cpuctrl |= CPU_CONTROL_VECRELOC; 2045129198Scognet /* Clear out the cache */ 2046129198Scognet cpu_idcache_wbinv_all(); 2047129198Scognet /* Set the control register */ 2048129198Scognet ctrl = cpuctrl; 2049129198Scognet cpu_control(0xffffffff, cpuctrl); 2050129198Scognet} 2051129198Scognet#endif /* CPU_SA1100 || CPU_SA1110 */ 2052129198Scognet 2053129198Scognet#if defined(CPU_IXP12X0) 2054129198Scognetstruct cpu_option ixp12x0_options[] = { 2055129198Scognet { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 2056129198Scognet { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 2057129198Scognet { "ixp12x0.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 2058129198Scognet { "ixp12x0.icache", BIC, OR, CPU_CONTROL_IC_ENABLE }, 2059129198Scognet { "ixp12x0.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE }, 2060129198Scognet { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 2061129198Scognet { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, 2062129198Scognet { "ixp12x0.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, 2063129198Scognet { NULL, IGN, IGN, 0 } 2064129198Scognet}; 2065129198Scognet 2066129198Scognetvoid 2067129198Scognetixp12x0_setup(args) 2068129198Scognet char *args; 2069129198Scognet{ 2070129198Scognet int cpuctrl, cpuctrlmask; 2071129198Scognet 2072129198Scognet 2073129198Scognet cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE 2074129198Scognet | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_SYST_ENABLE 2075129198Scognet | CPU_CONTROL_IC_ENABLE; 2076129198Scognet 2077129198Scognet cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_AFLT_ENABLE 2078129198Scognet | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_WBUF_ENABLE 2079129198Scognet | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_SYST_ENABLE 2080129198Scognet | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_IC_ENABLE 2081129198Scognet | CPU_CONTROL_VECRELOC; 2082129198Scognet 2083129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 2084129198Scognet cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 2085129198Scognet#endif 2086129198Scognet 2087129198Scognet cpuctrl = parse_cpu_options(args, ixp12x0_options, cpuctrl); 2088129198Scognet 2089129198Scognet#ifdef __ARMEB__ 2090129198Scognet cpuctrl |= CPU_CONTROL_BEND_ENABLE; 2091129198Scognet#endif 2092129198Scognet 2093129198Scognet if (vector_page == ARM_VECTORS_HIGH) 2094129198Scognet cpuctrl |= CPU_CONTROL_VECRELOC; 2095129198Scognet 2096129198Scognet /* Clear out the cache */ 2097129198Scognet cpu_idcache_wbinv_all(); 2098129198Scognet 2099129198Scognet /* Set the control register */ 2100129198Scognet ctrl = cpuctrl; 2101129198Scognet /* cpu_control(0xffffffff, cpuctrl); */ 2102129198Scognet cpu_control(cpuctrlmask, cpuctrl); 2103129198Scognet} 2104129198Scognet#endif /* CPU_IXP12X0 */ 2105129198Scognet 2106129198Scognet#if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ 2107129198Scognet defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) 2108129198Scognetstruct cpu_option xscale_options[] = { 2109129198Scognet#ifdef COMPAT_12 2110129198Scognet { "branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, 2111129198Scognet { "nocache", IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 2112129198Scognet#endif /* COMPAT_12 */ 2113129198Scognet { "cpu.branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, 2114129198Scognet { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 2115129198Scognet { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 2116129198Scognet { "xscale.branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, 2117129198Scognet { "xscale.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, 2118129198Scognet { "xscale.icache", BIC, OR, CPU_CONTROL_IC_ENABLE }, 2119129198Scognet { "xscale.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE }, 2120129198Scognet { NULL, IGN, IGN, 0 } 2121129198Scognet}; 2122129198Scognet 2123129198Scognetvoid 2124129198Scognetxscale_setup(args) 2125129198Scognet char *args; 2126129198Scognet{ 2127129198Scognet uint32_t auxctl; 2128129198Scognet int cpuctrl, cpuctrlmask; 2129129198Scognet 2130129198Scognet /* 2131129198Scognet * The XScale Write Buffer is always enabled. Our option 2132129198Scognet * is to enable/disable coalescing. Note that bits 6:3 2133129198Scognet * must always be enabled. 2134129198Scognet */ 2135129198Scognet 2136129198Scognet cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 2137129198Scognet | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 2138129198Scognet | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 2139129198Scognet | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE 2140129198Scognet | CPU_CONTROL_BPRD_ENABLE; 2141129198Scognet cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE 2142129198Scognet | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE 2143129198Scognet | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE 2144129198Scognet | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE 2145129198Scognet | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE 2146129198Scognet | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE 2147129198Scognet | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC; 2148129198Scognet 2149129198Scognet#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS 2150129198Scognet cpuctrl |= CPU_CONTROL_AFLT_ENABLE; 2151129198Scognet#endif 2152129198Scognet 2153129198Scognet cpuctrl = parse_cpu_options(args, xscale_options, cpuctrl); 2154129198Scognet 2155129198Scognet#ifdef __ARMEB__ 2156129198Scognet cpuctrl |= CPU_CONTROL_BEND_ENABLE; 2157129198Scognet#endif 2158129198Scognet 2159129198Scognet if (vector_page == ARM_VECTORS_HIGH) 2160129198Scognet cpuctrl |= CPU_CONTROL_VECRELOC; 2161129198Scognet 2162129198Scognet /* Clear out the cache */ 2163129198Scognet cpu_idcache_wbinv_all(); 2164129198Scognet 2165129198Scognet /* 2166129198Scognet * Set the control register. Note that bits 6:3 must always 2167129198Scognet * be set to 1. 2168129198Scognet */ 2169129198Scognet ctrl = cpuctrl; 2170129198Scognet/* cpu_control(cpuctrlmask, cpuctrl);*/ 2171129198Scognet cpu_control(0xffffffff, cpuctrl); 2172129198Scognet 2173129198Scognet /* Make sure write coalescing is turned on */ 2174129198Scognet __asm __volatile("mrc p15, 0, %0, c1, c0, 1" 2175129198Scognet : "=r" (auxctl)); 2176129198Scognet#ifdef XSCALE_NO_COALESCE_WRITES 2177129198Scognet auxctl |= XSCALE_AUXCTL_K; 2178129198Scognet#else 2179129198Scognet auxctl &= ~XSCALE_AUXCTL_K; 2180129198Scognet#endif 2181129198Scognet __asm __volatile("mcr p15, 0, %0, c1, c0, 1" 2182129198Scognet : : "r" (auxctl)); 2183129198Scognet} 2184129198Scognet#endif /* CPU_XSCALE_80200 || CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 */ 2185