root/arch/mips/include/asm/mips-cps.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. mips_cps_numclusters
  2. mips_cps_cluster_config
  3. mips_cps_numcores
  4. mips_cps_numiocu
  5. mips_cps_numvps

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

/* [<][>][^][v][top][bottom][index][help] */