mips-cps.h 6.5 KB

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