xref: /nrf52832-nimble/rt-thread/libcpu/mips/x1000/cache.c (revision 104654410c56c573564690304ae786df310c91fc)
1 /*
2  * File      : cache.c
3  * This file is part of RT-Thread RTOS
4  * COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License along
17  *  with this program; if not, write to the Free Software Foundation, Inc.,
18  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  * Change Logs:
21  * Date           Author       Notes
22  * 2016/11/02     Urey         the first version
23  */
24 
25 #include <rtthread.h>
26 #include <board.h>
27 #include <rthw.h>
28 
29 #include "../common/mips.h"
30 
31 
32 #define CONFIG_SYS_DCACHE_SIZE      16384
33 #define CONFIG_SYS_ICACHE_SIZE      16384
34 #define CONFIG_SYS_CACHELINE_SIZE   32
35 
36 #define K0_TO_K1()                      \
37 do {                                    \
38     unsigned long __k0_addr;            \
39                                         \
40     __asm__ __volatile__(               \
41     "la %0, 1f\n\t"                     \
42     "or %0, %0, %1\n\t"                 \
43     "jr %0\n\t"                         \
44     "nop\n\t"                           \
45     "1: nop\n"                          \
46     : "=&r"(__k0_addr)                  \
47     : "r" (0x20000000) );               \
48 } while(0)
49 
50 #define K1_TO_K0()                      \
51 do {                                    \
52     unsigned long __k0_addr;            \
53     __asm__ __volatile__(               \
54     "nop;nop;nop;nop;nop;nop;nop\n\t"       \
55     "la %0, 1f\n\t"             \
56     "jr %0\n\t"                 \
57     "nop\n\t"                   \
58     "1: nop\n"                  \
59     : "=&r" (__k0_addr));       \
60 } while (0)
61 
62 #define INVALIDATE_BTB()        \
63 do {                            \
64     unsigned long tmp;         \
65     __asm__ __volatile__(     \
66     ".set mips32\n\t"           \
67     "mfc0 %0, $16, 7\n\t"       \
68     "nop\n\t"                   \
69     "ori %0, 2\n\t"             \
70     "mtc0 %0, $16, 7\n\t"       \
71     "nop\n\t"                   \
72     ".set mips2\n\t"            \
73     : "=&r" (tmp));             \
74 } while (0)
75 
76 #define __sync()                \
77     __asm__ __volatile__(           \
78         ".set   push\n\t"       \
79         ".set   noreorder\n\t"      \
80         ".set   mips2\n\t"      \
81         "sync\n\t"          \
82         ".set   pop"            \
83         : /* no output */       \
84         : /* no input */        \
85         : "memory")
86 
87 #if defined(JZ4775) || defined(X1000)
88 #define SYNC_WB()               \
89 do {                        \
90     __asm__ __volatile__ (          \
91     "sync\n\t"              \
92     "lw $0, %0\n\t"             \
93     :                   \
94     :"m"(*(int *)0xa0000000)        \
95     :"memory");             \
96 } while (0)
97 #else
98 #error "not define sync wb"
99 #define SYNC_WB() __asm__ __volatile__ ("sync")
100 #endif
101 
102 
103 #undef cache_op
104 #define cache_op(op, addr)      \
105     __asm__ __volatile__(       \
106         ".set   push\n"     \
107         ".set   noreorder\n"    \
108         ".set   mips3\n"    \
109         "cache  %0, %1\n"   \
110         ".set   pop\n"      \
111         :           \
112         : "i" (op), "R" (*(unsigned char *)(addr)))
113 
114 
rt_hw_dcache_flush_line(rt_uint32_t addr)115 void rt_hw_dcache_flush_line(rt_uint32_t addr)
116 {
117 	cache_op(HIT_WRITEBACK_INV_D, addr);
118 	SYNC_WB();
119 }
120 
rt_hw_dcache_flush_range(rt_uint32_t start_addr,rt_uint32_t size)121 void rt_hw_dcache_flush_range(rt_uint32_t start_addr, rt_uint32_t size)
122 {
123     rt_uint32_t lsize = CONFIG_SYS_CACHELINE_SIZE;
124     rt_uint32_t addr = start_addr & ~(lsize - 1);
125     rt_uint32_t aend = (start_addr + size - 1) & ~(lsize - 1);
126     rt_uint32_t writebuffer;
127 
128     for (; addr <= aend; addr += lsize)
129     {
130         cache_op(HIT_WRITEBACK_INV_D, addr);
131     }
132     SYNC_WB();
133 }
134 
rt_hw_dcache_flush_all(void)135 void rt_hw_dcache_flush_all(void)
136 {
137     rt_uint32_t addr;
138 
139     for (addr = CKSEG0; addr < CKSEG0 + CONFIG_SYS_DCACHE_SIZE; addr += CONFIG_SYS_CACHELINE_SIZE)
140     {
141         cache_op(INDEX_WRITEBACK_INV_D, addr);
142     }
143 
144     SYNC_WB();
145 }
146 
rt_hw_dcache_invalidate_range(rt_uint32_t start_addr,rt_uint32_t size)147 void rt_hw_dcache_invalidate_range(rt_uint32_t start_addr,rt_uint32_t size)
148 {
149     rt_uint32_t lsize = CONFIG_SYS_CACHELINE_SIZE;
150     rt_uint32_t addr = start_addr & ~(lsize - 1);
151     rt_uint32_t aend = (start_addr + size - 1) & ~(lsize - 1);
152 
153     for (; addr <= aend; addr += lsize)
154         cache_op(HIT_INVALIDATE_D, addr);
155 }
156 
rt_hw_dcache_invalidate_all(void)157 void rt_hw_dcache_invalidate_all(void)
158 {
159     rt_uint32_t addr;
160 
161     for (addr = CKSEG0; addr < CKSEG0 + CONFIG_SYS_DCACHE_SIZE; addr += CONFIG_SYS_CACHELINE_SIZE)
162     {
163         cache_op(INDEX_STORE_TAG_D, addr);
164     }
165 
166     SYNC_WB();
167 }
168 
rt_hw_icache_flush_line(rt_uint32_t addr)169 void rt_hw_icache_flush_line(rt_uint32_t addr)
170 {
171     cache_op(HIT_INVALIDATE_I, addr);
172 }
173 
rt_hw_icache_flush_all(void)174 void rt_hw_icache_flush_all(void)
175 {
176     rt_uint32_t addr;
177 
178     asm volatile ("mtc0 $0, $28"); /* Clear Taglo */
179     asm volatile ("mtc0 $0, $29"); /* Clear TagHi */
180 
181     for (addr = CKSEG0; addr < CKSEG0 + CONFIG_SYS_DCACHE_SIZE; addr += CONFIG_SYS_CACHELINE_SIZE)
182     {
183         cache_op(INDEX_STORE_TAG_I, addr);
184     }
185 
186     INVALIDATE_BTB();
187 }
188 
rt_hw_icache_invalidate_all(void)189 void rt_hw_icache_invalidate_all(void)
190 {
191     rt_uint32_t i;
192 
193     K0_TO_K1();
194 
195     asm volatile (".set noreorder\n"
196               ".set mips32\n\t"
197               "mtc0\t$0,$28\n\t"
198               "mtc0\t$0,$29\n"
199               ".set mips0\n"
200               ".set reorder\n");
201     for (i = CKSEG0; i < CKSEG0 + CONFIG_SYS_ICACHE_SIZE; i += CONFIG_SYS_CACHELINE_SIZE)
202         cache_op(INDEX_STORE_TAG_I, i);
203 
204     K1_TO_K0();
205 
206     INVALIDATE_BTB();
207 }
208 
209 
rt_hw_flush_cache_all(void)210 void rt_hw_flush_cache_all(void)
211 {
212     rt_hw_dcache_flush_all();
213     rt_hw_icache_flush_all();
214 }
215 
216 
217 
218