pm8xxx-adc-scale.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  1. /*
  2. * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 and
  6. * only version 2 as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. */
  14. #include <linux/kernel.h>
  15. #include <linux/err.h>
  16. #include <linux/module.h>
  17. #include <linux/mfd/pm8xxx/pm8xxx-adc.h>
  18. #define KELVINMIL_DEGMIL 273160
  19. /* Units for temperature below (on x axis) is in 0.1DegC as
  20. required by the battery driver. Note the resolution used
  21. here to compute the table was done for DegC to milli-volts.
  22. In consideration to limit the size of the table for the given
  23. temperature range below, the result is linearly interpolated
  24. and provided to the battery driver in the units desired for
  25. their framework which is 0.1DegC. True resolution of 0.1DegC
  26. will result in the below table size to increase by 10 times */
  27. static const struct pm8xxx_adc_map_pt adcmap_btm_threshold[] = {
  28. {-300, 1642},
  29. {-200, 1544},
  30. {-100, 1414},
  31. {0, 1260},
  32. {10, 1244},
  33. {20, 1228},
  34. {30, 1212},
  35. {40, 1195},
  36. {50, 1179},
  37. {60, 1162},
  38. {70, 1146},
  39. {80, 1129},
  40. {90, 1113},
  41. {100, 1097},
  42. {110, 1080},
  43. {120, 1064},
  44. {130, 1048},
  45. {140, 1032},
  46. {150, 1016},
  47. {160, 1000},
  48. {170, 985},
  49. {180, 969},
  50. {190, 954},
  51. {200, 939},
  52. {210, 924},
  53. {220, 909},
  54. {230, 894},
  55. {240, 880},
  56. {250, 866},
  57. {260, 852},
  58. {270, 838},
  59. {280, 824},
  60. {290, 811},
  61. {300, 798},
  62. {310, 785},
  63. {320, 773},
  64. {330, 760},
  65. {340, 748},
  66. {350, 736},
  67. {360, 725},
  68. {370, 713},
  69. {380, 702},
  70. {390, 691},
  71. {400, 681},
  72. {410, 670},
  73. {420, 660},
  74. {430, 650},
  75. {440, 640},
  76. {450, 631},
  77. {460, 622},
  78. {470, 613},
  79. {480, 604},
  80. {490, 595},
  81. {500, 587},
  82. {510, 579},
  83. {520, 571},
  84. {530, 563},
  85. {540, 556},
  86. {550, 548},
  87. {560, 541},
  88. {570, 534},
  89. {580, 527},
  90. {590, 521},
  91. {600, 514},
  92. {610, 508},
  93. {620, 502},
  94. {630, 496},
  95. {640, 490},
  96. {650, 485},
  97. {660, 281},
  98. {670, 274},
  99. {680, 267},
  100. {690, 260},
  101. {700, 254},
  102. {710, 247},
  103. {720, 241},
  104. {730, 235},
  105. {740, 229},
  106. {750, 224},
  107. {760, 218},
  108. {770, 213},
  109. {780, 208},
  110. {790, 203}
  111. };
  112. static const struct pm8xxx_adc_map_pt adcmap_pa_therm[] = {
  113. {1731, -30},
  114. {1726, -29},
  115. {1721, -28},
  116. {1715, -27},
  117. {1710, -26},
  118. {1703, -25},
  119. {1697, -24},
  120. {1690, -23},
  121. {1683, -22},
  122. {1675, -21},
  123. {1667, -20},
  124. {1659, -19},
  125. {1650, -18},
  126. {1641, -17},
  127. {1632, -16},
  128. {1622, -15},
  129. {1611, -14},
  130. {1600, -13},
  131. {1589, -12},
  132. {1577, -11},
  133. {1565, -10},
  134. {1552, -9},
  135. {1539, -8},
  136. {1525, -7},
  137. {1511, -6},
  138. {1496, -5},
  139. {1481, -4},
  140. {1465, -3},
  141. {1449, -2},
  142. {1432, -1},
  143. {1415, 0},
  144. {1398, 1},
  145. {1380, 2},
  146. {1362, 3},
  147. {1343, 4},
  148. {1324, 5},
  149. {1305, 6},
  150. {1285, 7},
  151. {1265, 8},
  152. {1245, 9},
  153. {1224, 10},
  154. {1203, 11},
  155. {1182, 12},
  156. {1161, 13},
  157. {1139, 14},
  158. {1118, 15},
  159. {1096, 16},
  160. {1074, 17},
  161. {1052, 18},
  162. {1030, 19},
  163. {1008, 20},
  164. {986, 21},
  165. {964, 22},
  166. {943, 23},
  167. {921, 24},
  168. {899, 25},
  169. {878, 26},
  170. {857, 27},
  171. {836, 28},
  172. {815, 29},
  173. {794, 30},
  174. {774, 31},
  175. {754, 32},
  176. {734, 33},
  177. {714, 34},
  178. {695, 35},
  179. {676, 36},
  180. {657, 37},
  181. {639, 38},
  182. {621, 39},
  183. {604, 40},
  184. {586, 41},
  185. {570, 42},
  186. {553, 43},
  187. {537, 44},
  188. {521, 45},
  189. {506, 46},
  190. {491, 47},
  191. {476, 48},
  192. {462, 49},
  193. {448, 50},
  194. {435, 51},
  195. {421, 52},
  196. {409, 53},
  197. {396, 54},
  198. {384, 55},
  199. {372, 56},
  200. {361, 57},
  201. {350, 58},
  202. {339, 59},
  203. {329, 60},
  204. {318, 61},
  205. {309, 62},
  206. {299, 63},
  207. {290, 64},
  208. {281, 65},
  209. {272, 66},
  210. {264, 67},
  211. {256, 68},
  212. {248, 69},
  213. {240, 70},
  214. {233, 71},
  215. {226, 72},
  216. {219, 73},
  217. {212, 74},
  218. {206, 75},
  219. {199, 76},
  220. {193, 77},
  221. {187, 78},
  222. {182, 79},
  223. {176, 80},
  224. {171, 81},
  225. {166, 82},
  226. {161, 83},
  227. {156, 84},
  228. {151, 85},
  229. {147, 86},
  230. {142, 87},
  231. {138, 88},
  232. {134, 89},
  233. {130, 90},
  234. {126, 91},
  235. {122, 92},
  236. {119, 93},
  237. {115, 94},
  238. {112, 95},
  239. {109, 96},
  240. {106, 97},
  241. {103, 98},
  242. {100, 99},
  243. {97, 100},
  244. {94, 101},
  245. {91, 102},
  246. {89, 103},
  247. {86, 104},
  248. {84, 105},
  249. {82, 106},
  250. {79, 107},
  251. {77, 108},
  252. {75, 109},
  253. {73, 110},
  254. {71, 111},
  255. {69, 112},
  256. {67, 113},
  257. {65, 114},
  258. {64, 115},
  259. {62, 116},
  260. {60, 117},
  261. {59, 118},
  262. {57, 119},
  263. {56, 120},
  264. {54, 121},
  265. {53, 122},
  266. {51, 123},
  267. {50, 124},
  268. {49, 125}
  269. };
  270. static const struct pm8xxx_adc_map_pt adcmap_ntcg_104ef_104fb[] = {
  271. {374682, -40960},
  272. {360553, -39936},
  273. {346630, -38912},
  274. {332940, -37888},
  275. {319510, -36864},
  276. {306363, -35840},
  277. {293521, -34816},
  278. {281001, -33792},
  279. {268818, -32768},
  280. {256987, -31744},
  281. {245516, -30720},
  282. {234413, -29696},
  283. {223685, -28672},
  284. {213333, -27648},
  285. {203360, -26624},
  286. {193763, -25600},
  287. {184541, -24576},
  288. {175691, -23552},
  289. {167205, -22528},
  290. {159079, -21504},
  291. {151304, -20480},
  292. {143872, -19456},
  293. {136775, -18432},
  294. {130001, -17408},
  295. {123542, -16384},
  296. {117387, -15360},
  297. {111526, -14336},
  298. {105946, -13312},
  299. {100639, -12288},
  300. {95592, -11264},
  301. {90795, -10240},
  302. {86238, -9216},
  303. {81909, -8192},
  304. {77800, -7168},
  305. {73899, -6144},
  306. {70197, -5120},
  307. {66685, -4096},
  308. {63354, -3072},
  309. {60194, -2048},
  310. {57198, -1024},
  311. {54356, 0},
  312. {51662, 1024},
  313. {49108, 2048},
  314. {46687, 3072},
  315. {44391, 4096},
  316. {42215, 5120},
  317. {40151, 6144},
  318. {38195, 7168},
  319. {36340, 8192},
  320. {34582, 9216},
  321. {32914, 10240},
  322. {31333, 11264},
  323. {29833, 12288},
  324. {28410, 13312},
  325. {27061, 14336},
  326. {25781, 15360},
  327. {24566, 16384},
  328. {23413, 17408},
  329. {22319, 18432},
  330. {21280, 19456},
  331. {20294, 20480},
  332. {19358, 21504},
  333. {18469, 22528},
  334. {17624, 23552},
  335. {16822, 24576},
  336. {16060, 25600},
  337. {15335, 26624},
  338. {14646, 27648},
  339. {13992, 28672},
  340. {13369, 29696},
  341. {12777, 30720},
  342. {12214, 31744},
  343. {11678, 32768},
  344. {11168, 33792},
  345. {10682, 34816},
  346. {10220, 35840},
  347. {9780, 36864},
  348. {9361, 37888},
  349. {8962, 38912},
  350. {8582, 39936},
  351. {8219, 40960},
  352. {7874, 41984},
  353. {7545, 43008},
  354. {7231, 44032},
  355. {6931, 45056},
  356. {6646, 46080},
  357. {6373, 47104},
  358. {6113, 48128},
  359. {5865, 49152},
  360. {5628, 50176},
  361. {5402, 51200},
  362. {5185, 52224},
  363. {4979, 53248},
  364. {4782, 54272},
  365. {4593, 55296},
  366. {4413, 56320},
  367. {4241, 57344},
  368. {4076, 58368},
  369. {3919, 59392},
  370. {3768, 60416},
  371. {3624, 61440},
  372. {3486, 62464},
  373. {3354, 63488},
  374. {3227, 64512},
  375. {3106, 65536},
  376. {2990, 66560},
  377. {2879, 67584},
  378. {2773, 68608},
  379. {2671, 69632},
  380. {2573, 70656},
  381. {2479, 71680},
  382. {2390, 72704},
  383. {2303, 73728},
  384. {2221, 74752},
  385. {2142, 75776},
  386. {2066, 76800},
  387. {1993, 77824},
  388. {1923, 78848},
  389. {1855, 79872},
  390. {1791, 80896},
  391. {1729, 81920},
  392. {1669, 82944},
  393. {1612, 83968},
  394. {1557, 84992},
  395. {1504, 86016},
  396. {1453, 87040},
  397. {1404, 88064},
  398. {1357, 89088},
  399. {1312, 90112},
  400. {1269, 91136},
  401. {1227, 92160},
  402. {1187, 93184},
  403. {1148, 94208},
  404. {1111, 95232},
  405. {1075, 96256},
  406. {1040, 97280},
  407. {1007, 98304},
  408. {975, 99328},
  409. {944, 100352},
  410. {914, 101376},
  411. {886, 102400},
  412. {858, 103424},
  413. {831, 104448},
  414. {806, 105472},
  415. {781, 106496},
  416. {757, 107520},
  417. {734, 108544},
  418. {712, 109568},
  419. {690, 110592},
  420. {670, 111616},
  421. {650, 112640},
  422. {630, 113664},
  423. {612, 114688},
  424. {594, 115712},
  425. {576, 116736},
  426. {559, 117760},
  427. {543, 118784},
  428. {527, 119808},
  429. {512, 120832},
  430. {498, 121856},
  431. {483, 122880},
  432. {470, 123904},
  433. {456, 124928},
  434. {444, 125952},
  435. {431, 126976},
  436. {419, 128000},
  437. {408, 129024},
  438. {396, 130048}
  439. };
  440. static int32_t pm8xxx_adc_map_linear(const struct pm8xxx_adc_map_pt *pts,
  441. uint32_t tablesize, int32_t input, int64_t *output)
  442. {
  443. bool descending = 1;
  444. uint32_t i = 0;
  445. if ((pts == NULL) || (output == NULL))
  446. return -EINVAL;
  447. /* Check if table is descending or ascending */
  448. if (tablesize > 1) {
  449. if (pts[0].x < pts[1].x)
  450. descending = 0;
  451. }
  452. while (i < tablesize) {
  453. if ((descending == 1) && (pts[i].x < input)) {
  454. /* table entry is less than measured
  455. value and table is descending, stop */
  456. break;
  457. } else if ((descending == 0) &&
  458. (pts[i].x > input)) {
  459. /* table entry is greater than measured
  460. value and table is ascending, stop */
  461. break;
  462. } else {
  463. i++;
  464. }
  465. }
  466. if (i == 0)
  467. *output = pts[0].y;
  468. else if (i == tablesize)
  469. *output = pts[tablesize-1].y;
  470. else {
  471. /* result is between search_index and search_index-1 */
  472. /* interpolate linearly */
  473. *output = (((int32_t) ((pts[i].y - pts[i-1].y)*
  474. (input - pts[i-1].x))/
  475. (pts[i].x - pts[i-1].x))+
  476. pts[i-1].y);
  477. }
  478. return 0;
  479. }
  480. static int32_t pm8xxx_adc_map_batt_therm(const struct pm8xxx_adc_map_pt *pts,
  481. uint32_t tablesize, int32_t input, int64_t *output)
  482. {
  483. bool descending = 1;
  484. uint32_t i = 0;
  485. if ((pts == NULL) || (output == NULL))
  486. return -EINVAL;
  487. /* Check if table is descending or ascending */
  488. if (tablesize > 1) {
  489. if (pts[0].y < pts[1].y)
  490. descending = 0;
  491. }
  492. while (i < tablesize) {
  493. if ((descending == 1) && (pts[i].y < input)) {
  494. /* table entry is less than measured
  495. value and table is descending, stop */
  496. break;
  497. } else if ((descending == 0) && (pts[i].y > input)) {
  498. /* table entry is greater than measured
  499. value and table is ascending, stop */
  500. break;
  501. } else {
  502. i++;
  503. }
  504. }
  505. if (i == 0) {
  506. *output = pts[0].x;
  507. } else if (i == tablesize) {
  508. *output = pts[tablesize-1].x;
  509. } else {
  510. /* result is between search_index and search_index-1 */
  511. /* interpolate linearly */
  512. *output = (((int32_t) ((pts[i].x - pts[i-1].x)*
  513. (input - pts[i-1].y))/
  514. (pts[i].y - pts[i-1].y))+
  515. pts[i-1].x);
  516. }
  517. return 0;
  518. }
  519. int32_t pm8xxx_adc_scale_default(int32_t adc_code,
  520. const struct pm8xxx_adc_properties *adc_properties,
  521. const struct pm8xxx_adc_chan_properties *chan_properties,
  522. struct pm8xxx_adc_chan_result *adc_chan_result)
  523. {
  524. bool negative_rawfromoffset = 0, negative_offset = 0;
  525. int64_t scale_voltage = 0;
  526. if (!chan_properties || !chan_properties->offset_gain_numerator ||
  527. !chan_properties->offset_gain_denominator || !adc_properties
  528. || !adc_chan_result)
  529. return -EINVAL;
  530. scale_voltage = (adc_code -
  531. chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].adc_gnd)
  532. * chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dx;
  533. if (scale_voltage < 0) {
  534. negative_offset = 1;
  535. scale_voltage = -scale_voltage;
  536. }
  537. do_div(scale_voltage,
  538. chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dy);
  539. if (negative_offset)
  540. scale_voltage = -scale_voltage;
  541. scale_voltage += chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dx;
  542. if (scale_voltage < 0) {
  543. if (adc_properties->bipolar) {
  544. scale_voltage = -scale_voltage;
  545. negative_rawfromoffset = 1;
  546. } else {
  547. scale_voltage = 0;
  548. }
  549. }
  550. adc_chan_result->measurement = scale_voltage *
  551. chan_properties->offset_gain_denominator;
  552. /* do_div only perform positive integer division! */
  553. do_div(adc_chan_result->measurement,
  554. chan_properties->offset_gain_numerator);
  555. if (negative_rawfromoffset)
  556. adc_chan_result->measurement = -adc_chan_result->measurement;
  557. /* Note: adc_chan_result->measurement is in the unit of
  558. * adc_properties.adc_reference. For generic channel processing,
  559. * channel measurement is a scale/ratio relative to the adc
  560. * reference input */
  561. adc_chan_result->physical = adc_chan_result->measurement;
  562. return 0;
  563. }
  564. EXPORT_SYMBOL_GPL(pm8xxx_adc_scale_default);
  565. static int64_t pm8xxx_adc_scale_ratiometric_calib(int32_t adc_code,
  566. const struct pm8xxx_adc_properties *adc_properties,
  567. const struct pm8xxx_adc_chan_properties *chan_properties)
  568. {
  569. int64_t adc_voltage = 0;
  570. bool negative_offset = 0;
  571. if (!chan_properties || !chan_properties->offset_gain_numerator ||
  572. !chan_properties->offset_gain_denominator || !adc_properties)
  573. return -EINVAL;
  574. adc_voltage = (adc_code -
  575. chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].adc_gnd)
  576. * adc_properties->adc_vdd_reference;
  577. if (adc_voltage < 0) {
  578. negative_offset = 1;
  579. adc_voltage = -adc_voltage;
  580. }
  581. do_div(adc_voltage,
  582. chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].dy);
  583. if (negative_offset)
  584. adc_voltage = -adc_voltage;
  585. return adc_voltage;
  586. }
  587. int32_t pm8xxx_adc_scale_batt_therm(int32_t adc_code,
  588. const struct pm8xxx_adc_properties *adc_properties,
  589. const struct pm8xxx_adc_chan_properties *chan_properties,
  590. struct pm8xxx_adc_chan_result *adc_chan_result)
  591. {
  592. int64_t bat_voltage = 0;
  593. bat_voltage = pm8xxx_adc_scale_ratiometric_calib(adc_code,
  594. adc_properties, chan_properties);
  595. return pm8xxx_adc_map_batt_therm(
  596. adcmap_btm_threshold,
  597. ARRAY_SIZE(adcmap_btm_threshold),
  598. bat_voltage,
  599. &adc_chan_result->physical);
  600. }
  601. EXPORT_SYMBOL_GPL(pm8xxx_adc_scale_batt_therm);
  602. int32_t pm8xxx_adc_scale_pa_therm(int32_t adc_code,
  603. const struct pm8xxx_adc_properties *adc_properties,
  604. const struct pm8xxx_adc_chan_properties *chan_properties,
  605. struct pm8xxx_adc_chan_result *adc_chan_result)
  606. {
  607. int64_t pa_voltage = 0;
  608. pa_voltage = pm8xxx_adc_scale_ratiometric_calib(adc_code,
  609. adc_properties, chan_properties);
  610. return pm8xxx_adc_map_linear(
  611. adcmap_pa_therm,
  612. ARRAY_SIZE(adcmap_pa_therm),
  613. pa_voltage,
  614. &adc_chan_result->physical);
  615. }
  616. EXPORT_SYMBOL_GPL(pm8xxx_adc_scale_pa_therm);
  617. int32_t pm8xxx_adc_scale_batt_id(int32_t adc_code,
  618. const struct pm8xxx_adc_properties *adc_properties,
  619. const struct pm8xxx_adc_chan_properties *chan_properties,
  620. struct pm8xxx_adc_chan_result *adc_chan_result)
  621. {
  622. int64_t batt_id_voltage = 0;
  623. batt_id_voltage = pm8xxx_adc_scale_ratiometric_calib(adc_code,
  624. adc_properties, chan_properties);
  625. adc_chan_result->physical = batt_id_voltage;
  626. adc_chan_result->physical = adc_chan_result->measurement;
  627. return 0;
  628. }
  629. EXPORT_SYMBOL_GPL(pm8xxx_adc_scale_batt_id);
  630. int32_t pm8xxx_adc_scale_pmic_therm(int32_t adc_code,
  631. const struct pm8xxx_adc_properties *adc_properties,
  632. const struct pm8xxx_adc_chan_properties *chan_properties,
  633. struct pm8xxx_adc_chan_result *adc_chan_result)
  634. {
  635. int64_t pmic_voltage = 0;
  636. bool negative_offset = 0;
  637. if (!chan_properties || !chan_properties->offset_gain_numerator ||
  638. !chan_properties->offset_gain_denominator || !adc_properties
  639. || !adc_chan_result)
  640. return -EINVAL;
  641. pmic_voltage = (adc_code -
  642. chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].adc_gnd)
  643. * chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dx;
  644. if (pmic_voltage < 0) {
  645. negative_offset = 1;
  646. pmic_voltage = -pmic_voltage;
  647. }
  648. do_div(pmic_voltage,
  649. chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dy);
  650. if (negative_offset)
  651. pmic_voltage = -pmic_voltage;
  652. pmic_voltage += chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dx;
  653. if (pmic_voltage > 0) {
  654. /* 2mV/K */
  655. adc_chan_result->measurement = pmic_voltage*
  656. chan_properties->offset_gain_denominator;
  657. do_div(adc_chan_result->measurement,
  658. chan_properties->offset_gain_numerator * 2);
  659. } else {
  660. adc_chan_result->measurement = 0;
  661. }
  662. /* Change to .001 deg C */
  663. adc_chan_result->measurement -= KELVINMIL_DEGMIL;
  664. adc_chan_result->physical = (int32_t)adc_chan_result->measurement;
  665. return 0;
  666. }
  667. EXPORT_SYMBOL_GPL(pm8xxx_adc_scale_pmic_therm);
  668. /* Scales the ADC code to 0.001 degrees C using the map
  669. * table for the XO thermistor.
  670. */
  671. int32_t pm8xxx_adc_tdkntcg_therm(int32_t adc_code,
  672. const struct pm8xxx_adc_properties *adc_properties,
  673. const struct pm8xxx_adc_chan_properties *chan_properties,
  674. struct pm8xxx_adc_chan_result *adc_chan_result)
  675. {
  676. int64_t xo_thm = 0;
  677. uint32_t num1 = 0;
  678. uint32_t num2 = 0;
  679. uint32_t dnum = 0;
  680. uint32_t rt_r25 = 0;
  681. if (!chan_properties || !chan_properties->offset_gain_numerator ||
  682. !chan_properties->offset_gain_denominator || !adc_properties
  683. || !adc_chan_result)
  684. return -EINVAL;
  685. xo_thm = pm8xxx_adc_scale_ratiometric_calib(adc_code,
  686. adc_properties, chan_properties);
  687. if (xo_thm < 0)
  688. xo_thm = -xo_thm;
  689. num1 = xo_thm << 14;
  690. num2 = (adc_properties->adc_vdd_reference - xo_thm) >> 1;
  691. dnum = (adc_properties->adc_vdd_reference - xo_thm);
  692. if (dnum == 0)
  693. rt_r25 = 0x7FFFFFFF ;
  694. else
  695. rt_r25 = (num1 + num2)/dnum ;
  696. pm8xxx_adc_map_linear(adcmap_ntcg_104ef_104fb,
  697. ARRAY_SIZE(adcmap_ntcg_104ef_104fb),
  698. rt_r25, &adc_chan_result->physical);
  699. return 0;
  700. }
  701. EXPORT_SYMBOL_GPL(pm8xxx_adc_tdkntcg_therm);
  702. int32_t pm8xxx_adc_batt_scaler(struct pm8xxx_adc_arb_btm_param *btm_param,
  703. const struct pm8xxx_adc_properties *adc_properties,
  704. const struct pm8xxx_adc_chan_properties *chan_properties)
  705. {
  706. int rc;
  707. rc = pm8xxx_adc_map_linear(
  708. adcmap_btm_threshold,
  709. ARRAY_SIZE(adcmap_btm_threshold),
  710. (btm_param->low_thr_temp),
  711. &btm_param->low_thr_voltage);
  712. if (rc)
  713. return rc;
  714. btm_param->low_thr_voltage *=
  715. chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].dy;
  716. do_div(btm_param->low_thr_voltage, adc_properties->adc_vdd_reference);
  717. btm_param->low_thr_voltage +=
  718. chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].adc_gnd;
  719. rc = pm8xxx_adc_map_linear(
  720. adcmap_btm_threshold,
  721. ARRAY_SIZE(adcmap_btm_threshold),
  722. (btm_param->high_thr_temp),
  723. &btm_param->high_thr_voltage);
  724. if (rc)
  725. return rc;
  726. btm_param->high_thr_voltage *=
  727. chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].dy;
  728. do_div(btm_param->high_thr_voltage, adc_properties->adc_vdd_reference);
  729. btm_param->high_thr_voltage +=
  730. chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].adc_gnd;
  731. return rc;
  732. }
  733. EXPORT_SYMBOL_GPL(pm8xxx_adc_batt_scaler);