1*10465441SEvalZero /*
2*10465441SEvalZero * File : mips_cache.h
3*10465441SEvalZero * This file is part of RT-Thread RTOS
4*10465441SEvalZero * COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
5*10465441SEvalZero *
6*10465441SEvalZero * This program is free software; you can redistribute it and/or modify
7*10465441SEvalZero * it under the terms of the GNU General Public License as published by
8*10465441SEvalZero * the Free Software Foundation; either version 2 of the License, or
9*10465441SEvalZero * (at your option) any later version.
10*10465441SEvalZero *
11*10465441SEvalZero * This program is distributed in the hope that it will be useful,
12*10465441SEvalZero * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*10465441SEvalZero * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*10465441SEvalZero * GNU General Public License for more details.
15*10465441SEvalZero *
16*10465441SEvalZero * You should have received a copy of the GNU General Public License along
17*10465441SEvalZero * with this program; if not, write to the Free Software Foundation, Inc.,
18*10465441SEvalZero * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*10465441SEvalZero *
20*10465441SEvalZero * Change Logs:
21*10465441SEvalZero * Date Author Notes
22*10465441SEvalZero * 2016��9��10�� Urey the first version
23*10465441SEvalZero */
24*10465441SEvalZero
25*10465441SEvalZero #ifndef _MIPS_CACHE_H_
26*10465441SEvalZero #define _MIPS_CACHE_H_
27*10465441SEvalZero
28*10465441SEvalZero #ifndef __ASSEMBLER__
29*10465441SEvalZero #include <rtdef.h>
30*10465441SEvalZero #include <mips_cfg.h>
31*10465441SEvalZero
32*10465441SEvalZero /*
33*10465441SEvalZero * Cache Operations available on all MIPS processors with R4000-style caches
34*10465441SEvalZero */
35*10465441SEvalZero #define INDEX_INVALIDATE_I 0x00
36*10465441SEvalZero #define INDEX_WRITEBACK_INV_D 0x01
37*10465441SEvalZero #define INDEX_LOAD_TAG_I 0x04
38*10465441SEvalZero #define INDEX_LOAD_TAG_D 0x05
39*10465441SEvalZero #define INDEX_STORE_TAG_I 0x08
40*10465441SEvalZero #define INDEX_STORE_TAG_D 0x09
41*10465441SEvalZero #if defined(CONFIG_CPU_LOONGSON2)
42*10465441SEvalZero #define HIT_INVALIDATE_I 0x00
43*10465441SEvalZero #else
44*10465441SEvalZero #define HIT_INVALIDATE_I 0x10
45*10465441SEvalZero #endif
46*10465441SEvalZero #define HIT_INVALIDATE_D 0x11
47*10465441SEvalZero #define HIT_WRITEBACK_INV_D 0x15
48*10465441SEvalZero
49*10465441SEvalZero /*
50*10465441SEvalZero *The lock state is cleared by executing an Index
51*10465441SEvalZero Invalidate, Index Writeback Invalidate, Hit
52*10465441SEvalZero Invalidate, or Hit Writeback Invalidate
53*10465441SEvalZero operation to the locked line, or via an Index
54*10465441SEvalZero Store Tag operation with the lock bit reset in
55*10465441SEvalZero the TagLo register.
56*10465441SEvalZero */
57*10465441SEvalZero #define FETCH_AND_LOCK_I 0x1c
58*10465441SEvalZero #define FETCH_AND_LOCK_D 0x1d
59*10465441SEvalZero
60*10465441SEvalZero
61*10465441SEvalZero enum dma_data_direction
62*10465441SEvalZero {
63*10465441SEvalZero DMA_BIDIRECTIONAL = 0,
64*10465441SEvalZero DMA_TO_DEVICE = 1,
65*10465441SEvalZero DMA_FROM_DEVICE = 2,
66*10465441SEvalZero DMA_NONE = 3,
67*10465441SEvalZero };
68*10465441SEvalZero
69*10465441SEvalZero /*
70*10465441SEvalZero * R4000-specific cacheops
71*10465441SEvalZero */
72*10465441SEvalZero #define CREATE_DIRTY_EXCL_D 0x0d
73*10465441SEvalZero #define FILL 0x14
74*10465441SEvalZero #define HIT_WRITEBACK_I 0x18
75*10465441SEvalZero #define HIT_WRITEBACK_D 0x19
76*10465441SEvalZero
77*10465441SEvalZero /*
78*10465441SEvalZero * R4000SC and R4400SC-specific cacheops
79*10465441SEvalZero */
80*10465441SEvalZero #define INDEX_INVALIDATE_SI 0x02
81*10465441SEvalZero #define INDEX_WRITEBACK_INV_SD 0x03
82*10465441SEvalZero #define INDEX_LOAD_TAG_SI 0x06
83*10465441SEvalZero #define INDEX_LOAD_TAG_SD 0x07
84*10465441SEvalZero #define INDEX_STORE_TAG_SI 0x0A
85*10465441SEvalZero #define INDEX_STORE_TAG_SD 0x0B
86*10465441SEvalZero #define CREATE_DIRTY_EXCL_SD 0x0f
87*10465441SEvalZero #define HIT_INVALIDATE_SI 0x12
88*10465441SEvalZero #define HIT_INVALIDATE_SD 0x13
89*10465441SEvalZero #define HIT_WRITEBACK_INV_SD 0x17
90*10465441SEvalZero #define HIT_WRITEBACK_SD 0x1b
91*10465441SEvalZero #define HIT_SET_VIRTUAL_SI 0x1e
92*10465441SEvalZero #define HIT_SET_VIRTUAL_SD 0x1f
93*10465441SEvalZero
94*10465441SEvalZero /*
95*10465441SEvalZero * R5000-specific cacheops
96*10465441SEvalZero */
97*10465441SEvalZero #define R5K_PAGE_INVALIDATE_S 0x17
98*10465441SEvalZero
99*10465441SEvalZero /*
100*10465441SEvalZero * RM7000-specific cacheops
101*10465441SEvalZero */
102*10465441SEvalZero #define PAGE_INVALIDATE_T 0x16
103*10465441SEvalZero
104*10465441SEvalZero /*
105*10465441SEvalZero * R10000-specific cacheops
106*10465441SEvalZero *
107*10465441SEvalZero * Cacheops 0x02, 0x06, 0x0a, 0x0c-0x0e, 0x16, 0x1a and 0x1e are unused.
108*10465441SEvalZero * Most of the _S cacheops are identical to the R4000SC _SD cacheops.
109*10465441SEvalZero */
110*10465441SEvalZero #define INDEX_WRITEBACK_INV_S 0x03
111*10465441SEvalZero #define INDEX_LOAD_TAG_S 0x07
112*10465441SEvalZero #define INDEX_STORE_TAG_S 0x0B
113*10465441SEvalZero #define HIT_INVALIDATE_S 0x13
114*10465441SEvalZero #define CACHE_BARRIER 0x14
115*10465441SEvalZero #define HIT_WRITEBACK_INV_S 0x17
116*10465441SEvalZero #define INDEX_LOAD_DATA_I 0x18
117*10465441SEvalZero #define INDEX_LOAD_DATA_D 0x19
118*10465441SEvalZero #define INDEX_LOAD_DATA_S 0x1b
119*10465441SEvalZero #define INDEX_STORE_DATA_I 0x1c
120*10465441SEvalZero #define INDEX_STORE_DATA_D 0x1d
121*10465441SEvalZero #define INDEX_STORE_DATA_S 0x1f
122*10465441SEvalZero
123*10465441SEvalZero #define cache_op(op, addr) \
124*10465441SEvalZero __asm__ __volatile__( \
125*10465441SEvalZero ".set push\n" \
126*10465441SEvalZero ".set noreorder\n" \
127*10465441SEvalZero ".set mips3\n" \
128*10465441SEvalZero "cache %0, %1\n" \
129*10465441SEvalZero ".set pop\n" \
130*10465441SEvalZero : \
131*10465441SEvalZero : "i" (op), "R" (*(unsigned char *)(addr)))
132*10465441SEvalZero
133*10465441SEvalZero #define cache16_unroll32(base, op) \
134*10465441SEvalZero __asm__ __volatile__( \
135*10465441SEvalZero " .set noreorder \n" \
136*10465441SEvalZero " .set mips3 \n" \
137*10465441SEvalZero " cache %1, 0x000(%0); cache %1, 0x010(%0) \n" \
138*10465441SEvalZero " cache %1, 0x020(%0); cache %1, 0x030(%0) \n" \
139*10465441SEvalZero " cache %1, 0x040(%0); cache %1, 0x050(%0) \n" \
140*10465441SEvalZero " cache %1, 0x060(%0); cache %1, 0x070(%0) \n" \
141*10465441SEvalZero " cache %1, 0x080(%0); cache %1, 0x090(%0) \n" \
142*10465441SEvalZero " cache %1, 0x0a0(%0); cache %1, 0x0b0(%0) \n" \
143*10465441SEvalZero " cache %1, 0x0c0(%0); cache %1, 0x0d0(%0) \n" \
144*10465441SEvalZero " cache %1, 0x0e0(%0); cache %1, 0x0f0(%0) \n" \
145*10465441SEvalZero " cache %1, 0x100(%0); cache %1, 0x110(%0) \n" \
146*10465441SEvalZero " cache %1, 0x120(%0); cache %1, 0x130(%0) \n" \
147*10465441SEvalZero " cache %1, 0x140(%0); cache %1, 0x150(%0) \n" \
148*10465441SEvalZero " cache %1, 0x160(%0); cache %1, 0x170(%0) \n" \
149*10465441SEvalZero " cache %1, 0x180(%0); cache %1, 0x190(%0) \n" \
150*10465441SEvalZero " cache %1, 0x1a0(%0); cache %1, 0x1b0(%0) \n" \
151*10465441SEvalZero " cache %1, 0x1c0(%0); cache %1, 0x1d0(%0) \n" \
152*10465441SEvalZero " cache %1, 0x1e0(%0); cache %1, 0x1f0(%0) \n" \
153*10465441SEvalZero " .set mips0 \n" \
154*10465441SEvalZero " .set reorder \n" \
155*10465441SEvalZero : \
156*10465441SEvalZero : "r" (base), \
157*10465441SEvalZero "i" (op));
158*10465441SEvalZero
159*10465441SEvalZero
flush_icache_line_indexed(rt_ubase_t addr)160*10465441SEvalZero static inline void flush_icache_line_indexed(rt_ubase_t addr)
161*10465441SEvalZero {
162*10465441SEvalZero cache_op(INDEX_INVALIDATE_I, addr);
163*10465441SEvalZero }
164*10465441SEvalZero
flush_dcache_line_indexed(rt_ubase_t addr)165*10465441SEvalZero static inline void flush_dcache_line_indexed(rt_ubase_t addr)
166*10465441SEvalZero {
167*10465441SEvalZero cache_op(INDEX_WRITEBACK_INV_D, addr);
168*10465441SEvalZero }
169*10465441SEvalZero
flush_icache_line(rt_ubase_t addr)170*10465441SEvalZero static inline void flush_icache_line(rt_ubase_t addr)
171*10465441SEvalZero {
172*10465441SEvalZero cache_op(HIT_INVALIDATE_I, addr);
173*10465441SEvalZero }
174*10465441SEvalZero
lock_icache_line(rt_ubase_t addr)175*10465441SEvalZero static inline void lock_icache_line(rt_ubase_t addr)
176*10465441SEvalZero {
177*10465441SEvalZero cache_op(FETCH_AND_LOCK_I, addr);
178*10465441SEvalZero }
179*10465441SEvalZero
lock_dcache_line(rt_ubase_t addr)180*10465441SEvalZero static inline void lock_dcache_line(rt_ubase_t addr)
181*10465441SEvalZero {
182*10465441SEvalZero cache_op(FETCH_AND_LOCK_D, addr);
183*10465441SEvalZero }
184*10465441SEvalZero
flush_dcache_line(rt_ubase_t addr)185*10465441SEvalZero static inline void flush_dcache_line(rt_ubase_t addr)
186*10465441SEvalZero {
187*10465441SEvalZero cache_op(HIT_WRITEBACK_INV_D, addr);
188*10465441SEvalZero }
189*10465441SEvalZero
invalidate_dcache_line(rt_ubase_t addr)190*10465441SEvalZero static inline void invalidate_dcache_line(rt_ubase_t addr)
191*10465441SEvalZero {
192*10465441SEvalZero cache_op(HIT_INVALIDATE_D, addr);
193*10465441SEvalZero }
blast_dcache16(void)194*10465441SEvalZero static inline void blast_dcache16(void)
195*10465441SEvalZero {
196*10465441SEvalZero rt_ubase_t start = KSEG0BASE;
197*10465441SEvalZero rt_ubase_t end = start + g_mips_core.dcache_size;
198*10465441SEvalZero rt_ubase_t addr;
199*10465441SEvalZero
200*10465441SEvalZero for (addr = start; addr < end; addr += g_mips_core.dcache_line_size)
201*10465441SEvalZero cache16_unroll32(addr, INDEX_WRITEBACK_INV_D);
202*10465441SEvalZero }
203*10465441SEvalZero
inv_dcache16(void)204*10465441SEvalZero static inline void inv_dcache16(void)
205*10465441SEvalZero {
206*10465441SEvalZero rt_ubase_t start = KSEG0BASE;
207*10465441SEvalZero rt_ubase_t end = start + g_mips_core.dcache_size;
208*10465441SEvalZero rt_ubase_t addr;
209*10465441SEvalZero
210*10465441SEvalZero for (addr = start; addr < end; addr += g_mips_core.dcache_line_size)
211*10465441SEvalZero cache16_unroll32(addr, HIT_INVALIDATE_D);
212*10465441SEvalZero }
213*10465441SEvalZero
blast_icache16(void)214*10465441SEvalZero static inline void blast_icache16(void)
215*10465441SEvalZero {
216*10465441SEvalZero rt_ubase_t start = KSEG0BASE;
217*10465441SEvalZero rt_ubase_t end = start + g_mips_core.icache_size;
218*10465441SEvalZero rt_ubase_t addr;
219*10465441SEvalZero
220*10465441SEvalZero for (addr = start; addr < end; addr += g_mips_core.icache_line_size)
221*10465441SEvalZero cache16_unroll32(addr, INDEX_INVALIDATE_I);
222*10465441SEvalZero }
223*10465441SEvalZero
224*10465441SEvalZero void r4k_cache_init(void);
225*10465441SEvalZero void r4k_cache_flush_all(void);
226*10465441SEvalZero void r4k_icache_flush_all(void);
227*10465441SEvalZero void r4k_icache_flush_range(rt_ubase_t addr, rt_ubase_t size);
228*10465441SEvalZero void r4k_icache_lock_range(rt_ubase_t addr, rt_ubase_t size);
229*10465441SEvalZero void r4k_dcache_inv(rt_ubase_t addr, rt_ubase_t size);
230*10465441SEvalZero void r4k_dcache_wback_inv(rt_ubase_t addr, rt_ubase_t size);
231*10465441SEvalZero void r4k_dma_cache_sync(rt_ubase_t addr, rt_size_t size, enum dma_data_direction direction);
232*10465441SEvalZero #endif
233*10465441SEvalZero
234*10465441SEvalZero #endif /* _MIPS_CACHE_H_ */
235