xref: /rk3399_rockchip-uboot/arch/arm/lib/cache-cp15.c (revision 880eff5cfb9df6f0855f4e48affd349ca64692e9)
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