blob: 56c352aaaf9d9ecd982ea90440b8ff550b1f9edf [file] [log] [blame]
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -07001/*
Dipen Parmarb54e1062013-01-02 11:56:00 +05302 * Copyright (c) 2011-2013, The Linux Foundation. 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[] = {
Dipen Parmarb54e1062013-01-02 11:56:00 +0530274 {374682, -40960},
275 {360553, -39936},
276 {346630, -38912},
277 {332940, -37888},
278 {319510, -36864},
279 {306363, -35840},
280 {293521, -34816},
281 {281001, -33792},
282 {268818, -32768},
283 {256987, -31744},
284 {245516, -30720},
285 {234413, -29696},
286 {223685, -28672},
287 {213333, -27648},
288 {203360, -26624},
289 {193763, -25600},
290 {184541, -24576},
291 {175691, -23552},
292 {167205, -22528},
293 {159079, -21504},
294 {151304, -20480},
295 {143872, -19456},
296 {136775, -18432},
297 {130001, -17408},
298 {123542, -16384},
299 {117387, -15360},
300 {111526, -14336},
301 {105946, -13312},
302 {100639, -12288},
303 {95592, -11264},
304 {90795, -10240},
305 {86238, -9216},
306 {81909, -8192},
307 {77800, -7168},
308 {73899, -6144},
309 {70197, -5120},
310 {66685, -4096},
311 {63354, -3072},
312 {60194, -2048},
313 {57198, -1024},
314 {54356, 0},
315 {51662, 1024},
316 {49108, 2048},
317 {46687, 3072},
318 {44391, 4096},
319 {42215, 5120},
320 {40151, 6144},
321 {38195, 7168},
322 {36340, 8192},
323 {34582, 9216},
324 {32914, 10240},
325 {31333, 11264},
326 {29833, 12288},
327 {28410, 13312},
328 {27061, 14336},
329 {25781, 15360},
330 {24566, 16384},
331 {23413, 17408},
332 {22319, 18432},
333 {21280, 19456},
334 {20294, 20480},
335 {19358, 21504},
336 {18469, 22528},
337 {17624, 23552},
338 {16822, 24576},
339 {16060, 25600},
340 {15335, 26624},
341 {14646, 27648},
342 {13992, 28672},
343 {13369, 29696},
344 {12777, 30720},
345 {12214, 31744},
346 {11678, 32768},
347 {11168, 33792},
348 {10682, 34816},
349 {10220, 35840},
350 {9780, 36864},
351 {9361, 37888},
352 {8962, 38912},
353 {8582, 39936},
354 {8219, 40960},
355 {7874, 41984},
356 {7545, 43008},
357 {7231, 44032},
358 {6931, 45056},
359 {6646, 46080},
360 {6373, 47104},
361 {6113, 48128},
362 {5865, 49152},
363 {5628, 50176},
364 {5402, 51200},
365 {5185, 52224},
366 {4979, 53248},
367 {4782, 54272},
368 {4593, 55296},
369 {4413, 56320},
370 {4241, 57344},
371 {4076, 58368},
372 {3919, 59392},
373 {3768, 60416},
374 {3624, 61440},
375 {3486, 62464},
376 {3354, 63488},
377 {3227, 64512},
378 {3106, 65536},
379 {2990, 66560},
380 {2879, 67584},
381 {2773, 68608},
382 {2671, 69632},
383 {2573, 70656},
384 {2479, 71680},
385 {2390, 72704},
386 {2303, 73728},
387 {2221, 74752},
388 {2142, 75776},
389 {2066, 76800},
390 {1993, 77824},
391 {1923, 78848},
392 {1855, 79872},
393 {1791, 80896},
394 {1729, 81920},
395 {1669, 82944},
396 {1612, 83968},
397 {1557, 84992},
398 {1504, 86016},
399 {1453, 87040},
400 {1404, 88064},
401 {1357, 89088},
402 {1312, 90112},
403 {1269, 91136},
404 {1227, 92160},
405 {1187, 93184},
406 {1148, 94208},
407 {1111, 95232},
408 {1075, 96256},
409 {1040, 97280},
410 {1007, 98304},
411 {975, 99328},
412 {944, 100352},
413 {914, 101376},
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700414 {886, 102400},
Dipen Parmarb54e1062013-01-02 11:56:00 +0530415 {858, 103424},
416 {831, 104448},
417 {806, 105472},
418 {781, 106496},
419 {757, 107520},
420 {734, 108544},
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700421 {712, 109568},
Dipen Parmarb54e1062013-01-02 11:56:00 +0530422 {690, 110592},
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700423 {670, 111616},
424 {650, 112640},
Dipen Parmarb54e1062013-01-02 11:56:00 +0530425 {630, 113664},
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700426 {612, 114688},
427 {594, 115712},
Dipen Parmarb54e1062013-01-02 11:56:00 +0530428 {576, 116736},
429 {559, 117760},
430 {543, 118784},
431 {527, 119808},
432 {512, 120832},
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700433 {498, 121856},
434 {483, 122880},
435 {470, 123904},
Dipen Parmarb54e1062013-01-02 11:56:00 +0530436 {456, 124928},
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700437 {444, 125952},
438 {431, 126976},
Dipen Parmarb54e1062013-01-02 11:56:00 +0530439 {419, 128000},
440 {408, 129024},
441 {396, 130048}
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700442};
443
444static int32_t pm8xxx_adc_map_linear(const struct pm8xxx_adc_map_pt *pts,
445 uint32_t tablesize, int32_t input, int64_t *output)
446{
447 bool descending = 1;
448 uint32_t i = 0;
449
450 if ((pts == NULL) || (output == NULL))
451 return -EINVAL;
452
453 /* Check if table is descending or ascending */
454 if (tablesize > 1) {
455 if (pts[0].x < pts[1].x)
456 descending = 0;
457 }
458
459 while (i < tablesize) {
460 if ((descending == 1) && (pts[i].x < input)) {
461 /* table entry is less than measured
462 value and table is descending, stop */
463 break;
464 } else if ((descending == 0) &&
465 (pts[i].x > input)) {
466 /* table entry is greater than measured
467 value and table is ascending, stop */
468 break;
469 } else {
470 i++;
471 }
472 }
473
474 if (i == 0)
475 *output = pts[0].y;
476 else if (i == tablesize)
477 *output = pts[tablesize-1].y;
478 else {
479 /* result is between search_index and search_index-1 */
480 /* interpolate linearly */
481 *output = (((int32_t) ((pts[i].y - pts[i-1].y)*
482 (input - pts[i-1].x))/
483 (pts[i].x - pts[i-1].x))+
484 pts[i-1].y);
485 }
486
487 return 0;
488}
489
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800490static int32_t pm8xxx_adc_map_batt_therm(const struct pm8xxx_adc_map_pt *pts,
491 uint32_t tablesize, int32_t input, int64_t *output)
492{
493 bool descending = 1;
494 uint32_t i = 0;
495
496 if ((pts == NULL) || (output == NULL))
497 return -EINVAL;
498
499 /* Check if table is descending or ascending */
500 if (tablesize > 1) {
501 if (pts[0].y < pts[1].y)
502 descending = 0;
503 }
504
505 while (i < tablesize) {
506 if ((descending == 1) && (pts[i].y < input)) {
507 /* table entry is less than measured
508 value and table is descending, stop */
509 break;
510 } else if ((descending == 0) && (pts[i].y > input)) {
511 /* table entry is greater than measured
512 value and table is ascending, stop */
513 break;
514 } else {
515 i++;
516 }
517 }
518
519 if (i == 0) {
520 *output = pts[0].x;
521 } else if (i == tablesize) {
522 *output = pts[tablesize-1].x;
523 } else {
524 /* result is between search_index and search_index-1 */
525 /* interpolate linearly */
526 *output = (((int32_t) ((pts[i].x - pts[i-1].x)*
527 (input - pts[i-1].y))/
528 (pts[i].y - pts[i-1].y))+
529 pts[i-1].x);
530 }
531
532 return 0;
533}
534
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700535int32_t pm8xxx_adc_scale_default(int32_t adc_code,
536 const struct pm8xxx_adc_properties *adc_properties,
537 const struct pm8xxx_adc_chan_properties *chan_properties,
538 struct pm8xxx_adc_chan_result *adc_chan_result)
539{
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800540 bool negative_rawfromoffset = 0, negative_offset = 0;
541 int64_t scale_voltage = 0;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700542
543 if (!chan_properties || !chan_properties->offset_gain_numerator ||
544 !chan_properties->offset_gain_denominator || !adc_properties
545 || !adc_chan_result)
546 return -EINVAL;
547
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800548 scale_voltage = (adc_code -
549 chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].adc_gnd)
550 * chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dx;
551 if (scale_voltage < 0) {
552 negative_offset = 1;
553 scale_voltage = -scale_voltage;
554 }
555 do_div(scale_voltage,
556 chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dy);
557 if (negative_offset)
558 scale_voltage = -scale_voltage;
559 scale_voltage += chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dx;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700560
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800561 if (scale_voltage < 0) {
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700562 if (adc_properties->bipolar) {
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800563 scale_voltage = -scale_voltage;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700564 negative_rawfromoffset = 1;
565 } else {
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800566 scale_voltage = 0;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700567 }
568 }
569
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800570 adc_chan_result->measurement = scale_voltage *
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700571 chan_properties->offset_gain_denominator;
572
573 /* do_div only perform positive integer division! */
574 do_div(adc_chan_result->measurement,
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700575 chan_properties->offset_gain_numerator);
576
577 if (negative_rawfromoffset)
578 adc_chan_result->measurement = -adc_chan_result->measurement;
579
580 /* Note: adc_chan_result->measurement is in the unit of
581 * adc_properties.adc_reference. For generic channel processing,
582 * channel measurement is a scale/ratio relative to the adc
583 * reference input */
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800584 adc_chan_result->physical = adc_chan_result->measurement;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700585
586 return 0;
587}
588EXPORT_SYMBOL_GPL(pm8xxx_adc_scale_default);
589
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800590static int64_t pm8xxx_adc_scale_ratiometric_calib(int32_t adc_code,
591 const struct pm8xxx_adc_properties *adc_properties,
592 const struct pm8xxx_adc_chan_properties *chan_properties)
593{
594 int64_t adc_voltage = 0;
595 bool negative_offset = 0;
596
597 if (!chan_properties || !chan_properties->offset_gain_numerator ||
598 !chan_properties->offset_gain_denominator || !adc_properties)
599 return -EINVAL;
600
601 adc_voltage = (adc_code -
602 chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].adc_gnd)
603 * adc_properties->adc_vdd_reference;
604 if (adc_voltage < 0) {
605 negative_offset = 1;
606 adc_voltage = -adc_voltage;
607 }
608 do_div(adc_voltage,
609 chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].dy);
610 if (negative_offset)
611 adc_voltage = -adc_voltage;
612
613 return adc_voltage;
614}
615
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700616int32_t pm8xxx_adc_scale_batt_therm(int32_t adc_code,
617 const struct pm8xxx_adc_properties *adc_properties,
618 const struct pm8xxx_adc_chan_properties *chan_properties,
619 struct pm8xxx_adc_chan_result *adc_chan_result)
620{
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800621 int64_t bat_voltage = 0;
622
623 bat_voltage = pm8xxx_adc_scale_ratiometric_calib(adc_code,
624 adc_properties, chan_properties);
625
626 return pm8xxx_adc_map_batt_therm(
627 adcmap_btm_threshold,
628 ARRAY_SIZE(adcmap_btm_threshold),
629 bat_voltage,
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700630 &adc_chan_result->physical);
631}
632EXPORT_SYMBOL_GPL(pm8xxx_adc_scale_batt_therm);
633
634int32_t pm8xxx_adc_scale_pa_therm(int32_t adc_code,
635 const struct pm8xxx_adc_properties *adc_properties,
636 const struct pm8xxx_adc_chan_properties *chan_properties,
637 struct pm8xxx_adc_chan_result *adc_chan_result)
638{
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800639 int64_t pa_voltage = 0;
640
641 pa_voltage = pm8xxx_adc_scale_ratiometric_calib(adc_code,
642 adc_properties, chan_properties);
643
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700644 return pm8xxx_adc_map_linear(
645 adcmap_pa_therm,
646 ARRAY_SIZE(adcmap_pa_therm),
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800647 pa_voltage,
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700648 &adc_chan_result->physical);
649}
650EXPORT_SYMBOL_GPL(pm8xxx_adc_scale_pa_therm);
651
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800652int32_t pm8xxx_adc_scale_batt_id(int32_t adc_code,
653 const struct pm8xxx_adc_properties *adc_properties,
654 const struct pm8xxx_adc_chan_properties *chan_properties,
655 struct pm8xxx_adc_chan_result *adc_chan_result)
656{
657 int64_t batt_id_voltage = 0;
658
659 batt_id_voltage = pm8xxx_adc_scale_ratiometric_calib(adc_code,
660 adc_properties, chan_properties);
661 adc_chan_result->physical = batt_id_voltage;
662 adc_chan_result->physical = adc_chan_result->measurement;
663
664 return 0;
665}
666EXPORT_SYMBOL_GPL(pm8xxx_adc_scale_batt_id);
667
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700668int32_t pm8xxx_adc_scale_pmic_therm(int32_t adc_code,
669 const struct pm8xxx_adc_properties *adc_properties,
670 const struct pm8xxx_adc_chan_properties *chan_properties,
671 struct pm8xxx_adc_chan_result *adc_chan_result)
672{
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800673 int64_t pmic_voltage = 0;
674 bool negative_offset = 0;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700675
676 if (!chan_properties || !chan_properties->offset_gain_numerator ||
677 !chan_properties->offset_gain_denominator || !adc_properties
678 || !adc_chan_result)
679 return -EINVAL;
680
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800681 pmic_voltage = (adc_code -
682 chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].adc_gnd)
683 * chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dx;
684 if (pmic_voltage < 0) {
685 negative_offset = 1;
686 pmic_voltage = -pmic_voltage;
687 }
688 do_div(pmic_voltage,
689 chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dy);
690 if (negative_offset)
691 pmic_voltage = -pmic_voltage;
692 pmic_voltage += chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dx;
693
694 if (pmic_voltage > 0) {
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700695 /* 2mV/K */
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800696 adc_chan_result->measurement = pmic_voltage*
697 chan_properties->offset_gain_denominator;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700698
699 do_div(adc_chan_result->measurement,
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800700 chan_properties->offset_gain_numerator * 2);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700701 } else {
702 adc_chan_result->measurement = 0;
703 }
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700704 /* Change to .001 deg C */
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800705 adc_chan_result->measurement -= KELVINMIL_DEGMIL;
706 adc_chan_result->physical = (int32_t)adc_chan_result->measurement;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700707
708 return 0;
709}
710EXPORT_SYMBOL_GPL(pm8xxx_adc_scale_pmic_therm);
711
712/* Scales the ADC code to 0.001 degrees C using the map
713 * table for the XO thermistor.
714 */
715int32_t pm8xxx_adc_tdkntcg_therm(int32_t adc_code,
716 const struct pm8xxx_adc_properties *adc_properties,
717 const struct pm8xxx_adc_chan_properties *chan_properties,
718 struct pm8xxx_adc_chan_result *adc_chan_result)
719{
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800720 int64_t xo_thm = 0;
Dipen Parmarb54e1062013-01-02 11:56:00 +0530721 uint32_t num1 = 0;
722 uint32_t num2 = 0;
723 uint32_t dnum = 0;
724 uint32_t rt_r25 = 0;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700725
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800726 if (!chan_properties || !chan_properties->offset_gain_numerator ||
727 !chan_properties->offset_gain_denominator || !adc_properties
728 || !adc_chan_result)
729 return -EINVAL;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700730
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800731 xo_thm = pm8xxx_adc_scale_ratiometric_calib(adc_code,
732 adc_properties, chan_properties);
Dipen Parmarb54e1062013-01-02 11:56:00 +0530733 if (xo_thm < 0)
734 xo_thm = -xo_thm;
735
736 num1 = xo_thm << 14;
737 num2 = (adc_properties->adc_vdd_reference - xo_thm) >> 1;
738 dnum = (adc_properties->adc_vdd_reference - xo_thm);
739
740 if (dnum == 0)
741 rt_r25 = 0x7FFFFFFF ;
742 else
743 rt_r25 = (num1 + num2)/dnum ;
744
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700745 pm8xxx_adc_map_linear(adcmap_ntcg_104ef_104fb,
746 ARRAY_SIZE(adcmap_ntcg_104ef_104fb),
Dipen Parmarb54e1062013-01-02 11:56:00 +0530747 rt_r25, &adc_chan_result->physical);
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700748
749 return 0;
750}
751EXPORT_SYMBOL_GPL(pm8xxx_adc_tdkntcg_therm);
752
Siddartha Mohanadossae39c902011-11-09 17:54:31 -0800753int32_t pm8xxx_adc_batt_scaler(struct pm8xxx_adc_arb_btm_param *btm_param,
754 const struct pm8xxx_adc_properties *adc_properties,
755 const struct pm8xxx_adc_chan_properties *chan_properties)
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700756{
757 int rc;
758
759 rc = pm8xxx_adc_map_linear(
760 adcmap_btm_threshold,
761 ARRAY_SIZE(adcmap_btm_threshold),
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800762 (btm_param->low_thr_temp),
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700763 &btm_param->low_thr_voltage);
Siddartha Mohanadossae39c902011-11-09 17:54:31 -0800764 if (rc)
765 return rc;
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700766
Siddartha Mohanadossae39c902011-11-09 17:54:31 -0800767 btm_param->low_thr_voltage *=
768 chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].dy;
769 do_div(btm_param->low_thr_voltage, adc_properties->adc_vdd_reference);
770 btm_param->low_thr_voltage +=
771 chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].adc_gnd;
772
773 rc = pm8xxx_adc_map_linear(
774 adcmap_btm_threshold,
775 ARRAY_SIZE(adcmap_btm_threshold),
Siddartha Mohanadoss37e6fc02011-11-16 16:57:03 -0800776 (btm_param->high_thr_temp),
Siddartha Mohanadossae39c902011-11-09 17:54:31 -0800777 &btm_param->high_thr_voltage);
778 if (rc)
779 return rc;
780
781 btm_param->high_thr_voltage *=
782 chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].dy;
783 do_div(btm_param->high_thr_voltage, adc_properties->adc_vdd_reference);
784 btm_param->high_thr_voltage +=
785 chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].adc_gnd;
786
Siddartha Mohanadoss17607d22011-10-05 10:36:20 -0700787
788 return rc;
789}
790EXPORT_SYMBOL_GPL(pm8xxx_adc_batt_scaler);