Merge branch 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszer...
[deliverable/linux.git] / arch / metag / include / asm / l2cache.h
CommitLineData
99ef7c2a
JH
1#ifndef _METAG_L2CACHE_H
2#define _METAG_L2CACHE_H
3
4#ifdef CONFIG_METAG_L2C
5
6#include <asm/global_lock.h>
7#include <asm/io.h>
8
9/*
10 * Store the last known value of pfenable (we don't want prefetch enabled while
11 * L2 is off).
12 */
13extern int l2c_pfenable;
14
15/* defined in arch/metag/drivers/core-sysfs.c */
16extern struct sysdev_class cache_sysclass;
17
18static inline void wr_fence(void);
19
20/*
21 * Functions for reading of L2 cache configuration.
22 */
23
24/* Get raw L2 config register (CORE_CONFIG3) */
25static inline unsigned int meta_l2c_config(void)
26{
27 const unsigned int *corecfg3 = (const unsigned int *)METAC_CORE_CONFIG3;
28 return *corecfg3;
29}
30
31/* Get whether the L2 is present */
32static inline int meta_l2c_is_present(void)
33{
34 return meta_l2c_config() & METAC_CORECFG3_L2C_HAVE_L2C_BIT;
35}
36
37/* Get whether the L2 is configured for write-back instead of write-through */
38static inline int meta_l2c_is_writeback(void)
39{
40 return meta_l2c_config() & METAC_CORECFG3_L2C_MODE_BIT;
41}
42
43/* Get whether the L2 is unified instead of separated code/data */
44static inline int meta_l2c_is_unified(void)
45{
46 return meta_l2c_config() & METAC_CORECFG3_L2C_UNIFIED_BIT;
47}
48
49/* Get the L2 cache size in bytes */
50static inline unsigned int meta_l2c_size(void)
51{
52 unsigned int size_s;
53 if (!meta_l2c_is_present())
54 return 0;
55 size_s = (meta_l2c_config() & METAC_CORECFG3_L2C_SIZE_BITS)
56 >> METAC_CORECFG3_L2C_SIZE_S;
57 /* L2CSIZE is in KiB */
58 return 1024 << size_s;
59}
60
61/* Get the number of ways in the L2 cache */
62static inline unsigned int meta_l2c_ways(void)
63{
64 unsigned int ways_s;
65 if (!meta_l2c_is_present())
66 return 0;
67 ways_s = (meta_l2c_config() & METAC_CORECFG3_L2C_NUM_WAYS_BITS)
68 >> METAC_CORECFG3_L2C_NUM_WAYS_S;
69 return 0x1 << ways_s;
70}
71
72/* Get the line size of the L2 cache */
73static inline unsigned int meta_l2c_linesize(void)
74{
75 unsigned int line_size;
76 if (!meta_l2c_is_present())
77 return 0;
78 line_size = (meta_l2c_config() & METAC_CORECFG3_L2C_LINE_SIZE_BITS)
79 >> METAC_CORECFG3_L2C_LINE_SIZE_S;
80 switch (line_size) {
81 case METAC_CORECFG3_L2C_LINE_SIZE_64B:
82 return 64;
83 default:
84 return 0;
85 }
86}
87
88/* Get the revision ID of the L2 cache */
89static inline unsigned int meta_l2c_revision(void)
90{
91 return (meta_l2c_config() & METAC_CORECFG3_L2C_REV_ID_BITS)
92 >> METAC_CORECFG3_L2C_REV_ID_S;
93}
94
95
96/*
97 * Start an initialisation of the L2 cachelines and wait for completion.
98 * This should only be done in a LOCK1 or LOCK2 critical section while the L2
99 * is disabled.
100 */
101static inline void _meta_l2c_init(void)
102{
103 metag_out32(SYSC_L2C_INIT_INIT, SYSC_L2C_INIT);
104 while (metag_in32(SYSC_L2C_INIT) == SYSC_L2C_INIT_IN_PROGRESS)
105 /* do nothing */;
106}
107
108/*
109 * Start a writeback of dirty L2 cachelines and wait for completion.
110 * This should only be done in a LOCK1 or LOCK2 critical section.
111 */
112static inline void _meta_l2c_purge(void)
113{
114 metag_out32(SYSC_L2C_PURGE_PURGE, SYSC_L2C_PURGE);
115 while (metag_in32(SYSC_L2C_PURGE) == SYSC_L2C_PURGE_IN_PROGRESS)
116 /* do nothing */;
117}
118
119/* Set whether the L2 cache is enabled. */
120static inline void _meta_l2c_enable(int enabled)
121{
122 unsigned int enable;
123
124 enable = metag_in32(SYSC_L2C_ENABLE);
125 if (enabled)
126 enable |= SYSC_L2C_ENABLE_ENABLE_BIT;
127 else
128 enable &= ~SYSC_L2C_ENABLE_ENABLE_BIT;
129 metag_out32(enable, SYSC_L2C_ENABLE);
130}
131
132/* Set whether the L2 cache prefetch is enabled. */
133static inline void _meta_l2c_pf_enable(int pfenabled)
134{
135 unsigned int enable;
136
137 enable = metag_in32(SYSC_L2C_ENABLE);
138 if (pfenabled)
139 enable |= SYSC_L2C_ENABLE_PFENABLE_BIT;
140 else
141 enable &= ~SYSC_L2C_ENABLE_PFENABLE_BIT;
142 metag_out32(enable, SYSC_L2C_ENABLE);
143}
144
145/* Return whether the L2 cache is enabled */
146static inline int _meta_l2c_is_enabled(void)
147{
148 return metag_in32(SYSC_L2C_ENABLE) & SYSC_L2C_ENABLE_ENABLE_BIT;
149}
150
151/* Return whether the L2 cache prefetch is enabled */
152static inline int _meta_l2c_pf_is_enabled(void)
153{
154 return metag_in32(SYSC_L2C_ENABLE) & SYSC_L2C_ENABLE_PFENABLE_BIT;
155}
156
157
158/* Return whether the L2 cache is enabled */
159static inline int meta_l2c_is_enabled(void)
160{
161 int en;
162
163 /*
164 * There is no need to lock at the moment, as the enable bit is never
165 * intermediately changed, so we will never see an intermediate result.
166 */
167 en = _meta_l2c_is_enabled();
168
169 return en;
170}
171
172/*
173 * Ensure the L2 cache is disabled.
174 * Return whether the L2 was previously disabled.
175 */
176int meta_l2c_disable(void);
177
178/*
179 * Ensure the L2 cache is enabled.
180 * Return whether the L2 was previously enabled.
181 */
182int meta_l2c_enable(void);
183
184/* Return whether the L2 cache prefetch is enabled */
185static inline int meta_l2c_pf_is_enabled(void)
186{
187 return l2c_pfenable;
188}
189
190/*
191 * Set whether the L2 cache prefetch is enabled.
192 * Return whether the L2 prefetch was previously enabled.
193 */
194int meta_l2c_pf_enable(int pfenable);
195
196/*
197 * Flush the L2 cache.
198 * Return 1 if the L2 is disabled.
199 */
200int meta_l2c_flush(void);
201
202/*
203 * Write back all dirty cache lines in the L2 cache.
204 * Return 1 if the L2 is disabled or there isn't any writeback.
205 */
206static inline int meta_l2c_writeback(void)
207{
208 unsigned long flags;
209 int en;
210
211 /* no need to purge if it's not a writeback cache */
212 if (!meta_l2c_is_writeback())
213 return 1;
214
215 /*
216 * Purge only works if the L2 is enabled, and involves reading back to
217 * detect completion, so keep this operation atomic with other threads.
218 */
219 __global_lock1(flags);
220 en = meta_l2c_is_enabled();
221 if (likely(en)) {
222 wr_fence();
223 _meta_l2c_purge();
224 }
225 __global_unlock1(flags);
226
227 return !en;
228}
229
230#else /* CONFIG_METAG_L2C */
231
232#define meta_l2c_config() 0
233#define meta_l2c_is_present() 0
234#define meta_l2c_is_writeback() 0
235#define meta_l2c_is_unified() 0
236#define meta_l2c_size() 0
237#define meta_l2c_ways() 0
238#define meta_l2c_linesize() 0
239#define meta_l2c_revision() 0
240
241#define meta_l2c_is_enabled() 0
242#define _meta_l2c_pf_is_enabled() 0
243#define meta_l2c_pf_is_enabled() 0
244#define meta_l2c_disable() 1
245#define meta_l2c_enable() 0
246#define meta_l2c_pf_enable(X) 0
247static inline int meta_l2c_flush(void)
248{
249 return 1;
250}
251static inline int meta_l2c_writeback(void)
252{
253 return 1;
254}
255
256#endif /* CONFIG_METAG_L2C */
257
258#endif /* _METAG_L2CACHE_H */
This page took 0.316318 seconds and 5 git commands to generate.