speedo-tegra30.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved.
  4. */
  5. #include <linux/bug.h>
  6. #include <linux/device.h>
  7. #include <linux/kernel.h>
  8. #include <soc/tegra/fuse.h>
  9. #include "fuse.h"
  10. #define SOC_PROCESS_CORNERS 1
  11. #define CPU_PROCESS_CORNERS 6
  12. #define FUSE_SPEEDO_CALIB_0 0x14
  13. #define FUSE_PACKAGE_INFO 0XFC
  14. #define FUSE_TEST_PROG_VER 0X28
  15. #define G_SPEEDO_BIT_MINUS1 58
  16. #define G_SPEEDO_BIT_MINUS1_R 59
  17. #define G_SPEEDO_BIT_MINUS2 60
  18. #define G_SPEEDO_BIT_MINUS2_R 61
  19. #define LP_SPEEDO_BIT_MINUS1 62
  20. #define LP_SPEEDO_BIT_MINUS1_R 63
  21. #define LP_SPEEDO_BIT_MINUS2 64
  22. #define LP_SPEEDO_BIT_MINUS2_R 65
  23. enum {
  24. THRESHOLD_INDEX_0,
  25. THRESHOLD_INDEX_1,
  26. THRESHOLD_INDEX_2,
  27. THRESHOLD_INDEX_3,
  28. THRESHOLD_INDEX_4,
  29. THRESHOLD_INDEX_5,
  30. THRESHOLD_INDEX_6,
  31. THRESHOLD_INDEX_7,
  32. THRESHOLD_INDEX_8,
  33. THRESHOLD_INDEX_9,
  34. THRESHOLD_INDEX_10,
  35. THRESHOLD_INDEX_11,
  36. THRESHOLD_INDEX_COUNT,
  37. };
  38. static const u32 __initconst soc_process_speedos[][SOC_PROCESS_CORNERS] = {
  39. {180},
  40. {170},
  41. {195},
  42. {180},
  43. {168},
  44. {192},
  45. {180},
  46. {170},
  47. {195},
  48. {180},
  49. {180},
  50. {180},
  51. };
  52. static const u32 __initconst cpu_process_speedos[][CPU_PROCESS_CORNERS] = {
  53. {306, 338, 360, 376, UINT_MAX},
  54. {295, 336, 358, 375, UINT_MAX},
  55. {325, 325, 358, 375, UINT_MAX},
  56. {325, 325, 358, 375, UINT_MAX},
  57. {292, 324, 348, 364, UINT_MAX},
  58. {324, 324, 348, 364, UINT_MAX},
  59. {324, 324, 348, 364, UINT_MAX},
  60. {295, 336, 358, 375, UINT_MAX},
  61. {358, 358, 358, 358, 397, UINT_MAX},
  62. {364, 364, 364, 364, 397, UINT_MAX},
  63. {295, 336, 358, 375, 391, UINT_MAX},
  64. {295, 336, 358, 375, 391, UINT_MAX},
  65. };
  66. static int threshold_index __initdata;
  67. static void __init fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
  68. {
  69. u32 reg;
  70. int ate_ver;
  71. int bit_minus1;
  72. int bit_minus2;
  73. reg = tegra_fuse_read_early(FUSE_SPEEDO_CALIB_0);
  74. *speedo_lp = (reg & 0xFFFF) * 4;
  75. *speedo_g = ((reg >> 16) & 0xFFFF) * 4;
  76. ate_ver = tegra_fuse_read_early(FUSE_TEST_PROG_VER);
  77. pr_debug("Tegra ATE prog ver %d.%d\n", ate_ver/10, ate_ver%10);
  78. if (ate_ver >= 26) {
  79. bit_minus1 = tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS1);
  80. bit_minus1 |= tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS1_R);
  81. bit_minus2 = tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS2);
  82. bit_minus2 |= tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS2_R);
  83. *speedo_lp |= (bit_minus1 << 1) | bit_minus2;
  84. bit_minus1 = tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS1);
  85. bit_minus1 |= tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS1_R);
  86. bit_minus2 = tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS2);
  87. bit_minus2 |= tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS2_R);
  88. *speedo_g |= (bit_minus1 << 1) | bit_minus2;
  89. } else {
  90. *speedo_lp |= 0x3;
  91. *speedo_g |= 0x3;
  92. }
  93. }
  94. static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info)
  95. {
  96. int package_id = tegra_fuse_read_early(FUSE_PACKAGE_INFO) & 0x0F;
  97. switch (sku_info->revision) {
  98. case TEGRA_REVISION_A01:
  99. sku_info->cpu_speedo_id = 0;
  100. sku_info->soc_speedo_id = 0;
  101. threshold_index = THRESHOLD_INDEX_0;
  102. break;
  103. case TEGRA_REVISION_A02:
  104. case TEGRA_REVISION_A03:
  105. switch (sku_info->sku_id) {
  106. case 0x87:
  107. case 0x82:
  108. sku_info->cpu_speedo_id = 1;
  109. sku_info->soc_speedo_id = 1;
  110. threshold_index = THRESHOLD_INDEX_1;
  111. break;
  112. case 0x81:
  113. switch (package_id) {
  114. case 1:
  115. sku_info->cpu_speedo_id = 2;
  116. sku_info->soc_speedo_id = 2;
  117. threshold_index = THRESHOLD_INDEX_2;
  118. break;
  119. case 2:
  120. sku_info->cpu_speedo_id = 4;
  121. sku_info->soc_speedo_id = 1;
  122. threshold_index = THRESHOLD_INDEX_7;
  123. break;
  124. default:
  125. pr_err("Tegra Unknown pkg %d\n", package_id);
  126. break;
  127. }
  128. break;
  129. case 0x80:
  130. switch (package_id) {
  131. case 1:
  132. sku_info->cpu_speedo_id = 5;
  133. sku_info->soc_speedo_id = 2;
  134. threshold_index = THRESHOLD_INDEX_8;
  135. break;
  136. case 2:
  137. sku_info->cpu_speedo_id = 6;
  138. sku_info->soc_speedo_id = 2;
  139. threshold_index = THRESHOLD_INDEX_9;
  140. break;
  141. default:
  142. pr_err("Tegra Unknown pkg %d\n", package_id);
  143. break;
  144. }
  145. break;
  146. case 0x83:
  147. switch (package_id) {
  148. case 1:
  149. sku_info->cpu_speedo_id = 7;
  150. sku_info->soc_speedo_id = 1;
  151. threshold_index = THRESHOLD_INDEX_10;
  152. break;
  153. case 2:
  154. sku_info->cpu_speedo_id = 3;
  155. sku_info->soc_speedo_id = 2;
  156. threshold_index = THRESHOLD_INDEX_3;
  157. break;
  158. default:
  159. pr_err("Tegra Unknown pkg %d\n", package_id);
  160. break;
  161. }
  162. break;
  163. case 0x8F:
  164. sku_info->cpu_speedo_id = 8;
  165. sku_info->soc_speedo_id = 1;
  166. threshold_index = THRESHOLD_INDEX_11;
  167. break;
  168. case 0x08:
  169. sku_info->cpu_speedo_id = 1;
  170. sku_info->soc_speedo_id = 1;
  171. threshold_index = THRESHOLD_INDEX_4;
  172. break;
  173. case 0x02:
  174. sku_info->cpu_speedo_id = 2;
  175. sku_info->soc_speedo_id = 2;
  176. threshold_index = THRESHOLD_INDEX_5;
  177. break;
  178. case 0x04:
  179. sku_info->cpu_speedo_id = 3;
  180. sku_info->soc_speedo_id = 2;
  181. threshold_index = THRESHOLD_INDEX_6;
  182. break;
  183. case 0:
  184. switch (package_id) {
  185. case 1:
  186. sku_info->cpu_speedo_id = 2;
  187. sku_info->soc_speedo_id = 2;
  188. threshold_index = THRESHOLD_INDEX_2;
  189. break;
  190. case 2:
  191. sku_info->cpu_speedo_id = 3;
  192. sku_info->soc_speedo_id = 2;
  193. threshold_index = THRESHOLD_INDEX_3;
  194. break;
  195. default:
  196. pr_err("Tegra Unknown pkg %d\n", package_id);
  197. break;
  198. }
  199. break;
  200. default:
  201. pr_warn("Tegra Unknown SKU %d\n", sku_info->sku_id);
  202. sku_info->cpu_speedo_id = 0;
  203. sku_info->soc_speedo_id = 0;
  204. threshold_index = THRESHOLD_INDEX_0;
  205. break;
  206. }
  207. break;
  208. default:
  209. pr_warn("Tegra Unknown chip rev %d\n", sku_info->revision);
  210. sku_info->cpu_speedo_id = 0;
  211. sku_info->soc_speedo_id = 0;
  212. threshold_index = THRESHOLD_INDEX_0;
  213. break;
  214. }
  215. }
  216. void __init tegra30_init_speedo_data(struct tegra_sku_info *sku_info)
  217. {
  218. u32 cpu_speedo_val;
  219. u32 soc_speedo_val;
  220. int i;
  221. BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
  222. THRESHOLD_INDEX_COUNT);
  223. BUILD_BUG_ON(ARRAY_SIZE(soc_process_speedos) !=
  224. THRESHOLD_INDEX_COUNT);
  225. rev_sku_to_speedo_ids(sku_info);
  226. fuse_speedo_calib(&cpu_speedo_val, &soc_speedo_val);
  227. pr_debug("Tegra CPU speedo value %u\n", cpu_speedo_val);
  228. pr_debug("Tegra Core speedo value %u\n", soc_speedo_val);
  229. for (i = 0; i < CPU_PROCESS_CORNERS; i++) {
  230. if (cpu_speedo_val < cpu_process_speedos[threshold_index][i])
  231. break;
  232. }
  233. sku_info->cpu_process_id = i - 1;
  234. if (sku_info->cpu_process_id == -1) {
  235. pr_warn("Tegra CPU speedo value %3d out of range",
  236. cpu_speedo_val);
  237. sku_info->cpu_process_id = 0;
  238. sku_info->cpu_speedo_id = 1;
  239. }
  240. for (i = 0; i < SOC_PROCESS_CORNERS; i++) {
  241. if (soc_speedo_val < soc_process_speedos[threshold_index][i])
  242. break;
  243. }
  244. sku_info->soc_process_id = i - 1;
  245. if (sku_info->soc_process_id == -1) {
  246. pr_warn("Tegra SoC speedo value %3d out of range",
  247. soc_speedo_val);
  248. sku_info->soc_process_id = 0;
  249. sku_info->soc_speedo_id = 1;
  250. }
  251. }