xref: /rk3399_rockchip-uboot/arch/arm/lib/cache-cp15.c (revision e47f2db5371047eb9bcd115fee084e6a8a92a239)
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 
27*e47f2db5SAneesh V #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
28880eff5cSHeiko Schocher 
29880eff5cSHeiko Schocher #if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH)
30880eff5cSHeiko Schocher #define CACHE_SETUP	0x1a
31880eff5cSHeiko Schocher #else
32880eff5cSHeiko Schocher #define CACHE_SETUP	0x1e
33880eff5cSHeiko Schocher #endif
34880eff5cSHeiko Schocher 
35880eff5cSHeiko Schocher DECLARE_GLOBAL_DATA_PTR;
36880eff5cSHeiko 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();
44880eff5cSHeiko Schocher 	asm volatile("" : : : "memory");
45880eff5cSHeiko Schocher }
46880eff5cSHeiko Schocher 
47f1d2b313SHeiko Schocher static inline void dram_bank_mmu_setup(int bank)
48f1d2b313SHeiko Schocher {
49f1d2b313SHeiko Schocher 	u32 *page_table = (u32 *)gd->tlb_addr;
50f1d2b313SHeiko Schocher 	bd_t *bd = gd->bd;
51f1d2b313SHeiko Schocher 	int	i;
52f1d2b313SHeiko Schocher 
53f1d2b313SHeiko Schocher 	debug("%s: bank: %d\n", __func__, bank);
54f1d2b313SHeiko Schocher 	for (i = bd->bi_dram[bank].start >> 20;
55f1d2b313SHeiko Schocher 	     i < (bd->bi_dram[bank].start + bd->bi_dram[bank].size) >> 20;
56f1d2b313SHeiko Schocher 	     i++) {
57f1d2b313SHeiko Schocher 		page_table[i] = i << 20 | (3 << 10) | CACHE_SETUP;
58f1d2b313SHeiko Schocher 	}
59f1d2b313SHeiko Schocher }
60f1d2b313SHeiko Schocher 
61f1d2b313SHeiko Schocher /* to activate the MMU we need to set up virtual memory: use 1M areas */
62880eff5cSHeiko Schocher static inline void mmu_setup(void)
63880eff5cSHeiko Schocher {
64f1d2b313SHeiko Schocher 	u32 *page_table = (u32 *)gd->tlb_addr;
65f1d2b313SHeiko Schocher 	int i;
66880eff5cSHeiko Schocher 	u32 reg;
67880eff5cSHeiko Schocher 
68880eff5cSHeiko Schocher 	/* Set up an identity-mapping for all 4GB, rw for everyone */
69880eff5cSHeiko Schocher 	for (i = 0; i < 4096; i++)
70880eff5cSHeiko Schocher 		page_table[i] = i << 20 | (3 << 10) | 0x12;
71f1d2b313SHeiko Schocher 
72f1d2b313SHeiko Schocher 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
73f1d2b313SHeiko Schocher 		dram_bank_mmu_setup(i);
74f1d2b313SHeiko Schocher 	}
75880eff5cSHeiko Schocher 
76880eff5cSHeiko Schocher 	/* Copy the page table address to cp15 */
77880eff5cSHeiko Schocher 	asm volatile("mcr p15, 0, %0, c2, c0, 0"
78880eff5cSHeiko Schocher 		     : : "r" (page_table) : "memory");
79880eff5cSHeiko Schocher 	/* Set the access control to all-supervisor */
80880eff5cSHeiko Schocher 	asm volatile("mcr p15, 0, %0, c3, c0, 0"
81880eff5cSHeiko Schocher 		     : : "r" (~0));
82880eff5cSHeiko Schocher 	/* and enable the mmu */
83880eff5cSHeiko Schocher 	reg = get_cr();	/* get control reg. */
84880eff5cSHeiko Schocher 	cp_delay();
85880eff5cSHeiko Schocher 	set_cr(reg | CR_M);
86ea0364f1SPeter Tyser }
87ea0364f1SPeter Tyser 
88ea0364f1SPeter Tyser /* cache_bit must be either CR_I or CR_C */
89ea0364f1SPeter Tyser static void cache_enable(uint32_t cache_bit)
90ea0364f1SPeter Tyser {
91ea0364f1SPeter Tyser 	uint32_t reg;
92ea0364f1SPeter Tyser 
93880eff5cSHeiko Schocher 	/* The data cache is not active unless the mmu is enabled too */
94880eff5cSHeiko Schocher 	if (cache_bit == CR_C)
95880eff5cSHeiko Schocher 		mmu_setup();
96ea0364f1SPeter Tyser 	reg = get_cr();	/* get control reg. */
97ea0364f1SPeter Tyser 	cp_delay();
98ea0364f1SPeter Tyser 	set_cr(reg | cache_bit);
99ea0364f1SPeter Tyser }
100ea0364f1SPeter Tyser 
101ea0364f1SPeter Tyser /* cache_bit must be either CR_I or CR_C */
102ea0364f1SPeter Tyser static void cache_disable(uint32_t cache_bit)
103ea0364f1SPeter Tyser {
104ea0364f1SPeter Tyser 	uint32_t reg;
105ea0364f1SPeter Tyser 
106880eff5cSHeiko Schocher 	if (cache_bit == CR_C) {
107f1d2b313SHeiko Schocher 		/* if cache isn;t enabled no need to disable */
108f1d2b313SHeiko Schocher 		reg = get_cr();
109f1d2b313SHeiko Schocher 		if ((reg & CR_C) != CR_C)
110f1d2b313SHeiko Schocher 			return;
111880eff5cSHeiko Schocher 		/* if disabling data cache, disable mmu too */
112880eff5cSHeiko Schocher 		cache_bit |= CR_M;
113880eff5cSHeiko Schocher 		flush_cache(0, ~0);
114880eff5cSHeiko Schocher 	}
115ea0364f1SPeter Tyser 	reg = get_cr();
116ea0364f1SPeter Tyser 	cp_delay();
117ea0364f1SPeter Tyser 	set_cr(reg & ~cache_bit);
118ea0364f1SPeter Tyser }
119ea0364f1SPeter Tyser #endif
120ea0364f1SPeter Tyser 
121*e47f2db5SAneesh V #ifdef CONFIG_SYS_ICACHE_OFF
122ea0364f1SPeter Tyser void icache_enable (void)
123ea0364f1SPeter Tyser {
124ea0364f1SPeter Tyser 	return;
125ea0364f1SPeter Tyser }
126ea0364f1SPeter Tyser 
127ea0364f1SPeter Tyser void icache_disable (void)
128ea0364f1SPeter Tyser {
129ea0364f1SPeter Tyser 	return;
130ea0364f1SPeter Tyser }
131ea0364f1SPeter Tyser 
132ea0364f1SPeter Tyser int icache_status (void)
133ea0364f1SPeter Tyser {
134ea0364f1SPeter Tyser 	return 0;					/* always off */
135ea0364f1SPeter Tyser }
136ea0364f1SPeter Tyser #else
137ea0364f1SPeter Tyser void icache_enable(void)
138ea0364f1SPeter Tyser {
139ea0364f1SPeter Tyser 	cache_enable(CR_I);
140ea0364f1SPeter Tyser }
141ea0364f1SPeter Tyser 
142ea0364f1SPeter Tyser void icache_disable(void)
143ea0364f1SPeter Tyser {
144ea0364f1SPeter Tyser 	cache_disable(CR_I);
145ea0364f1SPeter Tyser }
146ea0364f1SPeter Tyser 
147ea0364f1SPeter Tyser int icache_status(void)
148ea0364f1SPeter Tyser {
149ea0364f1SPeter Tyser 	return (get_cr() & CR_I) != 0;
150ea0364f1SPeter Tyser }
151ea0364f1SPeter Tyser #endif
152ea0364f1SPeter Tyser 
153*e47f2db5SAneesh V #ifdef CONFIG_SYS_DCACHE_OFF
154ea0364f1SPeter Tyser void dcache_enable (void)
155ea0364f1SPeter Tyser {
156ea0364f1SPeter Tyser 	return;
157ea0364f1SPeter Tyser }
158ea0364f1SPeter Tyser 
159ea0364f1SPeter Tyser void dcache_disable (void)
160ea0364f1SPeter Tyser {
161ea0364f1SPeter Tyser 	return;
162ea0364f1SPeter Tyser }
163ea0364f1SPeter Tyser 
164ea0364f1SPeter Tyser int dcache_status (void)
165ea0364f1SPeter Tyser {
166ea0364f1SPeter Tyser 	return 0;					/* always off */
167ea0364f1SPeter Tyser }
168ea0364f1SPeter Tyser #else
169ea0364f1SPeter Tyser void dcache_enable(void)
170ea0364f1SPeter Tyser {
171ea0364f1SPeter Tyser 	cache_enable(CR_C);
172ea0364f1SPeter Tyser }
173ea0364f1SPeter Tyser 
174ea0364f1SPeter Tyser void dcache_disable(void)
175ea0364f1SPeter Tyser {
176ea0364f1SPeter Tyser 	cache_disable(CR_C);
177ea0364f1SPeter Tyser }
178ea0364f1SPeter Tyser 
179ea0364f1SPeter Tyser int dcache_status(void)
180ea0364f1SPeter Tyser {
181ea0364f1SPeter Tyser 	return (get_cr() & CR_C) != 0;
182ea0364f1SPeter Tyser }
183ea0364f1SPeter Tyser #endif
184