blob: 60eb8e94609eaedaa50950012c0b8c3e3cbf7b13 [file] [log] [blame]
Siddartha Mohanadoss4a27b1c2012-11-16 09:34:41 -08001/* Copyright (c) 2012, 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
133static const struct qpnp_vadc_map_pt adcmap_ntcg_104ef_104fb[] = {
134 {696483, -40960},
135 {649148, -39936},
136 {605368, -38912},
137 {564809, -37888},
138 {527215, -36864},
139 {492322, -35840},
140 {460007, -34816},
141 {429982, -33792},
142 {402099, -32768},
143 {376192, -31744},
144 {352075, -30720},
145 {329714, -29696},
146 {308876, -28672},
147 {289480, -27648},
148 {271417, -26624},
149 {254574, -25600},
150 {238903, -24576},
151 {224276, -23552},
152 {210631, -22528},
153 {197896, -21504},
154 {186007, -20480},
155 {174899, -19456},
156 {164521, -18432},
157 {154818, -17408},
158 {145744, -16384},
159 {137265, -15360},
160 {129307, -14336},
161 {121866, -13312},
162 {114896, -12288},
163 {108365, -11264},
164 {102252, -10240},
165 {96499, -9216},
166 {91111, -8192},
167 {86055, -7168},
168 {81308, -6144},
169 {76857, -5120},
170 {72660, -4096},
171 {68722, -3072},
172 {65020, -2048},
173 {61538, -1024},
174 {58261, 0},
175 {55177, 1024},
176 {52274, 2048},
177 {49538, 3072},
178 {46962, 4096},
179 {44531, 5120},
180 {42243, 6144},
181 {40083, 7168},
182 {38045, 8192},
183 {36122, 9216},
184 {34308, 10240},
185 {32592, 11264},
186 {30972, 12288},
187 {29442, 13312},
188 {27995, 14336},
189 {26624, 15360},
190 {25333, 16384},
191 {24109, 17408},
192 {22951, 18432},
193 {21854, 19456},
194 {20807, 20480},
195 {19831, 21504},
196 {18899, 22528},
197 {18016, 23552},
198 {17178, 24576},
199 {16384, 25600},
200 {15631, 26624},
201 {14916, 27648},
202 {14237, 28672},
203 {13593, 29696},
204 {12976, 30720},
205 {12400, 31744},
206 {11848, 32768},
207 {11324, 33792},
208 {10825, 34816},
209 {10354, 35840},
210 {9900, 36864},
211 {9471, 37888},
212 {9062, 38912},
213 {8674, 39936},
214 {8306, 40960},
215 {7951, 41984},
216 {7616, 43008},
217 {7296, 44032},
218 {6991, 45056},
219 {6701, 46080},
220 {6424, 47104},
221 {6160, 48128},
222 {5908, 49152},
223 {5667, 50176},
224 {5439, 51200},
225 {5219, 52224},
226 {5010, 53248},
227 {4810, 54272},
228 {4619, 55296},
229 {4440, 56320},
230 {4263, 57344},
231 {4097, 58368},
232 {3938, 59392},
233 {3785, 60416},
234 {3637, 61440},
235 {3501, 62464},
236 {3368, 63488},
237 {3240, 64512},
238 {3118, 65536},
239 {2998, 66560},
240 {2889, 67584},
241 {2782, 68608},
242 {2680, 69632},
243 {2581, 70656},
244 {2490, 71680},
245 {2397, 72704},
246 {2310, 73728},
247 {2227, 74752},
248 {2147, 75776},
249 {2064, 76800},
250 {1998, 77824},
251 {1927, 78848},
252 {1860, 79872},
253 {1795, 80896},
254 {1736, 81920},
255 {1673, 82944},
256 {1615, 83968},
257 {1560, 84992},
258 {1507, 86016},
259 {1456, 87040},
260 {1407, 88064},
261 {1360, 89088},
262 {1314, 90112},
263 {1271, 91136},
264 {1228, 92160},
265 {1189, 93184},
266 {1150, 94208},
267 {1112, 95232},
268 {1076, 96256},
269 {1042, 97280},
270 {1008, 98304},
271 {976, 99328},
272 {945, 100352},
273 {915, 101376},
274 {886, 102400},
275 {859, 103424},
276 {832, 104448},
277 {807, 105472},
278 {782, 106496},
279 {756, 107520},
280 {735, 108544},
281 {712, 109568},
282 {691, 110592},
283 {670, 111616},
284 {650, 112640},
285 {631, 113664},
286 {612, 114688},
287 {594, 115712},
288 {577, 116736},
289 {560, 117760},
290 {544, 118784},
291 {528, 119808},
292 {513, 120832},
293 {498, 121856},
294 {483, 122880},
295 {470, 123904},
296 {457, 124928},
297 {444, 125952},
298 {431, 126976},
299 {419, 128000}
300};
301
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700302static const struct qpnp_vadc_map_pt adcmap_100k_104ef_104fb[] = {
303 {-40, 1758},
304 {-35, 1742},
305 {-30, 1719},
306 {-25, 1691},
307 {-20, 1654},
308 {-15, 1608},
309 {-10, 1551},
310 {-5, 1483},
311 {0, 1404},
312 {5, 1315},
313 {10, 1218},
314 {15, 1114},
315 {20, 1007},
316 {25, 900},
317 {30, 795},
318 {35, 696},
319 {40, 605},
320 {45, 522},
321 {50, 448},
322 {55, 383},
323 {60, 327},
324 {65, 278},
325 {70, 237},
326 {75, 202},
327 {80, 172},
328 {85, 146},
329 {90, 125},
330 {95, 107},
331 {100, 92},
332 {105, 79},
333 {110, 68},
334 {115, 59},
335 {120, 51},
336 {125, 44}
337};
338
339static const struct qpnp_vadc_map_pt adcmap_150k_104ef_104fb[] = {
340 {-40, 1738},
341 {-35, 1714},
342 {-30, 1682},
343 {-25, 1641},
344 {-20, 1589},
345 {-15, 1526},
346 {-10, 1451},
347 {-5, 1363},
348 {0, 1266},
349 {5, 1159},
350 {10, 1048},
351 {15, 936},
352 {20, 825},
353 {25, 720},
354 {30, 622},
355 {35, 533},
356 {40, 454},
357 {45, 385},
358 {50, 326},
359 {55, 275},
360 {60, 232},
361 {65, 195},
362 {70, 165},
363 {75, 139},
364 {80, 118},
365 {85, 100},
366 {90, 85},
367 {95, 73},
368 {100, 62},
369 {105, 53},
370 {110, 46},
371 {115, 40},
372 {120, 34},
373 {125, 30}
374};
375
Siddartha Mohanadoss4a27b1c2012-11-16 09:34:41 -0800376static int32_t qpnp_adc_map_voltage_temp(const struct qpnp_vadc_map_pt *pts,
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700377 uint32_t tablesize, int32_t input, int64_t *output)
378{
379 bool descending = 1;
380 uint32_t i = 0;
381
382 if ((pts == NULL) || (output == NULL))
383 return -EINVAL;
384
385 /* Check if table is descending or ascending */
386 if (tablesize > 1) {
387 if (pts[0].x < pts[1].x)
388 descending = 0;
389 }
390
391 while (i < tablesize) {
392 if ((descending == 1) && (pts[i].x < input)) {
393 /* table entry is less than measured
394 value and table is descending, stop */
395 break;
396 } else if ((descending == 0) &&
397 (pts[i].x > input)) {
398 /* table entry is greater than measured
399 value and table is ascending, stop */
400 break;
401 } else {
402 i++;
403 }
404 }
405
406 if (i == 0)
407 *output = pts[0].y;
408 else if (i == tablesize)
409 *output = pts[tablesize-1].y;
410 else {
411 /* result is between search_index and search_index-1 */
412 /* interpolate linearly */
413 *output = (((int32_t) ((pts[i].y - pts[i-1].y)*
414 (input - pts[i-1].x))/
415 (pts[i].x - pts[i-1].x))+
416 pts[i-1].y);
417 }
418
419 return 0;
420}
421
Siddartha Mohanadoss4a27b1c2012-11-16 09:34:41 -0800422static int32_t qpnp_adc_map_temp_voltage(const struct qpnp_vadc_map_pt *pts,
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700423 uint32_t tablesize, int32_t input, int64_t *output)
424{
425 bool descending = 1;
426 uint32_t i = 0;
427
428 if ((pts == NULL) || (output == NULL))
429 return -EINVAL;
430
431 /* Check if table is descending or ascending */
432 if (tablesize > 1) {
433 if (pts[0].y < pts[1].y)
434 descending = 0;
435 }
436
437 while (i < tablesize) {
438 if ((descending == 1) && (pts[i].y < input)) {
439 /* table entry is less than measured
440 value and table is descending, stop */
441 break;
442 } else if ((descending == 0) && (pts[i].y > input)) {
443 /* table entry is greater than measured
444 value and table is ascending, stop */
445 break;
446 } else {
447 i++;
448 }
449 }
450
451 if (i == 0) {
452 *output = pts[0].x;
453 } else if (i == tablesize) {
454 *output = pts[tablesize-1].x;
455 } else {
456 /* result is between search_index and search_index-1 */
457 /* interpolate linearly */
458 *output = (((int32_t) ((pts[i].x - pts[i-1].x)*
459 (input - pts[i-1].y))/
460 (pts[i].y - pts[i-1].y))+
461 pts[i-1].x);
462 }
463
464 return 0;
465}
466
467static int64_t qpnp_adc_scale_ratiometric_calib(int32_t adc_code,
468 const struct qpnp_adc_properties *adc_properties,
469 const struct qpnp_vadc_chan_properties *chan_properties)
470{
471 int64_t adc_voltage = 0;
472 bool negative_offset = 0;
473
474 if (!chan_properties || !chan_properties->offset_gain_numerator ||
475 !chan_properties->offset_gain_denominator || !adc_properties)
476 return -EINVAL;
477
478 adc_voltage = (adc_code -
479 chan_properties->adc_graph[CALIB_RATIOMETRIC].adc_gnd)
480 * adc_properties->adc_vdd_reference;
481 if (adc_voltage < 0) {
482 negative_offset = 1;
483 adc_voltage = -adc_voltage;
484 }
485 do_div(adc_voltage,
486 chan_properties->adc_graph[CALIB_RATIOMETRIC].dy);
487 if (negative_offset)
488 adc_voltage = -adc_voltage;
489
490 return adc_voltage;
491}
492
493int32_t qpnp_adc_scale_pmic_therm(int32_t adc_code,
494 const struct qpnp_adc_properties *adc_properties,
495 const struct qpnp_vadc_chan_properties *chan_properties,
496 struct qpnp_vadc_result *adc_chan_result)
497{
498 int64_t pmic_voltage = 0;
499 bool negative_offset = 0;
500
501 if (!chan_properties || !chan_properties->offset_gain_numerator ||
502 !chan_properties->offset_gain_denominator || !adc_properties
503 || !adc_chan_result)
504 return -EINVAL;
505
506 pmic_voltage = (adc_code -
507 chan_properties->adc_graph[CALIB_ABSOLUTE].adc_gnd)
508 * chan_properties->adc_graph[CALIB_ABSOLUTE].dx;
509 if (pmic_voltage < 0) {
510 negative_offset = 1;
511 pmic_voltage = -pmic_voltage;
512 }
513 do_div(pmic_voltage,
514 chan_properties->adc_graph[CALIB_ABSOLUTE].dy);
515 if (negative_offset)
516 pmic_voltage = -pmic_voltage;
517 pmic_voltage += chan_properties->adc_graph[CALIB_ABSOLUTE].dx;
518
519 if (pmic_voltage > 0) {
520 /* 2mV/K */
521 adc_chan_result->measurement = pmic_voltage*
522 chan_properties->offset_gain_denominator;
523
524 do_div(adc_chan_result->measurement,
525 chan_properties->offset_gain_numerator * 2);
526 } else {
527 adc_chan_result->measurement = 0;
528 }
529 /* Change to .001 deg C */
530 adc_chan_result->measurement -= KELVINMIL_DEGMIL;
531 adc_chan_result->physical = (int32_t)adc_chan_result->measurement;
532
533 return 0;
534}
535EXPORT_SYMBOL_GPL(qpnp_adc_scale_pmic_therm);
536
537/* Scales the ADC code to 0.001 degrees C using the map
538 * table for the XO thermistor.
539 */
540int32_t qpnp_adc_tdkntcg_therm(int32_t adc_code,
541 const struct qpnp_adc_properties *adc_properties,
542 const struct qpnp_vadc_chan_properties *chan_properties,
543 struct qpnp_vadc_result *adc_chan_result)
544{
545 int64_t xo_thm = 0;
546
547 if (!chan_properties || !chan_properties->offset_gain_numerator ||
548 !chan_properties->offset_gain_denominator || !adc_properties
549 || !adc_chan_result)
550 return -EINVAL;
551
552 xo_thm = qpnp_adc_scale_ratiometric_calib(adc_code,
553 adc_properties, chan_properties);
554 xo_thm <<= 4;
Siddartha Mohanadoss4a27b1c2012-11-16 09:34:41 -0800555 qpnp_adc_map_voltage_temp(adcmap_ntcg_104ef_104fb,
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700556 ARRAY_SIZE(adcmap_ntcg_104ef_104fb),
557 xo_thm, &adc_chan_result->physical);
558
559 return 0;
560}
561EXPORT_SYMBOL_GPL(qpnp_adc_tdkntcg_therm);
562
563int32_t qpnp_adc_scale_batt_therm(int32_t adc_code,
564 const struct qpnp_adc_properties *adc_properties,
565 const struct qpnp_vadc_chan_properties *chan_properties,
566 struct qpnp_vadc_result *adc_chan_result)
567{
568 int64_t bat_voltage = 0;
569
570 bat_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
571 adc_properties, chan_properties);
572
Siddartha Mohanadoss4a27b1c2012-11-16 09:34:41 -0800573 return qpnp_adc_map_temp_voltage(
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700574 adcmap_btm_threshold,
575 ARRAY_SIZE(adcmap_btm_threshold),
576 bat_voltage,
577 &adc_chan_result->physical);
578}
579EXPORT_SYMBOL_GPL(qpnp_adc_scale_batt_therm);
580
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700581int32_t qpnp_adc_scale_therm_pu1(int32_t adc_code,
582 const struct qpnp_adc_properties *adc_properties,
583 const struct qpnp_vadc_chan_properties *chan_properties,
584 struct qpnp_vadc_result *adc_chan_result)
585{
586 int64_t therm_voltage = 0;
587
588 therm_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
589 adc_properties, chan_properties);
590
Siddartha Mohanadoss4a27b1c2012-11-16 09:34:41 -0800591 qpnp_adc_map_temp_voltage(adcmap_150k_104ef_104fb,
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700592 ARRAY_SIZE(adcmap_150k_104ef_104fb),
593 therm_voltage, &adc_chan_result->physical);
594
595 return 0;
596}
597EXPORT_SYMBOL_GPL(qpnp_adc_scale_therm_pu1);
598
599int32_t qpnp_adc_scale_therm_pu2(int32_t adc_code,
600 const struct qpnp_adc_properties *adc_properties,
601 const struct qpnp_vadc_chan_properties *chan_properties,
602 struct qpnp_vadc_result *adc_chan_result)
603{
604 int64_t therm_voltage = 0;
605
606 therm_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
607 adc_properties, chan_properties);
608
Siddartha Mohanadoss4a27b1c2012-11-16 09:34:41 -0800609 qpnp_adc_map_temp_voltage(adcmap_100k_104ef_104fb,
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700610 ARRAY_SIZE(adcmap_100k_104ef_104fb),
611 therm_voltage, &adc_chan_result->physical);
612
613 return 0;
614}
615EXPORT_SYMBOL_GPL(qpnp_adc_scale_therm_pu2);
616
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700617int32_t qpnp_adc_scale_batt_id(int32_t adc_code,
618 const struct qpnp_adc_properties *adc_properties,
619 const struct qpnp_vadc_chan_properties *chan_properties,
620 struct qpnp_vadc_result *adc_chan_result)
621{
622 int64_t batt_id_voltage = 0;
623
624 batt_id_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
625 adc_properties, chan_properties);
626 adc_chan_result->physical = batt_id_voltage;
627 adc_chan_result->physical = adc_chan_result->measurement;
628
629 return 0;
630}
631EXPORT_SYMBOL_GPL(qpnp_adc_scale_batt_id);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700632
633int32_t qpnp_adc_scale_default(int32_t adc_code,
634 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 bool negative_rawfromoffset = 0, negative_offset = 0;
639 int64_t scale_voltage = 0;
640
641 if (!chan_properties || !chan_properties->offset_gain_numerator ||
642 !chan_properties->offset_gain_denominator || !adc_properties
643 || !adc_chan_result)
644 return -EINVAL;
645
646 scale_voltage = (adc_code -
647 chan_properties->adc_graph[CALIB_ABSOLUTE].adc_gnd)
648 * chan_properties->adc_graph[CALIB_ABSOLUTE].dx;
649 if (scale_voltage < 0) {
650 negative_offset = 1;
651 scale_voltage = -scale_voltage;
652 }
653 do_div(scale_voltage,
654 chan_properties->adc_graph[CALIB_ABSOLUTE].dy);
655 if (negative_offset)
656 scale_voltage = -scale_voltage;
657 scale_voltage += chan_properties->adc_graph[CALIB_ABSOLUTE].dx;
658
659 if (scale_voltage < 0) {
660 if (adc_properties->bipolar) {
661 scale_voltage = -scale_voltage;
662 negative_rawfromoffset = 1;
663 } else {
664 scale_voltage = 0;
665 }
666 }
667
668 adc_chan_result->measurement = scale_voltage *
669 chan_properties->offset_gain_denominator;
670
671 /* do_div only perform positive integer division! */
672 do_div(adc_chan_result->measurement,
673 chan_properties->offset_gain_numerator);
674
675 if (negative_rawfromoffset)
676 adc_chan_result->measurement = -adc_chan_result->measurement;
677
678 /*
679 * Note: adc_chan_result->measurement is in the unit of
680 * adc_properties.adc_reference. For generic channel processing,
681 * channel measurement is a scale/ratio relative to the adc
682 * reference input
683 */
684 adc_chan_result->physical = adc_chan_result->measurement;
685
686 return 0;
687}
688EXPORT_SYMBOL_GPL(qpnp_adc_scale_default);
689
690int32_t qpnp_vadc_check_result(int32_t *data)
691{
692 if (*data < QPNP_VADC_MIN_ADC_CODE)
693 *data = QPNP_VADC_MIN_ADC_CODE;
694 else if (*data > QPNP_VADC_MAX_ADC_CODE)
695 *data = QPNP_VADC_MAX_ADC_CODE;
696
697 return 0;
698}
699EXPORT_SYMBOL_GPL(qpnp_vadc_check_result);
700
701int32_t qpnp_adc_get_devicetree_data(struct spmi_device *spmi,
702 struct qpnp_adc_drv *adc_qpnp)
703{
704 struct device_node *node = spmi->dev.of_node;
705 struct resource *res;
706 struct device_node *child;
707 struct qpnp_vadc_amux *adc_channel_list;
708 struct qpnp_adc_properties *adc_prop;
Siddartha Mohanadossc4a6af12012-07-13 18:50:12 -0700709 struct qpnp_adc_amux_properties *amux_prop;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700710 int count_adc_channel_list = 0, decimation, rc = 0, i = 0;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700711
712 if (!node)
713 return -EINVAL;
714
715 for_each_child_of_node(node, child)
716 count_adc_channel_list++;
717
718 if (!count_adc_channel_list) {
719 pr_err("No channel listing\n");
720 return -EINVAL;
721 }
722
723 adc_qpnp->spmi = spmi;
724
725 adc_prop = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_adc_properties),
726 GFP_KERNEL);
727 if (!adc_prop) {
728 dev_err(&spmi->dev, "Unable to allocate memory\n");
729 return -ENOMEM;
730 }
731 adc_channel_list = devm_kzalloc(&spmi->dev,
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700732 sizeof(struct qpnp_vadc_amux) * count_adc_channel_list,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700733 GFP_KERNEL);
734 if (!adc_channel_list) {
735 dev_err(&spmi->dev, "Unable to allocate memory\n");
736 return -ENOMEM;
737 }
738
739 amux_prop = devm_kzalloc(&spmi->dev,
Siddartha Mohanadossc4a6af12012-07-13 18:50:12 -0700740 sizeof(struct qpnp_adc_amux_properties) +
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700741 sizeof(struct qpnp_vadc_chan_properties), GFP_KERNEL);
742 if (!amux_prop) {
743 dev_err(&spmi->dev, "Unable to allocate memory\n");
744 return -ENOMEM;
745 }
746
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700747 adc_qpnp->adc_channels = adc_channel_list;
748 adc_qpnp->amux_prop = amux_prop;
749
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700750 for_each_child_of_node(node, child) {
751 int channel_num, scaling, post_scaling, hw_settle_time;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700752 int fast_avg_setup, calib_type, rc;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700753 const char *calibration_param, *channel_name;
754
755 channel_name = of_get_property(child,
756 "label", NULL) ? : child->name;
757 if (!channel_name) {
758 pr_err("Invalid channel name\n");
759 return -EINVAL;
760 }
761
762 rc = of_property_read_u32(child, "qcom,channel-num",
763 &channel_num);
764 if (rc) {
765 pr_err("Invalid channel num\n");
766 return -EINVAL;
767 }
768 rc = of_property_read_u32(child, "qcom,decimation",
769 &decimation);
770 if (rc) {
771 pr_err("Invalid channel decimation property\n");
772 return -EINVAL;
773 }
774 rc = of_property_read_u32(child,
775 "qcom,pre-div-channel-scaling", &scaling);
776 if (rc) {
777 pr_err("Invalid channel scaling property\n");
778 return -EINVAL;
779 }
780 rc = of_property_read_u32(child,
781 "qcom,scale-function", &post_scaling);
782 if (rc) {
783 pr_err("Invalid channel post scaling property\n");
784 return -EINVAL;
785 }
786 rc = of_property_read_u32(child,
787 "qcom,hw-settle-time", &hw_settle_time);
788 if (rc) {
789 pr_err("Invalid channel hw settle time property\n");
790 return -EINVAL;
791 }
792 rc = of_property_read_u32(child,
793 "qcom,fast-avg-setup", &fast_avg_setup);
794 if (rc) {
795 pr_err("Invalid channel fast average setup\n");
796 return -EINVAL;
797 }
798 calibration_param = of_get_property(child,
799 "qcom,calibration-type", NULL);
800 if (!strncmp(calibration_param, "absolute", 8))
801 calib_type = CALIB_ABSOLUTE;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700802 else if (!strncmp(calibration_param, "ratiometric", 11))
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700803 calib_type = CALIB_RATIOMETRIC;
804 else {
805 pr_err("%s: Invalid calibration property\n", __func__);
806 return -EINVAL;
807 }
808 /* Individual channel properties */
809 adc_channel_list[i].name = (char *)channel_name;
810 adc_channel_list[i].channel_num = channel_num;
811 adc_channel_list[i].chan_path_prescaling = scaling;
812 adc_channel_list[i].adc_decimation = decimation;
813 adc_channel_list[i].adc_scale_fn = post_scaling;
814 adc_channel_list[i].hw_settle_time = hw_settle_time;
815 adc_channel_list[i].fast_avg_setup = fast_avg_setup;
816 i++;
817 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700818
819 /* Get the ADC VDD reference voltage and ADC bit resolution */
820 rc = of_property_read_u32(node, "qcom,adc-vdd-reference",
821 &adc_prop->adc_vdd_reference);
822 if (rc) {
823 pr_err("Invalid adc vdd reference property\n");
824 return -EINVAL;
825 }
826 rc = of_property_read_u32(node, "qcom,adc-bit-resolution",
827 &adc_prop->bitresolution);
828 if (rc) {
829 pr_err("Invalid adc bit resolution property\n");
830 return -EINVAL;
831 }
832 adc_qpnp->adc_prop = adc_prop;
833
834 /* Get the peripheral address */
835 res = spmi_get_resource(spmi, 0, IORESOURCE_MEM, 0);
836 if (!res) {
837 pr_err("No base address definition\n");
838 return -EINVAL;
839 }
840
841 adc_qpnp->slave = spmi->sid;
842 adc_qpnp->offset = res->start;
843
844 /* Register the ADC peripheral interrupt */
845 adc_qpnp->adc_irq = spmi_get_irq(spmi, 0, 0);
846 if (adc_qpnp->adc_irq < 0) {
847 pr_err("Invalid irq\n");
848 return -ENXIO;
849 }
850
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700851 init_completion(&adc_qpnp->adc_rslt_completion);
852
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700853 mutex_init(&adc_qpnp->adc_lock);
854
855 return 0;
856}
857EXPORT_SYMBOL(qpnp_adc_get_devicetree_data);