diff options
author | Lee Jones <lee.jones@linaro.org> | 2013-02-11 05:38:00 -0500 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2013-03-06 23:28:21 -0500 |
commit | e4bffe8d8ad9856143b6e941a17870aee37413d7 (patch) | |
tree | 591f0b3e5c7c08c14ef1483b810cd2eaa4ccdee4 /drivers/mfd/ab8500-gpadc.c | |
parent | 75932094601b404fc9ef28f7b6c0aa83dd619af0 (diff) |
mfd: ab8500-gpadc: Add support for the AB8540
This patch enables the GPADC to work on AB8540 based platforms.
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Acked-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd/ab8500-gpadc.c')
-rw-r--r-- | drivers/mfd/ab8500-gpadc.c | 316 |
1 files changed, 276 insertions, 40 deletions
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index fc8da4496e84..c985b90577f6 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c | |||
@@ -37,6 +37,13 @@ | |||
37 | #define AB8500_GPADC_AUTODATAL_REG 0x07 | 37 | #define AB8500_GPADC_AUTODATAL_REG 0x07 |
38 | #define AB8500_GPADC_AUTODATAH_REG 0x08 | 38 | #define AB8500_GPADC_AUTODATAH_REG 0x08 |
39 | #define AB8500_GPADC_MUX_CTRL_REG 0x09 | 39 | #define AB8500_GPADC_MUX_CTRL_REG 0x09 |
40 | #define AB8540_GPADC_MANDATA2L_REG 0x09 | ||
41 | #define AB8540_GPADC_MANDATA2H_REG 0x0A | ||
42 | #define AB8540_GPADC_APEAAX_REG 0x10 | ||
43 | #define AB8540_GPADC_APEAAT_REG 0x11 | ||
44 | #define AB8540_GPADC_APEAAM_REG 0x12 | ||
45 | #define AB8540_GPADC_APEAAH_REG 0x13 | ||
46 | #define AB8540_GPADC_APEAAL_REG 0x14 | ||
40 | 47 | ||
41 | /* | 48 | /* |
42 | * OTP register offsets | 49 | * OTP register offsets |
@@ -49,6 +56,10 @@ | |||
49 | #define AB8500_GPADC_CAL_5 0x13 | 56 | #define AB8500_GPADC_CAL_5 0x13 |
50 | #define AB8500_GPADC_CAL_6 0x14 | 57 | #define AB8500_GPADC_CAL_6 0x14 |
51 | #define AB8500_GPADC_CAL_7 0x15 | 58 | #define AB8500_GPADC_CAL_7 0x15 |
59 | /* New calibration for 8540 */ | ||
60 | #define AB8540_GPADC_OTP4_REG_7 0x38 | ||
61 | #define AB8540_GPADC_OTP4_REG_6 0x39 | ||
62 | #define AB8540_GPADC_OTP4_REG_5 0x3A | ||
52 | 63 | ||
53 | /* gpadc constants */ | 64 | /* gpadc constants */ |
54 | #define EN_VINTCORE12 0x04 | 65 | #define EN_VINTCORE12 0x04 |
@@ -67,6 +78,7 @@ | |||
67 | #define GPADC_BUSY 0x01 | 78 | #define GPADC_BUSY 0x01 |
68 | #define EN_FALLING 0x10 | 79 | #define EN_FALLING 0x10 |
69 | #define EN_TRIG_EDGE 0x02 | 80 | #define EN_TRIG_EDGE 0x02 |
81 | #define EN_VBIAS_XTAL_TEMP 0x02 | ||
70 | 82 | ||
71 | /* GPADC constants from AB8500 spec, UM0836 */ | 83 | /* GPADC constants from AB8500 spec, UM0836 */ |
72 | #define ADC_RESOLUTION 1024 | 84 | #define ADC_RESOLUTION 1024 |
@@ -85,8 +97,21 @@ | |||
85 | #define ADC_CH_BKBAT_MIN 0 | 97 | #define ADC_CH_BKBAT_MIN 0 |
86 | #define ADC_CH_BKBAT_MAX 3200 | 98 | #define ADC_CH_BKBAT_MAX 3200 |
87 | 99 | ||
100 | /* GPADC constants from AB8540 spec */ | ||
101 | #define ADC_CH_IBAT_MIN (-6000) /* mA range measured by ADC for ibat*/ | ||
102 | #define ADC_CH_IBAT_MAX 6000 | ||
103 | #define ADC_CH_IBAT_MIN_V (-60) /* mV range measured by ADC for ibat*/ | ||
104 | #define ADC_CH_IBAT_MAX_V 60 | ||
105 | #define IBAT_VDROP_L (-56) /* mV */ | ||
106 | #define IBAT_VDROP_H 56 | ||
107 | |||
88 | /* This is used to not lose precision when dividing to get gain and offset */ | 108 | /* This is used to not lose precision when dividing to get gain and offset */ |
89 | #define CALIB_SCALE 1000 | 109 | #define CALIB_SCALE 1000 |
110 | /* | ||
111 | * Number of bits shift used to not lose precision | ||
112 | * when dividing to get ibat gain. | ||
113 | */ | ||
114 | #define CALIB_SHIFT_IBAT 20 | ||
90 | 115 | ||
91 | /* Time in ms before disabling regulator */ | 116 | /* Time in ms before disabling regulator */ |
92 | #define GPADC_AUDOSUSPEND_DELAY 1 | 117 | #define GPADC_AUDOSUSPEND_DELAY 1 |
@@ -97,6 +122,7 @@ enum cal_channels { | |||
97 | ADC_INPUT_VMAIN = 0, | 122 | ADC_INPUT_VMAIN = 0, |
98 | ADC_INPUT_BTEMP, | 123 | ADC_INPUT_BTEMP, |
99 | ADC_INPUT_VBAT, | 124 | ADC_INPUT_VBAT, |
125 | ADC_INPUT_IBAT, | ||
100 | NBR_CAL_INPUTS, | 126 | NBR_CAL_INPUTS, |
101 | }; | 127 | }; |
102 | 128 | ||
@@ -107,8 +133,8 @@ enum cal_channels { | |||
107 | * @offset: Offset of the ADC channel | 133 | * @offset: Offset of the ADC channel |
108 | */ | 134 | */ |
109 | struct adc_cal_data { | 135 | struct adc_cal_data { |
110 | u64 gain; | 136 | s64 gain; |
111 | u64 offset; | 137 | s64 offset; |
112 | }; | 138 | }; |
113 | 139 | ||
114 | /** | 140 | /** |
@@ -180,6 +206,7 @@ int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel, | |||
180 | gpadc->cal_data[ADC_INPUT_VMAIN].offset) / CALIB_SCALE; | 206 | gpadc->cal_data[ADC_INPUT_VMAIN].offset) / CALIB_SCALE; |
181 | break; | 207 | break; |
182 | 208 | ||
209 | case XTAL_TEMP: | ||
183 | case BAT_CTRL: | 210 | case BAT_CTRL: |
184 | case BTEMP_BALL: | 211 | case BTEMP_BALL: |
185 | case ACC_DETECT1: | 212 | case ACC_DETECT1: |
@@ -198,6 +225,7 @@ int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel, | |||
198 | break; | 225 | break; |
199 | 226 | ||
200 | case MAIN_BAT_V: | 227 | case MAIN_BAT_V: |
228 | case VBAT_TRUE_MEAS: | ||
201 | /* For some reason we don't have calibrated data */ | 229 | /* For some reason we don't have calibrated data */ |
202 | if (!gpadc->cal_data[ADC_INPUT_VBAT].gain) { | 230 | if (!gpadc->cal_data[ADC_INPUT_VBAT].gain) { |
203 | res = ADC_CH_VBAT_MIN + (ADC_CH_VBAT_MAX - | 231 | res = ADC_CH_VBAT_MIN + (ADC_CH_VBAT_MAX - |
@@ -241,6 +269,20 @@ int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel, | |||
241 | ADC_RESOLUTION; | 269 | ADC_RESOLUTION; |
242 | break; | 270 | break; |
243 | 271 | ||
272 | case IBAT_VIRTUAL_CHANNEL: | ||
273 | /* For some reason we don't have calibrated data */ | ||
274 | if (!gpadc->cal_data[ADC_INPUT_IBAT].gain) { | ||
275 | res = ADC_CH_IBAT_MIN + (ADC_CH_IBAT_MAX - | ||
276 | ADC_CH_IBAT_MIN) * ad_value / | ||
277 | ADC_RESOLUTION; | ||
278 | break; | ||
279 | } | ||
280 | /* Here we can use the calibrated data */ | ||
281 | res = (int) (ad_value * gpadc->cal_data[ADC_INPUT_IBAT].gain + | ||
282 | gpadc->cal_data[ADC_INPUT_IBAT].offset) | ||
283 | >> CALIB_SHIFT_IBAT; | ||
284 | break; | ||
285 | |||
244 | default: | 286 | default: |
245 | dev_err(gpadc->dev, | 287 | dev_err(gpadc->dev, |
246 | "unknown channel, not possible to convert\n"); | 288 | "unknown channel, not possible to convert\n"); |
@@ -304,9 +346,19 @@ EXPORT_SYMBOL(ab8500_gpadc_convert); | |||
304 | int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel, | 346 | int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel, |
305 | u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type) | 347 | u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type) |
306 | { | 348 | { |
349 | int raw_data; | ||
350 | raw_data = ab8500_gpadc_double_read_raw(gpadc, channel, | ||
351 | avg_sample, trig_edge, trig_timer, conv_type, NULL); | ||
352 | return raw_data; | ||
353 | } | ||
354 | |||
355 | int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel, | ||
356 | u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type, | ||
357 | int *ibat) | ||
358 | { | ||
307 | int ret; | 359 | int ret; |
308 | int looplimit = 0; | 360 | int looplimit = 0; |
309 | u8 val, low_data, high_data; | 361 | u8 val, low_data, high_data, low_data2, high_data2; |
310 | 362 | ||
311 | if (!gpadc) | 363 | if (!gpadc) |
312 | return -ENODEV; | 364 | return -ENODEV; |
@@ -359,7 +411,6 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel, | |||
359 | default: | 411 | default: |
360 | val = channel | AVG_16; | 412 | val = channel | AVG_16; |
361 | break; | 413 | break; |
362 | |||
363 | } | 414 | } |
364 | 415 | ||
365 | if (conv_type == ADC_HW) | 416 | if (conv_type == ADC_HW) |
@@ -383,8 +434,8 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel, | |||
383 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | 434 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, |
384 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | 435 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, |
385 | EN_FALLING, EN_FALLING); | 436 | EN_FALLING, EN_FALLING); |
386 | |||
387 | } | 437 | } |
438 | |||
388 | switch (channel) { | 439 | switch (channel) { |
389 | case MAIN_CHARGER_C: | 440 | case MAIN_CHARGER_C: |
390 | case USB_CHARGER_C: | 441 | case USB_CHARGER_C: |
@@ -401,6 +452,55 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel, | |||
401 | EN_BUF | EN_ICHAR, | 452 | EN_BUF | EN_ICHAR, |
402 | EN_BUF | EN_ICHAR); | 453 | EN_BUF | EN_ICHAR); |
403 | break; | 454 | break; |
455 | |||
456 | case XTAL_TEMP: | ||
457 | if (conv_type == ADC_HW) | ||
458 | ret = abx500_mask_and_set_register_interruptible( | ||
459 | gpadc->dev, | ||
460 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
461 | EN_BUF | EN_TRIG_EDGE, | ||
462 | EN_BUF | EN_TRIG_EDGE); | ||
463 | else | ||
464 | ret = abx500_mask_and_set_register_interruptible( | ||
465 | gpadc->dev, | ||
466 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
467 | EN_BUF , | ||
468 | EN_BUF); | ||
469 | break; | ||
470 | |||
471 | case VBAT_TRUE_MEAS: | ||
472 | if (conv_type == ADC_HW) | ||
473 | ret = abx500_mask_and_set_register_interruptible( | ||
474 | gpadc->dev, | ||
475 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
476 | EN_BUF | EN_TRIG_EDGE, | ||
477 | EN_BUF | EN_TRIG_EDGE); | ||
478 | else | ||
479 | ret = abx500_mask_and_set_register_interruptible( | ||
480 | gpadc->dev, | ||
481 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
482 | EN_BUF , | ||
483 | EN_BUF); | ||
484 | break; | ||
485 | |||
486 | case BAT_CTRL_AND_IBAT: | ||
487 | case VBAT_MEAS_AND_IBAT: | ||
488 | case VBAT_TRUE_MEAS_AND_IBAT: | ||
489 | case BAT_TEMP_AND_IBAT: | ||
490 | if (conv_type == ADC_HW) | ||
491 | ret = abx500_mask_and_set_register_interruptible( | ||
492 | gpadc->dev, | ||
493 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
494 | EN_TRIG_EDGE, | ||
495 | EN_TRIG_EDGE); | ||
496 | else | ||
497 | ret = abx500_mask_and_set_register_interruptible( | ||
498 | gpadc->dev, | ||
499 | AB8500_GPADC, AB8500_GPADC_CTRL1_REG, | ||
500 | EN_BUF, | ||
501 | 0); | ||
502 | break; | ||
503 | |||
404 | case BTEMP_BALL: | 504 | case BTEMP_BALL: |
405 | if (!is_ab8500_2p0_or_earlier(gpadc->parent)) { | 505 | if (!is_ab8500_2p0_or_earlier(gpadc->parent)) { |
406 | if (conv_type == ADC_HW) | 506 | if (conv_type == ADC_HW) |
@@ -471,21 +571,19 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel, | |||
471 | /* wait for completion of conversion */ | 571 | /* wait for completion of conversion */ |
472 | if (conv_type == ADC_HW) { | 572 | if (conv_type == ADC_HW) { |
473 | if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, | 573 | if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, |
474 | 2*HZ)) { | 574 | 2 * HZ)) { |
475 | dev_err(gpadc->dev, | 575 | dev_err(gpadc->dev, |
476 | "timeout didn't receive" | 576 | "timeout didn't receive hw GPADC conv interrupt\n"); |
477 | " hw GPADC conv interrupt\n"); | 577 | ret = -EINVAL; |
478 | ret = -EINVAL; | 578 | goto out; |
479 | goto out; | ||
480 | } | 579 | } |
481 | } else { | 580 | } else { |
482 | if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, | 581 | if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, |
483 | msecs_to_jiffies(CONVERSION_TIME))) { | 582 | msecs_to_jiffies(CONVERSION_TIME))) { |
484 | dev_err(gpadc->dev, | 583 | dev_err(gpadc->dev, |
485 | "timeout didn't receive" | 584 | "timeout didn't receive sw GPADC conv interrupt\n"); |
486 | " sw GPADC conv interrupt\n"); | 585 | ret = -EINVAL; |
487 | ret = -EINVAL; | 586 | goto out; |
488 | goto out; | ||
489 | } | 587 | } |
490 | } | 588 | } |
491 | 589 | ||
@@ -523,6 +621,46 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel, | |||
523 | goto out; | 621 | goto out; |
524 | } | 622 | } |
525 | } | 623 | } |
624 | /* Check if double convertion is required */ | ||
625 | if ((channel == BAT_CTRL_AND_IBAT) || | ||
626 | (channel == VBAT_MEAS_AND_IBAT) || | ||
627 | (channel == VBAT_TRUE_MEAS_AND_IBAT) || | ||
628 | (channel == BAT_TEMP_AND_IBAT)) { | ||
629 | |||
630 | if (conv_type == ADC_HW) { | ||
631 | /* not supported */ | ||
632 | ret = -ENOTSUPP; | ||
633 | dev_err(gpadc->dev, | ||
634 | "gpadc_conversion: only SW double conversion supported\n"); | ||
635 | goto out; | ||
636 | } else { | ||
637 | /* Read the converted RAW data 2 */ | ||
638 | ret = abx500_get_register_interruptible(gpadc->dev, | ||
639 | AB8500_GPADC, AB8540_GPADC_MANDATA2L_REG, | ||
640 | &low_data2); | ||
641 | if (ret < 0) { | ||
642 | dev_err(gpadc->dev, | ||
643 | "gpadc_conversion: read sw low data 2 failed\n"); | ||
644 | goto out; | ||
645 | } | ||
646 | |||
647 | ret = abx500_get_register_interruptible(gpadc->dev, | ||
648 | AB8500_GPADC, AB8540_GPADC_MANDATA2H_REG, | ||
649 | &high_data2); | ||
650 | if (ret < 0) { | ||
651 | dev_err(gpadc->dev, | ||
652 | "gpadc_conversion: read sw high data 2 failed\n"); | ||
653 | goto out; | ||
654 | } | ||
655 | if (ibat != NULL) { | ||
656 | *ibat = (high_data2 << 8) | low_data2; | ||
657 | } else { | ||
658 | dev_warn(gpadc->dev, | ||
659 | "gpadc_conversion: ibat not stored\n"); | ||
660 | } | ||
661 | |||
662 | } | ||
663 | } | ||
526 | 664 | ||
527 | /* Disable GPADC */ | 665 | /* Disable GPADC */ |
528 | ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, | 666 | ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, |
@@ -586,15 +724,27 @@ static int otp_cal_regs[] = { | |||
586 | AB8500_GPADC_CAL_7, | 724 | AB8500_GPADC_CAL_7, |
587 | }; | 725 | }; |
588 | 726 | ||
727 | static int otp4_cal_regs[] = { | ||
728 | AB8540_GPADC_OTP4_REG_7, | ||
729 | AB8540_GPADC_OTP4_REG_6, | ||
730 | AB8540_GPADC_OTP4_REG_5, | ||
731 | }; | ||
732 | |||
589 | static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc) | 733 | static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc) |
590 | { | 734 | { |
591 | int i; | 735 | int i; |
592 | int ret[ARRAY_SIZE(otp_cal_regs)]; | 736 | int ret[ARRAY_SIZE(otp_cal_regs)]; |
593 | u8 gpadc_cal[ARRAY_SIZE(otp_cal_regs)]; | 737 | u8 gpadc_cal[ARRAY_SIZE(otp_cal_regs)]; |
594 | 738 | int ret_otp4[ARRAY_SIZE(otp4_cal_regs)]; | |
739 | u8 gpadc_otp4[ARRAY_SIZE(otp4_cal_regs)]; | ||
595 | int vmain_high, vmain_low; | 740 | int vmain_high, vmain_low; |
596 | int btemp_high, btemp_low; | 741 | int btemp_high, btemp_low; |
597 | int vbat_high, vbat_low; | 742 | int vbat_high, vbat_low; |
743 | int ibat_high, ibat_low; | ||
744 | s64 V_gain, V_offset, V2A_gain, V2A_offset; | ||
745 | struct ab8500 *ab8500; | ||
746 | |||
747 | ab8500 = gpadc->parent; | ||
598 | 748 | ||
599 | /* First we read all OTP registers and store the error code */ | 749 | /* First we read all OTP registers and store the error code */ |
600 | for (i = 0; i < ARRAY_SIZE(otp_cal_regs); i++) { | 750 | for (i = 0; i < ARRAY_SIZE(otp_cal_regs); i++) { |
@@ -614,7 +764,7 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc) | |||
614 | * bt_h/l = btemp_high/low | 764 | * bt_h/l = btemp_high/low |
615 | * vb_h/l = vbat_high/low | 765 | * vb_h/l = vbat_high/low |
616 | * | 766 | * |
617 | * Data bits: | 767 | * Data bits 8500/9540: |
618 | * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 768 | * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
619 | * |.......|.......|.......|.......|.......|.......|.......|....... | 769 | * |.......|.......|.......|.......|.......|.......|.......|....... |
620 | * | | vm_h9 | vm_h8 | 770 | * | | vm_h9 | vm_h8 |
@@ -632,6 +782,35 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc) | |||
632 | * | vb_l5 | vb_l4 | vb_l3 | vb_l2 | vb_l1 | vb_l0 | | 782 | * | vb_l5 | vb_l4 | vb_l3 | vb_l2 | vb_l1 | vb_l0 | |
633 | * |.......|.......|.......|.......|.......|.......|.......|....... | 783 | * |.......|.......|.......|.......|.......|.......|.......|....... |
634 | * | 784 | * |
785 | * Data bits 8540: | ||
786 | * OTP2 | ||
787 | * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||
788 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
789 | * | | ||
790 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
791 | * | vm_h9 | vm_h8 | vm_h7 | vm_h6 | vm_h5 | vm_h4 | vm_h3 | vm_h2 | ||
792 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
793 | * | vm_h1 | vm_h0 | vm_l4 | vm_l3 | vm_l2 | vm_l1 | vm_l0 | bt_h9 | ||
794 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
795 | * | bt_h8 | bt_h7 | bt_h6 | bt_h5 | bt_h4 | bt_h3 | bt_h2 | bt_h1 | ||
796 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
797 | * | bt_h0 | bt_l4 | bt_l3 | bt_l2 | bt_l1 | bt_l0 | vb_h9 | vb_h8 | ||
798 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
799 | * | vb_h7 | vb_h6 | vb_h5 | vb_h4 | vb_h3 | vb_h2 | vb_h1 | vb_h0 | ||
800 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
801 | * | vb_l5 | vb_l4 | vb_l3 | vb_l2 | vb_l1 | vb_l0 | | ||
802 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
803 | * | ||
804 | * Data bits 8540: | ||
805 | * OTP4 | ||
806 | * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||
807 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
808 | * | | ib_h9 | ib_h8 | ib_h7 | ||
809 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
810 | * | ib_h6 | ib_h5 | ib_h4 | ib_h3 | ib_h2 | ib_h1 | ib_h0 | ib_l5 | ||
811 | * |.......|.......|.......|.......|.......|.......|.......|....... | ||
812 | * | ib_l4 | ib_l3 | ib_l2 | ib_l1 | ib_l0 | | ||
813 | * | ||
635 | * | 814 | * |
636 | * Ideal output ADC codes corresponding to injected input voltages | 815 | * Ideal output ADC codes corresponding to injected input voltages |
637 | * during manufacturing is: | 816 | * during manufacturing is: |
@@ -644,38 +823,96 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc) | |||
644 | * vbat_low: Vin = 2380mV / ADC ideal code = 33 | 823 | * vbat_low: Vin = 2380mV / ADC ideal code = 33 |
645 | */ | 824 | */ |
646 | 825 | ||
647 | /* Calculate gain and offset for VMAIN if all reads succeeded */ | 826 | if (is_ab8540(ab8500)) { |
648 | if (!(ret[0] < 0 || ret[1] < 0 || ret[2] < 0)) { | 827 | /* Calculate gain and offset for VMAIN if all reads succeeded*/ |
649 | vmain_high = (((gpadc_cal[0] & 0x03) << 8) | | 828 | if (!(ret[1] < 0 || ret[2] < 0)) { |
650 | ((gpadc_cal[1] & 0x3F) << 2) | | 829 | vmain_high = (((gpadc_cal[1] & 0xFF) << 2) | |
651 | ((gpadc_cal[2] & 0xC0) >> 6)); | 830 | ((gpadc_cal[2] & 0xC0) >> 6)); |
831 | vmain_low = ((gpadc_cal[2] & 0x3E) >> 1); | ||
832 | gpadc->cal_data[ADC_INPUT_VMAIN].gain = CALIB_SCALE * | ||
833 | (19500 - 315) / (vmain_high - vmain_low); | ||
834 | gpadc->cal_data[ADC_INPUT_VMAIN].offset = CALIB_SCALE * | ||
835 | 19500 - (CALIB_SCALE * (19500 - 315) / | ||
836 | (vmain_high - vmain_low)) * vmain_high; | ||
837 | } else { | ||
838 | gpadc->cal_data[ADC_INPUT_VMAIN].gain = 0; | ||
839 | } | ||
652 | 840 | ||
653 | vmain_low = ((gpadc_cal[2] & 0x3E) >> 1); | 841 | /* Read IBAT calibration Data */ |
842 | for (i = 0; i < ARRAY_SIZE(otp4_cal_regs); i++) { | ||
843 | ret_otp4[i] = abx500_get_register_interruptible( | ||
844 | gpadc->dev, AB8500_OTP_EMUL, | ||
845 | otp4_cal_regs[i], &gpadc_otp4[i]); | ||
846 | if (ret_otp4[i] < 0) | ||
847 | dev_err(gpadc->dev, | ||
848 | "%s: read otp4 reg 0x%02x failed\n", | ||
849 | __func__, otp4_cal_regs[i]); | ||
850 | } | ||
654 | 851 | ||
655 | gpadc->cal_data[ADC_INPUT_VMAIN].gain = CALIB_SCALE * | 852 | /* Calculate gain and offset for IBAT if all reads succeeded */ |
656 | (19500 - 315) / (vmain_high - vmain_low); | 853 | if (!(ret_otp4[0] < 0 || ret_otp4[1] < 0 || ret_otp4[2] < 0)) { |
854 | ibat_high = (((gpadc_otp4[0] & 0x07) << 7) | | ||
855 | ((gpadc_otp4[1] & 0xFE) >> 1)); | ||
856 | ibat_low = (((gpadc_otp4[1] & 0x01) << 5) | | ||
857 | ((gpadc_otp4[2] & 0xF8) >> 3)); | ||
858 | |||
859 | V_gain = ((IBAT_VDROP_H - IBAT_VDROP_L) | ||
860 | << CALIB_SHIFT_IBAT) / (ibat_high - ibat_low); | ||
861 | |||
862 | V_offset = (IBAT_VDROP_H << CALIB_SHIFT_IBAT) - | ||
863 | (((IBAT_VDROP_H - IBAT_VDROP_L) << | ||
864 | CALIB_SHIFT_IBAT) / (ibat_high - ibat_low)) | ||
865 | * ibat_high; | ||
866 | /* | ||
867 | * Result obtained is in mV (at a scale factor), | ||
868 | * we need to calculate gain and offset to get mA | ||
869 | */ | ||
870 | V2A_gain = (ADC_CH_IBAT_MAX - ADC_CH_IBAT_MIN)/ | ||
871 | (ADC_CH_IBAT_MAX_V - ADC_CH_IBAT_MIN_V); | ||
872 | V2A_offset = ((ADC_CH_IBAT_MAX_V * ADC_CH_IBAT_MIN - | ||
873 | ADC_CH_IBAT_MAX * ADC_CH_IBAT_MIN_V) | ||
874 | << CALIB_SHIFT_IBAT) | ||
875 | / (ADC_CH_IBAT_MAX_V - ADC_CH_IBAT_MIN_V); | ||
876 | |||
877 | gpadc->cal_data[ADC_INPUT_IBAT].gain = V_gain * V2A_gain; | ||
878 | gpadc->cal_data[ADC_INPUT_IBAT].offset = V_offset * | ||
879 | V2A_gain + V2A_offset; | ||
880 | } else { | ||
881 | gpadc->cal_data[ADC_INPUT_IBAT].gain = 0; | ||
882 | } | ||
657 | 883 | ||
658 | gpadc->cal_data[ADC_INPUT_VMAIN].offset = CALIB_SCALE * 19500 - | 884 | dev_dbg(gpadc->dev, "IBAT gain %llu offset %llu\n", |
659 | (CALIB_SCALE * (19500 - 315) / | 885 | gpadc->cal_data[ADC_INPUT_IBAT].gain, |
660 | (vmain_high - vmain_low)) * vmain_high; | 886 | gpadc->cal_data[ADC_INPUT_IBAT].offset); |
661 | } else { | 887 | } else { |
662 | gpadc->cal_data[ADC_INPUT_VMAIN].gain = 0; | 888 | /* Calculate gain and offset for VMAIN if all reads succeeded */ |
889 | if (!(ret[0] < 0 || ret[1] < 0 || ret[2] < 0)) { | ||
890 | vmain_high = (((gpadc_cal[0] & 0x03) << 8) | | ||
891 | ((gpadc_cal[1] & 0x3F) << 2) | | ||
892 | ((gpadc_cal[2] & 0xC0) >> 6)); | ||
893 | vmain_low = ((gpadc_cal[2] & 0x3E) >> 1); | ||
894 | |||
895 | gpadc->cal_data[ADC_INPUT_VMAIN].gain = CALIB_SCALE * | ||
896 | (19500 - 315) / (vmain_high - vmain_low); | ||
897 | |||
898 | gpadc->cal_data[ADC_INPUT_VMAIN].offset = CALIB_SCALE * | ||
899 | 19500 - (CALIB_SCALE * (19500 - 315) / | ||
900 | (vmain_high - vmain_low)) * vmain_high; | ||
901 | } else { | ||
902 | gpadc->cal_data[ADC_INPUT_VMAIN].gain = 0; | ||
903 | } | ||
663 | } | 904 | } |
664 | |||
665 | /* Calculate gain and offset for BTEMP if all reads succeeded */ | 905 | /* Calculate gain and offset for BTEMP if all reads succeeded */ |
666 | if (!(ret[2] < 0 || ret[3] < 0 || ret[4] < 0)) { | 906 | if (!(ret[2] < 0 || ret[3] < 0 || ret[4] < 0)) { |
667 | btemp_high = (((gpadc_cal[2] & 0x01) << 9) | | 907 | btemp_high = (((gpadc_cal[2] & 0x01) << 9) | |
668 | (gpadc_cal[3] << 1) | | 908 | (gpadc_cal[3] << 1) | ((gpadc_cal[4] & 0x80) >> 7)); |
669 | ((gpadc_cal[4] & 0x80) >> 7)); | ||
670 | |||
671 | btemp_low = ((gpadc_cal[4] & 0x7C) >> 2); | 909 | btemp_low = ((gpadc_cal[4] & 0x7C) >> 2); |
672 | 910 | ||
673 | gpadc->cal_data[ADC_INPUT_BTEMP].gain = | 911 | gpadc->cal_data[ADC_INPUT_BTEMP].gain = |
674 | CALIB_SCALE * (1300 - 21) / (btemp_high - btemp_low); | 912 | CALIB_SCALE * (1300 - 21) / (btemp_high - btemp_low); |
675 | |||
676 | gpadc->cal_data[ADC_INPUT_BTEMP].offset = CALIB_SCALE * 1300 - | 913 | gpadc->cal_data[ADC_INPUT_BTEMP].offset = CALIB_SCALE * 1300 - |
677 | (CALIB_SCALE * (1300 - 21) / | 914 | (CALIB_SCALE * (1300 - 21) / (btemp_high - btemp_low)) |
678 | (btemp_high - btemp_low)) * btemp_high; | 915 | * btemp_high; |
679 | } else { | 916 | } else { |
680 | gpadc->cal_data[ADC_INPUT_BTEMP].gain = 0; | 917 | gpadc->cal_data[ADC_INPUT_BTEMP].gain = 0; |
681 | } | 918 | } |
@@ -687,7 +924,6 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc) | |||
687 | 924 | ||
688 | gpadc->cal_data[ADC_INPUT_VBAT].gain = CALIB_SCALE * | 925 | gpadc->cal_data[ADC_INPUT_VBAT].gain = CALIB_SCALE * |
689 | (4700 - 2380) / (vbat_high - vbat_low); | 926 | (4700 - 2380) / (vbat_high - vbat_low); |
690 | |||
691 | gpadc->cal_data[ADC_INPUT_VBAT].offset = CALIB_SCALE * 4700 - | 927 | gpadc->cal_data[ADC_INPUT_VBAT].offset = CALIB_SCALE * 4700 - |
692 | (CALIB_SCALE * (4700 - 2380) / | 928 | (CALIB_SCALE * (4700 - 2380) / |
693 | (vbat_high - vbat_low)) * vbat_high; | 929 | (vbat_high - vbat_low)) * vbat_high; |