aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAshish Jangam <ashish.jangam@kpitcummins.com>2012-05-18 06:19:18 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-05-20 11:27:08 -0400
commit16e5e204c92800aad4e7db52d289565cc82240ce (patch)
treee32f850cb2b226901d5f6a904fc1ec745ce53e25 /drivers
parent21f7541d8861fdcdff663c68903e961ca1b06dc6 (diff)
mfd: Add ADC support to the DA9052/53 core
This patch adds ADC support to the DA9052/53 core. Tested on smdkv6410 and i.mx53 QS boards. Signed-off-by: Ashish Jangam <ashish.jangam@kpitcummins.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mfd/da9052-core.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c
index 7ff313fe9fb1..5036cf5fc077 100644
--- a/drivers/mfd/da9052-core.c
+++ b/drivers/mfd/da9052-core.c
@@ -318,6 +318,135 @@ static bool da9052_reg_volatile(struct device *dev, unsigned int reg)
318 } 318 }
319} 319}
320 320
321/*
322 * TBAT look-up table is computed from the R90 reg (8 bit register)
323 * reading as below. The battery temperature is in milliCentigrade
324 * TBAT = (1/(t1+1/298) - 273) * 1000 mC
325 * where t1 = (1/B)* ln(( ADCval * 2.5)/(R25*ITBAT*255))
326 * Default values are R25 = 10e3, B = 3380, ITBAT = 50e-6
327 * Example:
328 * R25=10E3, B=3380, ITBAT=50e-6, ADCVAL=62d calculates
329 * TBAT = 20015 mili degrees Centrigrade
330 *
331*/
332static const int32_t tbat_lookup[255] = {
333 183258, 144221, 124334, 111336, 101826, 94397, 88343, 83257,
334 78889, 75071, 71688, 68656, 65914, 63414, 61120, 59001,
335 570366, 55204, 53490, 51881, 50364, 48931, 47574, 46285,
336 45059, 43889, 42772, 41703, 40678, 39694, 38748, 37838,
337 36961, 36115, 35297, 34507, 33743, 33002, 32284, 31588,
338 30911, 30254, 29615, 28994, 28389, 27799, 27225, 26664,
339 26117, 25584, 25062, 24553, 24054, 23567, 23091, 22624,
340 22167, 21719, 21281, 20851, 20429, 20015, 19610, 19211,
341 18820, 18436, 18058, 17688, 17323, 16965, 16612, 16266,
342 15925, 15589, 15259, 14933, 14613, 14298, 13987, 13681,
343 13379, 13082, 12788, 12499, 12214, 11933, 11655, 11382,
344 11112, 10845, 10582, 10322, 10066, 9812, 9562, 9315,
345 9071, 8830, 8591, 8356, 8123, 7893, 7665, 7440,
346 7218, 6998, 6780, 6565, 6352, 6141, 5933, 5726,
347 5522, 5320, 5120, 4922, 4726, 4532, 4340, 4149,
348 3961, 3774, 3589, 3406, 3225, 3045, 2867, 2690,
349 2516, 2342, 2170, 2000, 1831, 1664, 1498, 1334,
350 1171, 1009, 849, 690, 532, 376, 221, 67,
351 -84, -236, -386, -535, -683, -830, -975, -1119,
352 -1263, -1405, -1546, -1686, -1825, -1964, -2101, -2237,
353 -2372, -2506, -2639, -2771, -2902, -3033, -3162, -3291,
354 -3418, -3545, -3671, -3796, -3920, -4044, -4166, -4288,
355 -4409, -4529, -4649, -4767, -4885, -5002, -5119, -5235,
356 -5349, -5464, -5577, -5690, -5802, -5913, -6024, -6134,
357 -6244, -6352, -6461, -6568, -6675, -6781, -6887, -6992,
358 -7096, -7200, -7303, -7406, -7508, -7609, -7710, -7810,
359 -7910, -8009, -8108, -8206, -8304, -8401, -8497, -8593,
360 -8689, -8784, -8878, -8972, -9066, -9159, -9251, -9343,
361 -9435, -9526, -9617, -9707, -9796, -9886, -9975, -10063,
362 -10151, -10238, -10325, -10412, -10839, -10923, -11007, -11090,
363 -11173, -11256, -11338, -11420, -11501, -11583, -11663, -11744,
364 -11823, -11903, -11982
365};
366
367static const u8 chan_mux[DA9052_ADC_VBBAT + 1] = {
368 [DA9052_ADC_VDDOUT] = DA9052_ADC_MAN_MUXSEL_VDDOUT,
369 [DA9052_ADC_ICH] = DA9052_ADC_MAN_MUXSEL_ICH,
370 [DA9052_ADC_TBAT] = DA9052_ADC_MAN_MUXSEL_TBAT,
371 [DA9052_ADC_VBAT] = DA9052_ADC_MAN_MUXSEL_VBAT,
372 [DA9052_ADC_IN4] = DA9052_ADC_MAN_MUXSEL_AD4,
373 [DA9052_ADC_IN5] = DA9052_ADC_MAN_MUXSEL_AD5,
374 [DA9052_ADC_IN6] = DA9052_ADC_MAN_MUXSEL_AD6,
375 [DA9052_ADC_VBBAT] = DA9052_ADC_MAN_MUXSEL_VBBAT
376};
377
378int da9052_adc_manual_read(struct da9052 *da9052, unsigned char channel)
379{
380 int ret;
381 unsigned short calc_data;
382 unsigned short data;
383 unsigned char mux_sel;
384
385 if (channel > DA9052_ADC_VBBAT)
386 return -EINVAL;
387
388 mutex_lock(&da9052->auxadc_lock);
389
390 /* Channel gets activated on enabling the Conversion bit */
391 mux_sel = chan_mux[channel] | DA9052_ADC_MAN_MAN_CONV;
392
393 ret = da9052_reg_write(da9052, DA9052_ADC_MAN_REG, mux_sel);
394 if (ret < 0)
395 goto err;
396
397 /* Wait for an interrupt */
398 if (!wait_for_completion_timeout(&da9052->done,
399 msecs_to_jiffies(500))) {
400 dev_err(da9052->dev,
401 "timeout waiting for ADC conversion interrupt\n");
402 ret = -ETIMEDOUT;
403 goto err;
404 }
405
406 ret = da9052_reg_read(da9052, DA9052_ADC_RES_H_REG);
407 if (ret < 0)
408 goto err;
409
410 calc_data = (unsigned short)ret;
411 data = calc_data << 2;
412
413 ret = da9052_reg_read(da9052, DA9052_ADC_RES_L_REG);
414 if (ret < 0)
415 goto err;
416
417 calc_data = (unsigned short)(ret & DA9052_ADC_RES_LSB);
418 data |= calc_data;
419
420 ret = data;
421
422err:
423 mutex_unlock(&da9052->auxadc_lock);
424 return ret;
425}
426EXPORT_SYMBOL_GPL(da9052_adc_manual_read);
427
428static irqreturn_t da9052_auxadc_irq(int irq, void *irq_data)
429{
430 struct da9052 *da9052 = irq_data;
431
432 complete(&da9052->done);
433
434 return IRQ_HANDLED;
435}
436
437int da9052_adc_read_temp(struct da9052 *da9052)
438{
439 int tbat;
440
441 tbat = da9052_reg_read(da9052, DA9052_TBAT_RES_REG);
442 if (tbat <= 0)
443 return tbat;
444
445 /* ARRAY_SIZE check is not needed since TBAT is a 8-bit register */
446 return tbat_lookup[tbat - 1];
447}
448EXPORT_SYMBOL_GPL(da9052_adc_read_temp);
449
321static struct resource da9052_rtc_resource = { 450static struct resource da9052_rtc_resource = {
322 .name = "ALM", 451 .name = "ALM",
323 .start = DA9052_IRQ_ALARM, 452 .start = DA9052_IRQ_ALARM,
@@ -646,6 +775,9 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id)
646 struct irq_desc *desc; 775 struct irq_desc *desc;
647 int ret; 776 int ret;
648 777
778 mutex_init(&da9052->auxadc_lock);
779 init_completion(&da9052->done);
780
649 if (pdata && pdata->init != NULL) 781 if (pdata && pdata->init != NULL)
650 pdata->init(da9052); 782 pdata->init(da9052);
651 783
@@ -666,6 +798,12 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id)
666 desc = irq_to_desc(da9052->chip_irq); 798 desc = irq_to_desc(da9052->chip_irq);
667 da9052->irq_base = regmap_irq_chip_get_base(desc->action->dev_id); 799 da9052->irq_base = regmap_irq_chip_get_base(desc->action->dev_id);
668 800
801 ret = request_threaded_irq(DA9052_IRQ_ADC_EOM, NULL, da9052_auxadc_irq,
802 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
803 "adc irq", da9052);
804 if (ret != 0)
805 dev_err(da9052->dev, "DA9052 ADC IRQ failed ret=%d\n", ret);
806
669 ret = mfd_add_devices(da9052->dev, -1, da9052_subdev_info, 807 ret = mfd_add_devices(da9052->dev, -1, da9052_subdev_info,
670 ARRAY_SIZE(da9052_subdev_info), NULL, 0); 808 ARRAY_SIZE(da9052_subdev_info), NULL, 0);
671 if (ret) 809 if (ret)
@@ -674,6 +812,7 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id)
674 return 0; 812 return 0;
675 813
676err: 814err:
815 free_irq(DA9052_IRQ_ADC_EOM, da9052);
677 mfd_remove_devices(da9052->dev); 816 mfd_remove_devices(da9052->dev);
678regmap_err: 817regmap_err:
679 return ret; 818 return ret;
@@ -681,6 +820,7 @@ regmap_err:
681 820
682void da9052_device_exit(struct da9052 *da9052) 821void da9052_device_exit(struct da9052 *da9052)
683{ 822{
823 free_irq(DA9052_IRQ_ADC_EOM, da9052);
684 regmap_del_irq_chip(da9052->chip_irq, 824 regmap_del_irq_chip(da9052->chip_irq,
685 irq_get_irq_data(da9052->irq_base)->chip_data); 825 irq_get_irq_data(da9052->irq_base)->chip_data);
686 mfd_remove_devices(da9052->dev); 826 mfd_remove_devices(da9052->dev);