blob: 6fb07341f91923d43611bdf6d87c89a57c1b04c6 [file] [log] [blame]
Siddartha Mohanadoss68b4e082014-01-28 10:53:13 -08001/* Copyright (c) 2012-2014, 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
Siddartha Mohanadoss93761842013-09-11 17:46:54 -0700989int qpnp_adc_get_revid_version(struct device *dev)
990{
991 struct pmic_revid_data *revid_data;
992 struct device_node *revid_dev_node;
993
994 revid_dev_node = of_parse_phandle(dev->of_node,
995 "qcom,pmic-revid", 0);
996 if (!revid_dev_node) {
997 pr_debug("Missing qcom,pmic-revid property\n");
998 return -EINVAL;
999 }
1000
1001 revid_data = get_revid_data(revid_dev_node);
1002 if (IS_ERR(revid_data)) {
1003 pr_err("revid error rc = %ld\n", PTR_ERR(revid_data));
1004 return -EINVAL;
1005 }
1006
1007 if ((revid_data->rev1 == PM8941_V3P1_REV1) &&
1008 (revid_data->rev2 == PM8941_V3P1_REV2) &&
1009 (revid_data->rev3 == PM8941_V3P1_REV3) &&
1010 (revid_data->rev4 == PM8941_V3P1_REV4) &&
1011 (revid_data->pmic_type == PM8941_V3P1_TYPE) &&
1012 (revid_data->pmic_subtype == PM8941_V3P1_SUBTYPE))
1013 return QPNP_REV_ID_8941_3_1;
Siddartha Mohanadoss68b4e082014-01-28 10:53:13 -08001014 else if ((revid_data->rev1 == PM8226_V2P2_REV1) &&
1015 (revid_data->rev2 == PM8226_V2P2_REV2) &&
1016 (revid_data->rev3 == PM8226_V2P2_REV3) &&
1017 (revid_data->rev4 == PM8226_V2P2_REV4) &&
1018 (revid_data->pmic_type == PM8226_V2P2_TYPE) &&
1019 (revid_data->pmic_subtype == PM8226_V2P2_SUBTYPE))
1020 return QPNP_REV_ID_8026_2_2;
Siddartha Mohanadoss93761842013-09-11 17:46:54 -07001021 else if ((revid_data->rev1 == PM8226_V2P1_REV1) &&
1022 (revid_data->rev2 == PM8226_V2P1_REV2) &&
1023 (revid_data->rev3 == PM8226_V2P1_REV3) &&
1024 (revid_data->rev4 == PM8226_V2P1_REV4) &&
1025 (revid_data->pmic_type == PM8226_V2P1_TYPE) &&
1026 (revid_data->pmic_subtype == PM8226_V2P1_SUBTYPE))
1027 return QPNP_REV_ID_8026_2_1;
1028 else if ((revid_data->rev1 == PM8226_V2P0_REV1) &&
1029 (revid_data->rev2 == PM8226_V2P0_REV2) &&
1030 (revid_data->rev3 == PM8226_V2P0_REV3) &&
1031 (revid_data->rev4 == PM8226_V2P0_REV4) &&
1032 (revid_data->pmic_type == PM8226_V2P0_TYPE) &&
1033 (revid_data->pmic_subtype == PM8226_V2P0_SUBTYPE))
1034 return QPNP_REV_ID_8026_2_0;
1035 else if ((revid_data->rev1 == PM8226_V1P0_REV1) &&
1036 (revid_data->rev2 == PM8226_V1P0_REV2) &&
1037 (revid_data->rev3 == PM8226_V1P0_REV3) &&
1038 (revid_data->rev4 == PM8226_V1P0_REV4) &&
1039 (revid_data->pmic_type == PM8226_V1P0_TYPE) &&
1040 (revid_data->pmic_subtype == PM8226_V1P0_SUBTYPE))
1041 return QPNP_REV_ID_8026_1_0;
1042 else if ((revid_data->rev1 == PM8110_V1P0_REV1) &&
1043 (revid_data->rev2 == PM8110_V1P0_REV2) &&
1044 (revid_data->rev3 == PM8110_V1P0_REV3) &&
1045 (revid_data->rev4 == PM8110_V1P0_REV4) &&
1046 (revid_data->pmic_type == PM8110_V1P0_TYPE) &&
1047 (revid_data->pmic_subtype == PM8110_V1P0_SUBTYPE))
1048 return QPNP_REV_ID_8110_1_0;
Xiaozhe Shi80754222013-10-30 14:11:41 -07001049 else if ((revid_data->rev1 == PM8110_V2P0_REV1) &&
1050 (revid_data->rev2 == PM8110_V2P0_REV2) &&
1051 (revid_data->rev3 == PM8110_V2P0_REV3) &&
1052 (revid_data->rev4 == PM8110_V2P0_REV4) &&
1053 (revid_data->pmic_type == PM8110_V2P0_TYPE) &&
1054 (revid_data->pmic_subtype == PM8110_V2P0_SUBTYPE))
1055 return QPNP_REV_ID_8110_2_0;
Siddartha Mohanadoss93761842013-09-11 17:46:54 -07001056 else
1057 return -EINVAL;
1058}
1059EXPORT_SYMBOL(qpnp_adc_get_revid_version);
1060
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001061int32_t qpnp_adc_get_devicetree_data(struct spmi_device *spmi,
1062 struct qpnp_adc_drv *adc_qpnp)
1063{
1064 struct device_node *node = spmi->dev.of_node;
1065 struct resource *res;
1066 struct device_node *child;
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -08001067 struct qpnp_adc_amux *adc_channel_list;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001068 struct qpnp_adc_properties *adc_prop;
Siddartha Mohanadossc4a6af12012-07-13 18:50:12 -07001069 struct qpnp_adc_amux_properties *amux_prop;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -07001070 int count_adc_channel_list = 0, decimation, rc = 0, i = 0;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001071
1072 if (!node)
1073 return -EINVAL;
1074
1075 for_each_child_of_node(node, child)
1076 count_adc_channel_list++;
1077
1078 if (!count_adc_channel_list) {
1079 pr_err("No channel listing\n");
1080 return -EINVAL;
1081 }
1082
1083 adc_qpnp->spmi = spmi;
1084
1085 adc_prop = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_adc_properties),
1086 GFP_KERNEL);
1087 if (!adc_prop) {
1088 dev_err(&spmi->dev, "Unable to allocate memory\n");
1089 return -ENOMEM;
1090 }
1091 adc_channel_list = devm_kzalloc(&spmi->dev,
Siddartha Mohanadoss31f60962012-11-27 14:11:02 -08001092 ((sizeof(struct qpnp_adc_amux)) * count_adc_channel_list),
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001093 GFP_KERNEL);
1094 if (!adc_channel_list) {
1095 dev_err(&spmi->dev, "Unable to allocate memory\n");
1096 return -ENOMEM;
1097 }
1098
1099 amux_prop = devm_kzalloc(&spmi->dev,
Siddartha Mohanadossc4a6af12012-07-13 18:50:12 -07001100 sizeof(struct qpnp_adc_amux_properties) +
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001101 sizeof(struct qpnp_vadc_chan_properties), GFP_KERNEL);
1102 if (!amux_prop) {
1103 dev_err(&spmi->dev, "Unable to allocate memory\n");
1104 return -ENOMEM;
1105 }
1106
Siddartha Mohanadossae1da732012-08-08 16:39:02 -07001107 adc_qpnp->adc_channels = adc_channel_list;
1108 adc_qpnp->amux_prop = amux_prop;
1109
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001110 for_each_child_of_node(node, child) {
1111 int channel_num, scaling, post_scaling, hw_settle_time;
Siddartha Mohanadossae1da732012-08-08 16:39:02 -07001112 int fast_avg_setup, calib_type, rc;
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001113 const char *calibration_param, *channel_name;
1114
1115 channel_name = of_get_property(child,
1116 "label", NULL) ? : child->name;
1117 if (!channel_name) {
1118 pr_err("Invalid channel name\n");
1119 return -EINVAL;
1120 }
1121
Siddartha Mohanadoss96be0a02012-12-07 14:38:48 -08001122 rc = of_property_read_u32(child, "reg", &channel_num);
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001123 if (rc) {
1124 pr_err("Invalid channel num\n");
1125 return -EINVAL;
1126 }
1127 rc = of_property_read_u32(child, "qcom,decimation",
1128 &decimation);
1129 if (rc) {
1130 pr_err("Invalid channel decimation property\n");
1131 return -EINVAL;
1132 }
1133 rc = of_property_read_u32(child,
1134 "qcom,pre-div-channel-scaling", &scaling);
1135 if (rc) {
1136 pr_err("Invalid channel scaling property\n");
1137 return -EINVAL;
1138 }
1139 rc = of_property_read_u32(child,
1140 "qcom,scale-function", &post_scaling);
1141 if (rc) {
1142 pr_err("Invalid channel post scaling property\n");
1143 return -EINVAL;
1144 }
1145 rc = of_property_read_u32(child,
1146 "qcom,hw-settle-time", &hw_settle_time);
1147 if (rc) {
1148 pr_err("Invalid channel hw settle time property\n");
1149 return -EINVAL;
1150 }
1151 rc = of_property_read_u32(child,
1152 "qcom,fast-avg-setup", &fast_avg_setup);
1153 if (rc) {
1154 pr_err("Invalid channel fast average setup\n");
1155 return -EINVAL;
1156 }
Siddartha Mohanadoss630def02013-06-27 14:53:38 -07001157 rc = of_property_read_string(child, "qcom,calibration-type",
1158 &calibration_param);
1159 if (rc) {
1160 pr_err("Invalid calibration type\n");
1161 return -EINVAL;
1162 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001163 if (!strncmp(calibration_param, "absolute", 8))
1164 calib_type = CALIB_ABSOLUTE;
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001165 else if (!strncmp(calibration_param, "ratiometric", 11))
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001166 calib_type = CALIB_RATIOMETRIC;
1167 else {
1168 pr_err("%s: Invalid calibration property\n", __func__);
1169 return -EINVAL;
1170 }
1171 /* Individual channel properties */
1172 adc_channel_list[i].name = (char *)channel_name;
1173 adc_channel_list[i].channel_num = channel_num;
1174 adc_channel_list[i].chan_path_prescaling = scaling;
1175 adc_channel_list[i].adc_decimation = decimation;
1176 adc_channel_list[i].adc_scale_fn = post_scaling;
1177 adc_channel_list[i].hw_settle_time = hw_settle_time;
1178 adc_channel_list[i].fast_avg_setup = fast_avg_setup;
1179 i++;
1180 }
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001181
1182 /* Get the ADC VDD reference voltage and ADC bit resolution */
1183 rc = of_property_read_u32(node, "qcom,adc-vdd-reference",
1184 &adc_prop->adc_vdd_reference);
1185 if (rc) {
1186 pr_err("Invalid adc vdd reference property\n");
1187 return -EINVAL;
1188 }
1189 rc = of_property_read_u32(node, "qcom,adc-bit-resolution",
1190 &adc_prop->bitresolution);
1191 if (rc) {
1192 pr_err("Invalid adc bit resolution property\n");
1193 return -EINVAL;
1194 }
1195 adc_qpnp->adc_prop = adc_prop;
1196
1197 /* Get the peripheral address */
1198 res = spmi_get_resource(spmi, 0, IORESOURCE_MEM, 0);
1199 if (!res) {
1200 pr_err("No base address definition\n");
1201 return -EINVAL;
1202 }
1203
1204 adc_qpnp->slave = spmi->sid;
1205 adc_qpnp->offset = res->start;
1206
1207 /* Register the ADC peripheral interrupt */
Siddartha Mohanadoss12109952012-11-20 14:57:51 -08001208 adc_qpnp->adc_irq_eoc = spmi_get_irq_byname(spmi, NULL,
1209 "eoc-int-en-set");
1210 if (adc_qpnp->adc_irq_eoc < 0) {
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001211 pr_err("Invalid irq\n");
1212 return -ENXIO;
1213 }
1214
Siddartha Mohanadoss5ace1102012-08-20 23:18:10 -07001215 init_completion(&adc_qpnp->adc_rslt_completion);
1216
Siddartha Mohanadoss7b116e12012-06-05 23:27:46 -07001217 return 0;
1218}
1219EXPORT_SYMBOL(qpnp_adc_get_devicetree_data);