k3_j72xx_bandgap.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * TI Bandgap temperature sensor driver for J72XX SoC Family
  4. *
  5. * Copyright (C) 2021 Texas Instruments Incorporated - http://www.ti.com/
  6. */
  7. #include <linux/math.h>
  8. #include <linux/math64.h>
  9. #include <linux/module.h>
  10. #include <linux/init.h>
  11. #include <linux/kernel.h>
  12. #include <linux/pm_runtime.h>
  13. #include <linux/err.h>
  14. #include <linux/types.h>
  15. #include <linux/of_platform.h>
  16. #include <linux/io.h>
  17. #include <linux/thermal.h>
  18. #include <linux/of.h>
  19. #include <linux/delay.h>
  20. #include <linux/slab.h>
  21. #define K3_VTM_DEVINFO_PWR0_OFFSET 0x4
  22. #define K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK 0xf0
  23. #define K3_VTM_TMPSENS0_CTRL_OFFSET 0x300
  24. #define K3_VTM_MISC_CTRL_OFFSET 0xc
  25. #define K3_VTM_TMPSENS_STAT_OFFSET 0x8
  26. #define K3_VTM_ANYMAXT_OUTRG_ALERT_EN 0x1
  27. #define K3_VTM_MISC_CTRL2_OFFSET 0x10
  28. #define K3_VTM_TS_STAT_DTEMP_MASK 0x3ff
  29. #define K3_VTM_MAX_NUM_TS 8
  30. #define K3_VTM_TMPSENS_CTRL_SOC BIT(5)
  31. #define K3_VTM_TMPSENS_CTRL_CLRZ BIT(6)
  32. #define K3_VTM_TMPSENS_CTRL_CLKON_REQ BIT(7)
  33. #define K3_VTM_TMPSENS_CTRL_MAXT_OUTRG_EN BIT(11)
  34. #define K3_VTM_CORRECTION_TEMP_CNT 3
  35. #define MINUS40CREF 5
  36. #define PLUS30CREF 253
  37. #define PLUS125CREF 730
  38. #define PLUS150CREF 940
  39. #define TABLE_SIZE 1024
  40. #define MAX_TEMP 123000
  41. #define COOL_DOWN_TEMP 105000
  42. #define FACTORS_REDUCTION 13
  43. static int *derived_table;
  44. static int compute_value(int index, const s64 *factors, int nr_factors,
  45. int reduction)
  46. {
  47. s64 value = 0;
  48. int i;
  49. for (i = 0; i < nr_factors; i++)
  50. value += factors[i] * int_pow(index, i);
  51. return (int)div64_s64(value, int_pow(10, reduction));
  52. }
  53. static void init_table(int factors_size, int *table, const s64 *factors)
  54. {
  55. int i;
  56. for (i = 0; i < TABLE_SIZE; i++)
  57. table[i] = compute_value(i, factors, factors_size,
  58. FACTORS_REDUCTION);
  59. }
  60. /**
  61. * struct err_values - structure containing error/reference values
  62. * @refs: reference error values for -40C, 30C, 125C & 150C
  63. * @errs: Actual error values for -40C, 30C, 125C & 150C read from the efuse
  64. */
  65. struct err_values {
  66. int refs[4];
  67. int errs[4];
  68. };
  69. static void create_table_segments(struct err_values *err_vals, int seg,
  70. int *ref_table)
  71. {
  72. int m = 0, c, num, den, i, err, idx1, idx2, err1, err2, ref1, ref2;
  73. if (seg == 0)
  74. idx1 = 0;
  75. else
  76. idx1 = err_vals->refs[seg];
  77. idx2 = err_vals->refs[seg + 1];
  78. err1 = err_vals->errs[seg];
  79. err2 = err_vals->errs[seg + 1];
  80. ref1 = err_vals->refs[seg];
  81. ref2 = err_vals->refs[seg + 1];
  82. /*
  83. * Calculate the slope with adc values read from the register
  84. * as the y-axis param and err in adc value as x-axis param
  85. */
  86. num = ref2 - ref1;
  87. den = err2 - err1;
  88. if (den)
  89. m = num / den;
  90. c = ref2 - m * err2;
  91. /*
  92. * Take care of divide by zero error if error values are same
  93. * Or when the slope is 0
  94. */
  95. if (den != 0 && m != 0) {
  96. for (i = idx1; i <= idx2; i++) {
  97. err = (i - c) / m;
  98. if (((i + err) < 0) || ((i + err) >= TABLE_SIZE))
  99. continue;
  100. derived_table[i] = ref_table[i + err];
  101. }
  102. } else { /* Constant error take care of divide by zero */
  103. for (i = idx1; i <= idx2; i++) {
  104. if (((i + err1) < 0) || ((i + err1) >= TABLE_SIZE))
  105. continue;
  106. derived_table[i] = ref_table[i + err1];
  107. }
  108. }
  109. }
  110. static int prep_lookup_table(struct err_values *err_vals, int *ref_table)
  111. {
  112. int inc, i, seg;
  113. /*
  114. * Fill up the lookup table under 3 segments
  115. * region -40C to +30C
  116. * region +30C to +125C
  117. * region +125C to +150C
  118. */
  119. for (seg = 0; seg < 3; seg++)
  120. create_table_segments(err_vals, seg, ref_table);
  121. /* Get to the first valid temperature */
  122. i = 0;
  123. while (!derived_table[i])
  124. i++;
  125. /*
  126. * Get to the last zero index and back fill the temperature for
  127. * sake of continuity
  128. */
  129. if (i) {
  130. /* 300 milli celsius steps */
  131. while (i--)
  132. derived_table[i] = derived_table[i + 1] - 300;
  133. }
  134. /*
  135. * Fill the last trailing 0s which are unfilled with increments of
  136. * 100 milli celsius till 1023 code
  137. */
  138. i = TABLE_SIZE - 1;
  139. while (!derived_table[i])
  140. i--;
  141. i++;
  142. inc = 1;
  143. while (i < TABLE_SIZE) {
  144. derived_table[i] = derived_table[i - 1] + inc * 100;
  145. i++;
  146. }
  147. return 0;
  148. }
  149. struct k3_thermal_data;
  150. struct k3_j72xx_bandgap {
  151. struct device *dev;
  152. void __iomem *base;
  153. void __iomem *cfg2_base;
  154. void __iomem *fuse_base;
  155. struct k3_thermal_data *ts_data[K3_VTM_MAX_NUM_TS];
  156. };
  157. /* common data structures */
  158. struct k3_thermal_data {
  159. struct k3_j72xx_bandgap *bgp;
  160. u32 ctrl_offset;
  161. u32 stat_offset;
  162. };
  163. static int two_cmp(int tmp, int mask)
  164. {
  165. tmp = ~(tmp);
  166. tmp &= mask;
  167. tmp += 1;
  168. /* Return negative value */
  169. return (0 - tmp);
  170. }
  171. static unsigned int vtm_get_best_value(unsigned int s0, unsigned int s1,
  172. unsigned int s2)
  173. {
  174. int d01 = abs(s0 - s1);
  175. int d02 = abs(s0 - s2);
  176. int d12 = abs(s1 - s2);
  177. if (d01 <= d02 && d01 <= d12)
  178. return (s0 + s1) / 2;
  179. if (d02 <= d01 && d02 <= d12)
  180. return (s0 + s2) / 2;
  181. return (s1 + s2) / 2;
  182. }
  183. static inline int k3_bgp_read_temp(struct k3_thermal_data *devdata,
  184. int *temp)
  185. {
  186. struct k3_j72xx_bandgap *bgp;
  187. unsigned int dtemp, s0, s1, s2;
  188. bgp = devdata->bgp;
  189. /*
  190. * Errata is applicable for am654 pg 1.0 silicon/J7ES. There
  191. * is a variation of the order for certain degree centigrade on AM654.
  192. * Work around that by getting the average of two closest
  193. * readings out of three readings everytime we want to
  194. * report temperatures.
  195. *
  196. * Errata workaround.
  197. */
  198. s0 = readl(bgp->base + devdata->stat_offset) &
  199. K3_VTM_TS_STAT_DTEMP_MASK;
  200. s1 = readl(bgp->base + devdata->stat_offset) &
  201. K3_VTM_TS_STAT_DTEMP_MASK;
  202. s2 = readl(bgp->base + devdata->stat_offset) &
  203. K3_VTM_TS_STAT_DTEMP_MASK;
  204. dtemp = vtm_get_best_value(s0, s1, s2);
  205. if (dtemp < 0 || dtemp >= TABLE_SIZE)
  206. return -EINVAL;
  207. *temp = derived_table[dtemp];
  208. return 0;
  209. }
  210. /* Get temperature callback function for thermal zone */
  211. static int k3_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
  212. {
  213. struct k3_thermal_data *data = tz->devdata;
  214. int ret = 0;
  215. ret = k3_bgp_read_temp(data, temp);
  216. if (ret)
  217. return ret;
  218. return ret;
  219. }
  220. static const struct thermal_zone_device_ops k3_of_thermal_ops = {
  221. .get_temp = k3_thermal_get_temp,
  222. };
  223. static int k3_j72xx_bandgap_temp_to_adc_code(int temp)
  224. {
  225. int low = 0, high = TABLE_SIZE - 1, mid;
  226. if (temp > 160000 || temp < -50000)
  227. return -EINVAL;
  228. /* Binary search to find the adc code */
  229. while (low < (high - 1)) {
  230. mid = (low + high) / 2;
  231. if (temp <= derived_table[mid])
  232. high = mid;
  233. else
  234. low = mid;
  235. }
  236. return mid;
  237. }
  238. static void get_efuse_values(int id, struct k3_thermal_data *data, int *err,
  239. struct k3_j72xx_bandgap *bgp)
  240. {
  241. int i, tmp, pow;
  242. int ct_offsets[5][K3_VTM_CORRECTION_TEMP_CNT] = {
  243. { 0x0, 0x8, 0x4 },
  244. { 0x0, 0x8, 0x4 },
  245. { 0x0, -1, 0x4 },
  246. { 0x0, 0xC, -1 },
  247. { 0x0, 0xc, 0x8 }
  248. };
  249. int ct_bm[5][K3_VTM_CORRECTION_TEMP_CNT] = {
  250. { 0x3f, 0x1fe000, 0x1ff },
  251. { 0xfc0, 0x1fe000, 0x3fe00 },
  252. { 0x3f000, 0x7f800000, 0x7fc0000 },
  253. { 0xfc0000, 0x1fe0, 0x1f800000 },
  254. { 0x3f000000, 0x1fe000, 0x1ff0 }
  255. };
  256. for (i = 0; i < 3; i++) {
  257. /* Extract the offset value using bit-mask */
  258. if (ct_offsets[id][i] == -1 && i == 1) {
  259. /* 25C offset Case of Sensor 2 split between 2 regs */
  260. tmp = (readl(bgp->fuse_base + 0x8) & 0xE0000000) >> (29);
  261. tmp |= ((readl(bgp->fuse_base + 0xC) & 0x1F) << 3);
  262. pow = tmp & 0x80;
  263. } else if (ct_offsets[id][i] == -1 && i == 2) {
  264. /* 125C Case of Sensor 3 split between 2 regs */
  265. tmp = (readl(bgp->fuse_base + 0x4) & 0xF8000000) >> (27);
  266. tmp |= ((readl(bgp->fuse_base + 0x8) & 0xF) << 5);
  267. pow = tmp & 0x100;
  268. } else {
  269. tmp = readl(bgp->fuse_base + ct_offsets[id][i]);
  270. tmp &= ct_bm[id][i];
  271. tmp = tmp >> __ffs(ct_bm[id][i]);
  272. /* Obtain the sign bit pow*/
  273. pow = ct_bm[id][i] >> __ffs(ct_bm[id][i]);
  274. pow += 1;
  275. pow /= 2;
  276. }
  277. /* Check for negative value */
  278. if (tmp & pow) {
  279. /* 2's complement value */
  280. tmp = two_cmp(tmp, ct_bm[id][i] >> __ffs(ct_bm[id][i]));
  281. }
  282. err[i] = tmp;
  283. }
  284. /* Err value for 150C is set to 0 */
  285. err[i] = 0;
  286. }
  287. static void print_look_up_table(struct device *dev, int *ref_table)
  288. {
  289. int i;
  290. dev_dbg(dev, "The contents of derived array\n");
  291. dev_dbg(dev, "Code Temperature\n");
  292. for (i = 0; i < TABLE_SIZE; i++)
  293. dev_dbg(dev, "%d %d %d\n", i, derived_table[i], ref_table[i]);
  294. }
  295. struct k3_j72xx_bandgap_data {
  296. unsigned int has_errata_i2128;
  297. };
  298. static int k3_j72xx_bandgap_probe(struct platform_device *pdev)
  299. {
  300. int ret = 0, cnt, val, id;
  301. int high_max, low_temp;
  302. struct resource *res;
  303. struct device *dev = &pdev->dev;
  304. struct k3_j72xx_bandgap *bgp;
  305. struct k3_thermal_data *data;
  306. int workaround_needed = 0;
  307. const struct k3_j72xx_bandgap_data *driver_data;
  308. struct thermal_zone_device *ti_thermal;
  309. int *ref_table;
  310. struct err_values err_vals;
  311. const s64 golden_factors[] = {
  312. -490019999999999936,
  313. 3251200000000000,
  314. -1705800000000,
  315. 603730000,
  316. -92627,
  317. };
  318. const s64 pvt_wa_factors[] = {
  319. -415230000000000000,
  320. 3126600000000000,
  321. -1157800000000,
  322. };
  323. bgp = devm_kzalloc(&pdev->dev, sizeof(*bgp), GFP_KERNEL);
  324. if (!bgp)
  325. return -ENOMEM;
  326. bgp->dev = dev;
  327. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  328. bgp->base = devm_ioremap_resource(dev, res);
  329. if (IS_ERR(bgp->base))
  330. return PTR_ERR(bgp->base);
  331. res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  332. bgp->cfg2_base = devm_ioremap_resource(dev, res);
  333. if (IS_ERR(bgp->cfg2_base))
  334. return PTR_ERR(bgp->cfg2_base);
  335. res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
  336. bgp->fuse_base = devm_ioremap_resource(dev, res);
  337. if (IS_ERR(bgp->fuse_base))
  338. return PTR_ERR(bgp->fuse_base);
  339. driver_data = of_device_get_match_data(dev);
  340. if (driver_data)
  341. workaround_needed = driver_data->has_errata_i2128;
  342. pm_runtime_enable(dev);
  343. ret = pm_runtime_get_sync(dev);
  344. if (ret < 0) {
  345. pm_runtime_put_noidle(dev);
  346. pm_runtime_disable(dev);
  347. return ret;
  348. }
  349. /* Get the sensor count in the VTM */
  350. val = readl(bgp->base + K3_VTM_DEVINFO_PWR0_OFFSET);
  351. cnt = val & K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK;
  352. cnt >>= __ffs(K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK);
  353. data = devm_kcalloc(bgp->dev, cnt, sizeof(*data), GFP_KERNEL);
  354. if (!data) {
  355. ret = -ENOMEM;
  356. goto err_alloc;
  357. }
  358. ref_table = kzalloc(sizeof(*ref_table) * TABLE_SIZE, GFP_KERNEL);
  359. if (!ref_table) {
  360. ret = -ENOMEM;
  361. goto err_alloc;
  362. }
  363. derived_table = devm_kzalloc(bgp->dev, sizeof(*derived_table) * TABLE_SIZE,
  364. GFP_KERNEL);
  365. if (!derived_table) {
  366. ret = -ENOMEM;
  367. goto err_free_ref_table;
  368. }
  369. /* Workaround not needed if bit30/bit31 is set even for J721e */
  370. if (workaround_needed && (readl(bgp->fuse_base + 0x0) & 0xc0000000) == 0xc0000000)
  371. workaround_needed = false;
  372. dev_dbg(bgp->dev, "Work around %sneeded\n",
  373. workaround_needed ? "" : "not ");
  374. if (!workaround_needed)
  375. init_table(5, ref_table, golden_factors);
  376. else
  377. init_table(3, ref_table, pvt_wa_factors);
  378. /* Register the thermal sensors */
  379. for (id = 0; id < cnt; id++) {
  380. data[id].bgp = bgp;
  381. data[id].ctrl_offset = K3_VTM_TMPSENS0_CTRL_OFFSET + id * 0x20;
  382. data[id].stat_offset = data[id].ctrl_offset +
  383. K3_VTM_TMPSENS_STAT_OFFSET;
  384. if (workaround_needed) {
  385. /* ref adc values for -40C, 30C & 125C respectively */
  386. err_vals.refs[0] = MINUS40CREF;
  387. err_vals.refs[1] = PLUS30CREF;
  388. err_vals.refs[2] = PLUS125CREF;
  389. err_vals.refs[3] = PLUS150CREF;
  390. get_efuse_values(id, &data[id], err_vals.errs, bgp);
  391. }
  392. if (id == 0 && workaround_needed)
  393. prep_lookup_table(&err_vals, ref_table);
  394. else if (id == 0 && !workaround_needed)
  395. memcpy(derived_table, ref_table, TABLE_SIZE * 4);
  396. val = readl(data[id].bgp->cfg2_base + data[id].ctrl_offset);
  397. val |= (K3_VTM_TMPSENS_CTRL_MAXT_OUTRG_EN |
  398. K3_VTM_TMPSENS_CTRL_SOC |
  399. K3_VTM_TMPSENS_CTRL_CLRZ | BIT(4));
  400. writel(val, data[id].bgp->cfg2_base + data[id].ctrl_offset);
  401. bgp->ts_data[id] = &data[id];
  402. ti_thermal = devm_thermal_of_zone_register(bgp->dev, id, &data[id],
  403. &k3_of_thermal_ops);
  404. if (IS_ERR(ti_thermal)) {
  405. dev_err(bgp->dev, "thermal zone device is NULL\n");
  406. ret = PTR_ERR(ti_thermal);
  407. goto err_free_ref_table;
  408. }
  409. }
  410. /*
  411. * Program TSHUT thresholds
  412. * Step 1: set the thresholds to ~123C and 105C WKUP_VTM_MISC_CTRL2
  413. * Step 2: WKUP_VTM_TMPSENS_CTRL_j set the MAXT_OUTRG_EN bit
  414. * This is already taken care as per of init
  415. * Step 3: WKUP_VTM_MISC_CTRL set the ANYMAXT_OUTRG_ALERT_EN bit
  416. */
  417. high_max = k3_j72xx_bandgap_temp_to_adc_code(MAX_TEMP);
  418. low_temp = k3_j72xx_bandgap_temp_to_adc_code(COOL_DOWN_TEMP);
  419. writel((low_temp << 16) | high_max, data[0].bgp->cfg2_base +
  420. K3_VTM_MISC_CTRL2_OFFSET);
  421. mdelay(100);
  422. writel(K3_VTM_ANYMAXT_OUTRG_ALERT_EN, data[0].bgp->cfg2_base +
  423. K3_VTM_MISC_CTRL_OFFSET);
  424. platform_set_drvdata(pdev, bgp);
  425. print_look_up_table(dev, ref_table);
  426. /*
  427. * Now that the derived_table has the appropriate look up values
  428. * Free up the ref_table
  429. */
  430. kfree(ref_table);
  431. return 0;
  432. err_free_ref_table:
  433. kfree(ref_table);
  434. err_alloc:
  435. pm_runtime_put_sync(&pdev->dev);
  436. pm_runtime_disable(&pdev->dev);
  437. return ret;
  438. }
  439. static int k3_j72xx_bandgap_remove(struct platform_device *pdev)
  440. {
  441. pm_runtime_put_sync(&pdev->dev);
  442. pm_runtime_disable(&pdev->dev);
  443. return 0;
  444. }
  445. static const struct k3_j72xx_bandgap_data k3_j72xx_bandgap_j721e_data = {
  446. .has_errata_i2128 = 1,
  447. };
  448. static const struct k3_j72xx_bandgap_data k3_j72xx_bandgap_j7200_data = {
  449. .has_errata_i2128 = 0,
  450. };
  451. static const struct of_device_id of_k3_j72xx_bandgap_match[] = {
  452. {
  453. .compatible = "ti,j721e-vtm",
  454. .data = &k3_j72xx_bandgap_j721e_data,
  455. },
  456. {
  457. .compatible = "ti,j7200-vtm",
  458. .data = &k3_j72xx_bandgap_j7200_data,
  459. },
  460. { /* sentinel */ },
  461. };
  462. MODULE_DEVICE_TABLE(of, of_k3_j72xx_bandgap_match);
  463. static struct platform_driver k3_j72xx_bandgap_sensor_driver = {
  464. .probe = k3_j72xx_bandgap_probe,
  465. .remove = k3_j72xx_bandgap_remove,
  466. .driver = {
  467. .name = "k3-j72xx-soc-thermal",
  468. .of_match_table = of_k3_j72xx_bandgap_match,
  469. },
  470. };
  471. module_platform_driver(k3_j72xx_bandgap_sensor_driver);
  472. MODULE_DESCRIPTION("K3 bandgap temperature sensor driver");
  473. MODULE_LICENSE("GPL");
  474. MODULE_AUTHOR("J Keerthy <[email protected]>");