blob: 4a1f58cfc4ae4973e1ae4b532bd6ffc140ccfbb4 [file] [log] [blame]
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -07001/*
Siddartha Mohanadoss9ae3efb2012-06-28 18:28:43 -07002 * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -07003 *
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
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -080020/* Units for temperature below (on x axis) is in 0.1DegC as
21 required by the battery driver. Note the resolution used
22 here to compute the table was done for DegC to milli-volts.
23 In consideration to limit the size of the table for the given
24 temperature range below, the result is linearly interpolated
25 and provided to the battery driver in the units desired for
26 their framework which is 0.1DegC. True resolution of 0.1DegC
27 will result in the below table size to increase by 10 times */
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -070028static const struct pm8xxx_adc_map_pt adcmap_btm_threshold[] = {
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -080029 {-300, 1642},
30 {-200, 1544},
31 {-100, 1414},
Siddartha Mohanadossae39c902011-11-09 17:54:31 -080032 {0, 1260},
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -080033 {10, 1244},
34 {20, 1228},
35 {30, 1212},
36 {40, 1195},
37 {50, 1179},
38 {60, 1162},
39 {70, 1146},
40 {80, 1129},
41 {90, 1113},
42 {100, 1097},
43 {110, 1080},
44 {120, 1064},
45 {130, 1048},
46 {140, 1032},
47 {150, 1016},
48 {160, 1000},
49 {170, 985},
50 {180, 969},
51 {190, 954},
52 {200, 939},
53 {210, 924},
54 {220, 909},
55 {230, 894},
56 {240, 880},
57 {250, 866},
58 {260, 852},
59 {270, 838},
60 {280, 824},
61 {290, 811},
62 {300, 798},
63 {310, 785},
64 {320, 773},
65 {330, 760},
66 {340, 748},
67 {350, 736},
68 {360, 725},
69 {370, 713},
70 {380, 702},
71 {390, 691},
72 {400, 681},
73 {410, 670},
74 {420, 660},
75 {430, 650},
76 {440, 640},
77 {450, 631},
78 {460, 622},
79 {470, 613},
80 {480, 604},
81 {490, 595},
82 {500, 587},
83 {510, 579},
84 {520, 571},
85 {530, 563},
86 {540, 556},
87 {550, 548},
88 {560, 541},
89 {570, 534},
90 {580, 527},
91 {590, 521},
92 {600, 514},
93 {610, 508},
94 {620, 502},
95 {630, 496},
96 {640, 490},
97 {650, 485},
98 {660, 281},
99 {670, 274},
100 {680, 267},
101 {690, 260},
102 {700, 254},
103 {710, 247},
104 {720, 241},
105 {730, 235},
106 {740, 229},
107 {750, 224},
108 {760, 218},
109 {770, 213},
110 {780, 208},
111 {790, 203}
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700112};
113
114static const struct pm8xxx_adc_map_pt adcmap_pa_therm[] = {
Siddartha Mohanadoss9ae3efb2012-06-28 18:28:43 -0700115 {1731, -30},
116 {1726, -29},
117 {1721, -28},
118 {1715, -27},
119 {1710, -26},
120 {1703, -25},
121 {1697, -24},
122 {1690, -23},
123 {1683, -22},
124 {1675, -21},
125 {1667, -20},
126 {1659, -19},
127 {1650, -18},
128 {1641, -17},
129 {1632, -16},
130 {1622, -15},
131 {1611, -14},
132 {1600, -13},
133 {1589, -12},
134 {1577, -11},
135 {1565, -10},
136 {1552, -9},
137 {1539, -8},
138 {1525, -7},
139 {1511, -6},
140 {1496, -5},
141 {1481, -4},
142 {1465, -3},
143 {1449, -2},
144 {1432, -1},
145 {1415, 0},
146 {1398, 1},
147 {1380, 2},
148 {1362, 3},
149 {1343, 4},
150 {1324, 5},
151 {1305, 6},
152 {1285, 7},
153 {1265, 8},
154 {1245, 9},
155 {1224, 10},
156 {1203, 11},
157 {1182, 12},
158 {1161, 13},
159 {1139, 14},
160 {1118, 15},
161 {1096, 16},
162 {1074, 17},
163 {1052, 18},
164 {1030, 19},
165 {1008, 20},
166 {986, 21},
167 {964, 22},
168 {943, 23},
169 {921, 24},
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800170 {899, 25},
Siddartha Mohanadoss9ae3efb2012-06-28 18:28:43 -0700171 {878, 26},
172 {857, 27},
173 {836, 28},
174 {815, 29},
175 {794, 30},
176 {774, 31},
177 {754, 32},
178 {734, 33},
179 {714, 34},
180 {695, 35},
181 {676, 36},
182 {657, 37},
183 {639, 38},
184 {621, 39},
185 {604, 40},
186 {586, 41},
187 {570, 42},
188 {553, 43},
189 {537, 44},
190 {521, 45},
191 {506, 46},
192 {491, 47},
193 {476, 48},
194 {462, 49},
195 {448, 50},
196 {435, 51},
197 {421, 52},
198 {409, 53},
199 {396, 54},
200 {384, 55},
201 {372, 56},
202 {361, 57},
203 {350, 58},
204 {339, 59},
205 {329, 60},
206 {318, 61},
207 {309, 62},
208 {299, 63},
209 {290, 64},
210 {281, 65},
211 {272, 66},
212 {264, 67},
213 {256, 68},
214 {248, 69},
215 {240, 70},
216 {233, 71},
217 {226, 72},
218 {219, 73},
219 {212, 74},
220 {206, 75},
221 {199, 76},
222 {193, 77},
223 {187, 78},
224 {182, 79},
225 {176, 80},
226 {171, 81},
227 {166, 82},
228 {161, 83},
229 {156, 84},
230 {151, 85},
231 {147, 86},
232 {142, 87},
233 {138, 88},
234 {134, 89},
235 {130, 90},
236 {126, 91},
237 {122, 92},
238 {119, 93},
239 {115, 94},
240 {112, 95},
241 {109, 96},
242 {106, 97},
243 {103, 98},
244 {100, 99},
245 {97, 100},
246 {94, 101},
247 {91, 102},
248 {89, 103},
249 {86, 104},
250 {84, 105},
251 {82, 106},
252 {79, 107},
253 {77, 108},
254 {75, 109},
255 {73, 110},
256 {71, 111},
257 {69, 112},
258 {67, 113},
259 {65, 114},
260 {64, 115},
261 {62, 116},
262 {60, 117},
263 {59, 118},
264 {57, 119},
265 {56, 120},
266 {54, 121},
267 {53, 122},
268 {51, 123},
269 {50, 124},
270 {49, 125}
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700271};
272
273static const struct pm8xxx_adc_map_pt adcmap_ntcg_104ef_104fb[] = {
274 {696483, -40960},
275 {649148, -39936},
276 {605368, -38912},
277 {564809, -37888},
278 {527215, -36864},
279 {492322, -35840},
280 {460007, -34816},
281 {429982, -33792},
282 {402099, -32768},
283 {376192, -31744},
284 {352075, -30720},
285 {329714, -29696},
286 {308876, -28672},
287 {289480, -27648},
288 {271417, -26624},
289 {254574, -25600},
290 {238903, -24576},
291 {224276, -23552},
292 {210631, -22528},
293 {197896, -21504},
294 {186007, -20480},
295 {174899, -19456},
296 {164521, -18432},
297 {154818, -17408},
298 {145744, -16384},
299 {137265, -15360},
300 {129307, -14336},
301 {121866, -13312},
302 {114896, -12288},
303 {108365, -11264},
304 {102252, -10240},
305 {96499, -9216},
306 {91111, -8192},
307 {86055, -7168},
308 {81308, -6144},
309 {76857, -5120},
310 {72660, -4096},
311 {68722, -3072},
312 {65020, -2048},
313 {61538, -1024},
314 {58261, 0},
315 {55177, 1024},
316 {52274, 2048},
317 {49538, 3072},
318 {46962, 4096},
319 {44531, 5120},
320 {42243, 6144},
321 {40083, 7168},
322 {38045, 8192},
323 {36122, 9216},
324 {34308, 10240},
325 {32592, 11264},
326 {30972, 12288},
327 {29442, 13312},
328 {27995, 14336},
329 {26624, 15360},
330 {25333, 16384},
331 {24109, 17408},
332 {22951, 18432},
333 {21854, 19456},
334 {20807, 20480},
335 {19831, 21504},
336 {18899, 22528},
337 {18016, 23552},
338 {17178, 24576},
339 {16384, 25600},
340 {15631, 26624},
341 {14916, 27648},
342 {14237, 28672},
343 {13593, 29696},
344 {12976, 30720},
345 {12400, 31744},
346 {11848, 32768},
347 {11324, 33792},
348 {10825, 34816},
349 {10354, 35840},
350 {9900, 36864},
351 {9471, 37888},
352 {9062, 38912},
353 {8674, 39936},
354 {8306, 40960},
355 {7951, 41984},
356 {7616, 43008},
357 {7296, 44032},
358 {6991, 45056},
359 {6701, 46080},
360 {6424, 47104},
361 {6160, 48128},
362 {5908, 49152},
363 {5667, 50176},
364 {5439, 51200},
365 {5219, 52224},
366 {5010, 53248},
367 {4810, 54272},
368 {4619, 55296},
369 {4440, 56320},
370 {4263, 57344},
371 {4097, 58368},
372 {3938, 59392},
373 {3785, 60416},
374 {3637, 61440},
375 {3501, 62464},
376 {3368, 63488},
377 {3240, 64512},
378 {3118, 65536},
379 {2998, 66560},
380 {2889, 67584},
381 {2782, 68608},
382 {2680, 69632},
383 {2581, 70656},
384 {2490, 71680},
385 {2397, 72704},
386 {2310, 73728},
387 {2227, 74752},
388 {2147, 75776},
389 {2064, 76800},
390 {1998, 77824},
391 {1927, 78848},
392 {1860, 79872},
393 {1795, 80896},
394 {1736, 81920},
395 {1673, 82944},
396 {1615, 83968},
397 {1560, 84992},
398 {1507, 86016},
399 {1456, 87040},
400 {1407, 88064},
401 {1360, 89088},
402 {1314, 90112},
403 {1271, 91136},
404 {1228, 92160},
405 {1189, 93184},
406 {1150, 94208},
407 {1112, 95232},
408 {1076, 96256},
409 {1042, 97280},
410 {1008, 98304},
411 {976, 99328},
412 {945, 100352},
413 {915, 101376},
414 {886, 102400},
415 {859, 103424},
416 {832, 104448},
417 {807, 105472},
418 {782, 106496},
419 {756, 107520},
420 {735, 108544},
421 {712, 109568},
422 {691, 110592},
423 {670, 111616},
424 {650, 112640},
425 {631, 113664},
426 {612, 114688},
427 {594, 115712},
428 {577, 116736},
429 {560, 117760},
430 {544, 118784},
431 {528, 119808},
432 {513, 120832},
433 {498, 121856},
434 {483, 122880},
435 {470, 123904},
436 {457, 124928},
437 {444, 125952},
438 {431, 126976},
439 {419, 128000}
440};
441
442static int32_t pm8xxx_adc_map_linear(const struct pm8xxx_adc_map_pt *pts,
443 uint32_t tablesize, int32_t input, int64_t *output)
444{
445 bool descending = 1;
446 uint32_t i = 0;
447
448 if ((pts == NULL) || (output == NULL))
449 return -EINVAL;
450
451 /* Check if table is descending or ascending */
452 if (tablesize > 1) {
453 if (pts[0].x < pts[1].x)
454 descending = 0;
455 }
456
457 while (i < tablesize) {
458 if ((descending == 1) && (pts[i].x < input)) {
459 /* table entry is less than measured
460 value and table is descending, stop */
461 break;
462 } else if ((descending == 0) &&
463 (pts[i].x > input)) {
464 /* table entry is greater than measured
465 value and table is ascending, stop */
466 break;
467 } else {
468 i++;
469 }
470 }
471
472 if (i == 0)
473 *output = pts[0].y;
474 else if (i == tablesize)
475 *output = pts[tablesize-1].y;
476 else {
477 /* result is between search_index and search_index-1 */
478 /* interpolate linearly */
479 *output = (((int32_t) ((pts[i].y - pts[i-1].y)*
480 (input - pts[i-1].x))/
481 (pts[i].x - pts[i-1].x))+
482 pts[i-1].y);
483 }
484
485 return 0;
486}
487
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800488static int32_t pm8xxx_adc_map_batt_therm(const struct pm8xxx_adc_map_pt *pts,
489 uint32_t tablesize, int32_t input, int64_t *output)
490{
491 bool descending = 1;
492 uint32_t i = 0;
493
494 if ((pts == NULL) || (output == NULL))
495 return -EINVAL;
496
497 /* Check if table is descending or ascending */
498 if (tablesize > 1) {
499 if (pts[0].y < pts[1].y)
500 descending = 0;
501 }
502
503 while (i < tablesize) {
504 if ((descending == 1) && (pts[i].y < input)) {
505 /* table entry is less than measured
506 value and table is descending, stop */
507 break;
508 } else if ((descending == 0) && (pts[i].y > input)) {
509 /* table entry is greater than measured
510 value and table is ascending, stop */
511 break;
512 } else {
513 i++;
514 }
515 }
516
517 if (i == 0) {
518 *output = pts[0].x;
519 } else if (i == tablesize) {
520 *output = pts[tablesize-1].x;
521 } else {
522 /* result is between search_index and search_index-1 */
523 /* interpolate linearly */
524 *output = (((int32_t) ((pts[i].x - pts[i-1].x)*
525 (input - pts[i-1].y))/
526 (pts[i].y - pts[i-1].y))+
527 pts[i-1].x);
528 }
529
530 return 0;
531}
532
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700533int32_t pm8xxx_adc_scale_default(int32_t adc_code,
534 const struct pm8xxx_adc_properties *adc_properties,
535 const struct pm8xxx_adc_chan_properties *chan_properties,
536 struct pm8xxx_adc_chan_result *adc_chan_result)
537{
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800538 bool negative_rawfromoffset = 0, negative_offset = 0;
539 int64_t scale_voltage = 0;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700540
541 if (!chan_properties || !chan_properties->offset_gain_numerator ||
542 !chan_properties->offset_gain_denominator || !adc_properties
543 || !adc_chan_result)
544 return -EINVAL;
545
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800546 scale_voltage = (adc_code -
547 chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].adc_gnd)
548 * chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dx;
549 if (scale_voltage < 0) {
550 negative_offset = 1;
551 scale_voltage = -scale_voltage;
552 }
553 do_div(scale_voltage,
554 chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dy);
555 if (negative_offset)
556 scale_voltage = -scale_voltage;
557 scale_voltage += chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dx;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700558
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800559 if (scale_voltage < 0) {
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700560 if (adc_properties->bipolar) {
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800561 scale_voltage = -scale_voltage;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700562 negative_rawfromoffset = 1;
563 } else {
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800564 scale_voltage = 0;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700565 }
566 }
567
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800568 adc_chan_result->measurement = scale_voltage *
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700569 chan_properties->offset_gain_denominator;
570
571 /* do_div only perform positive integer division! */
572 do_div(adc_chan_result->measurement,
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700573 chan_properties->offset_gain_numerator);
574
575 if (negative_rawfromoffset)
576 adc_chan_result->measurement = -adc_chan_result->measurement;
577
578 /* Note: adc_chan_result->measurement is in the unit of
579 * adc_properties.adc_reference. For generic channel processing,
580 * channel measurement is a scale/ratio relative to the adc
581 * reference input */
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800582 adc_chan_result->physical = adc_chan_result->measurement;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700583
584 return 0;
585}
586EXPORT_SYMBOL_GPL(pm8xxx_adc_scale_default);
587
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800588static int64_t pm8xxx_adc_scale_ratiometric_calib(int32_t adc_code,
589 const struct pm8xxx_adc_properties *adc_properties,
590 const struct pm8xxx_adc_chan_properties *chan_properties)
591{
592 int64_t adc_voltage = 0;
593 bool negative_offset = 0;
594
595 if (!chan_properties || !chan_properties->offset_gain_numerator ||
596 !chan_properties->offset_gain_denominator || !adc_properties)
597 return -EINVAL;
598
599 adc_voltage = (adc_code -
600 chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].adc_gnd)
601 * adc_properties->adc_vdd_reference;
602 if (adc_voltage < 0) {
603 negative_offset = 1;
604 adc_voltage = -adc_voltage;
605 }
606 do_div(adc_voltage,
607 chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].dy);
608 if (negative_offset)
609 adc_voltage = -adc_voltage;
610
611 return adc_voltage;
612}
613
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700614int32_t pm8xxx_adc_scale_batt_therm(int32_t adc_code,
615 const struct pm8xxx_adc_properties *adc_properties,
616 const struct pm8xxx_adc_chan_properties *chan_properties,
617 struct pm8xxx_adc_chan_result *adc_chan_result)
618{
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800619 int64_t bat_voltage = 0;
620
621 bat_voltage = pm8xxx_adc_scale_ratiometric_calib(adc_code,
622 adc_properties, chan_properties);
623
624 return pm8xxx_adc_map_batt_therm(
625 adcmap_btm_threshold,
626 ARRAY_SIZE(adcmap_btm_threshold),
627 bat_voltage,
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700628 &adc_chan_result->physical);
629}
630EXPORT_SYMBOL_GPL(pm8xxx_adc_scale_batt_therm);
631
632int32_t pm8xxx_adc_scale_pa_therm(int32_t adc_code,
633 const struct pm8xxx_adc_properties *adc_properties,
634 const struct pm8xxx_adc_chan_properties *chan_properties,
635 struct pm8xxx_adc_chan_result *adc_chan_result)
636{
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800637 int64_t pa_voltage = 0;
638
639 pa_voltage = pm8xxx_adc_scale_ratiometric_calib(adc_code,
640 adc_properties, chan_properties);
641
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700642 return pm8xxx_adc_map_linear(
643 adcmap_pa_therm,
644 ARRAY_SIZE(adcmap_pa_therm),
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800645 pa_voltage,
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700646 &adc_chan_result->physical);
647}
648EXPORT_SYMBOL_GPL(pm8xxx_adc_scale_pa_therm);
649
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800650int32_t pm8xxx_adc_scale_batt_id(int32_t adc_code,
651 const struct pm8xxx_adc_properties *adc_properties,
652 const struct pm8xxx_adc_chan_properties *chan_properties,
653 struct pm8xxx_adc_chan_result *adc_chan_result)
654{
655 int64_t batt_id_voltage = 0;
656
657 batt_id_voltage = pm8xxx_adc_scale_ratiometric_calib(adc_code,
658 adc_properties, chan_properties);
659 adc_chan_result->physical = batt_id_voltage;
660 adc_chan_result->physical = adc_chan_result->measurement;
661
662 return 0;
663}
664EXPORT_SYMBOL_GPL(pm8xxx_adc_scale_batt_id);
665
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700666int32_t pm8xxx_adc_scale_pmic_therm(int32_t adc_code,
667 const struct pm8xxx_adc_properties *adc_properties,
668 const struct pm8xxx_adc_chan_properties *chan_properties,
669 struct pm8xxx_adc_chan_result *adc_chan_result)
670{
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800671 int64_t pmic_voltage = 0;
672 bool negative_offset = 0;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700673
674 if (!chan_properties || !chan_properties->offset_gain_numerator ||
675 !chan_properties->offset_gain_denominator || !adc_properties
676 || !adc_chan_result)
677 return -EINVAL;
678
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800679 pmic_voltage = (adc_code -
680 chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].adc_gnd)
681 * chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dx;
682 if (pmic_voltage < 0) {
683 negative_offset = 1;
684 pmic_voltage = -pmic_voltage;
685 }
686 do_div(pmic_voltage,
687 chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dy);
688 if (negative_offset)
689 pmic_voltage = -pmic_voltage;
690 pmic_voltage += chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dx;
691
692 if (pmic_voltage > 0) {
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700693 /* 2mV/K */
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800694 adc_chan_result->measurement = pmic_voltage*
695 chan_properties->offset_gain_denominator;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700696
697 do_div(adc_chan_result->measurement,
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800698 chan_properties->offset_gain_numerator * 2);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700699 } else {
700 adc_chan_result->measurement = 0;
701 }
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700702 /* Change to .001 deg C */
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800703 adc_chan_result->measurement -= KELVINMIL_DEGMIL;
704 adc_chan_result->physical = (int32_t)adc_chan_result->measurement;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700705
706 return 0;
707}
708EXPORT_SYMBOL_GPL(pm8xxx_adc_scale_pmic_therm);
709
710/* Scales the ADC code to 0.001 degrees C using the map
711 * table for the XO thermistor.
712 */
713int32_t pm8xxx_adc_tdkntcg_therm(int32_t adc_code,
714 const struct pm8xxx_adc_properties *adc_properties,
715 const struct pm8xxx_adc_chan_properties *chan_properties,
716 struct pm8xxx_adc_chan_result *adc_chan_result)
717{
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800718 int64_t xo_thm = 0;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700719
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800720 if (!chan_properties || !chan_properties->offset_gain_numerator ||
721 !chan_properties->offset_gain_denominator || !adc_properties
722 || !adc_chan_result)
723 return -EINVAL;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700724
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800725 xo_thm = pm8xxx_adc_scale_ratiometric_calib(adc_code,
726 adc_properties, chan_properties);
727 xo_thm <<= 4;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700728 pm8xxx_adc_map_linear(adcmap_ntcg_104ef_104fb,
729 ARRAY_SIZE(adcmap_ntcg_104ef_104fb),
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800730 xo_thm, &adc_chan_result->physical);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700731
732 return 0;
733}
734EXPORT_SYMBOL_GPL(pm8xxx_adc_tdkntcg_therm);
735
Siddartha Mohanadossae39c902011-11-09 17:54:31 -0800736int32_t pm8xxx_adc_batt_scaler(struct pm8xxx_adc_arb_btm_param *btm_param,
737 const struct pm8xxx_adc_properties *adc_properties,
738 const struct pm8xxx_adc_chan_properties *chan_properties)
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700739{
740 int rc;
741
742 rc = pm8xxx_adc_map_linear(
743 adcmap_btm_threshold,
744 ARRAY_SIZE(adcmap_btm_threshold),
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800745 (btm_param->low_thr_temp),
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700746 &btm_param->low_thr_voltage);
Siddartha Mohanadossae39c902011-11-09 17:54:31 -0800747 if (rc)
748 return rc;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700749
Siddartha Mohanadossae39c902011-11-09 17:54:31 -0800750 btm_param->low_thr_voltage *=
751 chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].dy;
752 do_div(btm_param->low_thr_voltage, adc_properties->adc_vdd_reference);
753 btm_param->low_thr_voltage +=
754 chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].adc_gnd;
755
756 rc = pm8xxx_adc_map_linear(
757 adcmap_btm_threshold,
758 ARRAY_SIZE(adcmap_btm_threshold),
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800759 (btm_param->high_thr_temp),
Siddartha Mohanadossae39c902011-11-09 17:54:31 -0800760 &btm_param->high_thr_voltage);
761 if (rc)
762 return rc;
763
764 btm_param->high_thr_voltage *=
765 chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].dy;
766 do_div(btm_param->high_thr_voltage, adc_properties->adc_vdd_reference);
767 btm_param->high_thr_voltage +=
768 chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].adc_gnd;
769
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700770
771 return rc;
772}
773EXPORT_SYMBOL_GPL(pm8xxx_adc_batt_scaler);