xref: /rk3399_rockchip-uboot/arch/arm/lib/cache.c (revision bcc53bf095893fbdae531a9a7b5d4ef4a125a7fc)
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 /* for now: just dummy functions to satisfy the linker */
9ea0364f1SPeter Tyser 
10ea0364f1SPeter Tyser #include <common.h>
111dfdd9baSThierry Reding #include <malloc.h>
12ea0364f1SPeter Tyser 
13397b5697SSimon Glass #ifndef CONFIG_SYS_CACHELINE_SIZE
14397b5697SSimon Glass #define CONFIG_SYS_CACHELINE_SIZE 32
15397b5697SSimon Glass #endif
16397b5697SSimon Glass 
17633b6cceSWu, Josh /*
18633b6cceSWu, Josh  * Flush range from all levels of d-cache/unified-cache.
19633b6cceSWu, Josh  * Affects the range [start, start + size - 1].
20633b6cceSWu, Josh  */
21fcfddfd5SJeroen Hofstee __weak void flush_cache(unsigned long start, unsigned long size)
22ea0364f1SPeter Tyser {
23633b6cceSWu, Josh 	flush_dcache_range(start, start + size);
24ea0364f1SPeter Tyser }
25e05f0079SAneesh V 
26e05f0079SAneesh V /*
27e05f0079SAneesh V  * Default implementation:
28e05f0079SAneesh V  * do a range flush for the entire range
29e05f0079SAneesh V  */
30fcfddfd5SJeroen Hofstee __weak void flush_dcache_all(void)
31e05f0079SAneesh V {
32e05f0079SAneesh V 	flush_cache(0, ~0);
33e05f0079SAneesh V }
34cba4b180SAneesh V 
35cba4b180SAneesh V /*
36cba4b180SAneesh V  * Default implementation of enable_caches()
37cba4b180SAneesh V  * Real implementation should be in platform code
38cba4b180SAneesh V  */
39fcfddfd5SJeroen Hofstee __weak void enable_caches(void)
40cba4b180SAneesh V {
41cba4b180SAneesh V 	puts("WARNING: Caches not enabled\n");
42cba4b180SAneesh V }
431dfdd9baSThierry Reding 
44387871a1SWu, Josh __weak void invalidate_dcache_range(unsigned long start, unsigned long stop)
45387871a1SWu, Josh {
46387871a1SWu, Josh 	/* An empty stub, real implementation should be in platform code */
47387871a1SWu, Josh }
48387871a1SWu, Josh __weak void flush_dcache_range(unsigned long start, unsigned long stop)
49387871a1SWu, Josh {
50387871a1SWu, Josh 	/* An empty stub, real implementation should be in platform code */
51387871a1SWu, Josh }
52387871a1SWu, Josh 
53397b5697SSimon Glass int check_cache_range(unsigned long start, unsigned long stop)
54397b5697SSimon Glass {
55397b5697SSimon Glass 	int ok = 1;
56397b5697SSimon Glass 
57397b5697SSimon Glass 	if (start & (CONFIG_SYS_CACHELINE_SIZE - 1))
58397b5697SSimon Glass 		ok = 0;
59397b5697SSimon Glass 
60397b5697SSimon Glass 	if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1))
61397b5697SSimon Glass 		ok = 0;
62397b5697SSimon Glass 
63397b5697SSimon Glass 	if (!ok) {
64*bcc53bf0SSimon Glass 		warn_non_spl("CACHE: Misaligned operation at range [%08lx, %08lx]\n",
65397b5697SSimon Glass 			     start, stop);
66397b5697SSimon Glass 	}
67397b5697SSimon Glass 
68397b5697SSimon Glass 	return ok;
69397b5697SSimon Glass }
70397b5697SSimon Glass 
711dfdd9baSThierry Reding #ifdef CONFIG_SYS_NONCACHED_MEMORY
721dfdd9baSThierry Reding /*
731dfdd9baSThierry Reding  * Reserve one MMU section worth of address space below the malloc() area that
741dfdd9baSThierry Reding  * will be mapped uncached.
751dfdd9baSThierry Reding  */
761dfdd9baSThierry Reding static unsigned long noncached_start;
771dfdd9baSThierry Reding static unsigned long noncached_end;
781dfdd9baSThierry Reding static unsigned long noncached_next;
791dfdd9baSThierry Reding 
801dfdd9baSThierry Reding void noncached_init(void)
811dfdd9baSThierry Reding {
821dfdd9baSThierry Reding 	phys_addr_t start, end;
831dfdd9baSThierry Reding 	size_t size;
841dfdd9baSThierry Reding 
851dfdd9baSThierry Reding 	end = ALIGN(mem_malloc_start, MMU_SECTION_SIZE) - MMU_SECTION_SIZE;
861dfdd9baSThierry Reding 	size = ALIGN(CONFIG_SYS_NONCACHED_MEMORY, MMU_SECTION_SIZE);
871dfdd9baSThierry Reding 	start = end - size;
881dfdd9baSThierry Reding 
891dfdd9baSThierry Reding 	debug("mapping memory %pa-%pa non-cached\n", &start, &end);
901dfdd9baSThierry Reding 
911dfdd9baSThierry Reding 	noncached_start = start;
921dfdd9baSThierry Reding 	noncached_end = end;
931dfdd9baSThierry Reding 	noncached_next = start;
941dfdd9baSThierry Reding 
951dfdd9baSThierry Reding #ifndef CONFIG_SYS_DCACHE_OFF
961dfdd9baSThierry Reding 	mmu_set_region_dcache_behaviour(noncached_start, size, DCACHE_OFF);
971dfdd9baSThierry Reding #endif
981dfdd9baSThierry Reding }
991dfdd9baSThierry Reding 
1001dfdd9baSThierry Reding phys_addr_t noncached_alloc(size_t size, size_t align)
1011dfdd9baSThierry Reding {
1021dfdd9baSThierry Reding 	phys_addr_t next = ALIGN(noncached_next, align);
1031dfdd9baSThierry Reding 
1041dfdd9baSThierry Reding 	if (next >= noncached_end || (noncached_end - next) < size)
1051dfdd9baSThierry Reding 		return 0;
1061dfdd9baSThierry Reding 
1071dfdd9baSThierry Reding 	debug("allocated %zu bytes of uncached memory @%pa\n", size, &next);
1081dfdd9baSThierry Reding 	noncached_next = next + size;
1091dfdd9baSThierry Reding 
1101dfdd9baSThierry Reding 	return next;
1111dfdd9baSThierry Reding }
1121dfdd9baSThierry Reding #endif /* CONFIG_SYS_NONCACHED_MEMORY */
11362e92077SAlbert ARIBAUD 
11462e92077SAlbert ARIBAUD #if defined(CONFIG_SYS_THUMB_BUILD)
11562e92077SAlbert ARIBAUD void invalidate_l2_cache(void)
11662e92077SAlbert ARIBAUD {
11762e92077SAlbert ARIBAUD 	unsigned int val = 0;
11862e92077SAlbert ARIBAUD 
11962e92077SAlbert ARIBAUD 	asm volatile("mcr p15, 1, %0, c15, c11, 0 @ invl l2 cache"
12062e92077SAlbert ARIBAUD 		: : "r" (val) : "cc");
12162e92077SAlbert ARIBAUD 	isb();
12262e92077SAlbert ARIBAUD }
12362e92077SAlbert ARIBAUD #endif
124