0001
0002
0003
0004
0005
0006
0007 #ifndef __MIPS_ASM_MIPS_CPS_H__
0008 #define __MIPS_ASM_MIPS_CPS_H__
0009
0010 #include <linux/bitfield.h>
0011 #include <linux/io.h>
0012 #include <linux/types.h>
0013
0014 extern unsigned long __cps_access_bad_size(void)
0015 __compiletime_error("Bad size for CPS accessor");
0016
0017 #define CPS_ACCESSOR_A(unit, off, name) \
0018 static inline void *addr_##unit##_##name(void) \
0019 { \
0020 return mips_##unit##_base + (off); \
0021 }
0022
0023 #define CPS_ACCESSOR_R(unit, sz, name) \
0024 static inline uint##sz##_t read_##unit##_##name(void) \
0025 { \
0026 uint64_t val64; \
0027 \
0028 switch (sz) { \
0029 case 32: \
0030 return __raw_readl(addr_##unit##_##name()); \
0031 \
0032 case 64: \
0033 if (mips_cm_is64) \
0034 return __raw_readq(addr_##unit##_##name()); \
0035 \
0036 val64 = __raw_readl(addr_##unit##_##name() + 4); \
0037 val64 <<= 32; \
0038 val64 |= __raw_readl(addr_##unit##_##name()); \
0039 return val64; \
0040 \
0041 default: \
0042 return __cps_access_bad_size(); \
0043 } \
0044 }
0045
0046 #define CPS_ACCESSOR_W(unit, sz, name) \
0047 static inline void write_##unit##_##name(uint##sz##_t val) \
0048 { \
0049 switch (sz) { \
0050 case 32: \
0051 __raw_writel(val, addr_##unit##_##name()); \
0052 break; \
0053 \
0054 case 64: \
0055 if (mips_cm_is64) { \
0056 __raw_writeq(val, addr_##unit##_##name()); \
0057 break; \
0058 } \
0059 \
0060 __raw_writel((uint64_t)val >> 32, \
0061 addr_##unit##_##name() + 4); \
0062 __raw_writel(val, addr_##unit##_##name()); \
0063 break; \
0064 \
0065 default: \
0066 __cps_access_bad_size(); \
0067 break; \
0068 } \
0069 }
0070
0071 #define CPS_ACCESSOR_M(unit, sz, name) \
0072 static inline void change_##unit##_##name(uint##sz##_t mask, \
0073 uint##sz##_t val) \
0074 { \
0075 uint##sz##_t reg_val = read_##unit##_##name(); \
0076 reg_val &= ~mask; \
0077 reg_val |= val; \
0078 write_##unit##_##name(reg_val); \
0079 } \
0080 \
0081 static inline void set_##unit##_##name(uint##sz##_t val) \
0082 { \
0083 change_##unit##_##name(val, val); \
0084 } \
0085 \
0086 static inline void clear_##unit##_##name(uint##sz##_t val) \
0087 { \
0088 change_##unit##_##name(val, 0); \
0089 }
0090
0091 #define CPS_ACCESSOR_RO(unit, sz, off, name) \
0092 CPS_ACCESSOR_A(unit, off, name) \
0093 CPS_ACCESSOR_R(unit, sz, name)
0094
0095 #define CPS_ACCESSOR_WO(unit, sz, off, name) \
0096 CPS_ACCESSOR_A(unit, off, name) \
0097 CPS_ACCESSOR_W(unit, sz, name)
0098
0099 #define CPS_ACCESSOR_RW(unit, sz, off, name) \
0100 CPS_ACCESSOR_A(unit, off, name) \
0101 CPS_ACCESSOR_R(unit, sz, name) \
0102 CPS_ACCESSOR_W(unit, sz, name) \
0103 CPS_ACCESSOR_M(unit, sz, name)
0104
0105 #include <asm/mips-cm.h>
0106 #include <asm/mips-cpc.h>
0107 #include <asm/mips-gic.h>
0108
0109
0110
0111
0112
0113
0114 static inline unsigned int mips_cps_numclusters(void)
0115 {
0116 if (mips_cm_revision() < CM_REV_CM3_5)
0117 return 1;
0118
0119 return FIELD_GET(CM_GCR_CONFIG_NUM_CLUSTERS, read_gcr_config());
0120 }
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 static inline uint64_t mips_cps_cluster_config(unsigned int cluster)
0131 {
0132 uint64_t config;
0133
0134 if (mips_cm_revision() < CM_REV_CM3_5) {
0135
0136
0137
0138
0139
0140 WARN_ON(cluster != 0);
0141 config = read_gcr_config();
0142 } else {
0143
0144
0145
0146
0147
0148 mips_cm_lock_other(cluster, 0, 0, CM_GCR_Cx_OTHER_BLOCK_GLOBAL);
0149 config = read_cpc_redir_config();
0150 mips_cm_unlock_other();
0151 }
0152
0153 return config;
0154 }
0155
0156
0157
0158
0159
0160
0161
0162
0163 static inline unsigned int mips_cps_numcores(unsigned int cluster)
0164 {
0165 if (!mips_cm_present())
0166 return 0;
0167
0168
0169 return FIELD_GET(CM_GCR_CONFIG_PCORES,
0170 mips_cps_cluster_config(cluster) + 1);
0171 }
0172
0173
0174
0175
0176
0177
0178
0179
0180 static inline unsigned int mips_cps_numiocu(unsigned int cluster)
0181 {
0182 if (!mips_cm_present())
0183 return 0;
0184
0185 return FIELD_GET(CM_GCR_CONFIG_NUMIOCU,
0186 mips_cps_cluster_config(cluster));
0187 }
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198 static inline unsigned int mips_cps_numvps(unsigned int cluster, unsigned int core)
0199 {
0200 unsigned int cfg;
0201
0202 if (!mips_cm_present())
0203 return 1;
0204
0205 if ((!IS_ENABLED(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt)
0206 && (!IS_ENABLED(CONFIG_CPU_MIPSR6) || !cpu_has_vp))
0207 return 1;
0208
0209 mips_cm_lock_other(cluster, core, 0, CM_GCR_Cx_OTHER_BLOCK_LOCAL);
0210
0211 if (mips_cm_revision() < CM_REV_CM3_5) {
0212
0213
0214
0215
0216 cfg = read_gcr_co_config();
0217 } else {
0218
0219
0220
0221
0222
0223 cfg = read_cpc_co_config();
0224 }
0225
0226 mips_cm_unlock_other();
0227
0228 return FIELD_GET(CM_GCR_Cx_CONFIG_PVPE, cfg + 1);
0229 }
0230
0231 #endif