~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/mips/include/asm/mips-cps.h

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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/bitfield.h>
 11 #include <linux/cpumask.h>
 12 #include <linux/io.h>
 13 #include <linux/types.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         if (mips_cm_revision() < CM_REV_CM3_5)
118                 return 1;
119 
120         return FIELD_GET(CM_GCR_CONFIG_NUM_CLUSTERS, read_gcr_config());
121 }
122 
123 /**
124  * mips_cps_cluster_config - return (GCR|CPC)_CONFIG from a cluster
125  * @cluster: the ID of the cluster whose config we want
126  *
127  * Read the value of GCR_CONFIG (or its CPC_CONFIG mirror) from a @cluster.
128  *
129  * Returns the value of GCR_CONFIG.
130  */
131 static inline uint64_t mips_cps_cluster_config(unsigned int cluster)
132 {
133         uint64_t config;
134 
135         if (mips_cm_revision() < CM_REV_CM3_5) {
136                 /*
137                  * Prior to CM 3.5 we don't have the notion of multiple
138                  * clusters so we can trivially read the GCR_CONFIG register
139                  * within this cluster.
140                  */
141                 WARN_ON(cluster != 0);
142                 config = read_gcr_config();
143         } else {
144                 /*
145                  * From CM 3.5 onwards we read the CPC_CONFIG mirror of
146                  * GCR_CONFIG via the redirect region, since the CPC is always
147                  * powered up allowing us not to need to power up the CM.
148                  */
149                 mips_cm_lock_other(cluster, 0, 0, CM_GCR_Cx_OTHER_BLOCK_GLOBAL);
150                 config = read_cpc_redir_config();
151                 mips_cm_unlock_other();
152         }
153 
154         return config;
155 }
156 
157 /**
158  * mips_cps_numcores - return the number of cores present in a cluster
159  * @cluster: the ID of the cluster whose core count we want
160  *
161  * Returns the value of the PCORES field of the GCR_CONFIG register plus 1, or
162  * zero if no Coherence Manager is present.
163  */
164 static inline unsigned int mips_cps_numcores(unsigned int cluster)
165 {
166         if (!mips_cm_present())
167                 return 0;
168 
169         /* Add one before masking to handle 0xff indicating no cores */
170         return FIELD_GET(CM_GCR_CONFIG_PCORES,
171                          mips_cps_cluster_config(cluster) + 1);
172 }
173 
174 /**
175  * mips_cps_numiocu - return the number of IOCUs present in a cluster
176  * @cluster: the ID of the cluster whose IOCU count we want
177  *
178  * Returns the value of the NUMIOCU field of the GCR_CONFIG register, or zero
179  * if no Coherence Manager is present.
180  */
181 static inline unsigned int mips_cps_numiocu(unsigned int cluster)
182 {
183         if (!mips_cm_present())
184                 return 0;
185 
186         return FIELD_GET(CM_GCR_CONFIG_NUMIOCU,
187                          mips_cps_cluster_config(cluster));
188 }
189 
190 /**
191  * mips_cps_numvps - return the number of VPs (threads) supported by a core
192  * @cluster: the ID of the cluster containing the core we want to examine
193  * @core: the ID of the core whose VP count we want
194  *
195  * Returns the number of Virtual Processors (VPs, ie. hardware threads) that
196  * are supported by the given @core in the given @cluster. If the core or the
197  * kernel do not support hardware mutlti-threading this returns 1.
198  */
199 static inline unsigned int mips_cps_numvps(unsigned int cluster, unsigned int core)
200 {
201         unsigned int cfg;
202 
203         if (!mips_cm_present())
204                 return 1;
205 
206         if ((!IS_ENABLED(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt)
207                 && (!IS_ENABLED(CONFIG_CPU_MIPSR6) || !cpu_has_vp))
208                 return 1;
209 
210         mips_cm_lock_other(cluster, core, 0, CM_GCR_Cx_OTHER_BLOCK_LOCAL);
211 
212         if (mips_cm_revision() < CM_REV_CM3_5) {
213                 /*
214                  * Prior to CM 3.5 we can only have one cluster & don't have
215                  * CPC_Cx_CONFIG, so we read GCR_Cx_CONFIG.
216                  */
217                 cfg = read_gcr_co_config();
218         } else {
219                 /*
220                  * From CM 3.5 onwards we read CPC_Cx_CONFIG because the CPC is
221                  * always powered, which allows us to not worry about powering
222                  * up the cluster's CM here.
223                  */
224                 cfg = read_cpc_co_config();
225         }
226 
227         mips_cm_unlock_other();
228 
229         return FIELD_GET(CM_GCR_Cx_CONFIG_PVPE, cfg + 1);
230 }
231 
232 /**
233  * mips_cps_multicluster_cpus() - Detect whether CPUs are in multiple clusters
234  *
235  * Determine whether the system includes CPUs in multiple clusters - ie.
236  * whether we can treat the system as single or multi-cluster as far as CPUs
237  * are concerned. Note that this is slightly different to simply checking
238  * whether multiple clusters are present - it is possible for there to be
239  * clusters which contain no CPUs, which this function will effectively ignore.
240  *
241  * Returns true if CPUs are spread across multiple clusters, else false.
242  */
243 static inline bool mips_cps_multicluster_cpus(void)
244 {
245         unsigned int first_cl, last_cl;
246 
247         /*
248          * CPUs are numbered sequentially by cluster - ie. CPUs 0..X will be in
249          * cluster 0, CPUs X+1..Y in cluster 1, CPUs Y+1..Z in cluster 2 etc.
250          *
251          * Thus we can detect multiple clusters trivially by checking whether
252          * the first & last CPUs belong to the same cluster.
253          */
254         first_cl = cpu_cluster(&boot_cpu_data);
255         last_cl = cpu_cluster(&cpu_data[nr_cpu_ids - 1]);
256         return first_cl != last_cl;
257 }
258 
259 /**
260  * mips_cps_first_online_in_cluster() - Detect if CPU is first online in cluster
261  *
262  * Determine whether the local CPU is the first to be brought online in its
263  * cluster - that is, whether there are any other online CPUs in the local
264  * cluster.
265  *
266  * Returns true if this CPU is first online, else false.
267  */
268 extern unsigned int mips_cps_first_online_in_cluster(void);
269 
270 #endif /* __MIPS_ASM_MIPS_CPS_H__ */
271 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php