1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2016 Vladimir Zapolskiy <vz@mleia.com>
4  * (C) Copyright 2007 Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
5  */
6 
7 #include <command.h>
8 #include <cpu_func.h>
9 #include <stdio.h>
10 #include <asm/cache.h>
11 #include <asm/io.h>
12 #include <asm/processor.h>
13 #include <asm/system.h>
14 #include <linux/errno.h>
15 
16 #define CACHE_VALID       1
17 #define CACHE_UPDATED     2
18 
cache_wback_all(void)19 static inline void cache_wback_all(void)
20 {
21 	unsigned long addr, data, i, j;
22 
23 	for (i = 0; i < CACHE_OC_NUM_ENTRIES; i++) {
24 		for (j = 0; j < CACHE_OC_NUM_WAYS; j++) {
25 			addr = CACHE_OC_ADDRESS_ARRAY
26 				| (j << CACHE_OC_WAY_SHIFT)
27 				| (i << CACHE_OC_ENTRY_SHIFT);
28 			data = inl(addr);
29 			if (data & CACHE_UPDATED) {
30 				data &= ~CACHE_UPDATED;
31 				outl(data, addr);
32 			}
33 		}
34 	}
35 }
36 
37 #define CACHE_ENABLE		0
38 #define CACHE_DISABLE		1
39 #define CACHE_INVALIDATE	2
40 
cache_control(unsigned int cmd)41 static int cache_control(unsigned int cmd)
42 {
43 	unsigned long ccr;
44 
45 	jump_to_P2();
46 	ccr = inl(CCR);
47 
48 	if (ccr & CCR_CACHE_ENABLE)
49 		cache_wback_all();
50 
51 	if (cmd == CACHE_INVALIDATE)
52 		outl(CCR_CACHE_ICI | ccr, CCR);
53 	else if (cmd == CACHE_DISABLE)
54 		outl(CCR_CACHE_STOP, CCR);
55 	else
56 		outl(CCR_CACHE_INIT, CCR);
57 	back_to_P1();
58 
59 	return 0;
60 }
61 
flush_dcache_range(unsigned long start,unsigned long end)62 void flush_dcache_range(unsigned long start, unsigned long end)
63 {
64 	u32 v;
65 
66 	start &= ~(L1_CACHE_BYTES - 1);
67 	for (v = start; v < end; v += L1_CACHE_BYTES) {
68 		asm volatile ("ocbp     %0" :	/* no output */
69 			      : "m" (__m(v)));
70 	}
71 }
72 
73 /*
74  * Default implementation:
75  * do a range flush for the entire range
76  */
flush_dcache_all(void)77 void flush_dcache_all(void)
78 {
79 	flush_dcache_range(0, ~0);
80 }
81 
invalidate_dcache_range(unsigned long start,unsigned long end)82 void invalidate_dcache_range(unsigned long start, unsigned long end)
83 {
84 	u32 v;
85 
86 	start &= ~(L1_CACHE_BYTES - 1);
87 	for (v = start; v < end; v += L1_CACHE_BYTES) {
88 		asm volatile ("ocbi     %0" :	/* no output */
89 			      : "m" (__m(v)));
90 	}
91 }
92 
flush_cache(unsigned long addr,unsigned long size)93 void flush_cache(unsigned long addr, unsigned long size)
94 {
95 	flush_dcache_range(addr , addr + size);
96 }
97 
icache_enable(void)98 void icache_enable(void)
99 {
100 	cache_control(CACHE_ENABLE);
101 }
102 
icache_disable(void)103 void icache_disable(void)
104 {
105 	cache_control(CACHE_DISABLE);
106 }
107 
invalidate_icache_all(void)108 void invalidate_icache_all(void)
109 {
110 	cache_control(CACHE_INVALIDATE);
111 }
112 
icache_status(void)113 int icache_status(void)
114 {
115 	return 0;
116 }
117 
dcache_enable(void)118 void dcache_enable(void)
119 {
120 }
121 
dcache_disable(void)122 void dcache_disable(void)
123 {
124 }
125 
dcache_status(void)126 int dcache_status(void)
127 {
128 	return 0;
129 }
130 
pgprot_set_attrs(phys_addr_t addr,size_t size,enum pgprot_attrs perm)131 int __weak pgprot_set_attrs(phys_addr_t addr, size_t size, enum pgprot_attrs perm)
132 {
133 	return -ENOSYS;
134 }
135