blob: 9e0be5986f35f5ff0f975c9a9c8efb0a5cb15f37 [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
Siddartha Mohanadosse84f8e62012-11-16 09:34:41 -0800241/* Voltage to temperature */
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700242static const struct qpnp_vadc_map_pt adcmap_100k_104ef_104fb[] = {
Siddartha Mohanadosse84f8e62012-11-16 09:34:41 -0800243 {1758, -40},
244 {1742, -35},
245 {1719, -30},
246 {1691, -25},
247 {1654, -20},
248 {1608, -15},
249 {1551, -10},
250 {1483, -5},
251 {1404, 0},
252 {1315, 5},
253 {1218, 10},
254 {1114, 15},
255 {1007, 20},
256 {900, 25},
257 {795, 30},
258 {696, 35},
259 {605, 40},
260 {522, 45},
261 {448, 50},
262 {383, 55},
263 {327, 60},
264 {278, 65},
265 {237, 70},
266 {202, 75},
267 {172, 80},
268 {146, 85},
269 {125, 90},
270 {107, 95},
271 {92, 100},
272 {79, 105},
273 {68, 110},
274 {59, 115},
275 {51, 120},
276 {44, 125}
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700277};
278
Siddartha Mohanadosse84f8e62012-11-16 09:34:41 -0800279/* Voltage to temperature */
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700280static const struct qpnp_vadc_map_pt adcmap_150k_104ef_104fb[] = {
Siddartha Mohanadosse84f8e62012-11-16 09:34:41 -0800281 {1738, -40},
282 {1714, -35},
283 {1682, -30},
284 {1641, -25},
285 {1589, -20},
286 {1526, -15},
287 {1451, -10},
288 {1363, -5},
289 {1266, 0},
290 {1159, 5},
291 {1048, 10},
292 {936, 15},
293 {825, 20},
294 {720, 25},
295 {622, 30},
296 {533, 35},
297 {454, 40},
298 {385, 45},
299 {326, 50},
300 {275, 55},
301 {232, 60},
302 {195, 65},
303 {165, 70},
304 {139, 75},
305 {118, 80},
306 {100, 85},
307 {85, 90},
308 {73, 95},
309 {62, 100},
310 {53, 105},
311 {46, 110},
312 {40, 115},
313 {34, 120},
314 {30, 125}
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700315};
316
Siddartha Mohanadoss4a27b1c2012-11-16 09:34:41 -0800317static int32_t qpnp_adc_map_voltage_temp(const struct qpnp_vadc_map_pt *pts,
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700318 uint32_t tablesize, int32_t input, int64_t *output)
319{
320 bool descending = 1;
321 uint32_t i = 0;
322
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700323 if (pts == NULL)
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700324 return -EINVAL;
325
326 /* Check if table is descending or ascending */
327 if (tablesize > 1) {
328 if (pts[0].x < pts[1].x)
329 descending = 0;
330 }
331
332 while (i < tablesize) {
333 if ((descending == 1) && (pts[i].x < input)) {
334 /* table entry is less than measured
335 value and table is descending, stop */
336 break;
337 } else if ((descending == 0) &&
338 (pts[i].x > input)) {
339 /* table entry is greater than measured
340 value and table is ascending, stop */
341 break;
342 } else {
343 i++;
344 }
345 }
346
347 if (i == 0)
348 *output = pts[0].y;
349 else if (i == tablesize)
350 *output = pts[tablesize-1].y;
351 else {
352 /* result is between search_index and search_index-1 */
353 /* interpolate linearly */
354 *output = (((int32_t) ((pts[i].y - pts[i-1].y)*
355 (input - pts[i-1].x))/
356 (pts[i].x - pts[i-1].x))+
357 pts[i-1].y);
358 }
359
360 return 0;
361}
362
Siddartha Mohanadoss4a27b1c2012-11-16 09:34:41 -0800363static int32_t qpnp_adc_map_temp_voltage(const struct qpnp_vadc_map_pt *pts,
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700364 uint32_t tablesize, int32_t input, int64_t *output)
365{
366 bool descending = 1;
367 uint32_t i = 0;
368
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700369 if (pts == NULL)
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700370 return -EINVAL;
371
372 /* Check if table is descending or ascending */
373 if (tablesize > 1) {
374 if (pts[0].y < pts[1].y)
375 descending = 0;
376 }
377
378 while (i < tablesize) {
379 if ((descending == 1) && (pts[i].y < input)) {
380 /* table entry is less than measured
381 value and table is descending, stop */
382 break;
383 } else if ((descending == 0) && (pts[i].y > input)) {
384 /* table entry is greater than measured
385 value and table is ascending, stop */
386 break;
387 } else {
388 i++;
389 }
390 }
391
392 if (i == 0) {
393 *output = pts[0].x;
394 } else if (i == tablesize) {
395 *output = pts[tablesize-1].x;
396 } else {
397 /* result is between search_index and search_index-1 */
398 /* interpolate linearly */
399 *output = (((int32_t) ((pts[i].x - pts[i-1].x)*
400 (input - pts[i-1].y))/
401 (pts[i].y - pts[i-1].y))+
402 pts[i-1].x);
403 }
404
405 return 0;
406}
407
408static int64_t qpnp_adc_scale_ratiometric_calib(int32_t adc_code,
409 const struct qpnp_adc_properties *adc_properties,
410 const struct qpnp_vadc_chan_properties *chan_properties)
411{
412 int64_t adc_voltage = 0;
413 bool negative_offset = 0;
414
415 if (!chan_properties || !chan_properties->offset_gain_numerator ||
416 !chan_properties->offset_gain_denominator || !adc_properties)
417 return -EINVAL;
418
419 adc_voltage = (adc_code -
420 chan_properties->adc_graph[CALIB_RATIOMETRIC].adc_gnd)
421 * adc_properties->adc_vdd_reference;
422 if (adc_voltage < 0) {
423 negative_offset = 1;
424 adc_voltage = -adc_voltage;
425 }
426 do_div(adc_voltage,
427 chan_properties->adc_graph[CALIB_RATIOMETRIC].dy);
428 if (negative_offset)
429 adc_voltage = -adc_voltage;
430
431 return adc_voltage;
432}
433
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700434int32_t qpnp_adc_scale_pmic_therm(struct qpnp_vadc_chip *vadc,
435 int32_t adc_code,
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700436 const struct qpnp_adc_properties *adc_properties,
437 const struct qpnp_vadc_chan_properties *chan_properties,
438 struct qpnp_vadc_result *adc_chan_result)
439{
440 int64_t pmic_voltage = 0;
441 bool negative_offset = 0;
442
443 if (!chan_properties || !chan_properties->offset_gain_numerator ||
444 !chan_properties->offset_gain_denominator || !adc_properties
445 || !adc_chan_result)
446 return -EINVAL;
447
448 pmic_voltage = (adc_code -
449 chan_properties->adc_graph[CALIB_ABSOLUTE].adc_gnd)
450 * chan_properties->adc_graph[CALIB_ABSOLUTE].dx;
451 if (pmic_voltage < 0) {
452 negative_offset = 1;
453 pmic_voltage = -pmic_voltage;
454 }
455 do_div(pmic_voltage,
456 chan_properties->adc_graph[CALIB_ABSOLUTE].dy);
457 if (negative_offset)
458 pmic_voltage = -pmic_voltage;
459 pmic_voltage += chan_properties->adc_graph[CALIB_ABSOLUTE].dx;
460
461 if (pmic_voltage > 0) {
462 /* 2mV/K */
463 adc_chan_result->measurement = pmic_voltage*
464 chan_properties->offset_gain_denominator;
465
466 do_div(adc_chan_result->measurement,
467 chan_properties->offset_gain_numerator * 2);
468 } else {
469 adc_chan_result->measurement = 0;
470 }
471 /* Change to .001 deg C */
472 adc_chan_result->measurement -= KELVINMIL_DEGMIL;
473 adc_chan_result->physical = (int32_t)adc_chan_result->measurement;
474
475 return 0;
476}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700477EXPORT_SYMBOL(qpnp_adc_scale_pmic_therm);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700478
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700479int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(struct qpnp_vadc_chip *chip,
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800480 struct qpnp_adc_tm_btm_param *param,
481 uint32_t *low_threshold, uint32_t *high_threshold)
482{
483 struct qpnp_vadc_linear_graph btm_param;
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700484 int64_t low_output = 0, high_output = 0;
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700485 int rc = 0, sign = 0;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800486
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700487 rc = qpnp_get_vadc_gain_and_offset(chip, &btm_param, CALIB_ABSOLUTE);
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800488 if (rc < 0) {
489 pr_err("Could not acquire gain and offset\n");
490 return rc;
491 }
492
493 /* Convert to Kelvin and account for voltage to be written as 2mV/K */
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700494 low_output = (param->low_temp + KELVINMIL_DEGMIL) * 2;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800495 /* Convert to voltage threshold */
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700496 low_output = (low_output - QPNP_ADC_625_UV) * btm_param.dy;
497 if (low_output < 0) {
498 sign = 1;
499 low_output = -low_output;
500 }
501 do_div(low_output, QPNP_ADC_625_UV);
502 if (sign)
503 low_output = -low_output;
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700504 low_output += btm_param.adc_gnd;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800505
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700506 sign = 0;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800507 /* Convert to Kelvin and account for voltage to be written as 2mV/K */
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700508 high_output = (param->high_temp + KELVINMIL_DEGMIL) * 2;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800509 /* Convert to voltage threshold */
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700510 high_output = (high_output - QPNP_ADC_625_UV) * btm_param.dy;
511 if (high_output < 0) {
512 sign = 1;
513 high_output = -high_output;
514 }
515 do_div(high_output, QPNP_ADC_625_UV);
516 if (sign)
517 high_output = -high_output;
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700518 high_output += btm_param.adc_gnd;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800519
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700520 *low_threshold = (uint32_t) low_output;
521 *high_threshold = (uint32_t) high_output;
522 pr_debug("high_temp:%d, low_temp:%d\n", param->high_temp,
523 param->low_temp);
524 pr_debug("adc_code_high:%x, adc_code_low:%x\n", *high_threshold,
525 *low_threshold);
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800526
527 return 0;
528}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700529EXPORT_SYMBOL(qpnp_adc_scale_millidegc_pmic_voltage_thr);
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800530
531/* Scales the ADC code to degC using the mapping
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700532 * table for the XO thermistor.
533 */
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700534int32_t qpnp_adc_tdkntcg_therm(struct qpnp_vadc_chip *chip,
535 int32_t adc_code,
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700536 const struct qpnp_adc_properties *adc_properties,
537 const struct qpnp_vadc_chan_properties *chan_properties,
538 struct qpnp_vadc_result *adc_chan_result)
539{
540 int64_t xo_thm = 0;
541
542 if (!chan_properties || !chan_properties->offset_gain_numerator ||
543 !chan_properties->offset_gain_denominator || !adc_properties
544 || !adc_chan_result)
545 return -EINVAL;
546
547 xo_thm = qpnp_adc_scale_ratiometric_calib(adc_code,
548 adc_properties, chan_properties);
Siddartha Mohanadoss0dc06942012-12-23 17:10:10 -0800549
550 qpnp_adc_map_voltage_temp(adcmap_100k_104ef_104fb,
551 ARRAY_SIZE(adcmap_100k_104ef_104fb),
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700552 xo_thm, &adc_chan_result->physical);
553
554 return 0;
555}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700556EXPORT_SYMBOL(qpnp_adc_tdkntcg_therm);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700557
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700558int32_t qpnp_adc_scale_batt_therm(struct qpnp_vadc_chip *chip,
559 int32_t adc_code,
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700560 const struct qpnp_adc_properties *adc_properties,
561 const struct qpnp_vadc_chan_properties *chan_properties,
562 struct qpnp_vadc_result *adc_chan_result)
563{
564 int64_t bat_voltage = 0;
565
566 bat_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
567 adc_properties, chan_properties);
568
Siddartha Mohanadoss4a27b1c2012-11-16 09:34:41 -0800569 return qpnp_adc_map_temp_voltage(
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700570 adcmap_btm_threshold,
571 ARRAY_SIZE(adcmap_btm_threshold),
572 bat_voltage,
573 &adc_chan_result->physical);
574}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700575EXPORT_SYMBOL(qpnp_adc_scale_batt_therm);
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700576
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700577int32_t qpnp_adc_scale_qrd_batt_therm(struct qpnp_vadc_chip *chip,
578 int32_t adc_code,
Siddartha Mohanadossb99cfa92013-05-01 20:19:58 -0700579 const struct qpnp_adc_properties *adc_properties,
580 const struct qpnp_vadc_chan_properties *chan_properties,
581 struct qpnp_vadc_result *adc_chan_result)
582{
583 int64_t bat_voltage = 0;
584
585 bat_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
586 adc_properties, chan_properties);
587
588 return qpnp_adc_map_temp_voltage(
589 adcmap_qrd_btm_threshold,
590 ARRAY_SIZE(adcmap_qrd_btm_threshold),
591 bat_voltage,
592 &adc_chan_result->physical);
593}
594EXPORT_SYMBOL(qpnp_adc_scale_qrd_batt_therm);
595
Xu Kai81c60522013-07-27 14:26:04 +0800596int32_t qpnp_adc_scale_qrd_skuaa_batt_therm(struct qpnp_vadc_chip *chip,
597 int32_t adc_code,
598 const struct qpnp_adc_properties *adc_properties,
599 const struct qpnp_vadc_chan_properties *chan_properties,
600 struct qpnp_vadc_result *adc_chan_result)
601{
602 int64_t bat_voltage = 0;
603
604 bat_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
605 adc_properties, chan_properties);
606
607 return qpnp_adc_map_temp_voltage(
608 adcmap_qrd_skuaa_btm_threshold,
609 ARRAY_SIZE(adcmap_qrd_skuaa_btm_threshold),
610 bat_voltage,
611 &adc_chan_result->physical);
612}
613EXPORT_SYMBOL(qpnp_adc_scale_qrd_skuaa_batt_therm);
614
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700615int32_t qpnp_adc_scale_therm_pu1(struct qpnp_vadc_chip *chip,
616 int32_t adc_code,
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700617 const struct qpnp_adc_properties *adc_properties,
618 const struct qpnp_vadc_chan_properties *chan_properties,
619 struct qpnp_vadc_result *adc_chan_result)
620{
621 int64_t therm_voltage = 0;
622
623 therm_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
624 adc_properties, chan_properties);
625
Siddartha Mohanadosse84f8e62012-11-16 09:34:41 -0800626 qpnp_adc_map_voltage_temp(adcmap_150k_104ef_104fb,
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700627 ARRAY_SIZE(adcmap_150k_104ef_104fb),
628 therm_voltage, &adc_chan_result->physical);
629
630 return 0;
631}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700632EXPORT_SYMBOL(qpnp_adc_scale_therm_pu1);
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700633
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700634int32_t qpnp_adc_scale_therm_pu2(struct qpnp_vadc_chip *chip,
635 int32_t adc_code,
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700636 const struct qpnp_adc_properties *adc_properties,
637 const struct qpnp_vadc_chan_properties *chan_properties,
638 struct qpnp_vadc_result *adc_chan_result)
639{
640 int64_t therm_voltage = 0;
641
642 therm_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
643 adc_properties, chan_properties);
644
Siddartha Mohanadosse84f8e62012-11-16 09:34:41 -0800645 qpnp_adc_map_voltage_temp(adcmap_100k_104ef_104fb,
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700646 ARRAY_SIZE(adcmap_100k_104ef_104fb),
647 therm_voltage, &adc_chan_result->physical);
648
649 return 0;
650}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700651EXPORT_SYMBOL(qpnp_adc_scale_therm_pu2);
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700652
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700653int32_t qpnp_adc_tm_scale_voltage_therm_pu2(struct qpnp_vadc_chip *chip,
654 uint32_t reg, int64_t *result)
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800655{
656 int64_t adc_voltage = 0;
657 struct qpnp_vadc_linear_graph param1;
658 int negative_offset;
659
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700660 qpnp_get_vadc_gain_and_offset(chip, &param1, CALIB_RATIOMETRIC);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800661
662 adc_voltage = (reg - param1.adc_gnd) * param1.adc_vref;
663 if (adc_voltage < 0) {
664 negative_offset = 1;
665 adc_voltage = -adc_voltage;
666 }
667
668 do_div(adc_voltage, param1.dy);
669
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -0800670 qpnp_adc_map_voltage_temp(adcmap_100k_104ef_104fb,
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800671 ARRAY_SIZE(adcmap_100k_104ef_104fb),
672 adc_voltage, result);
673 if (negative_offset)
674 adc_voltage = -adc_voltage;
675
676 return 0;
677}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700678EXPORT_SYMBOL(qpnp_adc_tm_scale_voltage_therm_pu2);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800679
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700680int32_t qpnp_adc_tm_scale_therm_voltage_pu2(struct qpnp_vadc_chip *chip,
681 struct qpnp_adc_tm_config *param)
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800682{
683 struct qpnp_vadc_linear_graph param1;
684 int rc;
685
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700686 qpnp_get_vadc_gain_and_offset(chip, &param1, CALIB_RATIOMETRIC);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800687
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -0800688 rc = qpnp_adc_map_temp_voltage(adcmap_100k_104ef_104fb,
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800689 ARRAY_SIZE(adcmap_100k_104ef_104fb),
690 param->low_thr_temp, &param->low_thr_voltage);
691 if (rc)
692 return rc;
693
694 param->low_thr_voltage *= param1.dy;
695 do_div(param->low_thr_voltage, param1.adc_vref);
696 param->low_thr_voltage += param1.adc_gnd;
697
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -0800698 rc = qpnp_adc_map_temp_voltage(adcmap_100k_104ef_104fb,
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800699 ARRAY_SIZE(adcmap_100k_104ef_104fb),
700 param->high_thr_temp, &param->high_thr_voltage);
701 if (rc)
702 return rc;
703
704 param->high_thr_voltage *= param1.dy;
705 do_div(param->high_thr_voltage, param1.adc_vref);
706 param->high_thr_voltage += param1.adc_gnd;
707
708 return 0;
709}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700710EXPORT_SYMBOL(qpnp_adc_tm_scale_therm_voltage_pu2);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800711
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700712int32_t qpnp_adc_scale_batt_id(struct qpnp_vadc_chip *chip,
713 int32_t adc_code,
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700714 const struct qpnp_adc_properties *adc_properties,
715 const struct qpnp_vadc_chan_properties *chan_properties,
716 struct qpnp_vadc_result *adc_chan_result)
717{
718 int64_t batt_id_voltage = 0;
719
720 batt_id_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
721 adc_properties, chan_properties);
722 adc_chan_result->physical = batt_id_voltage;
723 adc_chan_result->physical = adc_chan_result->measurement;
724
725 return 0;
726}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700727EXPORT_SYMBOL(qpnp_adc_scale_batt_id);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700728
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700729int32_t qpnp_adc_scale_default(struct qpnp_vadc_chip *vadc,
730 int32_t adc_code,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700731 const struct qpnp_adc_properties *adc_properties,
732 const struct qpnp_vadc_chan_properties *chan_properties,
733 struct qpnp_vadc_result *adc_chan_result)
734{
735 bool negative_rawfromoffset = 0, negative_offset = 0;
736 int64_t scale_voltage = 0;
737
738 if (!chan_properties || !chan_properties->offset_gain_numerator ||
739 !chan_properties->offset_gain_denominator || !adc_properties
740 || !adc_chan_result)
741 return -EINVAL;
742
743 scale_voltage = (adc_code -
744 chan_properties->adc_graph[CALIB_ABSOLUTE].adc_gnd)
745 * chan_properties->adc_graph[CALIB_ABSOLUTE].dx;
746 if (scale_voltage < 0) {
747 negative_offset = 1;
748 scale_voltage = -scale_voltage;
749 }
750 do_div(scale_voltage,
751 chan_properties->adc_graph[CALIB_ABSOLUTE].dy);
752 if (negative_offset)
753 scale_voltage = -scale_voltage;
754 scale_voltage += chan_properties->adc_graph[CALIB_ABSOLUTE].dx;
755
756 if (scale_voltage < 0) {
757 if (adc_properties->bipolar) {
758 scale_voltage = -scale_voltage;
759 negative_rawfromoffset = 1;
760 } else {
761 scale_voltage = 0;
762 }
763 }
764
765 adc_chan_result->measurement = scale_voltage *
766 chan_properties->offset_gain_denominator;
767
768 /* do_div only perform positive integer division! */
769 do_div(adc_chan_result->measurement,
770 chan_properties->offset_gain_numerator);
771
772 if (negative_rawfromoffset)
773 adc_chan_result->measurement = -adc_chan_result->measurement;
774
775 /*
776 * Note: adc_chan_result->measurement is in the unit of
777 * adc_properties.adc_reference. For generic channel processing,
778 * channel measurement is a scale/ratio relative to the adc
779 * reference input
780 */
781 adc_chan_result->physical = adc_chan_result->measurement;
782
783 return 0;
784}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700785EXPORT_SYMBOL(qpnp_adc_scale_default);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700786
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700787int32_t qpnp_adc_usb_scaler(struct qpnp_vadc_chip *chip,
788 struct qpnp_adc_tm_btm_param *param,
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800789 uint32_t *low_threshold, uint32_t *high_threshold)
790{
791 struct qpnp_vadc_linear_graph usb_param;
792
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700793 qpnp_get_vadc_gain_and_offset(chip, &usb_param, CALIB_RATIOMETRIC);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800794
795 *low_threshold = param->low_thr * usb_param.dy;
796 do_div(*low_threshold, usb_param.adc_vref);
797 *low_threshold += usb_param.adc_gnd;
798
799 *high_threshold = param->high_thr * usb_param.dy;
800 do_div(*high_threshold, usb_param.adc_vref);
801 *high_threshold += usb_param.adc_gnd;
802
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800803 pr_debug("high_volt:%d, low_volt:%d\n", param->high_thr,
804 param->low_thr);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800805 return 0;
806}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700807EXPORT_SYMBOL(qpnp_adc_usb_scaler);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800808
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700809int32_t qpnp_adc_vbatt_rscaler(struct qpnp_vadc_chip *chip,
810 struct qpnp_adc_tm_btm_param *param,
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800811 uint32_t *low_threshold, uint32_t *high_threshold)
812{
813 struct qpnp_vadc_linear_graph vbatt_param;
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700814 int rc = 0, sign = 0;
Siddartha Mohanadoss91a1cd62013-04-19 19:34:36 -0700815 int64_t low_thr = 0, high_thr = 0;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800816
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700817 rc = qpnp_get_vadc_gain_and_offset(chip, &vbatt_param, CALIB_ABSOLUTE);
Siddartha Mohanadossc4140482013-03-28 18:44:54 -0700818 if (rc < 0)
819 return rc;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800820
Siddartha Mohanadoss91a1cd62013-04-19 19:34:36 -0700821 low_thr = (((param->low_thr/3) - QPNP_ADC_625_UV) *
Siddartha Mohanadossc4140482013-03-28 18:44:54 -0700822 vbatt_param.dy);
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700823 if (low_thr < 0) {
824 sign = 1;
825 low_thr = -low_thr;
826 }
Siddartha Mohanadoss91a1cd62013-04-19 19:34:36 -0700827 do_div(low_thr, QPNP_ADC_625_UV);
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700828 if (sign)
829 low_thr = -low_thr;
Siddartha Mohanadoss91a1cd62013-04-19 19:34:36 -0700830 *low_threshold = low_thr + vbatt_param.adc_gnd;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800831
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700832 sign = 0;
Siddartha Mohanadoss91a1cd62013-04-19 19:34:36 -0700833 high_thr = (((param->high_thr/3) - QPNP_ADC_625_UV) *
Siddartha Mohanadossc4140482013-03-28 18:44:54 -0700834 vbatt_param.dy);
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700835 if (high_thr < 0) {
836 sign = 1;
837 high_thr = -high_thr;
838 }
Siddartha Mohanadoss91a1cd62013-04-19 19:34:36 -0700839 do_div(high_thr, QPNP_ADC_625_UV);
Siddartha Mohanadoss71218f22013-04-23 16:24:14 -0700840 if (sign)
841 high_thr = -high_thr;
Siddartha Mohanadoss91a1cd62013-04-19 19:34:36 -0700842 *high_threshold = high_thr + vbatt_param.adc_gnd;
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800843
844 pr_debug("high_volt:%d, low_volt:%d\n", param->high_thr,
845 param->low_thr);
Siddartha Mohanadossc4140482013-03-28 18:44:54 -0700846 pr_debug("adc_code_high:%x, adc_code_low:%x\n", *high_threshold,
847 *low_threshold);
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800848 return 0;
849}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700850EXPORT_SYMBOL(qpnp_adc_vbatt_rscaler);
Siddartha Mohanadossa3e35512013-02-22 17:06:07 -0800851
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700852int32_t qpnp_adc_btm_scaler(struct qpnp_vadc_chip *chip,
853 struct qpnp_adc_tm_btm_param *param,
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800854 uint32_t *low_threshold, uint32_t *high_threshold)
855{
856 struct qpnp_vadc_linear_graph btm_param;
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700857 int64_t low_output = 0, high_output = 0;
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800858 int rc = 0;
859
Siddartha Mohanadoss3cb2b6b2013-06-21 12:07:05 -0700860 qpnp_get_vadc_gain_and_offset(chip, &btm_param, CALIB_RATIOMETRIC);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800861
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700862 pr_debug("warm_temp:%d and cool_temp:%d\n", param->high_temp,
863 param->low_temp);
864 rc = qpnp_adc_map_voltage_temp(
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800865 adcmap_btm_threshold,
866 ARRAY_SIZE(adcmap_btm_threshold),
867 (param->low_temp),
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700868 &low_output);
869 if (rc) {
870 pr_debug("low_temp mapping failed with %d\n", rc);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800871 return rc;
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700872 }
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800873
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700874 pr_debug("low_output:%lld\n", low_output);
875 low_output *= btm_param.dy;
876 do_div(low_output, btm_param.adc_vref);
877 low_output += btm_param.adc_gnd;
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800878
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700879 rc = qpnp_adc_map_voltage_temp(
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800880 adcmap_btm_threshold,
881 ARRAY_SIZE(adcmap_btm_threshold),
882 (param->high_temp),
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700883 &high_output);
884 if (rc) {
885 pr_debug("high temp mapping failed with %d\n", rc);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800886 return rc;
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700887 }
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800888
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700889 pr_debug("high_output:%lld\n", high_output);
890 high_output *= btm_param.dy;
891 do_div(high_output, btm_param.adc_vref);
892 high_output += btm_param.adc_gnd;
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800893
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700894 /* btm low temperature correspondes to high voltage threshold */
895 *low_threshold = high_output;
896 /* btm high temperature correspondes to low voltage threshold */
897 *high_threshold = low_output;
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800898
Siddartha Mohanadossb8109da2013-03-25 09:53:43 -0700899 pr_debug("high_volt:%d, low_volt:%d\n", *high_threshold,
900 *low_threshold);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800901 return 0;
902}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700903EXPORT_SYMBOL(qpnp_adc_btm_scaler);
Siddartha Mohanadossd0f4fd12012-11-20 16:28:40 -0800904
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700905int32_t qpnp_vadc_check_result(int32_t *data)
906{
907 if (*data < QPNP_VADC_MIN_ADC_CODE)
908 *data = QPNP_VADC_MIN_ADC_CODE;
909 else if (*data > QPNP_VADC_MAX_ADC_CODE)
910 *data = QPNP_VADC_MAX_ADC_CODE;
911
912 return 0;
913}
Siddartha Mohanadoss271d00f2013-03-26 18:24:14 -0700914EXPORT_SYMBOL(qpnp_vadc_check_result);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700915
916int32_t qpnp_adc_get_devicetree_data(struct spmi_device *spmi,
917 struct qpnp_adc_drv *adc_qpnp)
918{
919 struct device_node *node = spmi->dev.of_node;
920 struct resource *res;
921 struct device_node *child;
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -0800922 struct qpnp_adc_amux *adc_channel_list;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700923 struct qpnp_adc_properties *adc_prop;
Siddartha Mohanadossc4a6af12012-07-13 18:50:12 -0700924 struct qpnp_adc_amux_properties *amux_prop;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700925 int count_adc_channel_list = 0, decimation, rc = 0, i = 0;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700926
927 if (!node)
928 return -EINVAL;
929
930 for_each_child_of_node(node, child)
931 count_adc_channel_list++;
932
933 if (!count_adc_channel_list) {
934 pr_err("No channel listing\n");
935 return -EINVAL;
936 }
937
938 adc_qpnp->spmi = spmi;
939
940 adc_prop = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_adc_properties),
941 GFP_KERNEL);
942 if (!adc_prop) {
943 dev_err(&spmi->dev, "Unable to allocate memory\n");
944 return -ENOMEM;
945 }
946 adc_channel_list = devm_kzalloc(&spmi->dev,
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -0800947 ((sizeof(struct qpnp_adc_amux)) * count_adc_channel_list),
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700948 GFP_KERNEL);
949 if (!adc_channel_list) {
950 dev_err(&spmi->dev, "Unable to allocate memory\n");
951 return -ENOMEM;
952 }
953
954 amux_prop = devm_kzalloc(&spmi->dev,
Siddartha Mohanadossc4a6af12012-07-13 18:50:12 -0700955 sizeof(struct qpnp_adc_amux_properties) +
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700956 sizeof(struct qpnp_vadc_chan_properties), GFP_KERNEL);
957 if (!amux_prop) {
958 dev_err(&spmi->dev, "Unable to allocate memory\n");
959 return -ENOMEM;
960 }
961
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700962 adc_qpnp->adc_channels = adc_channel_list;
963 adc_qpnp->amux_prop = amux_prop;
964
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700965 for_each_child_of_node(node, child) {
966 int channel_num, scaling, post_scaling, hw_settle_time;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700967 int fast_avg_setup, calib_type, rc;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700968 const char *calibration_param, *channel_name;
969
970 channel_name = of_get_property(child,
971 "label", NULL) ? : child->name;
972 if (!channel_name) {
973 pr_err("Invalid channel name\n");
974 return -EINVAL;
975 }
976
Siddartha Mohanadoss96be0a02012-12-07 14:38:48 -0800977 rc = of_property_read_u32(child, "reg", &channel_num);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700978 if (rc) {
979 pr_err("Invalid channel num\n");
980 return -EINVAL;
981 }
982 rc = of_property_read_u32(child, "qcom,decimation",
983 &decimation);
984 if (rc) {
985 pr_err("Invalid channel decimation property\n");
986 return -EINVAL;
987 }
988 rc = of_property_read_u32(child,
989 "qcom,pre-div-channel-scaling", &scaling);
990 if (rc) {
991 pr_err("Invalid channel scaling property\n");
992 return -EINVAL;
993 }
994 rc = of_property_read_u32(child,
995 "qcom,scale-function", &post_scaling);
996 if (rc) {
997 pr_err("Invalid channel post scaling property\n");
998 return -EINVAL;
999 }
1000 rc = of_property_read_u32(child,
1001 "qcom,hw-settle-time", &hw_settle_time);
1002 if (rc) {
1003 pr_err("Invalid channel hw settle time property\n");
1004 return -EINVAL;
1005 }
1006 rc = of_property_read_u32(child,
1007 "qcom,fast-avg-setup", &fast_avg_setup);
1008 if (rc) {
1009 pr_err("Invalid channel fast average setup\n");
1010 return -EINVAL;
1011 }
Siddartha Mohanadoss630def02013-06-27 14:53:38 -07001012 rc = of_property_read_string(child, "qcom,calibration-type",
1013 &calibration_param);
1014 if (rc) {
1015 pr_err("Invalid calibration type\n");
1016 return -EINVAL;
1017 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001018 if (!strncmp(calibration_param, "absolute", 8))
1019 calib_type = CALIB_ABSOLUTE;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001020 else if (!strncmp(calibration_param, "ratiometric", 11))
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001021 calib_type = CALIB_RATIOMETRIC;
1022 else {
1023 pr_err("%s: Invalid calibration property\n", __func__);
1024 return -EINVAL;
1025 }
1026 /* Individual channel properties */
1027 adc_channel_list[i].name = (char *)channel_name;
1028 adc_channel_list[i].channel_num = channel_num;
1029 adc_channel_list[i].chan_path_prescaling = scaling;
1030 adc_channel_list[i].adc_decimation = decimation;
1031 adc_channel_list[i].adc_scale_fn = post_scaling;
1032 adc_channel_list[i].hw_settle_time = hw_settle_time;
1033 adc_channel_list[i].fast_avg_setup = fast_avg_setup;
1034 i++;
1035 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001036
1037 /* Get the ADC VDD reference voltage and ADC bit resolution */
1038 rc = of_property_read_u32(node, "qcom,adc-vdd-reference",
1039 &adc_prop->adc_vdd_reference);
1040 if (rc) {
1041 pr_err("Invalid adc vdd reference property\n");
1042 return -EINVAL;
1043 }
1044 rc = of_property_read_u32(node, "qcom,adc-bit-resolution",
1045 &adc_prop->bitresolution);
1046 if (rc) {
1047 pr_err("Invalid adc bit resolution property\n");
1048 return -EINVAL;
1049 }
1050 adc_qpnp->adc_prop = adc_prop;
1051
1052 /* Get the peripheral address */
1053 res = spmi_get_resource(spmi, 0, IORESOURCE_MEM, 0);
1054 if (!res) {
1055 pr_err("No base address definition\n");
1056 return -EINVAL;
1057 }
1058
1059 adc_qpnp->slave = spmi->sid;
1060 adc_qpnp->offset = res->start;
1061
1062 /* Register the ADC peripheral interrupt */
Siddartha Mohanadoss12109952012-11-20 14:57:51 -08001063 adc_qpnp->adc_irq_eoc = spmi_get_irq_byname(spmi, NULL,
1064 "eoc-int-en-set");
1065 if (adc_qpnp->adc_irq_eoc < 0) {
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001066 pr_err("Invalid irq\n");
1067 return -ENXIO;
1068 }
1069
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001070 init_completion(&adc_qpnp->adc_rslt_completion);
1071
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001072 return 0;
1073}
1074EXPORT_SYMBOL(qpnp_adc_get_devicetree_data);