Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4f51956 authored by Ludovic Desroches's avatar Ludovic Desroches Committed by Jonathan Cameron
Browse files

iio: adc: at91: don't use the last converted data register



If touchscreen mode is enabled and a conversion is requested on another
channel, the result in the last converted data register can be a
touchscreen relative value. Starting a conversion involves to do a
conversion for all active channel. It starts with ADC channels and ends
with touchscreen channels. Then if ADC_LCD register is not read quickly,
its content may be a touchscreen conversion.
To remove this temporal constraint, the conversion value is taken from
the channel data register.

Signed-off-by: default avatarLudovic Desroches <ludovic.desroches@atmel.com>
Acked-by: default avatarAlexandre Belloni <alexandre.belloni@free-electrons.com>
Acked-by: default avatarNicolas Ferre <nicolas.ferre@atmel.com>
Cc: Stable@vger.kernel.org
Signed-off-by: default avatarJonathan Cameron <jic23@kernel.org>
parent 1887e724
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -196,6 +196,7 @@ struct at91_adc_state {
	bool			done;
	int			irq;
	u16			last_value;
	int			chnb;
	struct mutex		lock;
	u8			num_channels;
	void __iomem		*reg_base;
@@ -274,7 +275,7 @@ void handle_adc_eoc_trigger(int irq, struct iio_dev *idev)
		disable_irq_nosync(irq);
		iio_trigger_poll(idev->trig);
	} else {
		st->last_value = at91_adc_readl(st, AT91_ADC_LCDR);
		st->last_value = at91_adc_readl(st, AT91_ADC_CHAN(st, st->chnb));
		st->done = true;
		wake_up_interruptible(&st->wq_data_avail);
	}
@@ -351,7 +352,7 @@ static irqreturn_t at91_adc_rl_interrupt(int irq, void *private)
	unsigned int reg;

	status &= at91_adc_readl(st, AT91_ADC_IMR);
	if (status & st->registers->drdy_mask)
	if (status & GENMASK(st->num_channels - 1, 0))
		handle_adc_eoc_trigger(irq, idev);

	if (status & AT91RL_ADC_IER_PEN) {
@@ -418,7 +419,7 @@ static irqreturn_t at91_adc_9x5_interrupt(int irq, void *private)
		AT91_ADC_IER_YRDY |
		AT91_ADC_IER_PRDY;

	if (status & st->registers->drdy_mask)
	if (status & GENMASK(st->num_channels - 1, 0))
		handle_adc_eoc_trigger(irq, idev);

	if (status & AT91_ADC_IER_PEN) {
@@ -689,9 +690,10 @@ static int at91_adc_read_raw(struct iio_dev *idev,
	case IIO_CHAN_INFO_RAW:
		mutex_lock(&st->lock);

		st->chnb = chan->channel;
		at91_adc_writel(st, AT91_ADC_CHER,
				AT91_ADC_CH(chan->channel));
		at91_adc_writel(st, AT91_ADC_IER, st->registers->drdy_mask);
		at91_adc_writel(st, AT91_ADC_IER, BIT(chan->channel));
		at91_adc_writel(st, AT91_ADC_CR, AT91_ADC_START);

		ret = wait_event_interruptible_timeout(st->wq_data_avail,
@@ -708,7 +710,7 @@ static int at91_adc_read_raw(struct iio_dev *idev,

		at91_adc_writel(st, AT91_ADC_CHDR,
				AT91_ADC_CH(chan->channel));
		at91_adc_writel(st, AT91_ADC_IDR, st->registers->drdy_mask);
		at91_adc_writel(st, AT91_ADC_IDR, BIT(chan->channel));

		st->last_value = 0;
		st->done = false;