diff options
author | Hans de Goede <hdegoede@redhat.com> | 2017-06-30 13:42:54 -0400 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2017-07-04 15:31:50 -0400 |
commit | 631b010abc5b57009c6a8328f51492665f6ef310 (patch) | |
tree | 983ad0cca7438be2d469827702c6c65574d154fe | |
parent | be2ea53330f1865ac5b00377f2074f8e255bf74c (diff) |
iio: adc: Revert "axp288: Drop bogus AXP288_ADC_TS_PIN_CTRL register modifications"
Inheriting the ADC BIAS current settings from the BIOS instead of
hardcoding then causes the AXP288 to disable charging (I think it
mis-detects an overheated battery) on at least one model tablet.
So lets go back to hard coding the values, this reverts
commit fa2849e9649b ("iio: adc: axp288: Drop bogus
AXP288_ADC_TS_PIN_CTRL register modifications"), fixing charging not
working on the model tablet in question.
The exact cause is not fully understood, hence the revert to a known working
state.
Cc: stable@vger.kernel.org
Reported-by: Umberto Ixxo <sfumato1977@gmail.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r-- | drivers/iio/adc/axp288_adc.c | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c index 64799ad7ebad..7fd24949c0c1 100644 --- a/drivers/iio/adc/axp288_adc.c +++ b/drivers/iio/adc/axp288_adc.c | |||
@@ -28,6 +28,8 @@ | |||
28 | #include <linux/iio/driver.h> | 28 | #include <linux/iio/driver.h> |
29 | 29 | ||
30 | #define AXP288_ADC_EN_MASK 0xF1 | 30 | #define AXP288_ADC_EN_MASK 0xF1 |
31 | #define AXP288_ADC_TS_PIN_GPADC 0xF2 | ||
32 | #define AXP288_ADC_TS_PIN_ON 0xF3 | ||
31 | 33 | ||
32 | enum axp288_adc_id { | 34 | enum axp288_adc_id { |
33 | AXP288_ADC_TS, | 35 | AXP288_ADC_TS, |
@@ -121,6 +123,16 @@ static int axp288_adc_read_channel(int *val, unsigned long address, | |||
121 | return IIO_VAL_INT; | 123 | return IIO_VAL_INT; |
122 | } | 124 | } |
123 | 125 | ||
126 | static int axp288_adc_set_ts(struct regmap *regmap, unsigned int mode, | ||
127 | unsigned long address) | ||
128 | { | ||
129 | /* channels other than GPADC do not need to switch TS pin */ | ||
130 | if (address != AXP288_GP_ADC_H) | ||
131 | return 0; | ||
132 | |||
133 | return regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, mode); | ||
134 | } | ||
135 | |||
124 | static int axp288_adc_read_raw(struct iio_dev *indio_dev, | 136 | static int axp288_adc_read_raw(struct iio_dev *indio_dev, |
125 | struct iio_chan_spec const *chan, | 137 | struct iio_chan_spec const *chan, |
126 | int *val, int *val2, long mask) | 138 | int *val, int *val2, long mask) |
@@ -131,7 +143,16 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev, | |||
131 | mutex_lock(&indio_dev->mlock); | 143 | mutex_lock(&indio_dev->mlock); |
132 | switch (mask) { | 144 | switch (mask) { |
133 | case IIO_CHAN_INFO_RAW: | 145 | case IIO_CHAN_INFO_RAW: |
146 | if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_GPADC, | ||
147 | chan->address)) { | ||
148 | dev_err(&indio_dev->dev, "GPADC mode\n"); | ||
149 | ret = -EINVAL; | ||
150 | break; | ||
151 | } | ||
134 | ret = axp288_adc_read_channel(val, chan->address, info->regmap); | 152 | ret = axp288_adc_read_channel(val, chan->address, info->regmap); |
153 | if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_ON, | ||
154 | chan->address)) | ||
155 | dev_err(&indio_dev->dev, "TS pin restore\n"); | ||
135 | break; | 156 | break; |
136 | default: | 157 | default: |
137 | ret = -EINVAL; | 158 | ret = -EINVAL; |
@@ -141,6 +162,15 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev, | |||
141 | return ret; | 162 | return ret; |
142 | } | 163 | } |
143 | 164 | ||
165 | static int axp288_adc_set_state(struct regmap *regmap) | ||
166 | { | ||
167 | /* ADC should be always enabled for internal FG to function */ | ||
168 | if (regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON)) | ||
169 | return -EIO; | ||
170 | |||
171 | return regmap_write(regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK); | ||
172 | } | ||
173 | |||
144 | static const struct iio_info axp288_adc_iio_info = { | 174 | static const struct iio_info axp288_adc_iio_info = { |
145 | .read_raw = &axp288_adc_read_raw, | 175 | .read_raw = &axp288_adc_read_raw, |
146 | .driver_module = THIS_MODULE, | 176 | .driver_module = THIS_MODULE, |
@@ -169,7 +199,7 @@ static int axp288_adc_probe(struct platform_device *pdev) | |||
169 | * Set ADC to enabled state at all time, including system suspend. | 199 | * Set ADC to enabled state at all time, including system suspend. |
170 | * otherwise internal fuel gauge functionality may be affected. | 200 | * otherwise internal fuel gauge functionality may be affected. |
171 | */ | 201 | */ |
172 | ret = regmap_write(info->regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK); | 202 | ret = axp288_adc_set_state(axp20x->regmap); |
173 | if (ret) { | 203 | if (ret) { |
174 | dev_err(&pdev->dev, "unable to enable ADC device\n"); | 204 | dev_err(&pdev->dev, "unable to enable ADC device\n"); |
175 | return ret; | 205 | return ret; |