blob: 6324c6265cb43e7c5af4457eb2855b1cd39e64b9 [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 Mohanadosse84f8e62012-11-16 09:34:41 -0800302/* Voltage to temperature */
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700303static const struct qpnp_vadc_map_pt adcmap_100k_104ef_104fb[] = {
Siddartha Mohanadosse84f8e62012-11-16 09:34:41 -0800304 {1758, -40},
305 {1742, -35},
306 {1719, -30},
307 {1691, -25},
308 {1654, -20},
309 {1608, -15},
310 {1551, -10},
311 {1483, -5},
312 {1404, 0},
313 {1315, 5},
314 {1218, 10},
315 {1114, 15},
316 {1007, 20},
317 {900, 25},
318 {795, 30},
319 {696, 35},
320 {605, 40},
321 {522, 45},
322 {448, 50},
323 {383, 55},
324 {327, 60},
325 {278, 65},
326 {237, 70},
327 {202, 75},
328 {172, 80},
329 {146, 85},
330 {125, 90},
331 {107, 95},
332 {92, 100},
333 {79, 105},
334 {68, 110},
335 {59, 115},
336 {51, 120},
337 {44, 125}
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700338};
339
Siddartha Mohanadosse84f8e62012-11-16 09:34:41 -0800340/* Voltage to temperature */
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700341static const struct qpnp_vadc_map_pt adcmap_150k_104ef_104fb[] = {
Siddartha Mohanadosse84f8e62012-11-16 09:34:41 -0800342 {1738, -40},
343 {1714, -35},
344 {1682, -30},
345 {1641, -25},
346 {1589, -20},
347 {1526, -15},
348 {1451, -10},
349 {1363, -5},
350 {1266, 0},
351 {1159, 5},
352 {1048, 10},
353 {936, 15},
354 {825, 20},
355 {720, 25},
356 {622, 30},
357 {533, 35},
358 {454, 40},
359 {385, 45},
360 {326, 50},
361 {275, 55},
362 {232, 60},
363 {195, 65},
364 {165, 70},
365 {139, 75},
366 {118, 80},
367 {100, 85},
368 {85, 90},
369 {73, 95},
370 {62, 100},
371 {53, 105},
372 {46, 110},
373 {40, 115},
374 {34, 120},
375 {30, 125}
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700376};
377
Siddartha Mohanadoss4a27b1c2012-11-16 09:34:41 -0800378static int32_t qpnp_adc_map_voltage_temp(const struct qpnp_vadc_map_pt *pts,
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700379 uint32_t tablesize, int32_t input, int64_t *output)
380{
381 bool descending = 1;
382 uint32_t i = 0;
383
384 if ((pts == NULL) || (output == NULL))
385 return -EINVAL;
386
387 /* Check if table is descending or ascending */
388 if (tablesize > 1) {
389 if (pts[0].x < pts[1].x)
390 descending = 0;
391 }
392
393 while (i < tablesize) {
394 if ((descending == 1) && (pts[i].x < input)) {
395 /* table entry is less than measured
396 value and table is descending, stop */
397 break;
398 } else if ((descending == 0) &&
399 (pts[i].x > input)) {
400 /* table entry is greater than measured
401 value and table is ascending, stop */
402 break;
403 } else {
404 i++;
405 }
406 }
407
408 if (i == 0)
409 *output = pts[0].y;
410 else if (i == tablesize)
411 *output = pts[tablesize-1].y;
412 else {
413 /* result is between search_index and search_index-1 */
414 /* interpolate linearly */
415 *output = (((int32_t) ((pts[i].y - pts[i-1].y)*
416 (input - pts[i-1].x))/
417 (pts[i].x - pts[i-1].x))+
418 pts[i-1].y);
419 }
420
421 return 0;
422}
423
Siddartha Mohanadoss4a27b1c2012-11-16 09:34:41 -0800424static int32_t qpnp_adc_map_temp_voltage(const struct qpnp_vadc_map_pt *pts,
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700425 uint32_t tablesize, int32_t input, int64_t *output)
426{
427 bool descending = 1;
428 uint32_t i = 0;
429
430 if ((pts == NULL) || (output == NULL))
431 return -EINVAL;
432
433 /* Check if table is descending or ascending */
434 if (tablesize > 1) {
435 if (pts[0].y < pts[1].y)
436 descending = 0;
437 }
438
439 while (i < tablesize) {
440 if ((descending == 1) && (pts[i].y < input)) {
441 /* table entry is less than measured
442 value and table is descending, stop */
443 break;
444 } else if ((descending == 0) && (pts[i].y > input)) {
445 /* table entry is greater than measured
446 value and table is ascending, stop */
447 break;
448 } else {
449 i++;
450 }
451 }
452
453 if (i == 0) {
454 *output = pts[0].x;
455 } else if (i == tablesize) {
456 *output = pts[tablesize-1].x;
457 } else {
458 /* result is between search_index and search_index-1 */
459 /* interpolate linearly */
460 *output = (((int32_t) ((pts[i].x - pts[i-1].x)*
461 (input - pts[i-1].y))/
462 (pts[i].y - pts[i-1].y))+
463 pts[i-1].x);
464 }
465
466 return 0;
467}
468
469static int64_t qpnp_adc_scale_ratiometric_calib(int32_t adc_code,
470 const struct qpnp_adc_properties *adc_properties,
471 const struct qpnp_vadc_chan_properties *chan_properties)
472{
473 int64_t adc_voltage = 0;
474 bool negative_offset = 0;
475
476 if (!chan_properties || !chan_properties->offset_gain_numerator ||
477 !chan_properties->offset_gain_denominator || !adc_properties)
478 return -EINVAL;
479
480 adc_voltage = (adc_code -
481 chan_properties->adc_graph[CALIB_RATIOMETRIC].adc_gnd)
482 * adc_properties->adc_vdd_reference;
483 if (adc_voltage < 0) {
484 negative_offset = 1;
485 adc_voltage = -adc_voltage;
486 }
487 do_div(adc_voltage,
488 chan_properties->adc_graph[CALIB_RATIOMETRIC].dy);
489 if (negative_offset)
490 adc_voltage = -adc_voltage;
491
492 return adc_voltage;
493}
494
495int32_t qpnp_adc_scale_pmic_therm(int32_t adc_code,
496 const struct qpnp_adc_properties *adc_properties,
497 const struct qpnp_vadc_chan_properties *chan_properties,
498 struct qpnp_vadc_result *adc_chan_result)
499{
500 int64_t pmic_voltage = 0;
501 bool negative_offset = 0;
502
503 if (!chan_properties || !chan_properties->offset_gain_numerator ||
504 !chan_properties->offset_gain_denominator || !adc_properties
505 || !adc_chan_result)
506 return -EINVAL;
507
508 pmic_voltage = (adc_code -
509 chan_properties->adc_graph[CALIB_ABSOLUTE].adc_gnd)
510 * chan_properties->adc_graph[CALIB_ABSOLUTE].dx;
511 if (pmic_voltage < 0) {
512 negative_offset = 1;
513 pmic_voltage = -pmic_voltage;
514 }
515 do_div(pmic_voltage,
516 chan_properties->adc_graph[CALIB_ABSOLUTE].dy);
517 if (negative_offset)
518 pmic_voltage = -pmic_voltage;
519 pmic_voltage += chan_properties->adc_graph[CALIB_ABSOLUTE].dx;
520
521 if (pmic_voltage > 0) {
522 /* 2mV/K */
523 adc_chan_result->measurement = pmic_voltage*
524 chan_properties->offset_gain_denominator;
525
526 do_div(adc_chan_result->measurement,
527 chan_properties->offset_gain_numerator * 2);
528 } else {
529 adc_chan_result->measurement = 0;
530 }
531 /* Change to .001 deg C */
532 adc_chan_result->measurement -= KELVINMIL_DEGMIL;
533 adc_chan_result->physical = (int32_t)adc_chan_result->measurement;
534
535 return 0;
536}
537EXPORT_SYMBOL_GPL(qpnp_adc_scale_pmic_therm);
538
539/* Scales the ADC code to 0.001 degrees C using the map
540 * table for the XO thermistor.
541 */
542int32_t qpnp_adc_tdkntcg_therm(int32_t adc_code,
543 const struct qpnp_adc_properties *adc_properties,
544 const struct qpnp_vadc_chan_properties *chan_properties,
545 struct qpnp_vadc_result *adc_chan_result)
546{
547 int64_t xo_thm = 0;
548
549 if (!chan_properties || !chan_properties->offset_gain_numerator ||
550 !chan_properties->offset_gain_denominator || !adc_properties
551 || !adc_chan_result)
552 return -EINVAL;
553
554 xo_thm = qpnp_adc_scale_ratiometric_calib(adc_code,
555 adc_properties, chan_properties);
556 xo_thm <<= 4;
Siddartha Mohanadoss4a27b1c2012-11-16 09:34:41 -0800557 qpnp_adc_map_voltage_temp(adcmap_ntcg_104ef_104fb,
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700558 ARRAY_SIZE(adcmap_ntcg_104ef_104fb),
559 xo_thm, &adc_chan_result->physical);
560
561 return 0;
562}
563EXPORT_SYMBOL_GPL(qpnp_adc_tdkntcg_therm);
564
565int32_t qpnp_adc_scale_batt_therm(int32_t adc_code,
566 const struct qpnp_adc_properties *adc_properties,
567 const struct qpnp_vadc_chan_properties *chan_properties,
568 struct qpnp_vadc_result *adc_chan_result)
569{
570 int64_t bat_voltage = 0;
571
572 bat_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
573 adc_properties, chan_properties);
574
Siddartha Mohanadoss4a27b1c2012-11-16 09:34:41 -0800575 return qpnp_adc_map_temp_voltage(
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700576 adcmap_btm_threshold,
577 ARRAY_SIZE(adcmap_btm_threshold),
578 bat_voltage,
579 &adc_chan_result->physical);
580}
581EXPORT_SYMBOL_GPL(qpnp_adc_scale_batt_therm);
582
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700583int32_t qpnp_adc_scale_therm_pu1(int32_t adc_code,
584 const struct qpnp_adc_properties *adc_properties,
585 const struct qpnp_vadc_chan_properties *chan_properties,
586 struct qpnp_vadc_result *adc_chan_result)
587{
588 int64_t therm_voltage = 0;
589
590 therm_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
591 adc_properties, chan_properties);
592
Siddartha Mohanadosse84f8e62012-11-16 09:34:41 -0800593 qpnp_adc_map_voltage_temp(adcmap_150k_104ef_104fb,
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700594 ARRAY_SIZE(adcmap_150k_104ef_104fb),
595 therm_voltage, &adc_chan_result->physical);
596
597 return 0;
598}
599EXPORT_SYMBOL_GPL(qpnp_adc_scale_therm_pu1);
600
601int32_t qpnp_adc_scale_therm_pu2(int32_t adc_code,
602 const struct qpnp_adc_properties *adc_properties,
603 const struct qpnp_vadc_chan_properties *chan_properties,
604 struct qpnp_vadc_result *adc_chan_result)
605{
606 int64_t therm_voltage = 0;
607
608 therm_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
609 adc_properties, chan_properties);
610
Siddartha Mohanadosse84f8e62012-11-16 09:34:41 -0800611 qpnp_adc_map_voltage_temp(adcmap_100k_104ef_104fb,
Siddartha Mohanadosse77edf12012-09-13 14:26:32 -0700612 ARRAY_SIZE(adcmap_100k_104ef_104fb),
613 therm_voltage, &adc_chan_result->physical);
614
615 return 0;
616}
617EXPORT_SYMBOL_GPL(qpnp_adc_scale_therm_pu2);
618
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700619int32_t qpnp_adc_scale_batt_id(int32_t adc_code,
620 const struct qpnp_adc_properties *adc_properties,
621 const struct qpnp_vadc_chan_properties *chan_properties,
622 struct qpnp_vadc_result *adc_chan_result)
623{
624 int64_t batt_id_voltage = 0;
625
626 batt_id_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
627 adc_properties, chan_properties);
628 adc_chan_result->physical = batt_id_voltage;
629 adc_chan_result->physical = adc_chan_result->measurement;
630
631 return 0;
632}
633EXPORT_SYMBOL_GPL(qpnp_adc_scale_batt_id);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700634
635int32_t qpnp_adc_scale_default(int32_t adc_code,
636 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 bool negative_rawfromoffset = 0, negative_offset = 0;
641 int64_t scale_voltage = 0;
642
643 if (!chan_properties || !chan_properties->offset_gain_numerator ||
644 !chan_properties->offset_gain_denominator || !adc_properties
645 || !adc_chan_result)
646 return -EINVAL;
647
648 scale_voltage = (adc_code -
649 chan_properties->adc_graph[CALIB_ABSOLUTE].adc_gnd)
650 * chan_properties->adc_graph[CALIB_ABSOLUTE].dx;
651 if (scale_voltage < 0) {
652 negative_offset = 1;
653 scale_voltage = -scale_voltage;
654 }
655 do_div(scale_voltage,
656 chan_properties->adc_graph[CALIB_ABSOLUTE].dy);
657 if (negative_offset)
658 scale_voltage = -scale_voltage;
659 scale_voltage += chan_properties->adc_graph[CALIB_ABSOLUTE].dx;
660
661 if (scale_voltage < 0) {
662 if (adc_properties->bipolar) {
663 scale_voltage = -scale_voltage;
664 negative_rawfromoffset = 1;
665 } else {
666 scale_voltage = 0;
667 }
668 }
669
670 adc_chan_result->measurement = scale_voltage *
671 chan_properties->offset_gain_denominator;
672
673 /* do_div only perform positive integer division! */
674 do_div(adc_chan_result->measurement,
675 chan_properties->offset_gain_numerator);
676
677 if (negative_rawfromoffset)
678 adc_chan_result->measurement = -adc_chan_result->measurement;
679
680 /*
681 * Note: adc_chan_result->measurement is in the unit of
682 * adc_properties.adc_reference. For generic channel processing,
683 * channel measurement is a scale/ratio relative to the adc
684 * reference input
685 */
686 adc_chan_result->physical = adc_chan_result->measurement;
687
688 return 0;
689}
690EXPORT_SYMBOL_GPL(qpnp_adc_scale_default);
691
692int32_t qpnp_vadc_check_result(int32_t *data)
693{
694 if (*data < QPNP_VADC_MIN_ADC_CODE)
695 *data = QPNP_VADC_MIN_ADC_CODE;
696 else if (*data > QPNP_VADC_MAX_ADC_CODE)
697 *data = QPNP_VADC_MAX_ADC_CODE;
698
699 return 0;
700}
701EXPORT_SYMBOL_GPL(qpnp_vadc_check_result);
702
703int32_t qpnp_adc_get_devicetree_data(struct spmi_device *spmi,
704 struct qpnp_adc_drv *adc_qpnp)
705{
706 struct device_node *node = spmi->dev.of_node;
707 struct resource *res;
708 struct device_node *child;
709 struct qpnp_vadc_amux *adc_channel_list;
710 struct qpnp_adc_properties *adc_prop;
Siddartha Mohanadossc4a6af12012-07-13 18:50:12 -0700711 struct qpnp_adc_amux_properties *amux_prop;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700712 int count_adc_channel_list = 0, decimation, rc = 0, i = 0;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700713
714 if (!node)
715 return -EINVAL;
716
717 for_each_child_of_node(node, child)
718 count_adc_channel_list++;
719
720 if (!count_adc_channel_list) {
721 pr_err("No channel listing\n");
722 return -EINVAL;
723 }
724
725 adc_qpnp->spmi = spmi;
726
727 adc_prop = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_adc_properties),
728 GFP_KERNEL);
729 if (!adc_prop) {
730 dev_err(&spmi->dev, "Unable to allocate memory\n");
731 return -ENOMEM;
732 }
733 adc_channel_list = devm_kzalloc(&spmi->dev,
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700734 sizeof(struct qpnp_vadc_amux) * count_adc_channel_list,
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700735 GFP_KERNEL);
736 if (!adc_channel_list) {
737 dev_err(&spmi->dev, "Unable to allocate memory\n");
738 return -ENOMEM;
739 }
740
741 amux_prop = devm_kzalloc(&spmi->dev,
Siddartha Mohanadossc4a6af12012-07-13 18:50:12 -0700742 sizeof(struct qpnp_adc_amux_properties) +
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700743 sizeof(struct qpnp_vadc_chan_properties), GFP_KERNEL);
744 if (!amux_prop) {
745 dev_err(&spmi->dev, "Unable to allocate memory\n");
746 return -ENOMEM;
747 }
748
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700749 adc_qpnp->adc_channels = adc_channel_list;
750 adc_qpnp->amux_prop = amux_prop;
751
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700752 for_each_child_of_node(node, child) {
753 int channel_num, scaling, post_scaling, hw_settle_time;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -0700754 int fast_avg_setup, calib_type, rc;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700755 const char *calibration_param, *channel_name;
756
757 channel_name = of_get_property(child,
758 "label", NULL) ? : child->name;
759 if (!channel_name) {
760 pr_err("Invalid channel name\n");
761 return -EINVAL;
762 }
763
764 rc = of_property_read_u32(child, "qcom,channel-num",
765 &channel_num);
766 if (rc) {
767 pr_err("Invalid channel num\n");
768 return -EINVAL;
769 }
770 rc = of_property_read_u32(child, "qcom,decimation",
771 &decimation);
772 if (rc) {
773 pr_err("Invalid channel decimation property\n");
774 return -EINVAL;
775 }
776 rc = of_property_read_u32(child,
777 "qcom,pre-div-channel-scaling", &scaling);
778 if (rc) {
779 pr_err("Invalid channel scaling property\n");
780 return -EINVAL;
781 }
782 rc = of_property_read_u32(child,
783 "qcom,scale-function", &post_scaling);
784 if (rc) {
785 pr_err("Invalid channel post scaling property\n");
786 return -EINVAL;
787 }
788 rc = of_property_read_u32(child,
789 "qcom,hw-settle-time", &hw_settle_time);
790 if (rc) {
791 pr_err("Invalid channel hw settle time property\n");
792 return -EINVAL;
793 }
794 rc = of_property_read_u32(child,
795 "qcom,fast-avg-setup", &fast_avg_setup);
796 if (rc) {
797 pr_err("Invalid channel fast average setup\n");
798 return -EINVAL;
799 }
800 calibration_param = of_get_property(child,
801 "qcom,calibration-type", NULL);
802 if (!strncmp(calibration_param, "absolute", 8))
803 calib_type = CALIB_ABSOLUTE;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700804 else if (!strncmp(calibration_param, "ratiometric", 11))
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700805 calib_type = CALIB_RATIOMETRIC;
806 else {
807 pr_err("%s: Invalid calibration property\n", __func__);
808 return -EINVAL;
809 }
810 /* Individual channel properties */
811 adc_channel_list[i].name = (char *)channel_name;
812 adc_channel_list[i].channel_num = channel_num;
813 adc_channel_list[i].chan_path_prescaling = scaling;
814 adc_channel_list[i].adc_decimation = decimation;
815 adc_channel_list[i].adc_scale_fn = post_scaling;
816 adc_channel_list[i].hw_settle_time = hw_settle_time;
817 adc_channel_list[i].fast_avg_setup = fast_avg_setup;
818 i++;
819 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700820
821 /* Get the ADC VDD reference voltage and ADC bit resolution */
822 rc = of_property_read_u32(node, "qcom,adc-vdd-reference",
823 &adc_prop->adc_vdd_reference);
824 if (rc) {
825 pr_err("Invalid adc vdd reference property\n");
826 return -EINVAL;
827 }
828 rc = of_property_read_u32(node, "qcom,adc-bit-resolution",
829 &adc_prop->bitresolution);
830 if (rc) {
831 pr_err("Invalid adc bit resolution property\n");
832 return -EINVAL;
833 }
834 adc_qpnp->adc_prop = adc_prop;
835
836 /* Get the peripheral address */
837 res = spmi_get_resource(spmi, 0, IORESOURCE_MEM, 0);
838 if (!res) {
839 pr_err("No base address definition\n");
840 return -EINVAL;
841 }
842
843 adc_qpnp->slave = spmi->sid;
844 adc_qpnp->offset = res->start;
845
846 /* Register the ADC peripheral interrupt */
Siddartha Mohanadoss12109952012-11-20 14:57:51 -0800847 adc_qpnp->adc_irq_eoc = spmi_get_irq_byname(spmi, NULL,
848 "eoc-int-en-set");
849 if (adc_qpnp->adc_irq_eoc < 0) {
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700850 pr_err("Invalid irq\n");
851 return -ENXIO;
852 }
853
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -0700854 init_completion(&adc_qpnp->adc_rslt_completion);
855
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -0700856 mutex_init(&adc_qpnp->adc_lock);
857
858 return 0;
859}
860EXPORT_SYMBOL(qpnp_adc_get_devicetree_data);