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