Skip to content

Commit 6d6aa29

Browse files
pcercueijic23
authored andcommitted
iio/adc: ingenic: Fix AUX/VBAT readings when touchscreen is used
When the command feature of the ADC is used, it is possible to program the ADC, and specify at each step what input should be processed, and in comparison to what reference. This broke the AUX and battery readings when the touchscreen was enabled, most likely because the CMD feature would change the VREF all the time. Now, when AUX or battery are read, we temporarily disable the CMD feature, which means that we won't get touchscreen readings in that time frame. But it now gives correct values for AUX / battery, and the touchscreen isn't disabled for long enough to be an actual issue. Fixes: b96952f ("IIO: Ingenic JZ47xx: Add touchscreen mode.") Signed-off-by: Paul Cercueil <paul@crapouillou.net> Acked-by: Artur Rojek <contact@artur-rojek.eu> Cc: <stable@vger.kernel.org> Link: https://lore.kernel.org/r/20201103201238.161083-1-paul@crapouillou.net Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
1 parent c91ebcc commit 6d6aa29

1 file changed

Lines changed: 26 additions & 6 deletions

File tree

drivers/iio/adc/ingenic-adc.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,12 @@ static void ingenic_adc_set_config(struct ingenic_adc *adc,
177177
mutex_unlock(&adc->lock);
178178
}
179179

180-
static void ingenic_adc_enable(struct ingenic_adc *adc,
181-
int engine,
182-
bool enabled)
180+
static void ingenic_adc_enable_unlocked(struct ingenic_adc *adc,
181+
int engine,
182+
bool enabled)
183183
{
184184
u8 val;
185185

186-
mutex_lock(&adc->lock);
187186
val = readb(adc->base + JZ_ADC_REG_ENABLE);
188187

189188
if (enabled)
@@ -192,20 +191,41 @@ static void ingenic_adc_enable(struct ingenic_adc *adc,
192191
val &= ~BIT(engine);
193192

194193
writeb(val, adc->base + JZ_ADC_REG_ENABLE);
194+
}
195+
196+
static void ingenic_adc_enable(struct ingenic_adc *adc,
197+
int engine,
198+
bool enabled)
199+
{
200+
mutex_lock(&adc->lock);
201+
ingenic_adc_enable_unlocked(adc, engine, enabled);
195202
mutex_unlock(&adc->lock);
196203
}
197204

198205
static int ingenic_adc_capture(struct ingenic_adc *adc,
199206
int engine)
200207
{
208+
u32 cfg;
201209
u8 val;
202210
int ret;
203211

204-
ingenic_adc_enable(adc, engine, true);
212+
/*
213+
* Disable CMD_SEL temporarily, because it causes wrong VBAT readings,
214+
* probably due to the switch of VREF. We must keep the lock here to
215+
* avoid races with the buffer enable/disable functions.
216+
*/
217+
mutex_lock(&adc->lock);
218+
cfg = readl(adc->base + JZ_ADC_REG_CFG);
219+
writel(cfg & ~JZ_ADC_REG_CFG_CMD_SEL, adc->base + JZ_ADC_REG_CFG);
220+
221+
ingenic_adc_enable_unlocked(adc, engine, true);
205222
ret = readb_poll_timeout(adc->base + JZ_ADC_REG_ENABLE, val,
206223
!(val & BIT(engine)), 250, 1000);
207224
if (ret)
208-
ingenic_adc_enable(adc, engine, false);
225+
ingenic_adc_enable_unlocked(adc, engine, false);
226+
227+
writel(cfg, adc->base + JZ_ADC_REG_CFG);
228+
mutex_unlock(&adc->lock);
209229

210230
return ret;
211231
}

0 commit comments

Comments
 (0)