mips: syscalls: define syscall offsets directly in <asm/unistd.h>
[linux-2.6-microblaze.git] / arch / mips / include / asm / mips-cps.h
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * Copyright (C) 2017 Imagination Technologies
4  * Author: Paul Burton <paul.burton@mips.com>
5  */
6
7 #ifndef __MIPS_ASM_MIPS_CPS_H__
8 #define __MIPS_ASM_MIPS_CPS_H__
9
10 #include <linux/io.h>
11 #include <linux/types.h>
12
13 #include <asm/mips-boards/launch.h>
14
15 extern unsigned long __cps_access_bad_size(void)
16         __compiletime_error("Bad size for CPS accessor");
17
18 #define CPS_ACCESSOR_A(unit, off, name)                                 \
19 static inline void *addr_##unit##_##name(void)                          \
20 {                                                                       \
21         return mips_##unit##_base + (off);                              \
22 }
23
24 #define CPS_ACCESSOR_R(unit, sz, name)                                  \
25 static inline uint##sz##_t read_##unit##_##name(void)                   \
26 {                                                                       \
27         uint64_t val64;                                                 \
28                                                                         \
29         switch (sz) {                                                   \
30         case 32:                                                        \
31                 return __raw_readl(addr_##unit##_##name());             \
32                                                                         \
33         case 64:                                                        \
34                 if (mips_cm_is64)                                       \
35                         return __raw_readq(addr_##unit##_##name());     \
36                                                                         \
37                 val64 = __raw_readl(addr_##unit##_##name() + 4);        \
38                 val64 <<= 32;                                           \
39                 val64 |= __raw_readl(addr_##unit##_##name());           \
40                 return val64;                                           \
41                                                                         \
42         default:                                                        \
43                 return __cps_access_bad_size();                         \
44         }                                                               \
45 }
46
47 #define CPS_ACCESSOR_W(unit, sz, name)                                  \
48 static inline void write_##unit##_##name(uint##sz##_t val)              \
49 {                                                                       \
50         switch (sz) {                                                   \
51         case 32:                                                        \
52                 __raw_writel(val, addr_##unit##_##name());              \
53                 break;                                                  \
54                                                                         \
55         case 64:                                                        \
56                 if (mips_cm_is64) {                                     \
57                         __raw_writeq(val, addr_##unit##_##name());      \
58                         break;                                          \
59                 }                                                       \
60                                                                         \
61                 __raw_writel((uint64_t)val >> 32,                       \
62                              addr_##unit##_##name() + 4);               \
63                 __raw_writel(val, addr_##unit##_##name());              \
64                 break;                                                  \
65                                                                         \
66         default:                                                        \
67                 __cps_access_bad_size();                                \
68                 break;                                                  \
69         }                                                               \
70 }
71
72 #define CPS_ACCESSOR_M(unit, sz, name)                                  \
73 static inline void change_##unit##_##name(uint##sz##_t mask,            \
74                                           uint##sz##_t val)             \
75 {                                                                       \
76         uint##sz##_t reg_val = read_##unit##_##name();                  \
77         reg_val &= ~mask;                                               \
78         reg_val |= val;                                                 \
79         write_##unit##_##name(reg_val);                                 \
80 }                                                                       \
81                                                                         \
82 static inline void set_##unit##_##name(uint##sz##_t val)                \
83 {                                                                       \
84         change_##unit##_##name(val, val);                               \
85 }                                                                       \
86                                                                         \
87 static inline void clear_##unit##_##name(uint##sz##_t val)              \
88 {                                                                       \
89         change_##unit##_##name(val, 0);                                 \
90 }
91
92 #define CPS_ACCESSOR_RO(unit, sz, off, name)                            \
93         CPS_ACCESSOR_A(unit, off, name)                                 \
94         CPS_ACCESSOR_R(unit, sz, name)
95
96 #define CPS_ACCESSOR_WO(unit, sz, off, name)                            \
97         CPS_ACCESSOR_A(unit, off, name)                                 \
98         CPS_ACCESSOR_W(unit, sz, name)
99
100 #define CPS_ACCESSOR_RW(unit, sz, off, name)                            \
101         CPS_ACCESSOR_A(unit, off, name)                                 \
102         CPS_ACCESSOR_R(unit, sz, name)                                  \
103         CPS_ACCESSOR_W(unit, sz, name)                                  \
104         CPS_ACCESSOR_M(unit, sz, name)
105
106 #include <asm/mips-cm.h>
107 #include <asm/mips-cpc.h>
108 #include <asm/mips-gic.h>
109
110 /**
111  * mips_cps_numclusters - return the number of clusters present in the system
112  *
113  * Returns the number of clusters in the system.
114  */
115 static inline unsigned int mips_cps_numclusters(void)
116 {
117         unsigned int num_clusters;
118
119         if (mips_cm_revision() < CM_REV_CM3_5)
120                 return 1;
121
122         num_clusters = read_gcr_config() & CM_GCR_CONFIG_NUM_CLUSTERS;
123         num_clusters >>= __ffs(CM_GCR_CONFIG_NUM_CLUSTERS);
124         return num_clusters;
125 }
126
127 /**
128  * mips_cps_cluster_config - return (GCR|CPC)_CONFIG from a cluster
129  * @cluster: the ID of the cluster whose config we want
130  *
131  * Read the value of GCR_CONFIG (or its CPC_CONFIG mirror) from a @cluster.
132  *
133  * Returns the value of GCR_CONFIG.
134  */
135 static inline uint64_t mips_cps_cluster_config(unsigned int cluster)
136 {
137         uint64_t config;
138
139         if (mips_cm_revision() < CM_REV_CM3_5) {
140                 /*
141                  * Prior to CM 3.5 we don't have the notion of multiple
142                  * clusters so we can trivially read the GCR_CONFIG register
143                  * within this cluster.
144                  */
145                 WARN_ON(cluster != 0);
146                 config = read_gcr_config();
147         } else {
148                 /*
149                  * From CM 3.5 onwards we read the CPC_CONFIG mirror of
150                  * GCR_CONFIG via the redirect region, since the CPC is always
151                  * powered up allowing us not to need to power up the CM.
152                  */
153                 mips_cm_lock_other(cluster, 0, 0, CM_GCR_Cx_OTHER_BLOCK_GLOBAL);
154                 config = read_cpc_redir_config();
155                 mips_cm_unlock_other();
156         }
157
158         return config;
159 }
160
161 /**
162  * mips_cps_numcores - return the number of cores present in a cluster
163  * @cluster: the ID of the cluster whose core count we want
164  *
165  * Returns the value of the PCORES field of the GCR_CONFIG register plus 1, or
166  * zero if no Coherence Manager is present.
167  */
168 static inline unsigned int mips_cps_numcores(unsigned int cluster)
169 {
170         unsigned int ncores;
171
172         if (!mips_cm_present())
173                 return 0;
174
175         /* Add one before masking to handle 0xff indicating no cores */
176         ncores = (mips_cps_cluster_config(cluster) + 1) & CM_GCR_CONFIG_PCORES;
177
178         if (IS_ENABLED(CONFIG_SOC_MT7621)) {
179                 struct cpulaunch *launch;
180
181                 /*
182                  * Ralink MT7621S SoC is single core, but the GCR_CONFIG method
183                  * always reports 2 cores. Check the second core's LAUNCH_FREADY
184                  * flag to detect if the second core is missing. This method
185                  * only works before the core has been started.
186                  */
187                 launch = (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH);
188                 launch += 2; /* MT7621 has 2 VPEs per core */
189                 if (!(launch->flags & LAUNCH_FREADY))
190                         ncores = 1;
191         }
192
193         return ncores;
194 }
195
196 /**
197  * mips_cps_numiocu - return the number of IOCUs present in a cluster
198  * @cluster: the ID of the cluster whose IOCU count we want
199  *
200  * Returns the value of the NUMIOCU field of the GCR_CONFIG register, or zero
201  * if no Coherence Manager is present.
202  */
203 static inline unsigned int mips_cps_numiocu(unsigned int cluster)
204 {
205         unsigned int num_iocu;
206
207         if (!mips_cm_present())
208                 return 0;
209
210         num_iocu = mips_cps_cluster_config(cluster) & CM_GCR_CONFIG_NUMIOCU;
211         num_iocu >>= __ffs(CM_GCR_CONFIG_NUMIOCU);
212         return num_iocu;
213 }
214
215 /**
216  * mips_cps_numvps - return the number of VPs (threads) supported by a core
217  * @cluster: the ID of the cluster containing the core we want to examine
218  * @core: the ID of the core whose VP count we want
219  *
220  * Returns the number of Virtual Processors (VPs, ie. hardware threads) that
221  * are supported by the given @core in the given @cluster. If the core or the
222  * kernel do not support hardware mutlti-threading this returns 1.
223  */
224 static inline unsigned int mips_cps_numvps(unsigned int cluster, unsigned int core)
225 {
226         unsigned int cfg;
227
228         if (!mips_cm_present())
229                 return 1;
230
231         if ((!IS_ENABLED(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt)
232                 && (!IS_ENABLED(CONFIG_CPU_MIPSR6) || !cpu_has_vp))
233                 return 1;
234
235         mips_cm_lock_other(cluster, core, 0, CM_GCR_Cx_OTHER_BLOCK_LOCAL);
236
237         if (mips_cm_revision() < CM_REV_CM3_5) {
238                 /*
239                  * Prior to CM 3.5 we can only have one cluster & don't have
240                  * CPC_Cx_CONFIG, so we read GCR_Cx_CONFIG.
241                  */
242                 cfg = read_gcr_co_config();
243         } else {
244                 /*
245                  * From CM 3.5 onwards we read CPC_Cx_CONFIG because the CPC is
246                  * always powered, which allows us to not worry about powering
247                  * up the cluster's CM here.
248                  */
249                 cfg = read_cpc_co_config();
250         }
251
252         mips_cm_unlock_other();
253
254         return (cfg + 1) & CM_GCR_Cx_CONFIG_PVPE;
255 }
256
257 #endif /* __MIPS_ASM_MIPS_CPS_H__ */