1ea0364f1SPeter Tyser /* 2ea0364f1SPeter Tyser * (C) Copyright 2002 3ea0364f1SPeter Tyser * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4ea0364f1SPeter Tyser * 5ea0364f1SPeter Tyser * See file CREDITS for list of people who contributed to this 6ea0364f1SPeter Tyser * project. 7ea0364f1SPeter Tyser * 8ea0364f1SPeter Tyser * This program is free software; you can redistribute it and/or 9ea0364f1SPeter Tyser * modify it under the terms of the GNU General Public License as 10ea0364f1SPeter Tyser * published by the Free Software Foundation; either version 2 of 11ea0364f1SPeter Tyser * the License, or (at your option) any later version. 12ea0364f1SPeter Tyser * 13ea0364f1SPeter Tyser * This program is distributed in the hope that it will be useful, 14ea0364f1SPeter Tyser * but WITHOUT ANY WARRANTY; without even the implied warranty of 15ea0364f1SPeter Tyser * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16ea0364f1SPeter Tyser * GNU General Public License for more details. 17ea0364f1SPeter Tyser * 18ea0364f1SPeter Tyser * You should have received a copy of the GNU General Public License 19ea0364f1SPeter Tyser * along with this program; if not, write to the Free Software 20ea0364f1SPeter Tyser * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21ea0364f1SPeter Tyser * MA 02111-1307 USA 22ea0364f1SPeter Tyser */ 23ea0364f1SPeter Tyser 24ea0364f1SPeter Tyser #include <common.h> 25ea0364f1SPeter Tyser #include <asm/system.h> 26ea0364f1SPeter Tyser 27ea0364f1SPeter Tyser #if !(defined(CONFIG_SYS_NO_ICACHE) && defined(CONFIG_SYS_NO_DCACHE)) 28*880eff5cSHeiko Schocher 29*880eff5cSHeiko Schocher #if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) 30*880eff5cSHeiko Schocher #define CACHE_SETUP 0x1a 31*880eff5cSHeiko Schocher #else 32*880eff5cSHeiko Schocher #define CACHE_SETUP 0x1e 33*880eff5cSHeiko Schocher #endif 34*880eff5cSHeiko Schocher 35*880eff5cSHeiko Schocher DECLARE_GLOBAL_DATA_PTR; 36*880eff5cSHeiko Schocher 37ea0364f1SPeter Tyser static void cp_delay (void) 38ea0364f1SPeter Tyser { 39ea0364f1SPeter Tyser volatile int i; 40ea0364f1SPeter Tyser 41ea0364f1SPeter Tyser /* copro seems to need some delay between reading and writing */ 42ea0364f1SPeter Tyser for (i = 0; i < 100; i++) 43ea0364f1SPeter Tyser nop(); 44*880eff5cSHeiko Schocher asm volatile("" : : : "memory"); 45*880eff5cSHeiko Schocher } 46*880eff5cSHeiko Schocher 47*880eff5cSHeiko Schocher /* to activate the MMU we need to set up virtual memory: use 1M areas in bss */ 48*880eff5cSHeiko Schocher static inline void mmu_setup(void) 49*880eff5cSHeiko Schocher { 50*880eff5cSHeiko Schocher static u32 __attribute__((aligned(16384))) page_table[4096]; 51*880eff5cSHeiko Schocher bd_t *bd = gd->bd; 52*880eff5cSHeiko Schocher int i, j; 53*880eff5cSHeiko Schocher u32 reg; 54*880eff5cSHeiko Schocher 55*880eff5cSHeiko Schocher /* Set up an identity-mapping for all 4GB, rw for everyone */ 56*880eff5cSHeiko Schocher for (i = 0; i < 4096; i++) 57*880eff5cSHeiko Schocher page_table[i] = i << 20 | (3 << 10) | 0x12; 58*880eff5cSHeiko Schocher /* Then, enable cacheable and bufferable for RAM only */ 59*880eff5cSHeiko Schocher for (j = 0; j < CONFIG_NR_DRAM_BANKS; j++) { 60*880eff5cSHeiko Schocher for (i = bd->bi_dram[j].start >> 20; 61*880eff5cSHeiko Schocher i < (bd->bi_dram[j].start + bd->bi_dram[j].size) >> 20; 62*880eff5cSHeiko Schocher i++) { 63*880eff5cSHeiko Schocher page_table[i] = i << 20 | (3 << 10) | CACHE_SETUP; 64*880eff5cSHeiko Schocher } 65*880eff5cSHeiko Schocher } 66*880eff5cSHeiko Schocher 67*880eff5cSHeiko Schocher /* Copy the page table address to cp15 */ 68*880eff5cSHeiko Schocher asm volatile("mcr p15, 0, %0, c2, c0, 0" 69*880eff5cSHeiko Schocher : : "r" (page_table) : "memory"); 70*880eff5cSHeiko Schocher /* Set the access control to all-supervisor */ 71*880eff5cSHeiko Schocher asm volatile("mcr p15, 0, %0, c3, c0, 0" 72*880eff5cSHeiko Schocher : : "r" (~0)); 73*880eff5cSHeiko Schocher /* and enable the mmu */ 74*880eff5cSHeiko Schocher reg = get_cr(); /* get control reg. */ 75*880eff5cSHeiko Schocher cp_delay(); 76*880eff5cSHeiko Schocher set_cr(reg | CR_M); 77*880eff5cSHeiko Schocher 78ea0364f1SPeter Tyser } 79ea0364f1SPeter Tyser 80ea0364f1SPeter Tyser /* cache_bit must be either CR_I or CR_C */ 81ea0364f1SPeter Tyser static void cache_enable(uint32_t cache_bit) 82ea0364f1SPeter Tyser { 83ea0364f1SPeter Tyser uint32_t reg; 84ea0364f1SPeter Tyser 85*880eff5cSHeiko Schocher /* The data cache is not active unless the mmu is enabled too */ 86*880eff5cSHeiko Schocher if (cache_bit == CR_C) 87*880eff5cSHeiko Schocher mmu_setup(); 88ea0364f1SPeter Tyser reg = get_cr(); /* get control reg. */ 89ea0364f1SPeter Tyser cp_delay(); 90ea0364f1SPeter Tyser set_cr(reg | cache_bit); 91ea0364f1SPeter Tyser } 92ea0364f1SPeter Tyser 93ea0364f1SPeter Tyser /* cache_bit must be either CR_I or CR_C */ 94ea0364f1SPeter Tyser static void cache_disable(uint32_t cache_bit) 95ea0364f1SPeter Tyser { 96ea0364f1SPeter Tyser uint32_t reg; 97ea0364f1SPeter Tyser 98*880eff5cSHeiko Schocher if (cache_bit == CR_C) { 99*880eff5cSHeiko Schocher /* if disabling data cache, disable mmu too */ 100*880eff5cSHeiko Schocher cache_bit |= CR_M; 101*880eff5cSHeiko Schocher flush_cache(0, ~0); 102*880eff5cSHeiko Schocher } 103ea0364f1SPeter Tyser reg = get_cr(); 104ea0364f1SPeter Tyser cp_delay(); 105ea0364f1SPeter Tyser set_cr(reg & ~cache_bit); 106ea0364f1SPeter Tyser } 107ea0364f1SPeter Tyser #endif 108ea0364f1SPeter Tyser 109ea0364f1SPeter Tyser #ifdef CONFIG_SYS_NO_ICACHE 110ea0364f1SPeter Tyser void icache_enable (void) 111ea0364f1SPeter Tyser { 112ea0364f1SPeter Tyser return; 113ea0364f1SPeter Tyser } 114ea0364f1SPeter Tyser 115ea0364f1SPeter Tyser void icache_disable (void) 116ea0364f1SPeter Tyser { 117ea0364f1SPeter Tyser return; 118ea0364f1SPeter Tyser } 119ea0364f1SPeter Tyser 120ea0364f1SPeter Tyser int icache_status (void) 121ea0364f1SPeter Tyser { 122ea0364f1SPeter Tyser return 0; /* always off */ 123ea0364f1SPeter Tyser } 124ea0364f1SPeter Tyser #else 125ea0364f1SPeter Tyser void icache_enable(void) 126ea0364f1SPeter Tyser { 127ea0364f1SPeter Tyser cache_enable(CR_I); 128ea0364f1SPeter Tyser } 129ea0364f1SPeter Tyser 130ea0364f1SPeter Tyser void icache_disable(void) 131ea0364f1SPeter Tyser { 132ea0364f1SPeter Tyser cache_disable(CR_I); 133ea0364f1SPeter Tyser } 134ea0364f1SPeter Tyser 135ea0364f1SPeter Tyser int icache_status(void) 136ea0364f1SPeter Tyser { 137ea0364f1SPeter Tyser return (get_cr() & CR_I) != 0; 138ea0364f1SPeter Tyser } 139ea0364f1SPeter Tyser #endif 140ea0364f1SPeter Tyser 141ea0364f1SPeter Tyser #ifdef CONFIG_SYS_NO_DCACHE 142ea0364f1SPeter Tyser void dcache_enable (void) 143ea0364f1SPeter Tyser { 144ea0364f1SPeter Tyser return; 145ea0364f1SPeter Tyser } 146ea0364f1SPeter Tyser 147ea0364f1SPeter Tyser void dcache_disable (void) 148ea0364f1SPeter Tyser { 149ea0364f1SPeter Tyser return; 150ea0364f1SPeter Tyser } 151ea0364f1SPeter Tyser 152ea0364f1SPeter Tyser int dcache_status (void) 153ea0364f1SPeter Tyser { 154ea0364f1SPeter Tyser return 0; /* always off */ 155ea0364f1SPeter Tyser } 156ea0364f1SPeter Tyser #else 157ea0364f1SPeter Tyser void dcache_enable(void) 158ea0364f1SPeter Tyser { 159ea0364f1SPeter Tyser cache_enable(CR_C); 160ea0364f1SPeter Tyser } 161ea0364f1SPeter Tyser 162ea0364f1SPeter Tyser void dcache_disable(void) 163ea0364f1SPeter Tyser { 164ea0364f1SPeter Tyser cache_disable(CR_C); 165ea0364f1SPeter Tyser } 166ea0364f1SPeter Tyser 167ea0364f1SPeter Tyser int dcache_status(void) 168ea0364f1SPeter Tyser { 169ea0364f1SPeter Tyser return (get_cr() & CR_C) != 0; 170ea0364f1SPeter Tyser } 171ea0364f1SPeter Tyser #endif 172