xref: /rk3399_rockchip-uboot/arch/arm/lib/cache-cp15.c (revision 0dde7f53797098cf7021f6a7ca6c15bfee405db1)
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 
27e47f2db5SAneesh V #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
28880eff5cSHeiko Schocher 
29880eff5cSHeiko Schocher DECLARE_GLOBAL_DATA_PTR;
30880eff5cSHeiko Schocher 
31c2dd0d45SAneesh V void __arm_init_before_mmu(void)
32c2dd0d45SAneesh V {
33c2dd0d45SAneesh V }
34c2dd0d45SAneesh V void arm_init_before_mmu(void)
35c2dd0d45SAneesh V 	__attribute__((weak, alias("__arm_init_before_mmu")));
36c2dd0d45SAneesh V 
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();
44880eff5cSHeiko Schocher 	asm volatile("" : : : "memory");
45880eff5cSHeiko Schocher }
46880eff5cSHeiko Schocher 
47*0dde7f53SSimon Glass void set_section_dcache(int section, enum dcache_option option)
48f1d2b313SHeiko Schocher {
49f1d2b313SHeiko Schocher 	u32 *page_table = (u32 *)gd->tlb_addr;
50*0dde7f53SSimon Glass 	u32 value;
51*0dde7f53SSimon Glass 
52*0dde7f53SSimon Glass 	value = (section << MMU_SECTION_SHIFT) | (3 << 10);
53*0dde7f53SSimon Glass 	value |= option;
54*0dde7f53SSimon Glass 	page_table[section] = value;
55*0dde7f53SSimon Glass }
56*0dde7f53SSimon Glass 
57*0dde7f53SSimon Glass void __mmu_page_table_flush(unsigned long start, unsigned long stop)
58*0dde7f53SSimon Glass {
59*0dde7f53SSimon Glass 	debug("%s: Warning: not implemented\n", __func__);
60*0dde7f53SSimon Glass }
61*0dde7f53SSimon Glass 
62*0dde7f53SSimon Glass void mmu_page_table_flush(unsigned long start, unsigned long stop)
63*0dde7f53SSimon Glass 	__attribute__((weak, alias("__mmu_page_table_flush")));
64*0dde7f53SSimon Glass 
65*0dde7f53SSimon Glass void mmu_set_region_dcache_behaviour(u32 start, int size,
66*0dde7f53SSimon Glass 				     enum dcache_option option)
67*0dde7f53SSimon Glass {
68*0dde7f53SSimon Glass 	u32 *page_table = (u32 *)gd->tlb_addr;
69*0dde7f53SSimon Glass 	u32 upto, end;
70*0dde7f53SSimon Glass 
71*0dde7f53SSimon Glass 	end = ALIGN(start + size, MMU_SECTION_SIZE) >> MMU_SECTION_SHIFT;
72*0dde7f53SSimon Glass 	start = start >> MMU_SECTION_SHIFT;
73*0dde7f53SSimon Glass 	debug("%s: start=%x, size=%x, option=%d\n", __func__, start, size,
74*0dde7f53SSimon Glass 	      option);
75*0dde7f53SSimon Glass 	for (upto = start; upto < end; upto++)
76*0dde7f53SSimon Glass 		set_section_dcache(upto, option);
77*0dde7f53SSimon Glass 	mmu_page_table_flush((u32)&page_table[start], (u32)&page_table[end]);
78*0dde7f53SSimon Glass }
79*0dde7f53SSimon Glass 
80*0dde7f53SSimon Glass static inline void dram_bank_mmu_setup(int bank)
81*0dde7f53SSimon Glass {
82f1d2b313SHeiko Schocher 	bd_t *bd = gd->bd;
83f1d2b313SHeiko Schocher 	int	i;
84f1d2b313SHeiko Schocher 
85f1d2b313SHeiko Schocher 	debug("%s: bank: %d\n", __func__, bank);
86f1d2b313SHeiko Schocher 	for (i = bd->bi_dram[bank].start >> 20;
87f1d2b313SHeiko Schocher 	     i < (bd->bi_dram[bank].start + bd->bi_dram[bank].size) >> 20;
88f1d2b313SHeiko Schocher 	     i++) {
89*0dde7f53SSimon Glass #if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH)
90*0dde7f53SSimon Glass 		set_section_dcache(i, DCACHE_WRITETHROUGH);
91*0dde7f53SSimon Glass #else
92*0dde7f53SSimon Glass 		set_section_dcache(i, DCACHE_WRITEBACK);
93*0dde7f53SSimon Glass #endif
94f1d2b313SHeiko Schocher 	}
95f1d2b313SHeiko Schocher }
96f1d2b313SHeiko Schocher 
97f1d2b313SHeiko Schocher /* to activate the MMU we need to set up virtual memory: use 1M areas */
98880eff5cSHeiko Schocher static inline void mmu_setup(void)
99880eff5cSHeiko Schocher {
100f1d2b313SHeiko Schocher 	int i;
101880eff5cSHeiko Schocher 	u32 reg;
102880eff5cSHeiko Schocher 
103c2dd0d45SAneesh V 	arm_init_before_mmu();
104880eff5cSHeiko Schocher 	/* Set up an identity-mapping for all 4GB, rw for everyone */
105880eff5cSHeiko Schocher 	for (i = 0; i < 4096; i++)
106*0dde7f53SSimon Glass 		set_section_dcache(i, DCACHE_OFF);
107f1d2b313SHeiko Schocher 
108f1d2b313SHeiko Schocher 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
109f1d2b313SHeiko Schocher 		dram_bank_mmu_setup(i);
110f1d2b313SHeiko Schocher 	}
111880eff5cSHeiko Schocher 
112880eff5cSHeiko Schocher 	/* Copy the page table address to cp15 */
113880eff5cSHeiko Schocher 	asm volatile("mcr p15, 0, %0, c2, c0, 0"
114*0dde7f53SSimon Glass 		     : : "r" (gd->tlb_addr) : "memory");
115880eff5cSHeiko Schocher 	/* Set the access control to all-supervisor */
116880eff5cSHeiko Schocher 	asm volatile("mcr p15, 0, %0, c3, c0, 0"
117880eff5cSHeiko Schocher 		     : : "r" (~0));
118880eff5cSHeiko Schocher 	/* and enable the mmu */
119880eff5cSHeiko Schocher 	reg = get_cr();	/* get control reg. */
120880eff5cSHeiko Schocher 	cp_delay();
121880eff5cSHeiko Schocher 	set_cr(reg | CR_M);
122ea0364f1SPeter Tyser }
123ea0364f1SPeter Tyser 
124e05f0079SAneesh V static int mmu_enabled(void)
125e05f0079SAneesh V {
126e05f0079SAneesh V 	return get_cr() & CR_M;
127e05f0079SAneesh V }
128e05f0079SAneesh V 
129ea0364f1SPeter Tyser /* cache_bit must be either CR_I or CR_C */
130ea0364f1SPeter Tyser static void cache_enable(uint32_t cache_bit)
131ea0364f1SPeter Tyser {
132ea0364f1SPeter Tyser 	uint32_t reg;
133ea0364f1SPeter Tyser 
134880eff5cSHeiko Schocher 	/* The data cache is not active unless the mmu is enabled too */
135e05f0079SAneesh V 	if ((cache_bit == CR_C) && !mmu_enabled())
136880eff5cSHeiko Schocher 		mmu_setup();
137ea0364f1SPeter Tyser 	reg = get_cr();	/* get control reg. */
138ea0364f1SPeter Tyser 	cp_delay();
139ea0364f1SPeter Tyser 	set_cr(reg | cache_bit);
140ea0364f1SPeter Tyser }
141ea0364f1SPeter Tyser 
142ea0364f1SPeter Tyser /* cache_bit must be either CR_I or CR_C */
143ea0364f1SPeter Tyser static void cache_disable(uint32_t cache_bit)
144ea0364f1SPeter Tyser {
145ea0364f1SPeter Tyser 	uint32_t reg;
146ea0364f1SPeter Tyser 
147d702b081SSRICHARAN R 	reg = get_cr();
148d702b081SSRICHARAN R 	cp_delay();
149d702b081SSRICHARAN R 
150880eff5cSHeiko Schocher 	if (cache_bit == CR_C) {
151f1d2b313SHeiko Schocher 		/* if cache isn;t enabled no need to disable */
152f1d2b313SHeiko Schocher 		if ((reg & CR_C) != CR_C)
153f1d2b313SHeiko Schocher 			return;
154880eff5cSHeiko Schocher 		/* if disabling data cache, disable mmu too */
155880eff5cSHeiko Schocher 		cache_bit |= CR_M;
156e05f0079SAneesh V 		flush_dcache_all();
157880eff5cSHeiko Schocher 	}
158ea0364f1SPeter Tyser 	set_cr(reg & ~cache_bit);
159ea0364f1SPeter Tyser }
160ea0364f1SPeter Tyser #endif
161ea0364f1SPeter Tyser 
162e47f2db5SAneesh V #ifdef CONFIG_SYS_ICACHE_OFF
163ea0364f1SPeter Tyser void icache_enable (void)
164ea0364f1SPeter Tyser {
165ea0364f1SPeter Tyser 	return;
166ea0364f1SPeter Tyser }
167ea0364f1SPeter Tyser 
168ea0364f1SPeter Tyser void icache_disable (void)
169ea0364f1SPeter Tyser {
170ea0364f1SPeter Tyser 	return;
171ea0364f1SPeter Tyser }
172ea0364f1SPeter Tyser 
173ea0364f1SPeter Tyser int icache_status (void)
174ea0364f1SPeter Tyser {
175ea0364f1SPeter Tyser 	return 0;					/* always off */
176ea0364f1SPeter Tyser }
177ea0364f1SPeter Tyser #else
178ea0364f1SPeter Tyser void icache_enable(void)
179ea0364f1SPeter Tyser {
180ea0364f1SPeter Tyser 	cache_enable(CR_I);
181ea0364f1SPeter Tyser }
182ea0364f1SPeter Tyser 
183ea0364f1SPeter Tyser void icache_disable(void)
184ea0364f1SPeter Tyser {
185ea0364f1SPeter Tyser 	cache_disable(CR_I);
186ea0364f1SPeter Tyser }
187ea0364f1SPeter Tyser 
188ea0364f1SPeter Tyser int icache_status(void)
189ea0364f1SPeter Tyser {
190ea0364f1SPeter Tyser 	return (get_cr() & CR_I) != 0;
191ea0364f1SPeter Tyser }
192ea0364f1SPeter Tyser #endif
193ea0364f1SPeter Tyser 
194e47f2db5SAneesh V #ifdef CONFIG_SYS_DCACHE_OFF
195ea0364f1SPeter Tyser void dcache_enable (void)
196ea0364f1SPeter Tyser {
197ea0364f1SPeter Tyser 	return;
198ea0364f1SPeter Tyser }
199ea0364f1SPeter Tyser 
200ea0364f1SPeter Tyser void dcache_disable (void)
201ea0364f1SPeter Tyser {
202ea0364f1SPeter Tyser 	return;
203ea0364f1SPeter Tyser }
204ea0364f1SPeter Tyser 
205ea0364f1SPeter Tyser int dcache_status (void)
206ea0364f1SPeter Tyser {
207ea0364f1SPeter Tyser 	return 0;					/* always off */
208ea0364f1SPeter Tyser }
209ea0364f1SPeter Tyser #else
210ea0364f1SPeter Tyser void dcache_enable(void)
211ea0364f1SPeter Tyser {
212ea0364f1SPeter Tyser 	cache_enable(CR_C);
213ea0364f1SPeter Tyser }
214ea0364f1SPeter Tyser 
215ea0364f1SPeter Tyser void dcache_disable(void)
216ea0364f1SPeter Tyser {
217ea0364f1SPeter Tyser 	cache_disable(CR_C);
218ea0364f1SPeter Tyser }
219ea0364f1SPeter Tyser 
220ea0364f1SPeter Tyser int dcache_status(void)
221ea0364f1SPeter Tyser {
222ea0364f1SPeter Tyser 	return (get_cr() & CR_C) != 0;
223ea0364f1SPeter Tyser }
224ea0364f1SPeter Tyser #endif
225