blob: 7bc877313e0c25cafe0dfa918069bda086e30d43 [file] [log] [blame]
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -08001/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#define pr_fmt(fmt) "%s: " fmt, __func__
14
15#include <linux/kernel.h>
16#include <linux/of.h>
17#include <linux/err.h>
18#include <linux/init.h>
19#include <linux/slab.h>
20#include <linux/delay.h>
21#include <linux/mutex.h>
22#include <linux/types.h>
23#include <linux/hwmon.h>
24#include <linux/module.h>
25#include <linux/debugfs.h>
26#include <linux/spmi.h>
27#include <linux/of_irq.h>
28#include <linux/interrupt.h>
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -070029#include <linux/completion.h>
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -070030#include <linux/qpnp/qpnp-adc.h>
31#include <linux/platform_device.h>
32
33/* Min ADC code represets 0V */
34#define QPNP_VADC_MIN_ADC_CODE 0x6000
35/* Max ADC code represents full-scale range of 1.8V */
36#define QPNP_VADC_MAX_ADC_CODE 0xA800
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -070037#define KELVINMIL_DEGMIL 273160
38
39/* Units for temperature below (on x axis) is in 0.1DegC as
40 required by the battery driver. Note the resolution used
41 here to compute the table was done for DegC to milli-volts.
42 In consideration to limit the size of the table for the given
43 temperature range below, the result is linearly interpolated
44 and provided to the battery driver in the units desired for
45 their framework which is 0.1DegC. True resolution of 0.1DegC
46 will result in the below table size to increase by 10 times */
47static const struct qpnp_vadc_map_pt adcmap_btm_threshold[] = {
48 {-300, 1642},
49 {-200, 1544},
50 {-100, 1414},
51 {0, 1260},
52 {10, 1244},
53 {20, 1228},
54 {30, 1212},
55 {40, 1195},
56 {50, 1179},
57 {60, 1162},
58 {70, 1146},
59 {80, 1129},
60 {90, 1113},
61 {100, 1097},
62 {110, 1080},
63 {120, 1064},
64 {130, 1048},
65 {140, 1032},
66 {150, 1016},
67 {160, 1000},
68 {170, 985},
69 {180, 969},
70 {190, 954},
71 {200, 939},
72 {210, 924},
73 {220, 909},
74 {230, 894},
75 {240, 880},
76 {250, 866},
77 {260, 852},
78 {270, 838},
79 {280, 824},
80 {290, 811},
81 {300, 798},
82 {310, 785},
83 {320, 773},
84 {330, 760},
85 {340, 748},
86 {350, 736},
87 {360, 725},
88 {370, 713},
89 {380, 702},
90 {390, 691},
91 {400, 681},
92 {410, 670},
93 {420, 660},
94 {430, 650},
95 {440, 640},
96 {450, 631},
97 {460, 622},
98 {470, 613},
99 {480, 604},
100 {490, 595},
101 {500, 587},
102 {510, 579},
103 {520, 571},
104 {530, 563},
105 {540, 556},
106 {550, 548},
107 {560, 541},
108 {570, 534},
109 {580, 527},
110 {590, 521},
111 {600, 514},
112 {610, 508},
113 {620, 502},
114 {630, 496},
115 {640, 490},
116 {650, 485},
117 {660, 281},
118 {670, 274},
119 {680, 267},
120 {690, 260},
121 {700, 254},
122 {710, 247},
123 {720, 241},
124 {730, 235},
125 {740, 229},
126 {750, 224},
127 {760, 218},
128 {770, 213},
129 {780, 208},
130 {790, 203}
131};
132
Siddartha Mohanadossb99cfa92013-05-01 20:19:58 -0700133static const struct qpnp_vadc_map_pt adcmap_qrd_btm_threshold[] = {
Xu Kaid6a9c312013-07-27 12:42:31 +0800134 {-200, 1540},
135 {-180, 1517},
136 {-160, 1492},
137 {-140, 1467},
138 {-120, 1440},
139 {-100, 1412},
140 {-80, 1383},
141 {-60, 1353},
142 {-40, 1323},
143 {-20, 1292},
144 {0, 1260},
145 {20, 1228},
146 {40, 1196},
147 {60, 1163},
148 {80, 1131},
149 {100, 1098},
150 {120, 1066},
151 {140, 1034},
152 {160, 1002},
153 {180, 971},
154 {200, 941},
155 {220, 911},
156 {240, 882},
157 {260, 854},
158 {280, 826},
159 {300, 800},
160 {320, 774},
161 {340, 749},
162 {360, 726},
163 {380, 703},
164 {400, 681},
165 {420, 660},
166 {440, 640},
167 {460, 621},
168 {480, 602},
169 {500, 585},
170 {520, 568},
171 {540, 552},
172 {560, 537},
173 {580, 523},
174 {600, 510},
175 {620, 497},
176 {640, 485},
177 {660, 473},
178 {680, 462},
179 {700, 452},
180 {720, 442},
181 {740, 433},
182 {760, 424},
183 {780, 416},
184 {800, 408},
Siddartha Mohanadossb99cfa92013-05-01 20:19:58 -0700185};
186
Xu Kai81c60522013-07-27 14:26:04 +0800187static const struct qpnp_vadc_map_pt adcmap_qrd_skuaa_btm_threshold[] = {
188 {-200, 1476},
189 {-180, 1450},
190 {-160, 1422},
191 {-140, 1394},
192 {-120, 1365},
193 {-100, 1336},
194 {-80, 1306},
195 {-60, 1276},
196 {-40, 1246},
197 {-20, 1216},
198 {0, 1185},
199 {20, 1155},
200 {40, 1126},
201 {60, 1096},
202 {80, 1068},
203 {100, 1040},
204 {120, 1012},
205 {140, 986},
206 {160, 960},
207 {180, 935},
208 {200, 911},
209 {220, 888},
210 {240, 866},
211 {260, 844},
212 {280, 824},
213 {300, 805},
214 {320, 786},
215 {340, 769},
216 {360, 752},
217 {380, 737},
218 {400, 722},
219 {420, 707},
220 {440, 694},
221 {460, 681},
222 {480, 669},
223 {500, 658},
224 {520, 648},
225 {540, 637},
226 {560, 628},
227 {580, 619},
228 {600, 611},
229 {620, 603},
230 {640, 595},
231 {660, 588},
232 {680, 582},
233 {700, 575},
234 {720, 569},
235 {740, 564},
236 {760, 559},
237 {780, 554},
238 {800, 549},
239};
240
Wu Fenglin2c6ef8f2013-12-17 11:33:33 +0800241static const struct qpnp_vadc_map_pt adcmap_qrd_skug_btm_threshold[] = {
242 {-200, 1338},
243 {-180, 1307},
244 {-160, 1276},
245 {-140, 1244},
246 {-120, 1213},
247 {-100, 1182},
248 {-80, 1151},
249 {-60, 1121},
250 {-40, 1092},
251 {-20, 1063},
252 {0, 1035},
253 {20, 1008},
254 {40, 982},
255 {60, 957},
256 {80, 933},
257 {100, 910},
258 {120, 889},
259 {140, 868},
260 {160, 848},
261 {180, 830},
262 {200, 812},
263 {220, 795},
264 {240, 780},
265 {260, 765},
266 {280, 751},
267 {300, 738},
268 {320, 726},
269 {340, 714},
270 {360, 704},
271 {380, 694},
272 {400, 684},
273 {420, 675},
274 {440, 667},
275 {460, 659},
276 {480, 652},
277 {500, 645},
278 {520, 639},
279 {540, 633},
280 {560, 627},
281 {580, 622},
282 {600, 617},
283 {620, 613},
284 {640, 608},
285 {660, 604},
286 {680, 600},
287 {700, 597},
288 {720, 593},
289 {740, 590},
290 {760, 587},
291 {780, 585},
292 {800, 582},
293};
294
Siddartha Mohanadosse84f8e62012-11-16 09:34:41 -0800295/* Voltage to temperature */
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700296static const struct qpnp_vadc_map_pt adcmap_100k_104ef_104fb[] = {
Siddartha Mohanadosse84f8e62012-11-16 09:34:41 -0800297 {1758, -40},
298 {1742, -35},
299 {1719, -30},
300 {1691, -25},
301 {1654, -20},
302 {1608, -15},
303 {1551, -10},
304 {1483, -5},
305 {1404, 0},
306 {1315, 5},
307 {1218, 10},
308 {1114, 15},
309 {1007, 20},
310 {900, 25},
311 {795, 30},
312 {696, 35},
313 {605, 40},
314 {522, 45},
315 {448, 50},
316 {383, 55},
317 {327, 60},
318 {278, 65},
319 {237, 70},
320 {202, 75},
321 {172, 80},
322 {146, 85},
323 {125, 90},
324 {107, 95},
325 {92, 100},
326 {79, 105},
327 {68, 110},
328 {59, 115},
329 {51, 120},
330 {44, 125}
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700331};
332
Siddartha Mohanadosse84f8e62012-11-16 09:34:41 -0800333/* Voltage to temperature */
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700334static const struct qpnp_vadc_map_pt adcmap_150k_104ef_104fb[] = {
Siddartha Mohanadosse84f8e62012-11-16 09:34:41 -0800335 {1738, -40},
336 {1714, -35},
337 {1682, -30},
338 {1641, -25},
339 {1589, -20},
340 {1526, -15},
341 {1451, -10},
342 {1363, -5},
343 {1266, 0},
344 {1159, 5},
345 {1048, 10},
346 {936, 15},
347 {825, 20},
348 {720, 25},
349 {622, 30},
350 {533, 35},
351 {454, 40},
352 {385, 45},
353 {326, 50},
354 {275, 55},
355 {232, 60},
356 {195, 65},
357 {165, 70},
358 {139, 75},
359 {118, 80},
360 {100, 85},
361 {85, 90},
362 {73, 95},
363 {62, 100},
364 {53, 105},
365 {46, 110},
366 {40, 115},
367 {34, 120},
368 {30, 125}
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700369};
370
Siddartha Mohanadoss4a27b1c2012-11-16 09:34:41 -0800371static int32_t qpnp_adc_map_voltage_temp(const struct qpnp_vadc_map_pt *pts,
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700372 uint32_t tablesize, int32_t input, int64_t *output)
373{
374 bool descending = 1;
375 uint32_t i = 0;
376
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700377 if (pts == NULL)
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700378 return -EINVAL;
379
380 /* Check if table is descending or ascending */
381 if (tablesize > 1) {
382 if (pts[0].x < pts[1].x)
383 descending = 0;
384 }
385
386 while (i < tablesize) {
387 if ((descending == 1) && (pts[i].x < input)) {
388 /* table entry is less than measured
389 value and table is descending, stop */
390 break;
391 } else if ((descending == 0) &&
392 (pts[i].x > input)) {
393 /* table entry is greater than measured
394 value and table is ascending, stop */
395 break;
396 } else {
397 i++;
398 }
399 }
400
401 if (i == 0)
402 *output = pts[0].y;
403 else if (i == tablesize)
404 *output = pts[tablesize-1].y;
405 else {
406 /* result is between search_index and search_index-1 */
407 /* interpolate linearly */
408 *output = (((int32_t) ((pts[i].y - pts[i-1].y)*
409 (input - pts[i-1].x))/
410 (pts[i].x - pts[i-1].x))+
411 pts[i-1].y);
412 }
413
414 return 0;
415}
416
Siddartha Mohanadoss4a27b1c2012-11-16 09:34:41 -0800417static int32_t qpnp_adc_map_temp_voltage(const struct qpnp_vadc_map_pt *pts,
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700418 uint32_t tablesize, int32_t input, int64_t *output)
419{
420 bool descending = 1;
421 uint32_t i = 0;
422
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700423 if (pts == NULL)
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700424 return -EINVAL;
425
426 /* Check if table is descending or ascending */
427 if (tablesize > 1) {
428 if (pts[0].y < pts[1].y)
429 descending = 0;
430 }
431
432 while (i < tablesize) {
433 if ((descending == 1) && (pts[i].y < input)) {
434 /* table entry is less than measured
435 value and table is descending, stop */
436 break;
437 } else if ((descending == 0) && (pts[i].y > input)) {
438 /* table entry is greater than measured
439 value and table is ascending, stop */
440 break;
441 } else {
442 i++;
443 }
444 }
445
446 if (i == 0) {
447 *output = pts[0].x;
448 } else if (i == tablesize) {
449 *output = pts[tablesize-1].x;
450 } else {
451 /* result is between search_index and search_index-1 */
452 /* interpolate linearly */
453 *output = (((int32_t) ((pts[i].x - pts[i-1].x)*
454 (input - pts[i-1].y))/
455 (pts[i].y - pts[i-1].y))+
456 pts[i-1].x);
457 }
458
459 return 0;
460}
461
462static int64_t qpnp_adc_scale_ratiometric_calib(int32_t adc_code,
463 const struct qpnp_adc_properties *adc_properties,
464 const struct qpnp_vadc_chan_properties *chan_properties)
465{
466 int64_t adc_voltage = 0;
467 bool negative_offset = 0;
468
469 if (!chan_properties || !chan_properties->offset_gain_numerator ||
470 !chan_properties->offset_gain_denominator || !adc_properties)
471 return -EINVAL;
472
473 adc_voltage = (adc_code -
474 chan_properties->adc_graph[CALIB_RATIOMETRIC].adc_gnd)
475 * adc_properties->adc_vdd_reference;
476 if (adc_voltage < 0) {
477 negative_offset = 1;
478 adc_voltage = -adc_voltage;
479 }
480 do_div(adc_voltage,
481 chan_properties->adc_graph[CALIB_RATIOMETRIC].dy);
482 if (negative_offset)
483 adc_voltage = -adc_voltage;
484
485 return adc_voltage;
486}
487
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700488int32_t qpnp_adc_scale_pmic_therm(struct qpnp_vadc_chip *vadc,
489 int32_t adc_code,
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700490 const struct qpnp_adc_properties *adc_properties,
491 const struct qpnp_vadc_chan_properties *chan_properties,
492 struct qpnp_vadc_result *adc_chan_result)
493{
494 int64_t pmic_voltage = 0;
495 bool negative_offset = 0;
496
497 if (!chan_properties || !chan_properties->offset_gain_numerator ||
498 !chan_properties->offset_gain_denominator || !adc_properties
Dipen Parmar454c4b12013-11-25 14:40:47 +0530499 || !adc_chan_result
500 || !chan_properties->adc_graph[CALIB_ABSOLUTE].dy)
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700501 return -EINVAL;
502
503 pmic_voltage = (adc_code -
504 chan_properties->adc_graph[CALIB_ABSOLUTE].adc_gnd)
505 * chan_properties->adc_graph[CALIB_ABSOLUTE].dx;
506 if (pmic_voltage < 0) {
507 negative_offset = 1;
508 pmic_voltage = -pmic_voltage;
509 }
510 do_div(pmic_voltage,
511 chan_properties->adc_graph[CALIB_ABSOLUTE].dy);
512 if (negative_offset)
513 pmic_voltage = -pmic_voltage;
514 pmic_voltage += chan_properties->adc_graph[CALIB_ABSOLUTE].dx;
515
516 if (pmic_voltage > 0) {
517 /* 2mV/K */
518 adc_chan_result->measurement = pmic_voltage*
519 chan_properties->offset_gain_denominator;
520
521 do_div(adc_chan_result->measurement,
522 chan_properties->offset_gain_numerator * 2);
523 } else {
524 adc_chan_result->measurement = 0;
525 }
526 /* Change to .001 deg C */
527 adc_chan_result->measurement -= KELVINMIL_DEGMIL;
528 adc_chan_result->physical = (int32_t)adc_chan_result->measurement;
529
530 return 0;
531}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700532EXPORT_SYMBOL(qpnp_adc_scale_pmic_therm);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700533
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700534int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(struct qpnp_vadc_chip *chip,
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800535 struct qpnp_adc_tm_btm_param *param,
536 uint32_t *low_threshold, uint32_t *high_threshold)
537{
538 struct qpnp_vadc_linear_graph btm_param;
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700539 int64_t low_output = 0, high_output = 0;
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700540 int rc = 0, sign = 0;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800541
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700542 rc = qpnp_get_vadc_gain_and_offset(chip, &btm_param, CALIB_ABSOLUTE);
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800543 if (rc < 0) {
544 pr_err("Could not acquire gain and offset\n");
545 return rc;
546 }
547
548 /* Convert to Kelvin and account for voltage to be written as 2mV/K */
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700549 low_output = (param->low_temp + KELVINMIL_DEGMIL) * 2;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800550 /* Convert to voltage threshold */
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700551 low_output = (low_output - QPNP_ADC_625_UV) * btm_param.dy;
552 if (low_output < 0) {
553 sign = 1;
554 low_output = -low_output;
555 }
556 do_div(low_output, QPNP_ADC_625_UV);
557 if (sign)
558 low_output = -low_output;
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700559 low_output += btm_param.adc_gnd;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800560
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700561 sign = 0;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800562 /* Convert to Kelvin and account for voltage to be written as 2mV/K */
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700563 high_output = (param->high_temp + KELVINMIL_DEGMIL) * 2;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800564 /* Convert to voltage threshold */
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700565 high_output = (high_output - QPNP_ADC_625_UV) * btm_param.dy;
566 if (high_output < 0) {
567 sign = 1;
568 high_output = -high_output;
569 }
570 do_div(high_output, QPNP_ADC_625_UV);
571 if (sign)
572 high_output = -high_output;
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700573 high_output += btm_param.adc_gnd;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800574
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700575 *low_threshold = (uint32_t) low_output;
576 *high_threshold = (uint32_t) high_output;
577 pr_debug("high_temp:%d, low_temp:%d\n", param->high_temp,
578 param->low_temp);
579 pr_debug("adc_code_high:%x, adc_code_low:%x\n", *high_threshold,
580 *low_threshold);
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800581
582 return 0;
583}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700584EXPORT_SYMBOL(qpnp_adc_scale_millidegc_pmic_voltage_thr);
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800585
586/* Scales the ADC code to degC using the mapping
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700587 * table for the XO thermistor.
588 */
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700589int32_t qpnp_adc_tdkntcg_therm(struct qpnp_vadc_chip *chip,
590 int32_t adc_code,
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700591 const struct qpnp_adc_properties *adc_properties,
592 const struct qpnp_vadc_chan_properties *chan_properties,
593 struct qpnp_vadc_result *adc_chan_result)
594{
595 int64_t xo_thm = 0;
596
597 if (!chan_properties || !chan_properties->offset_gain_numerator ||
598 !chan_properties->offset_gain_denominator || !adc_properties
599 || !adc_chan_result)
600 return -EINVAL;
601
602 xo_thm = qpnp_adc_scale_ratiometric_calib(adc_code,
603 adc_properties, chan_properties);
Siddartha Mohanadoss0dc06942012-12-23 17:10:10 -0800604
605 qpnp_adc_map_voltage_temp(adcmap_100k_104ef_104fb,
606 ARRAY_SIZE(adcmap_100k_104ef_104fb),
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700607 xo_thm, &adc_chan_result->physical);
608
609 return 0;
610}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700611EXPORT_SYMBOL(qpnp_adc_tdkntcg_therm);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700612
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700613int32_t qpnp_adc_scale_batt_therm(struct qpnp_vadc_chip *chip,
614 int32_t adc_code,
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700615 const struct qpnp_adc_properties *adc_properties,
616 const struct qpnp_vadc_chan_properties *chan_properties,
617 struct qpnp_vadc_result *adc_chan_result)
618{
619 int64_t bat_voltage = 0;
620
621 bat_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
622 adc_properties, chan_properties);
623
Siddartha Mohanadoss4a27b1c2012-11-16 09:34:41 -0800624 return qpnp_adc_map_temp_voltage(
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700625 adcmap_btm_threshold,
626 ARRAY_SIZE(adcmap_btm_threshold),
627 bat_voltage,
628 &adc_chan_result->physical);
629}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700630EXPORT_SYMBOL(qpnp_adc_scale_batt_therm);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700631
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700632int32_t qpnp_adc_scale_qrd_batt_therm(struct qpnp_vadc_chip *chip,
633 int32_t adc_code,
Siddartha Mohanadossb99cfa92013-05-01 20:19:58 -0700634 const struct qpnp_adc_properties *adc_properties,
635 const struct qpnp_vadc_chan_properties *chan_properties,
636 struct qpnp_vadc_result *adc_chan_result)
637{
638 int64_t bat_voltage = 0;
639
640 bat_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
641 adc_properties, chan_properties);
642
643 return qpnp_adc_map_temp_voltage(
644 adcmap_qrd_btm_threshold,
645 ARRAY_SIZE(adcmap_qrd_btm_threshold),
646 bat_voltage,
647 &adc_chan_result->physical);
648}
649EXPORT_SYMBOL(qpnp_adc_scale_qrd_batt_therm);
650
Xu Kai81c60522013-07-27 14:26:04 +0800651int32_t qpnp_adc_scale_qrd_skuaa_batt_therm(struct qpnp_vadc_chip *chip,
652 int32_t adc_code,
653 const struct qpnp_adc_properties *adc_properties,
654 const struct qpnp_vadc_chan_properties *chan_properties,
655 struct qpnp_vadc_result *adc_chan_result)
656{
657 int64_t bat_voltage = 0;
658
659 bat_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
660 adc_properties, chan_properties);
661
662 return qpnp_adc_map_temp_voltage(
663 adcmap_qrd_skuaa_btm_threshold,
664 ARRAY_SIZE(adcmap_qrd_skuaa_btm_threshold),
665 bat_voltage,
666 &adc_chan_result->physical);
667}
668EXPORT_SYMBOL(qpnp_adc_scale_qrd_skuaa_batt_therm);
669
Wu Fenglin2c6ef8f2013-12-17 11:33:33 +0800670int32_t qpnp_adc_scale_qrd_skug_batt_therm(struct qpnp_vadc_chip *chip,
671 int32_t adc_code,
672 const struct qpnp_adc_properties *adc_properties,
673 const struct qpnp_vadc_chan_properties *chan_properties,
674 struct qpnp_vadc_result *adc_chan_result)
675{
676 int64_t bat_voltage = 0;
677
678 bat_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
679 adc_properties, chan_properties);
680
681 return qpnp_adc_map_temp_voltage(
682 adcmap_qrd_skug_btm_threshold,
683 ARRAY_SIZE(adcmap_qrd_skug_btm_threshold),
684 bat_voltage,
685 &adc_chan_result->physical);
686}
687EXPORT_SYMBOL(qpnp_adc_scale_qrd_skug_batt_therm);
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700688int32_t qpnp_adc_scale_therm_pu1(struct qpnp_vadc_chip *chip,
689 int32_t adc_code,
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700690 const struct qpnp_adc_properties *adc_properties,
691 const struct qpnp_vadc_chan_properties *chan_properties,
692 struct qpnp_vadc_result *adc_chan_result)
693{
694 int64_t therm_voltage = 0;
695
696 therm_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
697 adc_properties, chan_properties);
698
Siddartha Mohanadosse84f8e62012-11-16 09:34:41 -0800699 qpnp_adc_map_voltage_temp(adcmap_150k_104ef_104fb,
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700700 ARRAY_SIZE(adcmap_150k_104ef_104fb),
701 therm_voltage, &adc_chan_result->physical);
702
703 return 0;
704}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700705EXPORT_SYMBOL(qpnp_adc_scale_therm_pu1);
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700706
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700707int32_t qpnp_adc_scale_therm_pu2(struct qpnp_vadc_chip *chip,
708 int32_t adc_code,
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700709 const struct qpnp_adc_properties *adc_properties,
710 const struct qpnp_vadc_chan_properties *chan_properties,
711 struct qpnp_vadc_result *adc_chan_result)
712{
713 int64_t therm_voltage = 0;
714
715 therm_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
716 adc_properties, chan_properties);
717
Siddartha Mohanadosse84f8e62012-11-16 09:34:41 -0800718 qpnp_adc_map_voltage_temp(adcmap_100k_104ef_104fb,
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700719 ARRAY_SIZE(adcmap_100k_104ef_104fb),
720 therm_voltage, &adc_chan_result->physical);
721
722 return 0;
723}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700724EXPORT_SYMBOL(qpnp_adc_scale_therm_pu2);
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700725
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700726int32_t qpnp_adc_tm_scale_voltage_therm_pu2(struct qpnp_vadc_chip *chip,
727 uint32_t reg, int64_t *result)
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800728{
729 int64_t adc_voltage = 0;
730 struct qpnp_vadc_linear_graph param1;
731 int negative_offset;
732
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700733 qpnp_get_vadc_gain_and_offset(chip, &param1, CALIB_RATIOMETRIC);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800734
735 adc_voltage = (reg - param1.adc_gnd) * param1.adc_vref;
736 if (adc_voltage < 0) {
737 negative_offset = 1;
738 adc_voltage = -adc_voltage;
739 }
740
741 do_div(adc_voltage, param1.dy);
742
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -0800743 qpnp_adc_map_voltage_temp(adcmap_100k_104ef_104fb,
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800744 ARRAY_SIZE(adcmap_100k_104ef_104fb),
745 adc_voltage, result);
746 if (negative_offset)
747 adc_voltage = -adc_voltage;
748
749 return 0;
750}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700751EXPORT_SYMBOL(qpnp_adc_tm_scale_voltage_therm_pu2);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800752
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700753int32_t qpnp_adc_tm_scale_therm_voltage_pu2(struct qpnp_vadc_chip *chip,
754 struct qpnp_adc_tm_config *param)
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800755{
756 struct qpnp_vadc_linear_graph param1;
757 int rc;
758
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700759 qpnp_get_vadc_gain_and_offset(chip, &param1, CALIB_RATIOMETRIC);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800760
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -0800761 rc = qpnp_adc_map_temp_voltage(adcmap_100k_104ef_104fb,
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800762 ARRAY_SIZE(adcmap_100k_104ef_104fb),
763 param->low_thr_temp, &param->low_thr_voltage);
764 if (rc)
765 return rc;
766
767 param->low_thr_voltage *= param1.dy;
768 do_div(param->low_thr_voltage, param1.adc_vref);
769 param->low_thr_voltage += param1.adc_gnd;
770
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -0800771 rc = qpnp_adc_map_temp_voltage(adcmap_100k_104ef_104fb,
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800772 ARRAY_SIZE(adcmap_100k_104ef_104fb),
773 param->high_thr_temp, &param->high_thr_voltage);
774 if (rc)
775 return rc;
776
777 param->high_thr_voltage *= param1.dy;
778 do_div(param->high_thr_voltage, param1.adc_vref);
779 param->high_thr_voltage += param1.adc_gnd;
780
781 return 0;
782}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700783EXPORT_SYMBOL(qpnp_adc_tm_scale_therm_voltage_pu2);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800784
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700785int32_t qpnp_adc_scale_batt_id(struct qpnp_vadc_chip *chip,
786 int32_t adc_code,
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700787 const struct qpnp_adc_properties *adc_properties,
788 const struct qpnp_vadc_chan_properties *chan_properties,
789 struct qpnp_vadc_result *adc_chan_result)
790{
791 int64_t batt_id_voltage = 0;
792
793 batt_id_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
794 adc_properties, chan_properties);
795 adc_chan_result->physical = batt_id_voltage;
796 adc_chan_result->physical = adc_chan_result->measurement;
797
798 return 0;
799}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700800EXPORT_SYMBOL(qpnp_adc_scale_batt_id);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700801
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700802int32_t qpnp_adc_scale_default(struct qpnp_vadc_chip *vadc,
803 int32_t adc_code,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700804 const struct qpnp_adc_properties *adc_properties,
805 const struct qpnp_vadc_chan_properties *chan_properties,
806 struct qpnp_vadc_result *adc_chan_result)
807{
808 bool negative_rawfromoffset = 0, negative_offset = 0;
809 int64_t scale_voltage = 0;
810
811 if (!chan_properties || !chan_properties->offset_gain_numerator ||
812 !chan_properties->offset_gain_denominator || !adc_properties
813 || !adc_chan_result)
814 return -EINVAL;
815
816 scale_voltage = (adc_code -
817 chan_properties->adc_graph[CALIB_ABSOLUTE].adc_gnd)
818 * chan_properties->adc_graph[CALIB_ABSOLUTE].dx;
819 if (scale_voltage < 0) {
820 negative_offset = 1;
821 scale_voltage = -scale_voltage;
822 }
823 do_div(scale_voltage,
824 chan_properties->adc_graph[CALIB_ABSOLUTE].dy);
825 if (negative_offset)
826 scale_voltage = -scale_voltage;
827 scale_voltage += chan_properties->adc_graph[CALIB_ABSOLUTE].dx;
828
829 if (scale_voltage < 0) {
830 if (adc_properties->bipolar) {
831 scale_voltage = -scale_voltage;
832 negative_rawfromoffset = 1;
833 } else {
834 scale_voltage = 0;
835 }
836 }
837
838 adc_chan_result->measurement = scale_voltage *
839 chan_properties->offset_gain_denominator;
840
841 /* do_div only perform positive integer division! */
842 do_div(adc_chan_result->measurement,
843 chan_properties->offset_gain_numerator);
844
845 if (negative_rawfromoffset)
846 adc_chan_result->measurement = -adc_chan_result->measurement;
847
848 /*
849 * Note: adc_chan_result->measurement is in the unit of
850 * adc_properties.adc_reference. For generic channel processing,
851 * channel measurement is a scale/ratio relative to the adc
852 * reference input
853 */
854 adc_chan_result->physical = adc_chan_result->measurement;
855
856 return 0;
857}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700858EXPORT_SYMBOL(qpnp_adc_scale_default);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700859
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700860int32_t qpnp_adc_usb_scaler(struct qpnp_vadc_chip *chip,
861 struct qpnp_adc_tm_btm_param *param,
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800862 uint32_t *low_threshold, uint32_t *high_threshold)
863{
864 struct qpnp_vadc_linear_graph usb_param;
865
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700866 qpnp_get_vadc_gain_and_offset(chip, &usb_param, CALIB_RATIOMETRIC);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800867
868 *low_threshold = param->low_thr * usb_param.dy;
869 do_div(*low_threshold, usb_param.adc_vref);
870 *low_threshold += usb_param.adc_gnd;
871
872 *high_threshold = param->high_thr * usb_param.dy;
873 do_div(*high_threshold, usb_param.adc_vref);
874 *high_threshold += usb_param.adc_gnd;
875
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800876 pr_debug("high_volt:%d, low_volt:%d\n", param->high_thr,
877 param->low_thr);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800878 return 0;
879}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700880EXPORT_SYMBOL(qpnp_adc_usb_scaler);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800881
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700882int32_t qpnp_adc_vbatt_rscaler(struct qpnp_vadc_chip *chip,
883 struct qpnp_adc_tm_btm_param *param,
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800884 uint32_t *low_threshold, uint32_t *high_threshold)
885{
886 struct qpnp_vadc_linear_graph vbatt_param;
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700887 int rc = 0, sign = 0;
Siddartha Mohanadoss91a1cd62013-04-19 19:34:36 -0700888 int64_t low_thr = 0, high_thr = 0;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800889
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700890 rc = qpnp_get_vadc_gain_and_offset(chip, &vbatt_param, CALIB_ABSOLUTE);
Siddartha Mohanadossc4140482013-03-28 18:44:54 -0700891 if (rc < 0)
892 return rc;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800893
Siddartha Mohanadoss91a1cd62013-04-19 19:34:36 -0700894 low_thr = (((param->low_thr/3) - QPNP_ADC_625_UV) *
Siddartha Mohanadossc4140482013-03-28 18:44:54 -0700895 vbatt_param.dy);
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700896 if (low_thr < 0) {
897 sign = 1;
898 low_thr = -low_thr;
899 }
Siddartha Mohanadoss91a1cd62013-04-19 19:34:36 -0700900 do_div(low_thr, QPNP_ADC_625_UV);
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700901 if (sign)
902 low_thr = -low_thr;
Siddartha Mohanadoss91a1cd62013-04-19 19:34:36 -0700903 *low_threshold = low_thr + vbatt_param.adc_gnd;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800904
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700905 sign = 0;
Siddartha Mohanadoss91a1cd62013-04-19 19:34:36 -0700906 high_thr = (((param->high_thr/3) - QPNP_ADC_625_UV) *
Siddartha Mohanadossc4140482013-03-28 18:44:54 -0700907 vbatt_param.dy);
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700908 if (high_thr < 0) {
909 sign = 1;
910 high_thr = -high_thr;
911 }
Siddartha Mohanadoss91a1cd62013-04-19 19:34:36 -0700912 do_div(high_thr, QPNP_ADC_625_UV);
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700913 if (sign)
914 high_thr = -high_thr;
Siddartha Mohanadoss91a1cd62013-04-19 19:34:36 -0700915 *high_threshold = high_thr + vbatt_param.adc_gnd;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800916
917 pr_debug("high_volt:%d, low_volt:%d\n", param->high_thr,
918 param->low_thr);
Siddartha Mohanadossc4140482013-03-28 18:44:54 -0700919 pr_debug("adc_code_high:%x, adc_code_low:%x\n", *high_threshold,
920 *low_threshold);
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800921 return 0;
922}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700923EXPORT_SYMBOL(qpnp_adc_vbatt_rscaler);
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800924
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700925int32_t qpnp_adc_btm_scaler(struct qpnp_vadc_chip *chip,
926 struct qpnp_adc_tm_btm_param *param,
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800927 uint32_t *low_threshold, uint32_t *high_threshold)
928{
929 struct qpnp_vadc_linear_graph btm_param;
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700930 int64_t low_output = 0, high_output = 0;
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800931 int rc = 0;
932
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700933 qpnp_get_vadc_gain_and_offset(chip, &btm_param, CALIB_RATIOMETRIC);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800934
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700935 pr_debug("warm_temp:%d and cool_temp:%d\n", param->high_temp,
936 param->low_temp);
937 rc = qpnp_adc_map_voltage_temp(
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800938 adcmap_btm_threshold,
939 ARRAY_SIZE(adcmap_btm_threshold),
940 (param->low_temp),
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700941 &low_output);
942 if (rc) {
943 pr_debug("low_temp mapping failed with %d\n", rc);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800944 return rc;
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700945 }
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800946
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700947 pr_debug("low_output:%lld\n", low_output);
948 low_output *= btm_param.dy;
949 do_div(low_output, btm_param.adc_vref);
950 low_output += btm_param.adc_gnd;
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800951
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700952 rc = qpnp_adc_map_voltage_temp(
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800953 adcmap_btm_threshold,
954 ARRAY_SIZE(adcmap_btm_threshold),
955 (param->high_temp),
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700956 &high_output);
957 if (rc) {
958 pr_debug("high temp mapping failed with %d\n", rc);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800959 return rc;
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700960 }
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800961
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700962 pr_debug("high_output:%lld\n", high_output);
963 high_output *= btm_param.dy;
964 do_div(high_output, btm_param.adc_vref);
965 high_output += btm_param.adc_gnd;
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800966
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700967 /* btm low temperature correspondes to high voltage threshold */
968 *low_threshold = high_output;
969 /* btm high temperature correspondes to low voltage threshold */
970 *high_threshold = low_output;
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800971
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700972 pr_debug("high_volt:%d, low_volt:%d\n", *high_threshold,
973 *low_threshold);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800974 return 0;
975}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700976EXPORT_SYMBOL(qpnp_adc_btm_scaler);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800977
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700978int32_t qpnp_vadc_check_result(int32_t *data)
979{
980 if (*data < QPNP_VADC_MIN_ADC_CODE)
981 *data = QPNP_VADC_MIN_ADC_CODE;
982 else if (*data > QPNP_VADC_MAX_ADC_CODE)
983 *data = QPNP_VADC_MAX_ADC_CODE;
984
985 return 0;
986}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700987EXPORT_SYMBOL(qpnp_vadc_check_result);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700988
989int32_t qpnp_adc_get_devicetree_data(struct spmi_device *spmi,
990 struct qpnp_adc_drv *adc_qpnp)
991{
992 struct device_node *node = spmi->dev.of_node;
993 struct resource *res;
994 struct device_node *child;
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -0800995 struct qpnp_adc_amux *adc_channel_list;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700996 struct qpnp_adc_properties *adc_prop;
Siddartha Mohanadossc4a6af12012-07-13 18:50:12 -0700997 struct qpnp_adc_amux_properties *amux_prop;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700998 int count_adc_channel_list = 0, decimation, rc = 0, i = 0;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700999
1000 if (!node)
1001 return -EINVAL;
1002
1003 for_each_child_of_node(node, child)
1004 count_adc_channel_list++;
1005
1006 if (!count_adc_channel_list) {
1007 pr_err("No channel listing\n");
1008 return -EINVAL;
1009 }
1010
1011 adc_qpnp->spmi = spmi;
1012
1013 adc_prop = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_adc_properties),
1014 GFP_KERNEL);
1015 if (!adc_prop) {
1016 dev_err(&spmi->dev, "Unable to allocate memory\n");
1017 return -ENOMEM;
1018 }
1019 adc_channel_list = devm_kzalloc(&spmi->dev,
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -08001020 ((sizeof(struct qpnp_adc_amux)) * count_adc_channel_list),
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001021 GFP_KERNEL);
1022 if (!adc_channel_list) {
1023 dev_err(&spmi->dev, "Unable to allocate memory\n");
1024 return -ENOMEM;
1025 }
1026
1027 amux_prop = devm_kzalloc(&spmi->dev,
Siddartha Mohanadossc4a6af12012-07-13 18:50:12 -07001028 sizeof(struct qpnp_adc_amux_properties) +
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001029 sizeof(struct qpnp_vadc_chan_properties), GFP_KERNEL);
1030 if (!amux_prop) {
1031 dev_err(&spmi->dev, "Unable to allocate memory\n");
1032 return -ENOMEM;
1033 }
1034
Siddartha Mohanadossae1da732012-08-08 16:39:02 -07001035 adc_qpnp->adc_channels = adc_channel_list;
1036 adc_qpnp->amux_prop = amux_prop;
1037
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001038 for_each_child_of_node(node, child) {
1039 int channel_num, scaling, post_scaling, hw_settle_time;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -07001040 int fast_avg_setup, calib_type, rc;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001041 const char *calibration_param, *channel_name;
1042
1043 channel_name = of_get_property(child,
1044 "label", NULL) ? : child->name;
1045 if (!channel_name) {
1046 pr_err("Invalid channel name\n");
1047 return -EINVAL;
1048 }
1049
Siddartha Mohanadoss96be0a02012-12-07 14:38:48 -08001050 rc = of_property_read_u32(child, "reg", &channel_num);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001051 if (rc) {
1052 pr_err("Invalid channel num\n");
1053 return -EINVAL;
1054 }
1055 rc = of_property_read_u32(child, "qcom,decimation",
1056 &decimation);
1057 if (rc) {
1058 pr_err("Invalid channel decimation property\n");
1059 return -EINVAL;
1060 }
1061 rc = of_property_read_u32(child,
1062 "qcom,pre-div-channel-scaling", &scaling);
1063 if (rc) {
1064 pr_err("Invalid channel scaling property\n");
1065 return -EINVAL;
1066 }
1067 rc = of_property_read_u32(child,
1068 "qcom,scale-function", &post_scaling);
1069 if (rc) {
1070 pr_err("Invalid channel post scaling property\n");
1071 return -EINVAL;
1072 }
1073 rc = of_property_read_u32(child,
1074 "qcom,hw-settle-time", &hw_settle_time);
1075 if (rc) {
1076 pr_err("Invalid channel hw settle time property\n");
1077 return -EINVAL;
1078 }
1079 rc = of_property_read_u32(child,
1080 "qcom,fast-avg-setup", &fast_avg_setup);
1081 if (rc) {
1082 pr_err("Invalid channel fast average setup\n");
1083 return -EINVAL;
1084 }
Siddartha Mohanadoss630def02013-06-27 14:53:38 -07001085 rc = of_property_read_string(child, "qcom,calibration-type",
1086 &calibration_param);
1087 if (rc) {
1088 pr_err("Invalid calibration type\n");
1089 return -EINVAL;
1090 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001091 if (!strncmp(calibration_param, "absolute", 8))
1092 calib_type = CALIB_ABSOLUTE;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001093 else if (!strncmp(calibration_param, "ratiometric", 11))
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001094 calib_type = CALIB_RATIOMETRIC;
1095 else {
1096 pr_err("%s: Invalid calibration property\n", __func__);
1097 return -EINVAL;
1098 }
1099 /* Individual channel properties */
1100 adc_channel_list[i].name = (char *)channel_name;
1101 adc_channel_list[i].channel_num = channel_num;
1102 adc_channel_list[i].chan_path_prescaling = scaling;
1103 adc_channel_list[i].adc_decimation = decimation;
1104 adc_channel_list[i].adc_scale_fn = post_scaling;
1105 adc_channel_list[i].hw_settle_time = hw_settle_time;
1106 adc_channel_list[i].fast_avg_setup = fast_avg_setup;
1107 i++;
1108 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001109
1110 /* Get the ADC VDD reference voltage and ADC bit resolution */
1111 rc = of_property_read_u32(node, "qcom,adc-vdd-reference",
1112 &adc_prop->adc_vdd_reference);
1113 if (rc) {
1114 pr_err("Invalid adc vdd reference property\n");
1115 return -EINVAL;
1116 }
1117 rc = of_property_read_u32(node, "qcom,adc-bit-resolution",
1118 &adc_prop->bitresolution);
1119 if (rc) {
1120 pr_err("Invalid adc bit resolution property\n");
1121 return -EINVAL;
1122 }
1123 adc_qpnp->adc_prop = adc_prop;
1124
1125 /* Get the peripheral address */
1126 res = spmi_get_resource(spmi, 0, IORESOURCE_MEM, 0);
1127 if (!res) {
1128 pr_err("No base address definition\n");
1129 return -EINVAL;
1130 }
1131
1132 adc_qpnp->slave = spmi->sid;
1133 adc_qpnp->offset = res->start;
1134
1135 /* Register the ADC peripheral interrupt */
Siddartha Mohanadoss12109952012-11-20 14:57:51 -08001136 adc_qpnp->adc_irq_eoc = spmi_get_irq_byname(spmi, NULL,
1137 "eoc-int-en-set");
1138 if (adc_qpnp->adc_irq_eoc < 0) {
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001139 pr_err("Invalid irq\n");
1140 return -ENXIO;
1141 }
1142
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001143 init_completion(&adc_qpnp->adc_rslt_completion);
1144
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001145 return 0;
1146}
1147EXPORT_SYMBOL(qpnp_adc_get_devicetree_data);