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