Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  * Copyright (C) 2017 Imagination Technologies
0004  * Author: Paul Burton <paul.burton@mips.com>
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  * mips_cps_numclusters - return the number of clusters present in the system
0111  *
0112  * Returns the number of clusters in the system.
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  * mips_cps_cluster_config - return (GCR|CPC)_CONFIG from a cluster
0124  * @cluster: the ID of the cluster whose config we want
0125  *
0126  * Read the value of GCR_CONFIG (or its CPC_CONFIG mirror) from a @cluster.
0127  *
0128  * Returns the value of GCR_CONFIG.
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          * Prior to CM 3.5 we don't have the notion of multiple
0137          * clusters so we can trivially read the GCR_CONFIG register
0138          * within this cluster.
0139          */
0140         WARN_ON(cluster != 0);
0141         config = read_gcr_config();
0142     } else {
0143         /*
0144          * From CM 3.5 onwards we read the CPC_CONFIG mirror of
0145          * GCR_CONFIG via the redirect region, since the CPC is always
0146          * powered up allowing us not to need to power up the CM.
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  * mips_cps_numcores - return the number of cores present in a cluster
0158  * @cluster: the ID of the cluster whose core count we want
0159  *
0160  * Returns the value of the PCORES field of the GCR_CONFIG register plus 1, or
0161  * zero if no Coherence Manager is present.
0162  */
0163 static inline unsigned int mips_cps_numcores(unsigned int cluster)
0164 {
0165     if (!mips_cm_present())
0166         return 0;
0167 
0168     /* Add one before masking to handle 0xff indicating no cores */
0169     return FIELD_GET(CM_GCR_CONFIG_PCORES,
0170              mips_cps_cluster_config(cluster) + 1);
0171 }
0172 
0173 /**
0174  * mips_cps_numiocu - return the number of IOCUs present in a cluster
0175  * @cluster: the ID of the cluster whose IOCU count we want
0176  *
0177  * Returns the value of the NUMIOCU field of the GCR_CONFIG register, or zero
0178  * if no Coherence Manager is present.
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  * mips_cps_numvps - return the number of VPs (threads) supported by a core
0191  * @cluster: the ID of the cluster containing the core we want to examine
0192  * @core: the ID of the core whose VP count we want
0193  *
0194  * Returns the number of Virtual Processors (VPs, ie. hardware threads) that
0195  * are supported by the given @core in the given @cluster. If the core or the
0196  * kernel do not support hardware mutlti-threading this returns 1.
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          * Prior to CM 3.5 we can only have one cluster & don't have
0214          * CPC_Cx_CONFIG, so we read GCR_Cx_CONFIG.
0215          */
0216         cfg = read_gcr_co_config();
0217     } else {
0218         /*
0219          * From CM 3.5 onwards we read CPC_Cx_CONFIG because the CPC is
0220          * always powered, which allows us to not worry about powering
0221          * up the cluster's CM here.
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 /* __MIPS_ASM_MIPS_CPS_H__ */