xref: /rk3399_rockchip-uboot/arch/arm/lib/cache-cp15.c (revision fcfddfd50472d7ce84ef4e2853242bbeb7b37325)
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 
17*fcfddfd5SJeroen 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 
45*fcfddfd5SJeroen 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;
72f1d2b313SHeiko Schocher 	     i < (bd->bi_dram[bank].start + 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);
760dde7f53SSimon Glass #else
770dde7f53SSimon Glass 		set_section_dcache(i, DCACHE_WRITEBACK);
780dde7f53SSimon Glass #endif
79f1d2b313SHeiko Schocher 	}
80f1d2b313SHeiko Schocher }
81f1d2b313SHeiko Schocher 
82f1d2b313SHeiko Schocher /* to activate the MMU we need to set up virtual memory: use 1M areas */
83880eff5cSHeiko Schocher static inline void mmu_setup(void)
84880eff5cSHeiko Schocher {
85f1d2b313SHeiko Schocher 	int i;
86880eff5cSHeiko Schocher 	u32 reg;
87880eff5cSHeiko Schocher 
88c2dd0d45SAneesh V 	arm_init_before_mmu();
89880eff5cSHeiko Schocher 	/* Set up an identity-mapping for all 4GB, rw for everyone */
90880eff5cSHeiko Schocher 	for (i = 0; i < 4096; i++)
910dde7f53SSimon Glass 		set_section_dcache(i, DCACHE_OFF);
92f1d2b313SHeiko Schocher 
93f1d2b313SHeiko Schocher 	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
94f1d2b313SHeiko Schocher 		dram_bank_mmu_setup(i);
95f1d2b313SHeiko Schocher 	}
96880eff5cSHeiko Schocher 
97880eff5cSHeiko Schocher 	/* Copy the page table address to cp15 */
98880eff5cSHeiko Schocher 	asm volatile("mcr p15, 0, %0, c2, c0, 0"
9934fd5d25SSimon Glass 		     : : "r" (gd->arch.tlb_addr) : "memory");
100880eff5cSHeiko Schocher 	/* Set the access control to all-supervisor */
101880eff5cSHeiko Schocher 	asm volatile("mcr p15, 0, %0, c3, c0, 0"
102880eff5cSHeiko Schocher 		     : : "r" (~0));
103de63ac27SR Sricharan 
104de63ac27SR Sricharan 	arm_init_domains();
105de63ac27SR Sricharan 
106880eff5cSHeiko Schocher 	/* and enable the mmu */
107880eff5cSHeiko Schocher 	reg = get_cr();	/* get control reg. */
108880eff5cSHeiko Schocher 	cp_delay();
109880eff5cSHeiko Schocher 	set_cr(reg | CR_M);
110ea0364f1SPeter Tyser }
111ea0364f1SPeter Tyser 
112e05f0079SAneesh V static int mmu_enabled(void)
113e05f0079SAneesh V {
114e05f0079SAneesh V 	return get_cr() & CR_M;
115e05f0079SAneesh V }
116e05f0079SAneesh V 
117ea0364f1SPeter Tyser /* cache_bit must be either CR_I or CR_C */
118ea0364f1SPeter Tyser static void cache_enable(uint32_t cache_bit)
119ea0364f1SPeter Tyser {
120ea0364f1SPeter Tyser 	uint32_t reg;
121ea0364f1SPeter Tyser 
122880eff5cSHeiko Schocher 	/* The data cache is not active unless the mmu is enabled too */
123e05f0079SAneesh V 	if ((cache_bit == CR_C) && !mmu_enabled())
124880eff5cSHeiko Schocher 		mmu_setup();
125ea0364f1SPeter Tyser 	reg = get_cr();	/* get control reg. */
126ea0364f1SPeter Tyser 	cp_delay();
127ea0364f1SPeter Tyser 	set_cr(reg | cache_bit);
128ea0364f1SPeter Tyser }
129ea0364f1SPeter Tyser 
130ea0364f1SPeter Tyser /* cache_bit must be either CR_I or CR_C */
131ea0364f1SPeter Tyser static void cache_disable(uint32_t cache_bit)
132ea0364f1SPeter Tyser {
133ea0364f1SPeter Tyser 	uint32_t reg;
134ea0364f1SPeter Tyser 
135d702b081SSRICHARAN R 	reg = get_cr();
136d702b081SSRICHARAN R 	cp_delay();
137d702b081SSRICHARAN R 
138880eff5cSHeiko Schocher 	if (cache_bit == CR_C) {
139f1d2b313SHeiko Schocher 		/* if cache isn;t enabled no need to disable */
140f1d2b313SHeiko Schocher 		if ((reg & CR_C) != CR_C)
141f1d2b313SHeiko Schocher 			return;
142880eff5cSHeiko Schocher 		/* if disabling data cache, disable mmu too */
143880eff5cSHeiko Schocher 		cache_bit |= CR_M;
144880eff5cSHeiko Schocher 	}
14544df5e8dSArun Mankuzhi 	reg = get_cr();
14644df5e8dSArun Mankuzhi 	cp_delay();
14744df5e8dSArun Mankuzhi 	if (cache_bit == (CR_C | CR_M))
14844df5e8dSArun Mankuzhi 		flush_dcache_all();
149ea0364f1SPeter Tyser 	set_cr(reg & ~cache_bit);
150ea0364f1SPeter Tyser }
151ea0364f1SPeter Tyser #endif
152ea0364f1SPeter Tyser 
153e47f2db5SAneesh V #ifdef CONFIG_SYS_ICACHE_OFF
154ea0364f1SPeter Tyser void icache_enable (void)
155ea0364f1SPeter Tyser {
156ea0364f1SPeter Tyser 	return;
157ea0364f1SPeter Tyser }
158ea0364f1SPeter Tyser 
159ea0364f1SPeter Tyser void icache_disable (void)
160ea0364f1SPeter Tyser {
161ea0364f1SPeter Tyser 	return;
162ea0364f1SPeter Tyser }
163ea0364f1SPeter Tyser 
164ea0364f1SPeter Tyser int icache_status (void)
165ea0364f1SPeter Tyser {
166ea0364f1SPeter Tyser 	return 0;					/* always off */
167ea0364f1SPeter Tyser }
168ea0364f1SPeter Tyser #else
169ea0364f1SPeter Tyser void icache_enable(void)
170ea0364f1SPeter Tyser {
171ea0364f1SPeter Tyser 	cache_enable(CR_I);
172ea0364f1SPeter Tyser }
173ea0364f1SPeter Tyser 
174ea0364f1SPeter Tyser void icache_disable(void)
175ea0364f1SPeter Tyser {
176ea0364f1SPeter Tyser 	cache_disable(CR_I);
177ea0364f1SPeter Tyser }
178ea0364f1SPeter Tyser 
179ea0364f1SPeter Tyser int icache_status(void)
180ea0364f1SPeter Tyser {
181ea0364f1SPeter Tyser 	return (get_cr() & CR_I) != 0;
182ea0364f1SPeter Tyser }
183ea0364f1SPeter Tyser #endif
184ea0364f1SPeter Tyser 
185e47f2db5SAneesh V #ifdef CONFIG_SYS_DCACHE_OFF
186ea0364f1SPeter Tyser void dcache_enable (void)
187ea0364f1SPeter Tyser {
188ea0364f1SPeter Tyser 	return;
189ea0364f1SPeter Tyser }
190ea0364f1SPeter Tyser 
191ea0364f1SPeter Tyser void dcache_disable (void)
192ea0364f1SPeter Tyser {
193ea0364f1SPeter Tyser 	return;
194ea0364f1SPeter Tyser }
195ea0364f1SPeter Tyser 
196ea0364f1SPeter Tyser int dcache_status (void)
197ea0364f1SPeter Tyser {
198ea0364f1SPeter Tyser 	return 0;					/* always off */
199ea0364f1SPeter Tyser }
200ea0364f1SPeter Tyser #else
201ea0364f1SPeter Tyser void dcache_enable(void)
202ea0364f1SPeter Tyser {
203ea0364f1SPeter Tyser 	cache_enable(CR_C);
204ea0364f1SPeter Tyser }
205ea0364f1SPeter Tyser 
206ea0364f1SPeter Tyser void dcache_disable(void)
207ea0364f1SPeter Tyser {
208ea0364f1SPeter Tyser 	cache_disable(CR_C);
209ea0364f1SPeter Tyser }
210ea0364f1SPeter Tyser 
211ea0364f1SPeter Tyser int dcache_status(void)
212ea0364f1SPeter Tyser {
213ea0364f1SPeter Tyser 	return (get_cr() & CR_C) != 0;
214ea0364f1SPeter Tyser }
215ea0364f1SPeter Tyser #endif
216