]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/sh/cpu/sh4/cache.c
Add GPL-2.0+ SPDX-License-Identifier to source files
[karo-tx-uboot.git] / arch / sh / cpu / sh4 / cache.c
1 /*
2  * (C) Copyright 2007
3  * Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9 #include <command.h>
10 #include <asm/processor.h>
11 #include <asm/io.h>
12
13 /*
14  * Jump to P2 area.
15  * When handling TLB or caches, we need to do it from P2 area.
16  */
17 #define jump_to_P2()                    \
18   do {                                  \
19     unsigned long __dummy;              \
20     __asm__ __volatile__(               \
21                 "mov.l  1f, %0\n\t"     \
22                 "or     %1, %0\n\t"     \
23                 "jmp    @%0\n\t"        \
24                 " nop\n\t"              \
25                 ".balign 4\n"           \
26                 "1:     .long 2f\n"     \
27                 "2:"                    \
28                 : "=&r" (__dummy)       \
29                 : "r" (0x20000000));    \
30   } while (0)
31
32 /*
33  * Back to P1 area.
34  */
35 #define back_to_P1()                                    \
36   do {                                                  \
37     unsigned long __dummy;                              \
38     __asm__ __volatile__(                               \
39                 "nop;nop;nop;nop;nop;nop;nop\n\t"       \
40                 "mov.l  1f, %0\n\t"                     \
41                 "jmp    @%0\n\t"                        \
42                 " nop\n\t"                              \
43                 ".balign 4\n"                           \
44                 "1:     .long 2f\n"                     \
45                 "2:"                                    \
46                 : "=&r" (__dummy));                     \
47   } while (0)
48
49 #define CACHE_VALID       1
50 #define CACHE_UPDATED     2
51
52 static inline void cache_wback_all(void)
53 {
54         unsigned long addr, data, i, j;
55
56         jump_to_P2();
57         for (i = 0; i < CACHE_OC_NUM_ENTRIES; i++){
58                 for (j = 0; j < CACHE_OC_NUM_WAYS; j++) {
59                         addr = CACHE_OC_ADDRESS_ARRAY | (j << CACHE_OC_WAY_SHIFT)
60                                 | (i << CACHE_OC_ENTRY_SHIFT);
61                         data = inl(addr);
62                         if (data & CACHE_UPDATED) {
63                                 data &= ~CACHE_UPDATED;
64                                 outl(data, addr);
65                         }
66                 }
67         }
68         back_to_P1();
69 }
70
71
72 #define CACHE_ENABLE      0
73 #define CACHE_DISABLE     1
74
75 int cache_control(unsigned int cmd)
76 {
77         unsigned long ccr;
78
79         jump_to_P2();
80         ccr = inl(CCR);
81
82         if (ccr & CCR_CACHE_ENABLE)
83                 cache_wback_all();
84
85         if (cmd == CACHE_DISABLE)
86                 outl(CCR_CACHE_STOP, CCR);
87         else
88                 outl(CCR_CACHE_INIT, CCR);
89         back_to_P1();
90
91         return 0;
92 }
93
94 void dcache_wback_range(u32 start, u32 end)
95 {
96         u32 v;
97
98         start &= ~(L1_CACHE_BYTES - 1);
99         for (v = start; v < end; v += L1_CACHE_BYTES) {
100                 asm volatile ("ocbwb     %0" :  /* no output */
101                               : "m" (__m(v)));
102         }
103 }
104
105 void dcache_invalid_range(u32 start, u32 end)
106 {
107         u32 v;
108
109         start &= ~(L1_CACHE_BYTES - 1);
110         for (v = start; v < end; v += L1_CACHE_BYTES) {
111                 asm volatile ("ocbi     %0" :   /* no output */
112                               : "m" (__m(v)));
113         }
114 }