2 * Copyright (C) 2017 Imagination Technologies
3 * Author: Paul Burton <paul.burton@mips.com>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
11 #ifndef __MIPS_ASM_MIPS_CPS_H__
12 #define __MIPS_ASM_MIPS_CPS_H__
15 #include <linux/types.h>
17 extern unsigned long __cps_access_bad_size(void)
18 __compiletime_error("Bad size for CPS accessor");
20 #define CPS_ACCESSOR_A(unit, off, name) \
21 static inline void *addr_##unit##_##name(void) \
23 return mips_##unit##_base + (off); \
26 #define CPS_ACCESSOR_R(unit, sz, name) \
27 static inline uint##sz##_t read_##unit##_##name(void) \
33 return __raw_readl(addr_##unit##_##name()); \
37 return __raw_readq(addr_##unit##_##name()); \
39 val64 = __raw_readl(addr_##unit##_##name() + 4); \
41 val64 |= __raw_readl(addr_##unit##_##name()); \
45 return __cps_access_bad_size(); \
49 #define CPS_ACCESSOR_W(unit, sz, name) \
50 static inline void write_##unit##_##name(uint##sz##_t val) \
54 __raw_writel(val, addr_##unit##_##name()); \
59 __raw_writeq(val, addr_##unit##_##name()); \
63 __raw_writel((uint64_t)val >> 32, \
64 addr_##unit##_##name() + 4); \
65 __raw_writel(val, addr_##unit##_##name()); \
69 __cps_access_bad_size(); \
74 #define CPS_ACCESSOR_M(unit, sz, name) \
75 static inline void change_##unit##_##name(uint##sz##_t mask, \
78 uint##sz##_t reg_val = read_##unit##_##name(); \
81 write_##unit##_##name(reg_val); \
84 static inline void set_##unit##_##name(uint##sz##_t val) \
86 change_##unit##_##name(val, val); \
89 static inline void clear_##unit##_##name(uint##sz##_t val) \
91 change_##unit##_##name(val, 0); \
94 #define CPS_ACCESSOR_RO(unit, sz, off, name) \
95 CPS_ACCESSOR_A(unit, off, name) \
96 CPS_ACCESSOR_R(unit, sz, name)
98 #define CPS_ACCESSOR_WO(unit, sz, off, name) \
99 CPS_ACCESSOR_A(unit, off, name) \
100 CPS_ACCESSOR_W(unit, sz, name)
102 #define CPS_ACCESSOR_RW(unit, sz, off, name) \
103 CPS_ACCESSOR_A(unit, off, name) \
104 CPS_ACCESSOR_R(unit, sz, name) \
105 CPS_ACCESSOR_W(unit, sz, name) \
106 CPS_ACCESSOR_M(unit, sz, name)
108 #include <asm/mips-cm.h>
109 #include <asm/mips-cpc.h>
110 #include <asm/mips-gic.h>
113 * mips_cps_numclusters - return the number of clusters present in the system
115 * Returns the number of clusters in the system.
117 static inline unsigned int mips_cps_numclusters(void)
119 unsigned int num_clusters
;
121 if (mips_cm_revision() < CM_REV_CM3_5
)
124 num_clusters
= read_gcr_config() & CM_GCR_CONFIG_NUM_CLUSTERS
;
125 num_clusters
>>= __ffs(CM_GCR_CONFIG_NUM_CLUSTERS
);
130 * mips_cps_cluster_config - return (GCR|CPC)_CONFIG from a cluster
131 * @cluster: the ID of the cluster whose config we want
133 * Read the value of GCR_CONFIG (or its CPC_CONFIG mirror) from a @cluster.
135 * Returns the value of GCR_CONFIG.
137 static inline uint64_t mips_cps_cluster_config(unsigned int cluster
)
141 if (mips_cm_revision() < CM_REV_CM3_5
) {
143 * Prior to CM 3.5 we don't have the notion of multiple
144 * clusters so we can trivially read the GCR_CONFIG register
145 * within this cluster.
147 WARN_ON(cluster
!= 0);
148 config
= read_gcr_config();
151 * From CM 3.5 onwards we read the CPC_CONFIG mirror of
152 * GCR_CONFIG via the redirect region, since the CPC is always
153 * powered up allowing us not to need to power up the CM.
155 mips_cm_lock_other(cluster
, 0, 0, CM_GCR_Cx_OTHER_BLOCK_GLOBAL
);
156 config
= read_cpc_redir_config();
157 mips_cm_unlock_other();
164 * mips_cps_numcores - return the number of cores present in a cluster
165 * @cluster: the ID of the cluster whose core count we want
167 * Returns the value of the PCORES field of the GCR_CONFIG register plus 1, or
168 * zero if no Coherence Manager is present.
170 static inline unsigned int mips_cps_numcores(unsigned int cluster
)
172 if (!mips_cm_present())
175 /* Add one before masking to handle 0xff indicating no cores */
176 return (mips_cps_cluster_config(cluster
) + 1) & CM_GCR_CONFIG_PCORES
;
180 * mips_cps_numiocu - return the number of IOCUs present in a cluster
181 * @cluster: the ID of the cluster whose IOCU count we want
183 * Returns the value of the NUMIOCU field of the GCR_CONFIG register, or zero
184 * if no Coherence Manager is present.
186 static inline unsigned int mips_cps_numiocu(unsigned int cluster
)
188 unsigned int num_iocu
;
190 if (!mips_cm_present())
193 num_iocu
= mips_cps_cluster_config(cluster
) & CM_GCR_CONFIG_NUMIOCU
;
194 num_iocu
>>= __ffs(CM_GCR_CONFIG_NUMIOCU
);
199 * mips_cps_numvps - return the number of VPs (threads) supported by a core
200 * @cluster: the ID of the cluster containing the core we want to examine
201 * @core: the ID of the core whose VP count we want
203 * Returns the number of Virtual Processors (VPs, ie. hardware threads) that
204 * are supported by the given @core in the given @cluster. If the core or the
205 * kernel do not support hardware mutlti-threading this returns 1.
207 static inline unsigned int mips_cps_numvps(unsigned int cluster
, unsigned int core
)
211 if (!mips_cm_present())
214 if ((!IS_ENABLED(CONFIG_MIPS_MT_SMP
) || !cpu_has_mipsmt
)
215 && (!IS_ENABLED(CONFIG_CPU_MIPSR6
) || !cpu_has_vp
))
218 mips_cm_lock_other(cluster
, core
, 0, CM_GCR_Cx_OTHER_BLOCK_LOCAL
);
220 if (mips_cm_revision() < CM_REV_CM3_5
) {
222 * Prior to CM 3.5 we can only have one cluster & don't have
223 * CPC_Cx_CONFIG, so we read GCR_Cx_CONFIG.
225 cfg
= read_gcr_co_config();
228 * From CM 3.5 onwards we read CPC_Cx_CONFIG because the CPC is
229 * always powered, which allows us to not worry about powering
230 * up the cluster's CM here.
232 cfg
= read_cpc_co_config();
235 mips_cm_unlock_other();
237 return (cfg
+ 1) & CM_GCR_Cx_CONFIG_PVPE
;
240 #endif /* __MIPS_ASM_MIPS_CPS_H__ */