blob: b63800ced63c09f7bfd4d65371f7d8520cbeb515 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
2 *
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#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/mutex.h>
16#include <linux/module.h>
17#include <linux/platform_device.h>
18#include <linux/err.h>
19#include <linux/msm_adc.h>
20#include <linux/pmic8058-xoadc.h>
21#include <linux/mfd/pmic8058.h>
22#include <linux/interrupt.h>
23#include <linux/slab.h>
24#include <linux/ratelimit.h>
25#include <linux/delay.h>
Siddartha Mohanadoss71128482011-10-05 15:16:10 -070026#include <linux/wakelock.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070027
28#include <mach/mpp.h>
29#include <mach/msm_xo.h>
30
31#define ADC_DRIVER_NAME "pm8058-xoadc"
32
33#define MAX_QUEUE_LENGTH 0X15
34#define MAX_CHANNEL_PROPERTIES_QUEUE 0X7
35#define MAX_QUEUE_SLOT 0x1
36
37/* User Processor */
38#define ADC_ARB_USRP_CNTRL 0x197
39 #define ADC_ARB_USRP_CNTRL_EN_ARB BIT(0)
40 #define ADC_ARB_USRP_CNTRL_RSV1 BIT(1)
41 #define ADC_ARB_USRP_CNTRL_RSV2 BIT(2)
42 #define ADC_ARB_USRP_CNTRL_RSV3 BIT(3)
43 #define ADC_ARB_USRP_CNTRL_RSV4 BIT(4)
44 #define ADC_ARB_USRP_CNTRL_RSV5 BIT(5)
45 #define ADC_ARB_USRP_CNTRL_EOC BIT(6)
46 #define ADC_ARB_USRP_CNTRL_REQ BIT(7)
47
48#define ADC_ARB_USRP_AMUX_CNTRL 0x198
49#define ADC_ARB_USRP_ANA_PARAM 0x199
50#define ADC_ARB_USRP_DIG_PARAM 0x19A
51#define ADC_ARB_USRP_RSV 0x19B
52
53#define ADC_ARB_USRP_DATA0 0x19D
54#define ADC_ARB_USRP_DATA1 0x19C
55
56struct pmic8058_adc {
57 struct xoadc_platform_data *pdata;
58 struct pm8058_chip *pm_chip;
59 struct adc_properties *adc_prop;
60 struct xoadc_conv_state conv[2];
61 int xoadc_queue_count;
62 int adc_irq;
63 struct linear_graph *adc_graph;
64 struct xoadc_conv_state *conv_slot_request;
65 struct xoadc_conv_state *conv_queue_list;
66 struct adc_conv_slot conv_queue_elements[MAX_QUEUE_LENGTH];
67 int xoadc_num;
68 struct msm_xo_voter *adc_voter;
Siddartha Mohanadoss71128482011-10-05 15:16:10 -070069 struct wake_lock adc_wakelock;
70 /* flag to warn/bug if wakelocks are taken after suspend_noirq */
71 int msm_suspend_check;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070072};
73
74static struct pmic8058_adc *pmic_adc[XOADC_PMIC_0 + 1];
75
76static bool xoadc_initialized, xoadc_calib_first_adc;
77
78DEFINE_RATELIMIT_STATE(pm8058_xoadc_msg_ratelimit,
79 DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST);
80
81static inline int pm8058_xoadc_can_print(void)
82{
83 return __ratelimit(&pm8058_xoadc_msg_ratelimit);
84}
85
86int32_t pm8058_xoadc_registered(void)
87{
88 return xoadc_initialized;
89}
90EXPORT_SYMBOL(pm8058_xoadc_registered);
91
92void pm8058_xoadc_restore_slot(uint32_t adc_instance,
93 struct adc_conv_slot *slot)
94{
95 struct pmic8058_adc *adc_pmic = pmic_adc[adc_instance];
96 struct xoadc_conv_state *slot_state = adc_pmic->conv_slot_request;
97
98 mutex_lock(&slot_state->list_lock);
99 list_add(&slot->list, &slot_state->slots);
100 mutex_unlock(&slot_state->list_lock);
101}
102EXPORT_SYMBOL(pm8058_xoadc_restore_slot);
103
104void pm8058_xoadc_slot_request(uint32_t adc_instance,
105 struct adc_conv_slot **slot)
106{
107 struct pmic8058_adc *adc_pmic = pmic_adc[adc_instance];
108 struct xoadc_conv_state *slot_state = adc_pmic->conv_slot_request;
109
110 mutex_lock(&slot_state->list_lock);
111
112 if (!list_empty(&slot_state->slots)) {
113 *slot = list_first_entry(&slot_state->slots,
114 struct adc_conv_slot, list);
115 list_del(&(*slot)->list);
116 } else
117 *slot = NULL;
118
119 mutex_unlock(&slot_state->list_lock);
120}
121EXPORT_SYMBOL(pm8058_xoadc_slot_request);
122
123static int32_t pm8058_xoadc_arb_cntrl(uint32_t arb_cntrl,
Siddartha Mohanadoss71128482011-10-05 15:16:10 -0700124 uint32_t adc_instance, uint32_t channel)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700125{
126 struct pmic8058_adc *adc_pmic = pmic_adc[adc_instance];
127 int i, rc;
128 u8 data_arb_cntrl;
129
130 data_arb_cntrl = ADC_ARB_USRP_CNTRL_EOC |
131 ADC_ARB_USRP_CNTRL_RSV5 |
132 ADC_ARB_USRP_CNTRL_RSV4;
133
134 if (arb_cntrl) {
Siddartha Mohanadoss71128482011-10-05 15:16:10 -0700135 if (adc_pmic->msm_suspend_check)
136 pr_err("XOADC request being made after suspend irq "
137 "with channel id:%d\n", channel);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700138 data_arb_cntrl |= ADC_ARB_USRP_CNTRL_EN_ARB;
139 msm_xo_mode_vote(adc_pmic->adc_voter, MSM_XO_MODE_ON);
140 adc_pmic->pdata->xoadc_mpp_config();
Siddartha Mohanadoss71128482011-10-05 15:16:10 -0700141 wake_lock(&adc_pmic->adc_wakelock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700142 }
143
144 /* Write twice to the CNTRL register for the arbiter settings
145 to take into effect */
146 for (i = 0; i < 2; i++) {
147 rc = pm8058_write(adc_pmic->pm_chip, ADC_ARB_USRP_CNTRL,
148 &data_arb_cntrl, 1);
149 if (rc < 0) {
150 pr_debug("%s: PM8058 write failed\n", __func__);
151 return rc;
152 }
153 }
154
Siddartha Mohanadoss71128482011-10-05 15:16:10 -0700155 if (!arb_cntrl) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700156 msm_xo_mode_vote(adc_pmic->adc_voter, MSM_XO_MODE_OFF);
Siddartha Mohanadoss71128482011-10-05 15:16:10 -0700157 wake_unlock(&adc_pmic->adc_wakelock);
158 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700159
160 return 0;
161}
162
163static int32_t pm8058_xoadc_configure(uint32_t adc_instance,
164 struct adc_conv_slot *slot)
165{
166
167 struct pmic8058_adc *adc_pmic = pmic_adc[adc_instance];
168 u8 data_arb_cntrl, data_amux_chan, data_arb_rsv, data_ana_param;
169 u8 data_dig_param, data_ana_param2;
170 int rc;
171
Siddartha Mohanadoss71128482011-10-05 15:16:10 -0700172 rc = pm8058_xoadc_arb_cntrl(1, adc_instance, slot->chan_path);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700173 if (rc < 0) {
174 pr_debug("%s: Configuring ADC Arbiter"
175 "enable failed\n", __func__);
176 return rc;
177 }
178
179 switch (slot->chan_path) {
180
181 case CHAN_PATH_TYPE1:
182 data_amux_chan = CHANNEL_VCOIN << 4;
183 data_arb_rsv = 0x20;
184 slot->chan_properties.gain_numerator = 1;
185 slot->chan_properties.gain_denominator = 2;
186 slot->chan_properties.adc_graph = &adc_pmic->adc_graph[0];
187 break;
188
189 case CHAN_PATH_TYPE2:
190 data_amux_chan = CHANNEL_VBAT << 4;
191 data_arb_rsv = 0x20;
192 slot->chan_properties.gain_numerator = 1;
193 slot->chan_properties.gain_denominator = 3;
194 slot->chan_properties.adc_graph = &adc_pmic->adc_graph[0];
195 break;
196
197 case CHAN_PATH_TYPE3:
198 data_amux_chan = CHANNEL_VCHG << 4;
199 data_arb_rsv = 0x20;
200 slot->chan_properties.gain_numerator = 1;
201 slot->chan_properties.gain_denominator = 10;
202 slot->chan_properties.adc_graph = &adc_pmic->adc_graph[0];
203 break;
204
205 case CHAN_PATH_TYPE4:
206 data_amux_chan = CHANNEL_CHG_MONITOR << 4;
207 data_arb_rsv = 0x20;
208 slot->chan_properties.gain_numerator = 1;
209 slot->chan_properties.gain_denominator = 1;
210 slot->chan_properties.adc_graph = &adc_pmic->adc_graph[0];
211 break;
212
213 case CHAN_PATH_TYPE5:
214 data_amux_chan = CHANNEL_VPH_PWR << 4;
215 data_arb_rsv = 0x20;
216 slot->chan_properties.gain_numerator = 1;
217 slot->chan_properties.gain_denominator = 3;
218 slot->chan_properties.adc_graph = &adc_pmic->adc_graph[0];
219 break;
220
221 case CHAN_PATH_TYPE6:
222 data_amux_chan = CHANNEL_MPP5 << 4;
223 data_arb_rsv = 0x20;
224 slot->chan_properties.gain_numerator = 1;
225 slot->chan_properties.gain_denominator = 1;
Siddartha Mohanadoss8d8df132011-10-21 10:55:26 -0700226 slot->chan_properties.adc_graph = &adc_pmic->adc_graph[1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700227 break;
228
229 case CHAN_PATH_TYPE7:
230 data_amux_chan = CHANNEL_MPP6 << 4;
231 data_arb_rsv = 0x20;
232 slot->chan_properties.gain_numerator = 1;
233 slot->chan_properties.gain_denominator = 1;
234 slot->chan_properties.adc_graph = &adc_pmic->adc_graph[0];
235 break;
236
237 case CHAN_PATH_TYPE8:
238 data_amux_chan = CHANNEL_MPP7 << 4;
239 data_arb_rsv = 0x20;
240 slot->chan_properties.gain_numerator = 1;
241 slot->chan_properties.gain_denominator = 2;
242 slot->chan_properties.adc_graph = &adc_pmic->adc_graph[0];
243 break;
244
245 case CHAN_PATH_TYPE9:
246 data_amux_chan = CHANNEL_MPP8 << 4;
247 data_arb_rsv = 0x20;
248 slot->chan_properties.gain_numerator = 1;
249 slot->chan_properties.gain_denominator = 2;
250 slot->chan_properties.adc_graph = &adc_pmic->adc_graph[0];
251 break;
252
253 case CHAN_PATH_TYPE10:
254 data_amux_chan = CHANNEL_MPP9 << 4;
255 data_arb_rsv = 0x20;
256 slot->chan_properties.gain_numerator = 1;
257 slot->chan_properties.gain_denominator = 3;
258 slot->chan_properties.adc_graph = &adc_pmic->adc_graph[0];
259 break;
260
261 case CHAN_PATH_TYPE11:
262 data_amux_chan = CHANNEL_USB_VBUS << 4;
263 data_arb_rsv = 0x20;
264 slot->chan_properties.gain_numerator = 1;
265 slot->chan_properties.gain_denominator = 3;
266 slot->chan_properties.adc_graph = &adc_pmic->adc_graph[0];
267 break;
268
269 case CHAN_PATH_TYPE12:
270 data_amux_chan = CHANNEL_DIE_TEMP << 4;
271 data_arb_rsv = 0x20;
272 slot->chan_properties.gain_numerator = 1;
273 slot->chan_properties.gain_denominator = 1;
274 slot->chan_properties.adc_graph = &adc_pmic->adc_graph[0];
275 break;
276
277 case CHAN_PATH_TYPE13:
278 data_amux_chan = CHANNEL_125V << 4;
279 data_arb_rsv = 0x20;
280 slot->chan_properties.gain_numerator = 1;
281 slot->chan_properties.gain_denominator = 1;
282 slot->chan_properties.adc_graph = &adc_pmic->adc_graph[0];
283 break;
284
285 case CHAN_PATH_TYPE14:
286 data_amux_chan = CHANNEL_INTERNAL_2 << 4;
287 data_arb_rsv = 0x20;
288 slot->chan_properties.gain_numerator = 1;
289 slot->chan_properties.gain_denominator = 1;
290 slot->chan_properties.adc_graph = &adc_pmic->adc_graph[0];
291 break;
292
293 case CHAN_PATH_TYPE_NONE:
294 data_amux_chan = CHANNEL_MUXOFF << 4;
295 data_arb_rsv = 0x10;
296 slot->chan_properties.gain_numerator = 1;
297 slot->chan_properties.gain_denominator = 1;
298 slot->chan_properties.adc_graph = &adc_pmic->adc_graph[1];
299 break;
300
301 case CHAN_PATH_TYPE15:
302 data_amux_chan = CHANNEL_INTERNAL << 4;
303 data_arb_rsv = 0x20;
304 slot->chan_properties.gain_numerator = 1;
305 slot->chan_properties.gain_denominator = 1;
306 slot->chan_properties.adc_graph = &adc_pmic->adc_graph[0];
307 break;
308 }
309
310 rc = pm8058_write(adc_pmic->pm_chip,
311 ADC_ARB_USRP_AMUX_CNTRL, &data_amux_chan, 1);
312 if (rc < 0) {
313 pr_debug("%s: PM8058 write failed\n", __func__);
314 return rc;
315 }
316
317 rc = pm8058_write(adc_pmic->pm_chip,
318 ADC_ARB_USRP_RSV, &data_arb_rsv, 1);
319 if (rc < 0) {
320 pr_debug("%s: PM8058 write failed\n", __func__);
321 return rc;
322 }
323
324 /* Set default clock rate to 2.4 MHz XO ADC clock digital */
325 switch (slot->chan_adc_config) {
326
327 case ADC_CONFIG_TYPE1:
328 data_ana_param = 0xFE;
329 data_dig_param = 0x23;
330 data_ana_param2 = 0xFF;
331 /* AMUX register data to start the ADC conversion */
332 data_arb_cntrl = 0xF1;
333 break;
334
335 case ADC_CONFIG_TYPE2:
336 data_ana_param = 0xFE;
337 data_dig_param = 0x03;
338 data_ana_param2 = 0xFF;
339 /* AMUX register data to start the ADC conversion */
340 data_arb_cntrl = 0xF1;
341 break;
342 }
343
344 rc = pm8058_write(adc_pmic->pm_chip,
345 ADC_ARB_USRP_ANA_PARAM, &data_ana_param, 1);
346 if (rc < 0) {
347 pr_debug("%s: PM8058 write failed\n", __func__);
348 return rc;
349 }
350
351 rc = pm8058_write(adc_pmic->pm_chip,
352 ADC_ARB_USRP_DIG_PARAM, &data_dig_param, 1);
353 if (rc < 0) {
354 pr_debug("%s: PM8058 write failed\n", __func__);
355 return rc;
356 }
357
358 rc = pm8058_write(adc_pmic->pm_chip,
359 ADC_ARB_USRP_ANA_PARAM, &data_ana_param2, 1);
360 if (rc < 0) {
361 pr_debug("%s: PM8058 write failed\n", __func__);
362 return rc;
363 }
364
365 enable_irq(adc_pmic->adc_irq);
366
367 rc = pm8058_write(adc_pmic->pm_chip,
368 ADC_ARB_USRP_CNTRL, &data_arb_cntrl, 1);
369 if (rc < 0) {
370 pr_debug("%s: PM8058 write failed\n", __func__);
371 return rc;
372 }
373
374 return 0;
375}
376
377int32_t pm8058_xoadc_select_chan_and_start_conv(uint32_t adc_instance,
378 struct adc_conv_slot *slot)
379{
380 struct pmic8058_adc *adc_pmic = pmic_adc[adc_instance];
381 struct xoadc_conv_state *slot_state = adc_pmic->conv_queue_list;
382
383 if (!xoadc_initialized)
384 return -ENODEV;
385
386 mutex_lock(&slot_state->list_lock);
387 list_add_tail(&slot->list, &slot_state->slots);
388 if (adc_pmic->xoadc_queue_count == 0) {
389 if (adc_pmic->pdata->xoadc_vreg_set != NULL)
390 adc_pmic->pdata->xoadc_vreg_set(1);
391 pm8058_xoadc_configure(adc_instance, slot);
392 }
393 adc_pmic->xoadc_queue_count++;
394 mutex_unlock(&slot_state->list_lock);
395
396 return 0;
397}
398EXPORT_SYMBOL(pm8058_xoadc_select_chan_and_start_conv);
399
400static int32_t pm8058_xoadc_dequeue_slot_request(uint32_t adc_instance,
401 struct adc_conv_slot **slot)
402{
403 struct pmic8058_adc *adc_pmic = pmic_adc[adc_instance];
404 struct xoadc_conv_state *slot_state = adc_pmic->conv_queue_list;
405 int rc = 0;
406
407 mutex_lock(&slot_state->list_lock);
408 if (adc_pmic->xoadc_queue_count > 0 &&
409 !list_empty(&slot_state->slots)) {
410 *slot = list_first_entry(&slot_state->slots,
411 struct adc_conv_slot, list);
412 list_del(&(*slot)->list);
413 } else
414 rc = -EINVAL;
415 mutex_unlock(&slot_state->list_lock);
416
417 if (rc < 0) {
418 if (pm8058_xoadc_can_print())
419 pr_err("Pmic 8058 xoadc spurious interrupt detected\n");
420 return rc;
421 }
422
423 return 0;
424}
425
426int32_t pm8058_xoadc_read_adc_code(uint32_t adc_instance, int32_t *data)
427{
428 struct pmic8058_adc *adc_pmic = pmic_adc[adc_instance];
429 struct xoadc_conv_state *slot_state = adc_pmic->conv_queue_list;
430 uint8_t rslt_lsb, rslt_msb;
431 struct adc_conv_slot *slot;
432 int32_t rc, max_ideal_adc_code = 1 << adc_pmic->adc_prop->bitresolution;
433
434 if (!xoadc_initialized)
435 return -ENODEV;
436
437 rc = pm8058_read(adc_pmic->pm_chip, ADC_ARB_USRP_DATA0, &rslt_lsb, 1);
438 if (rc < 0) {
439 pr_debug("%s: PM8058 read failed\n", __func__);
440 return rc;
441 }
442
443 rc = pm8058_read(adc_pmic->pm_chip, ADC_ARB_USRP_DATA1, &rslt_msb, 1);
444 if (rc < 0) {
445 pr_debug("%s: PM8058 read failed\n", __func__);
446 return rc;
447 }
448
449 *data = (rslt_msb << 8) | rslt_lsb;
450
451 /* Use the midpoint to determine underflow or overflow */
452 if (*data > max_ideal_adc_code + (max_ideal_adc_code >> 1))
453 *data |= ((1 << (8 * sizeof(*data) -
454 adc_pmic->adc_prop->bitresolution)) - 1) <<
455 adc_pmic->adc_prop->bitresolution;
456 /* Return if this is a calibration run since there
457 * is no need to check requests in the waiting queue */
458 if (xoadc_calib_first_adc)
459 return 0;
460
461 mutex_lock(&slot_state->list_lock);
462 adc_pmic->xoadc_queue_count--;
463 if (adc_pmic->xoadc_queue_count > 0) {
464 slot = list_first_entry(&slot_state->slots,
465 struct adc_conv_slot, list);
466 pm8058_xoadc_configure(adc_instance, slot);
467 }
468 mutex_unlock(&slot_state->list_lock);
469
470 mutex_lock(&slot_state->list_lock);
471 /* Default value for switching off the arbiter after reading
472 the ADC value. Bit 0 set to 0. */
473 if (adc_pmic->xoadc_queue_count == 0) {
Siddartha Mohanadoss71128482011-10-05 15:16:10 -0700474 rc = pm8058_xoadc_arb_cntrl(0, adc_instance, CHANNEL_MUXOFF);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700475 if (rc < 0) {
476 pr_debug("%s: Configuring ADC Arbiter disable"
477 "failed\n", __func__);
478 return rc;
479 }
480 if (adc_pmic->pdata->xoadc_vreg_set != NULL)
481 adc_pmic->pdata->xoadc_vreg_set(0);
482 }
483 mutex_unlock(&slot_state->list_lock);
484
485 return 0;
486}
487EXPORT_SYMBOL(pm8058_xoadc_read_adc_code);
488
489static irqreturn_t pm8058_xoadc(int irq, void *dev_id)
490{
491 struct pmic8058_adc *xoadc_8058 = dev_id;
492 struct adc_conv_slot *slot = NULL;
493 int rc;
494
495 disable_irq_nosync(xoadc_8058->adc_irq);
496
497 if (xoadc_calib_first_adc)
498 return IRQ_HANDLED;
499
500 rc = pm8058_xoadc_dequeue_slot_request(xoadc_8058->xoadc_num, &slot);
501
502 if (rc < 0)
503 return IRQ_NONE;
504
505 if (rc == 0)
506 msm_adc_conv_cb(slot, 0, NULL, 0);
507
508 return IRQ_HANDLED;
509}
510
511struct adc_properties *pm8058_xoadc_get_properties(uint32_t dev_instance)
512{
513 struct pmic8058_adc *xoadc_8058 = pmic_adc[dev_instance];
514
515 return xoadc_8058->adc_prop;
516}
517EXPORT_SYMBOL(pm8058_xoadc_get_properties);
518
519int32_t pm8058_xoadc_calib_device(uint32_t adc_instance)
520{
521 struct pmic8058_adc *adc_pmic = pmic_adc[adc_instance];
522 struct adc_conv_slot *slot;
523 int rc, offset_xoadc, slope_xoadc, calib_read_1, calib_read_2;
524
525 if (adc_pmic->pdata->xoadc_vreg_set != NULL)
526 adc_pmic->pdata->xoadc_vreg_set(1);
527
528 pm8058_xoadc_slot_request(adc_instance, &slot);
529 if (slot) {
530 slot->chan_path = CHAN_PATH_TYPE13;
531 slot->chan_adc_config = ADC_CONFIG_TYPE2;
532 slot->chan_adc_calib = ADC_CONFIG_TYPE2;
533 xoadc_calib_first_adc = true;
534 rc = pm8058_xoadc_configure(adc_instance, slot);
535 if (rc) {
536 pr_err("pm8058_xoadc configure failed\n");
537 goto fail;
538 }
539 } else {
540 rc = -EINVAL;
541 goto fail;
542 }
543
544 msleep(3);
545
546 rc = pm8058_xoadc_read_adc_code(adc_instance, &calib_read_1);
547 if (rc) {
548 pr_err("pm8058_xoadc read adc failed\n");
549 xoadc_calib_first_adc = false;
550 goto fail;
551 }
552 xoadc_calib_first_adc = false;
553
554 pm8058_xoadc_slot_request(adc_instance, &slot);
555 if (slot) {
556 slot->chan_path = CHAN_PATH_TYPE15;
557 slot->chan_adc_config = ADC_CONFIG_TYPE2;
558 slot->chan_adc_calib = ADC_CONFIG_TYPE2;
559 xoadc_calib_first_adc = true;
560 rc = pm8058_xoadc_configure(adc_instance, slot);
561 if (rc) {
562 pr_err("pm8058_xoadc configure failed\n");
563 goto fail;
564 }
565 } else {
566 rc = -EINVAL;
567 goto fail;
568 }
569
570 msleep(3);
571
572 rc = pm8058_xoadc_read_adc_code(adc_instance, &calib_read_2);
573 if (rc) {
574 pr_err("pm8058_xoadc read adc failed\n");
575 xoadc_calib_first_adc = false;
576 goto fail;
577 }
578 xoadc_calib_first_adc = false;
579
580 pm8058_xoadc_restore_slot(adc_instance, slot);
581
582 slope_xoadc = (((calib_read_1 - calib_read_2) << 10)/
583 CHANNEL_ADC_625_MV);
584 offset_xoadc = calib_read_2 -
585 ((slope_xoadc * CHANNEL_ADC_625_MV) >> 10);
586
587 printk(KERN_INFO"pmic8058_xoadc:The offset for AMUX calibration"
588 "was %d\n", offset_xoadc);
589
590 adc_pmic->adc_graph[0].offset = offset_xoadc;
591 adc_pmic->adc_graph[0].dy = (calib_read_1 - calib_read_2);
592 adc_pmic->adc_graph[0].dx = CHANNEL_ADC_625_MV;
593
594 /* Retain ideal calibration settings for therm readings */
595 adc_pmic->adc_graph[1].offset = 0 ;
596 adc_pmic->adc_graph[1].dy = (1 << 15) - 1;
597 adc_pmic->adc_graph[1].dx = 2200;
598
599 if (adc_pmic->pdata->xoadc_vreg_set != NULL)
600 adc_pmic->pdata->xoadc_vreg_set(0);
601
602 return 0;
603fail:
604 if (adc_pmic->pdata->xoadc_vreg_set != NULL)
605 adc_pmic->pdata->xoadc_vreg_set(0);
606
607 return rc;
608}
609EXPORT_SYMBOL(pm8058_xoadc_calib_device);
610
611int32_t pm8058_xoadc_calibrate(uint32_t dev_instance,
612 struct adc_conv_slot *slot, int *calib_status)
613{
614 *calib_status = CALIB_NOT_REQUIRED;
615
616 return 0;
617}
618EXPORT_SYMBOL(pm8058_xoadc_calibrate);
619
Siddartha Mohanadoss71128482011-10-05 15:16:10 -0700620#ifdef CONFIG_PM
621static int pm8058_xoadc_suspend_noirq(struct device *dev)
622{
623 struct platform_device *pdev = to_platform_device(dev);
624 struct pmic8058_adc *adc_pmic = platform_get_drvdata(pdev);
625
626 adc_pmic->msm_suspend_check = 1;
627
628 return 0;
629}
630
631static int pm8058_xoadc_resume_noirq(struct device *dev)
632{
633 struct platform_device *pdev = to_platform_device(dev);
634 struct pmic8058_adc *adc_pmic = platform_get_drvdata(pdev);
635
636 adc_pmic->msm_suspend_check = 0;
637
638 return 0;
639}
640
641static const struct dev_pm_ops pm8058_xoadc_dev_pm_ops = {
642 .suspend_noirq = pm8058_xoadc_suspend_noirq,
643 .resume_noirq = pm8058_xoadc_resume_noirq,
644};
645
646#define PM8058_XOADC_DEV_PM_OPS (&pm8058_xoadc_dev_pm_ops)
647#else
648#define PM8058_XOADC_DEV_PM_OPS NULL
649#endif
650
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700651static int __devexit pm8058_xoadc_teardown(struct platform_device *pdev)
652{
653 struct pmic8058_adc *adc_pmic = platform_get_drvdata(pdev);
654
655 if (adc_pmic->pdata->xoadc_vreg_shutdown != NULL)
656 adc_pmic->pdata->xoadc_vreg_shutdown();
657
Siddartha Mohanadoss71128482011-10-05 15:16:10 -0700658 wake_lock_destroy(&adc_pmic->adc_wakelock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700659 msm_xo_put(adc_pmic->adc_voter);
660 platform_set_drvdata(pdev, adc_pmic->pm_chip);
661 device_init_wakeup(&pdev->dev, 0);
662 kfree(adc_pmic);
663 xoadc_initialized = false;
664
665 return 0;
666}
667
668static int __devinit pm8058_xoadc_probe(struct platform_device *pdev)
669{
670 struct xoadc_platform_data *pdata = pdev->dev.platform_data;
671 struct pm8058_chip *pm_chip;
672 struct pmic8058_adc *adc_pmic;
673 int i, rc = 0;
674
675 pm_chip = dev_get_drvdata(pdev->dev.parent);
676 if (pm_chip == NULL) {
677 dev_err(&pdev->dev, "no parent data passed in\n");
678 return -EFAULT;
679 }
680
681 if (!pdata) {
682 dev_err(&pdev->dev, "no platform data?\n");
683 return -EINVAL;
684 }
685
686 adc_pmic = kzalloc(sizeof(struct pmic8058_adc), GFP_KERNEL);
687 if (!adc_pmic) {
688 dev_err(&pdev->dev, "Unable to allocate memory\n");
689 return -ENOMEM;
690 }
691
692 adc_pmic->pm_chip = pm_chip;
693 adc_pmic->adc_prop = pdata->xoadc_prop;
694 adc_pmic->xoadc_num = pdata->xoadc_num;
695 adc_pmic->xoadc_queue_count = 0;
696
697 platform_set_drvdata(pdev, adc_pmic);
698
699 if (adc_pmic->xoadc_num > XOADC_PMIC_0) {
700 dev_err(&pdev->dev, "ADC device not supported\n");
701 rc = -EINVAL;
702 goto err_cleanup;
703 }
704
705 adc_pmic->pdata = pdata;
706 adc_pmic->adc_graph = kzalloc(sizeof(struct linear_graph)
707 * MAX_CHANNEL_PROPERTIES_QUEUE, GFP_KERNEL);
708 if (!adc_pmic->adc_graph) {
709 dev_err(&pdev->dev, "Unable to allocate memory\n");
710 rc = -ENOMEM;
711 goto err_cleanup;
712 }
713
714 /* Will be replaced by individual channel calibration */
715 for (i = 0; i < MAX_CHANNEL_PROPERTIES_QUEUE; i++) {
716 adc_pmic->adc_graph[i].offset = 0 ;
717 adc_pmic->adc_graph[i].dy = (1 << 15) - 1;
718 adc_pmic->adc_graph[i].dx = 2200;
719 }
720
721 if (pdata->xoadc_mpp_config != NULL)
722 pdata->xoadc_mpp_config();
723
724 adc_pmic->conv_slot_request = &adc_pmic->conv[0];
725 adc_pmic->conv_slot_request->context =
726 &adc_pmic->conv_queue_elements[0];
727
728 mutex_init(&adc_pmic->conv_slot_request->list_lock);
729 INIT_LIST_HEAD(&adc_pmic->conv_slot_request->slots);
730
731 /* tie each slot and initwork them */
732 for (i = 0; i < MAX_QUEUE_LENGTH; i++) {
733 list_add(&adc_pmic->conv_slot_request->context[i].list,
734 &adc_pmic->conv_slot_request->slots);
735 INIT_WORK(&adc_pmic->conv_slot_request->context[i].work,
736 msm_adc_wq_work);
737 init_completion(&adc_pmic->conv_slot_request->context[i].comp);
738 adc_pmic->conv_slot_request->context[i].idx = i;
739 }
740
741 adc_pmic->conv_queue_list = &adc_pmic->conv[1];
742
743 mutex_init(&adc_pmic->conv_queue_list->list_lock);
744 INIT_LIST_HEAD(&adc_pmic->conv_queue_list->slots);
745
746 adc_pmic->adc_irq = platform_get_irq(pdev, 0);
747 if (adc_pmic->adc_irq < 0) {
748 rc = -ENXIO;
749 goto err_cleanup;
750 }
751
752 rc = request_threaded_irq(adc_pmic->adc_irq,
753 NULL, pm8058_xoadc,
754 IRQF_TRIGGER_RISING, "pm8058_adc_interrupt", adc_pmic);
755 if (rc) {
756 dev_err(&pdev->dev, "failed to request adc irq\n");
757 goto err_cleanup;
758 }
759
760 disable_irq(adc_pmic->adc_irq);
761
762 device_init_wakeup(&pdev->dev, pdata->xoadc_wakeup);
763
764 if (adc_pmic->adc_voter == NULL) {
765 adc_pmic->adc_voter = msm_xo_get(MSM_XO_TCXO_D1,
766 "pmic8058_xoadc");
767 if (IS_ERR(adc_pmic->adc_voter)) {
768 dev_err(&pdev->dev, "Failed to get XO vote\n");
769 goto err_cleanup;
770 }
771 }
772
Siddartha Mohanadoss71128482011-10-05 15:16:10 -0700773 wake_lock_init(&adc_pmic->adc_wakelock, WAKE_LOCK_SUSPEND,
774 "pmic8058_xoadc_wakelock");
775
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700776 pmic_adc[adc_pmic->xoadc_num] = adc_pmic;
777
778 if (pdata->xoadc_vreg_setup != NULL)
779 pdata->xoadc_vreg_setup();
780
781 xoadc_initialized = true;
782 xoadc_calib_first_adc = false;
783
784 return 0;
785
786err_cleanup:
787 pm8058_xoadc_teardown(pdev);
788
789 return rc;
790}
791
792static struct platform_driver pm8058_xoadc_driver = {
793 .probe = pm8058_xoadc_probe,
794 .remove = __devexit_p(pm8058_xoadc_teardown),
795 .driver = {
796 .name = "pm8058-xoadc",
797 .owner = THIS_MODULE,
Siddartha Mohanadoss71128482011-10-05 15:16:10 -0700798 .pm = PM8058_XOADC_DEV_PM_OPS,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700799 },
800};
801
802static int __init pm8058_xoadc_init(void)
803{
804 return platform_driver_register(&pm8058_xoadc_driver);
805}
806module_init(pm8058_xoadc_init);
807
808static void __exit pm8058_xoadc_exit(void)
809{
810 platform_driver_unregister(&pm8058_xoadc_driver);
811}
812module_exit(pm8058_xoadc_exit);
813
814MODULE_ALIAS("platform:pmic8058_xoadc");
815MODULE_DESCRIPTION("PMIC8058 XOADC driver");
816MODULE_LICENSE("GPL v2");