xref: /rk3399_rockchip-uboot/arch/arm/lib/cache-cp15.c (revision 34fd5d253dee74fa8e431fc2183aa9f2637afa04)
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 
470dde7f53SSimon Glass void set_section_dcache(int section, enum dcache_option option)
48f1d2b313SHeiko Schocher {
49*34fd5d25SSimon Glass 	u32 *page_table = (u32 *)gd->arch.tlb_addr;
500dde7f53SSimon Glass 	u32 value;
510dde7f53SSimon Glass 
520dde7f53SSimon Glass 	value = (section << MMU_SECTION_SHIFT) | (3 << 10);
530dde7f53SSimon Glass 	value |= option;
540dde7f53SSimon Glass 	page_table[section] = value;
550dde7f53SSimon Glass }
560dde7f53SSimon Glass 
570dde7f53SSimon Glass void __mmu_page_table_flush(unsigned long start, unsigned long stop)
580dde7f53SSimon Glass {
590dde7f53SSimon Glass 	debug("%s: Warning: not implemented\n", __func__);
600dde7f53SSimon Glass }
610dde7f53SSimon Glass 
620dde7f53SSimon Glass void mmu_page_table_flush(unsigned long start, unsigned long stop)
630dde7f53SSimon Glass 	__attribute__((weak, alias("__mmu_page_table_flush")));
640dde7f53SSimon Glass 
650dde7f53SSimon Glass void mmu_set_region_dcache_behaviour(u32 start, int size,
660dde7f53SSimon Glass 				     enum dcache_option option)
670dde7f53SSimon Glass {
68*34fd5d25SSimon Glass 	u32 *page_table = (u32 *)gd->arch.tlb_addr;
690dde7f53SSimon Glass 	u32 upto, end;
700dde7f53SSimon Glass 
710dde7f53SSimon Glass 	end = ALIGN(start + size, MMU_SECTION_SIZE) >> MMU_SECTION_SHIFT;
720dde7f53SSimon Glass 	start = start >> MMU_SECTION_SHIFT;
730dde7f53SSimon Glass 	debug("%s: start=%x, size=%x, option=%d\n", __func__, start, size,
740dde7f53SSimon Glass 	      option);
750dde7f53SSimon Glass 	for (upto = start; upto < end; upto++)
760dde7f53SSimon Glass 		set_section_dcache(upto, option);
770dde7f53SSimon Glass 	mmu_page_table_flush((u32)&page_table[start], (u32)&page_table[end]);
780dde7f53SSimon Glass }
790dde7f53SSimon Glass 
800dde7f53SSimon Glass static inline void dram_bank_mmu_setup(int bank)
810dde7f53SSimon 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++) {
890dde7f53SSimon Glass #if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH)
900dde7f53SSimon Glass 		set_section_dcache(i, DCACHE_WRITETHROUGH);
910dde7f53SSimon Glass #else
920dde7f53SSimon Glass 		set_section_dcache(i, DCACHE_WRITEBACK);
930dde7f53SSimon 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++)
1060dde7f53SSimon 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*34fd5d25SSimon Glass 		     : : "r" (gd->arch.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;
156880eff5cSHeiko Schocher 	}
15744df5e8dSArun Mankuzhi 	reg = get_cr();
15844df5e8dSArun Mankuzhi 	cp_delay();
15944df5e8dSArun Mankuzhi 	if (cache_bit == (CR_C | CR_M))
16044df5e8dSArun Mankuzhi 		flush_dcache_all();
161ea0364f1SPeter Tyser 	set_cr(reg & ~cache_bit);
162ea0364f1SPeter Tyser }
163ea0364f1SPeter Tyser #endif
164ea0364f1SPeter Tyser 
165e47f2db5SAneesh V #ifdef CONFIG_SYS_ICACHE_OFF
166ea0364f1SPeter Tyser void icache_enable (void)
167ea0364f1SPeter Tyser {
168ea0364f1SPeter Tyser 	return;
169ea0364f1SPeter Tyser }
170ea0364f1SPeter Tyser 
171ea0364f1SPeter Tyser void icache_disable (void)
172ea0364f1SPeter Tyser {
173ea0364f1SPeter Tyser 	return;
174ea0364f1SPeter Tyser }
175ea0364f1SPeter Tyser 
176ea0364f1SPeter Tyser int icache_status (void)
177ea0364f1SPeter Tyser {
178ea0364f1SPeter Tyser 	return 0;					/* always off */
179ea0364f1SPeter Tyser }
180ea0364f1SPeter Tyser #else
181ea0364f1SPeter Tyser void icache_enable(void)
182ea0364f1SPeter Tyser {
183ea0364f1SPeter Tyser 	cache_enable(CR_I);
184ea0364f1SPeter Tyser }
185ea0364f1SPeter Tyser 
186ea0364f1SPeter Tyser void icache_disable(void)
187ea0364f1SPeter Tyser {
188ea0364f1SPeter Tyser 	cache_disable(CR_I);
189ea0364f1SPeter Tyser }
190ea0364f1SPeter Tyser 
191ea0364f1SPeter Tyser int icache_status(void)
192ea0364f1SPeter Tyser {
193ea0364f1SPeter Tyser 	return (get_cr() & CR_I) != 0;
194ea0364f1SPeter Tyser }
195ea0364f1SPeter Tyser #endif
196ea0364f1SPeter Tyser 
197e47f2db5SAneesh V #ifdef CONFIG_SYS_DCACHE_OFF
198ea0364f1SPeter Tyser void dcache_enable (void)
199ea0364f1SPeter Tyser {
200ea0364f1SPeter Tyser 	return;
201ea0364f1SPeter Tyser }
202ea0364f1SPeter Tyser 
203ea0364f1SPeter Tyser void dcache_disable (void)
204ea0364f1SPeter Tyser {
205ea0364f1SPeter Tyser 	return;
206ea0364f1SPeter Tyser }
207ea0364f1SPeter Tyser 
208ea0364f1SPeter Tyser int dcache_status (void)
209ea0364f1SPeter Tyser {
210ea0364f1SPeter Tyser 	return 0;					/* always off */
211ea0364f1SPeter Tyser }
212ea0364f1SPeter Tyser #else
213ea0364f1SPeter Tyser void dcache_enable(void)
214ea0364f1SPeter Tyser {
215ea0364f1SPeter Tyser 	cache_enable(CR_C);
216ea0364f1SPeter Tyser }
217ea0364f1SPeter Tyser 
218ea0364f1SPeter Tyser void dcache_disable(void)
219ea0364f1SPeter Tyser {
220ea0364f1SPeter Tyser 	cache_disable(CR_C);
221ea0364f1SPeter Tyser }
222ea0364f1SPeter Tyser 
223ea0364f1SPeter Tyser int dcache_status(void)
224ea0364f1SPeter Tyser {
225ea0364f1SPeter Tyser 	return (get_cr() & CR_C) != 0;
226ea0364f1SPeter Tyser }
227ea0364f1SPeter Tyser #endif
228