summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2017-05-22 17:51:44 -0700
committerJonathan Cameron <jic23@kernel.org>2017-06-03 08:43:15 +0100
commit3f9f3a1a1451f4f389423dae4b5404b1abd48025 (patch)
treec5113dcf248346c03ef2c6b0966617cf51f56a32 /drivers
parent57d14635f976404fac165047389ff0dbe83bcd5b (diff)
downloadtalos-obmc-linux-3f9f3a1a1451f4f389423dae4b5404b1abd48025.tar.gz
talos-obmc-linux-3f9f3a1a1451f4f389423dae4b5404b1abd48025.zip
iio: adc: cpcap: Fix default register values and battery temperature
Looking at the register dumps from Android kernel on droid 4, I noticed the values with the mainline kernel don't match. Let's fix this by initializing the ADC registers to what Android does. For getting correct values from the battery thermistor, we need to toggle the CPCAP_BIT_THERMBIAS_EN when measuring battery temperature to get correct battery temperatures. And looks like we also need to wait a little bit before reading the battery temperature as otherwise the results are inaccurate. Cc: Marcel Partap <mpartap@gmx.net> Cc: Michael Scott <michael.scott@linaro.org> Cc: Sebastian Reichel <sre@kernel.org> Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/iio/adc/cpcap-adc.c57
1 files changed, 49 insertions, 8 deletions
diff --git a/drivers/iio/adc/cpcap-adc.c b/drivers/iio/adc/cpcap-adc.c
index 62d37f8725b8..73cf7964a5fe 100644
--- a/drivers/iio/adc/cpcap-adc.c
+++ b/drivers/iio/adc/cpcap-adc.c
@@ -52,6 +52,10 @@
#define CPCAP_BIT_RAND0 BIT(1) /* Set with CAL_MODE */
#define CPCAP_BIT_ADEN BIT(0) /* Currently unused */
+#define CPCAP_REG_ADCC1_DEFAULTS (CPCAP_BIT_ADEN_AUTO_CLR | \
+ CPCAP_BIT_ADC_CLK_SEL0 | \
+ CPCAP_BIT_RAND1)
+
/* Register CPCAP_REG_ADCC2 bits */
#define CPCAP_BIT_CAL_FACTOR_ENABLE BIT(15) /* Currently unused */
#define CPCAP_BIT_BATDETB_EN BIT(14) /* Currently unused */
@@ -62,7 +66,7 @@
#define CPCAP_BIT_ADC_PS_FACTOR0 BIT(9)
#define CPCAP_BIT_AD4_SELECT BIT(8) /* Currently unused */
#define CPCAP_BIT_ADC_BUSY BIT(7) /* Currently unused */
-#define CPCAP_BIT_THERMBIAS_EN BIT(6) /* Currently unused */
+#define CPCAP_BIT_THERMBIAS_EN BIT(6) /* Bias for AD0_BATTDETB */
#define CPCAP_BIT_ADTRIG_DIS BIT(5) /* Disable interrupt */
#define CPCAP_BIT_LIADC BIT(4) /* Currently unused */
#define CPCAP_BIT_TS_REFEN BIT(3) /* Currently unused */
@@ -70,6 +74,12 @@
#define CPCAP_BIT_TS_M1 BIT(1) /* Currently unused */
#define CPCAP_BIT_TS_M0 BIT(0) /* Currently unused */
+#define CPCAP_REG_ADCC2_DEFAULTS (CPCAP_BIT_AD4_SELECT | \
+ CPCAP_BIT_ADTRIG_DIS | \
+ CPCAP_BIT_LIADC | \
+ CPCAP_BIT_TS_M2 | \
+ CPCAP_BIT_TS_M1)
+
#define CPCAP_MAX_TEMP_LVL 27
#define CPCAP_FOUR_POINT_TWO_ADC 801
#define ST_ADC_CAL_CHRGI_HIGH_THRESHOLD 530
@@ -124,10 +134,10 @@ struct cpcap_adc {
*/
enum cpcap_adc_channel {
/* Bank0 channels */
- CPCAP_ADC_AD0_BATTDETB, /* Battery detection */
+ CPCAP_ADC_AD0, /* Battery temperature */
CPCAP_ADC_BATTP, /* Battery voltage */
CPCAP_ADC_VBUS, /* USB VBUS voltage */
- CPCAP_ADC_AD3, /* Battery temperature when charging */
+ CPCAP_ADC_AD3, /* Die temperature when charging */
CPCAP_ADC_BPLUS_AD4, /* Another battery or system voltage */
CPCAP_ADC_CHG_ISENSE, /* Calibrated charge current */
CPCAP_ADC_BATTI, /* Calibrated system current */
@@ -217,7 +227,7 @@ struct cpcap_adc_request {
/* Phasing table for channels. Note that channels 16 & 17 use BATTP and BATTI */
static const struct cpcap_adc_phasing_tbl bank_phasing[] = {
/* Bank0 */
- [CPCAP_ADC_AD0_BATTDETB] = {0, 0x80, 0x80, 0, 1023},
+ [CPCAP_ADC_AD0] = {0, 0x80, 0x80, 0, 1023},
[CPCAP_ADC_BATTP] = {0, 0x80, 0x80, 0, 1023},
[CPCAP_ADC_VBUS] = {0, 0x80, 0x80, 0, 1023},
[CPCAP_ADC_AD3] = {0, 0x80, 0x80, 0, 1023},
@@ -243,7 +253,7 @@ static const struct cpcap_adc_phasing_tbl bank_phasing[] = {
*/
static struct cpcap_adc_conversion_tbl bank_conversion[] = {
/* Bank0 */
- [CPCAP_ADC_AD0_BATTDETB] = {
+ [CPCAP_ADC_AD0] = {
IIO_CHAN_INFO_PROCESSED, 0, 0, 0, 1, 1,
},
[CPCAP_ADC_BATTP] = {
@@ -541,6 +551,15 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata,
return;
switch (req->channel) {
+ case CPCAP_ADC_AD0:
+ value2 |= CPCAP_BIT_THERMBIAS_EN;
+ error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
+ CPCAP_BIT_THERMBIAS_EN,
+ value2);
+ if (error)
+ return;
+ usleep_range(800, 1000);
+ break;
case CPCAP_ADC_AD8 ... CPCAP_ADC_TSY2_AD15:
value1 |= CPCAP_BIT_AD_SEL1;
break;
@@ -583,7 +602,8 @@ static void cpcap_adc_setup_bank(struct cpcap_adc *ddata,
error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
CPCAP_BIT_ATOX_PS_FACTOR |
CPCAP_BIT_ADC_PS_FACTOR1 |
- CPCAP_BIT_ADC_PS_FACTOR0,
+ CPCAP_BIT_ADC_PS_FACTOR0 |
+ CPCAP_BIT_THERMBIAS_EN,
value2);
if (error)
return;
@@ -664,6 +684,21 @@ static int cpcap_adc_start_bank(struct cpcap_adc *ddata,
return error;
}
+static int cpcap_adc_stop_bank(struct cpcap_adc *ddata)
+{
+ int error;
+
+ error = regmap_update_bits(ddata->reg, CPCAP_REG_ADCC1,
+ 0xffff,
+ CPCAP_REG_ADCC1_DEFAULTS);
+ if (error)
+ return error;
+
+ return regmap_update_bits(ddata->reg, CPCAP_REG_ADCC2,
+ 0xffff,
+ CPCAP_REG_ADCC2_DEFAULTS);
+}
+
static void cpcap_adc_phase(struct cpcap_adc_request *req)
{
const struct cpcap_adc_conversion_tbl *conv_tbl = req->conv_tbl;
@@ -758,7 +793,7 @@ static void cpcap_adc_convert(struct cpcap_adc_request *req)
return;
/* Temperatures use a lookup table instead of conversion table */
- if ((req->channel == CPCAP_ADC_AD0_BATTDETB) ||
+ if ((req->channel == CPCAP_ADC_AD0) ||
(req->channel == CPCAP_ADC_AD3)) {
req->result =
cpcap_adc_table_to_millicelcius(req->result);
@@ -820,7 +855,7 @@ static int cpcap_adc_init_request(struct cpcap_adc_request *req,
req->conv_tbl = bank_conversion;
switch (channel) {
- case CPCAP_ADC_AD0_BATTDETB ... CPCAP_ADC_USB_ID:
+ case CPCAP_ADC_AD0 ... CPCAP_ADC_USB_ID:
req->bank_index = channel;
break;
case CPCAP_ADC_AD8 ... CPCAP_ADC_TSY2_AD15:
@@ -860,6 +895,9 @@ static int cpcap_adc_read(struct iio_dev *indio_dev,
error = regmap_read(ddata->reg, chan->address, val);
if (error)
goto err_unlock;
+ error = cpcap_adc_stop_bank(ddata);
+ if (error)
+ goto err_unlock;
mutex_unlock(&ddata->lock);
break;
case IIO_CHAN_INFO_PROCESSED:
@@ -870,6 +908,9 @@ static int cpcap_adc_read(struct iio_dev *indio_dev,
error = cpcap_adc_read_bank_scaled(ddata, &req);
if (error)
goto err_unlock;
+ error = cpcap_adc_stop_bank(ddata);
+ if (error)
+ goto err_unlock;
mutex_unlock(&ddata->lock);
*val = req.result;
break;
OpenPOWER on IntegriCloud