xref: /rk3399_rockchip-uboot/arch/arm/lib/cache-cp15.c (revision ff7e9700eda14ccf8ebe399d3831ef266e743c2d)
1ea0364f1SPeter Tyser /*
2ea0364f1SPeter Tyser  * (C) Copyright 2002
3ea0364f1SPeter Tyser  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4ea0364f1SPeter Tyser  *
51a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
6ea0364f1SPeter Tyser  */
7ea0364f1SPeter Tyser 
8ea0364f1SPeter Tyser #include <common.h>
9ea0364f1SPeter Tyser #include <asm/system.h>
1096fdbec2SR Sricharan #include <asm/cache.h>
1196fdbec2SR Sricharan #include <linux/compiler.h>
12ea0364f1SPeter Tyser 
13e47f2db5SAneesh V #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
14880eff5cSHeiko Schocher 
15880eff5cSHeiko Schocher DECLARE_GLOBAL_DATA_PTR;
16880eff5cSHeiko Schocher 
17fcfddfd5SJeroen Hofstee __weak void arm_init_before_mmu(void)
18c2dd0d45SAneesh V {
19c2dd0d45SAneesh V }
20c2dd0d45SAneesh V 
21de63ac27SR Sricharan __weak void arm_init_domains(void)
22de63ac27SR Sricharan {
23de63ac27SR Sricharan }
24de63ac27SR Sricharan 
25ea0364f1SPeter Tyser static void cp_delay (void)
26ea0364f1SPeter Tyser {
27ea0364f1SPeter Tyser 	volatile int i;
28ea0364f1SPeter Tyser 
29ea0364f1SPeter Tyser 	/* copro seems to need some delay between reading and writing */
30ea0364f1SPeter Tyser 	for (i = 0; i < 100; i++)
31ea0364f1SPeter Tyser 		nop();
32880eff5cSHeiko Schocher 	asm volatile("" : : : "memory");
33880eff5cSHeiko Schocher }
34880eff5cSHeiko Schocher 
350dde7f53SSimon Glass void set_section_dcache(int section, enum dcache_option option)
36f1d2b313SHeiko Schocher {
3734fd5d25SSimon Glass 	u32 *page_table = (u32 *)gd->arch.tlb_addr;
380dde7f53SSimon Glass 	u32 value;
390dde7f53SSimon Glass 
400dde7f53SSimon Glass 	value = (section << MMU_SECTION_SHIFT) | (3 << 10);
410dde7f53SSimon Glass 	value |= option;
420dde7f53SSimon Glass 	page_table[section] = value;
430dde7f53SSimon Glass }
440dde7f53SSimon Glass 
45fcfddfd5SJeroen Hofstee __weak void mmu_page_table_flush(unsigned long start, unsigned long stop)
460dde7f53SSimon Glass {
470dde7f53SSimon Glass 	debug("%s: Warning: not implemented\n", __func__);
480dde7f53SSimon Glass }
490dde7f53SSimon Glass 
500dde7f53SSimon Glass void mmu_set_region_dcache_behaviour(u32 start, int size,
510dde7f53SSimon Glass 				     enum dcache_option option)
520dde7f53SSimon Glass {
5334fd5d25SSimon Glass 	u32 *page_table = (u32 *)gd->arch.tlb_addr;
540dde7f53SSimon Glass 	u32 upto, end;
550dde7f53SSimon Glass 
560dde7f53SSimon Glass 	end = ALIGN(start + size, MMU_SECTION_SIZE) >> MMU_SECTION_SHIFT;
570dde7f53SSimon Glass 	start = start >> MMU_SECTION_SHIFT;
580dde7f53SSimon Glass 	debug("%s: start=%x, size=%x, option=%d\n", __func__, start, size,
590dde7f53SSimon Glass 	      option);
600dde7f53SSimon Glass 	for (upto = start; upto < end; upto++)
610dde7f53SSimon Glass 		set_section_dcache(upto, option);
620dde7f53SSimon Glass 	mmu_page_table_flush((u32)&page_table[start], (u32)&page_table[end]);
630dde7f53SSimon Glass }
640dde7f53SSimon Glass 
6596fdbec2SR Sricharan __weak void dram_bank_mmu_setup(int bank)
660dde7f53SSimon Glass {
67f1d2b313SHeiko Schocher 	bd_t *bd = gd->bd;
68f1d2b313SHeiko Schocher 	int	i;
69f1d2b313SHeiko Schocher 
70f1d2b313SHeiko Schocher 	debug("%s: bank: %d\n", __func__, bank);
71f1d2b313SHeiko Schocher 	for (i = bd->bi_dram[bank].start >> 20;
72221a49d5SMarek Vasut 	     i < (bd->bi_dram[bank].start >> 20) + (bd->bi_dram[bank].size >> 20);
73f1d2b313SHeiko Schocher 	     i++) {
740dde7f53SSimon Glass #if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH)
750dde7f53SSimon Glass 		set_section_dcache(i, DCACHE_WRITETHROUGH);
76*ff7e9700SMarek Vasut #elif defined(CONFIG_SYS_ARM_CACHE_WRITEALLOC)
77*ff7e9700SMarek Vasut 		set_section_dcache(i, DCACHE_WRITEALLOC);
780dde7f53SSimon Glass #else
790dde7f53SSimon Glass 		set_section_dcache(i, DCACHE_WRITEBACK);
800dde7f53SSimon Glass #endif
81f1d2b313SHeiko Schocher 	}
82f1d2b313SHeiko Schocher }
83f1d2b313SHeiko Schocher 
84f1d2b313SHeiko Schocher /* to activate the MMU we need to set up virtual memory: use 1M areas */
85880eff5cSHeiko Schocher static inline void mmu_setup(void)
86880eff5cSHeiko Schocher {
87f1d2b313SHeiko Schocher 	int i;
88880eff5cSHeiko Schocher 	u32 reg;
89880eff5cSHeiko Schocher 
90c2dd0d45SAneesh V 	arm_init_before_mmu();
91880eff5cSHeiko Schocher 	/* Set up an identity-mapping for all 4GB, rw for everyone */
92880eff5cSHeiko Schocher 	for (i = 0; i < 4096; i++)
930dde7f53SSimon Glass 		set_section_dcache(i, DCACHE_OFF);
94f1d2b313SHeiko Schocher 
95f1d2b313SHeiko Schocher 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
96f1d2b313SHeiko Schocher 		dram_bank_mmu_setup(i);
97f1d2b313SHeiko Schocher 	}
98880eff5cSHeiko Schocher 
99880eff5cSHeiko Schocher 	/* Copy the page table address to cp15 */
100880eff5cSHeiko Schocher 	asm volatile("mcr p15, 0, %0, c2, c0, 0"
10134fd5d25SSimon Glass 		     : : "r" (gd->arch.tlb_addr) : "memory");
102880eff5cSHeiko Schocher 	/* Set the access control to all-supervisor */
103880eff5cSHeiko Schocher 	asm volatile("mcr p15, 0, %0, c3, c0, 0"
104880eff5cSHeiko Schocher 		     : : "r" (~0));
105de63ac27SR Sricharan 
106de63ac27SR Sricharan 	arm_init_domains();
107de63ac27SR Sricharan 
108880eff5cSHeiko Schocher 	/* and enable the mmu */
109880eff5cSHeiko Schocher 	reg = get_cr();	/* get control reg. */
110880eff5cSHeiko Schocher 	cp_delay();
111880eff5cSHeiko Schocher 	set_cr(reg | CR_M);
112ea0364f1SPeter Tyser }
113ea0364f1SPeter Tyser 
114e05f0079SAneesh V static int mmu_enabled(void)
115e05f0079SAneesh V {
116e05f0079SAneesh V 	return get_cr() & CR_M;
117e05f0079SAneesh V }
118e05f0079SAneesh V 
119ea0364f1SPeter Tyser /* cache_bit must be either CR_I or CR_C */
120ea0364f1SPeter Tyser static void cache_enable(uint32_t cache_bit)
121ea0364f1SPeter Tyser {
122ea0364f1SPeter Tyser 	uint32_t reg;
123ea0364f1SPeter Tyser 
124880eff5cSHeiko Schocher 	/* The data cache is not active unless the mmu is enabled too */
125e05f0079SAneesh V 	if ((cache_bit == CR_C) && !mmu_enabled())
126880eff5cSHeiko Schocher 		mmu_setup();
127ea0364f1SPeter Tyser 	reg = get_cr();	/* get control reg. */
128ea0364f1SPeter Tyser 	cp_delay();
129ea0364f1SPeter Tyser 	set_cr(reg | cache_bit);
130ea0364f1SPeter Tyser }
131ea0364f1SPeter Tyser 
132ea0364f1SPeter Tyser /* cache_bit must be either CR_I or CR_C */
133ea0364f1SPeter Tyser static void cache_disable(uint32_t cache_bit)
134ea0364f1SPeter Tyser {
135ea0364f1SPeter Tyser 	uint32_t reg;
136ea0364f1SPeter Tyser 
137d702b081SSRICHARAN R 	reg = get_cr();
138d702b081SSRICHARAN R 	cp_delay();
139d702b081SSRICHARAN R 
140880eff5cSHeiko Schocher 	if (cache_bit == CR_C) {
141f1d2b313SHeiko Schocher 		/* if cache isn;t enabled no need to disable */
142f1d2b313SHeiko Schocher 		if ((reg & CR_C) != CR_C)
143f1d2b313SHeiko Schocher 			return;
144880eff5cSHeiko Schocher 		/* if disabling data cache, disable mmu too */
145880eff5cSHeiko Schocher 		cache_bit |= CR_M;
146880eff5cSHeiko Schocher 	}
14744df5e8dSArun Mankuzhi 	reg = get_cr();
14844df5e8dSArun Mankuzhi 	cp_delay();
14944df5e8dSArun Mankuzhi 	if (cache_bit == (CR_C | CR_M))
15044df5e8dSArun Mankuzhi 		flush_dcache_all();
151ea0364f1SPeter Tyser 	set_cr(reg & ~cache_bit);
152ea0364f1SPeter Tyser }
153ea0364f1SPeter Tyser #endif
154ea0364f1SPeter Tyser 
155e47f2db5SAneesh V #ifdef CONFIG_SYS_ICACHE_OFF
156ea0364f1SPeter Tyser void icache_enable (void)
157ea0364f1SPeter Tyser {
158ea0364f1SPeter Tyser 	return;
159ea0364f1SPeter Tyser }
160ea0364f1SPeter Tyser 
161ea0364f1SPeter Tyser void icache_disable (void)
162ea0364f1SPeter Tyser {
163ea0364f1SPeter Tyser 	return;
164ea0364f1SPeter Tyser }
165ea0364f1SPeter Tyser 
166ea0364f1SPeter Tyser int icache_status (void)
167ea0364f1SPeter Tyser {
168ea0364f1SPeter Tyser 	return 0;					/* always off */
169ea0364f1SPeter Tyser }
170ea0364f1SPeter Tyser #else
171ea0364f1SPeter Tyser void icache_enable(void)
172ea0364f1SPeter Tyser {
173ea0364f1SPeter Tyser 	cache_enable(CR_I);
174ea0364f1SPeter Tyser }
175ea0364f1SPeter Tyser 
176ea0364f1SPeter Tyser void icache_disable(void)
177ea0364f1SPeter Tyser {
178ea0364f1SPeter Tyser 	cache_disable(CR_I);
179ea0364f1SPeter Tyser }
180ea0364f1SPeter Tyser 
181ea0364f1SPeter Tyser int icache_status(void)
182ea0364f1SPeter Tyser {
183ea0364f1SPeter Tyser 	return (get_cr() & CR_I) != 0;
184ea0364f1SPeter Tyser }
185ea0364f1SPeter Tyser #endif
186ea0364f1SPeter Tyser 
187e47f2db5SAneesh V #ifdef CONFIG_SYS_DCACHE_OFF
188ea0364f1SPeter Tyser void dcache_enable (void)
189ea0364f1SPeter Tyser {
190ea0364f1SPeter Tyser 	return;
191ea0364f1SPeter Tyser }
192ea0364f1SPeter Tyser 
193ea0364f1SPeter Tyser void dcache_disable (void)
194ea0364f1SPeter Tyser {
195ea0364f1SPeter Tyser 	return;
196ea0364f1SPeter Tyser }
197ea0364f1SPeter Tyser 
198ea0364f1SPeter Tyser int dcache_status (void)
199ea0364f1SPeter Tyser {
200ea0364f1SPeter Tyser 	return 0;					/* always off */
201ea0364f1SPeter Tyser }
202ea0364f1SPeter Tyser #else
203ea0364f1SPeter Tyser void dcache_enable(void)
204ea0364f1SPeter Tyser {
205ea0364f1SPeter Tyser 	cache_enable(CR_C);
206ea0364f1SPeter Tyser }
207ea0364f1SPeter Tyser 
208ea0364f1SPeter Tyser void dcache_disable(void)
209ea0364f1SPeter Tyser {
210ea0364f1SPeter Tyser 	cache_disable(CR_C);
211ea0364f1SPeter Tyser }
212ea0364f1SPeter Tyser 
213ea0364f1SPeter Tyser int dcache_status(void)
214ea0364f1SPeter Tyser {
215ea0364f1SPeter Tyser 	return (get_cr() & CR_C) != 0;
216ea0364f1SPeter Tyser }
217ea0364f1SPeter Tyser #endif
218