Merge branch 'master' of git://git.denx.de/u-boot-microblaze
[oweals/u-boot.git] / arch / nds32 / lib / cache.c
1 /*
2  * Copyright (C) 2012 Andes Technology Corporation
3  * Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com>
4  * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
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
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include <common.h>
23
24 static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache)
25 {
26         if (cache == ICACHE)
27                 return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \
28                                         >> ICM_CFG_OFF_ISZ) - 1);
29         else
30                 return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \
31                                         >> DCM_CFG_OFF_DSZ) - 1);
32 }
33
34 void flush_dcache_range(unsigned long start, unsigned long end)
35 {
36         unsigned long line_size;
37
38         line_size = CACHE_LINE_SIZE(DCACHE);
39
40         while (end > start) {
41                 asm volatile (
42                         "\n\tcctl %0, L1D_VA_WB"
43                         "\n\tcctl %0, L1D_VA_INVAL"
44                         :
45                         : "r" (start)
46                 );
47                 start += line_size;
48         }
49 }
50
51 void invalidate_icache_range(unsigned long start, unsigned long end)
52 {
53         unsigned long line_size;
54
55         line_size = CACHE_LINE_SIZE(ICACHE);
56         while (end > start) {
57                 asm volatile (
58                         "\n\tcctl %0, L1I_VA_INVAL"
59                         :
60                         : "r"(start)
61                 );
62                 start += line_size;
63         }
64 }
65
66 void invalidate_dcache_range(unsigned long start, unsigned long end)
67 {
68         unsigned long line_size;
69
70         line_size = CACHE_LINE_SIZE(DCACHE);
71         while (end > start) {
72                 asm volatile (
73                         "\n\tcctl %0, L1D_VA_INVAL"
74                         :
75                         : "r"(start)
76                 );
77                 start += line_size;
78         }
79 }
80
81 void flush_cache(unsigned long addr, unsigned long size)
82 {
83         flush_dcache_range(addr, addr + size);
84         invalidate_icache_range(addr, addr + size);
85 }
86
87 void icache_enable(void)
88 {
89         asm volatile (
90                 "mfsr   $p0, $mr8\n\t"
91                 "ori    $p0, $p0, 0x01\n\t"
92                 "mtsr   $p0, $mr8\n\t"
93                 "isb\n\t"
94         );
95 }
96
97 void icache_disable(void)
98 {
99         asm volatile (
100                 "mfsr   $p0, $mr8\n\t"
101                 "li     $p1, ~0x01\n\t"
102                 "and    $p0, $p0, $p1\n\t"
103                 "mtsr   $p0, $mr8\n\t"
104                 "isb\n\t"
105         );
106 }
107
108 int icache_status(void)
109 {
110         int ret;
111
112         asm volatile (
113                 "mfsr   $p0, $mr8\n\t"
114                 "andi   %0,  $p0, 0x01\n\t"
115                 : "=r" (ret)
116                 :
117                 : "memory"
118         );
119
120         return ret;
121 }
122
123 void dcache_enable(void)
124 {
125         asm volatile (
126                 "mfsr   $p0, $mr8\n\t"
127                 "ori    $p0, $p0, 0x02\n\t"
128                 "mtsr   $p0, $mr8\n\t"
129                 "isb\n\t"
130         );
131 }
132
133 void dcache_disable(void)
134 {
135         asm volatile (
136                 "mfsr   $p0, $mr8\n\t"
137                 "li     $p1, ~0x02\n\t"
138                 "and    $p0, $p0, $p1\n\t"
139                 "mtsr   $p0, $mr8\n\t"
140                 "isb\n\t"
141         );
142 }
143
144 int dcache_status(void)
145 {
146         int ret;
147
148         asm volatile (
149                 "mfsr   $p0, $mr8\n\t"
150                 "andi   %0, $p0, 0x02\n\t"
151                 : "=r" (ret)
152                 :
153                 : "memory"
154         );
155
156         return ret;
157 }