Skip to content

Commit a64317b

Browse files
ukleineknunojsa
authored andcommitted
iio: adc: ad_sigma_delta: Check for previous ready signals
It can happen if a previous conversion was aborted the ADC pulls down the R̅D̅Y̅ line but the event wasn't handled before. In that case enabling the irq might immediately fire (depending on the irq controller capabilities) and even with a rdy-gpio isn't identified as an unrelated one. To cure that problem check for a pending event before the measurement is started and clear it if needed. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com> Link: https://patch.msgid.link/3ec6b61fb1e527e935133dc56f589aab4b2094a3.1733504533.git.u.kleine-koenig@baylibre.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Origin: next-20241216~37^2~18, commit:132d44dc6966c1cf841ffe0f6f048165687e870b
1 parent 10a7413 commit a64317b

File tree

1 file changed

+98
-1
lines changed

1 file changed

+98
-1
lines changed

drivers/iio/adc/ad_sigma_delta.c

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,11 @@
3030
#define AD_SD_COMM_CHAN_MASK 0x3
3131

3232
#define AD_SD_REG_COMM 0x00
33+
#define AD_SD_REG_STATUS 0x00
3334
#define AD_SD_REG_DATA 0x03
3435

36+
#define AD_SD_REG_STATUS_RDY 0x80
37+
3538
/**
3639
* ad_sd_set_comm() - Set communications register
3740
*
@@ -223,6 +226,86 @@ static void ad_sd_enable_irq(struct ad_sigma_delta *sigma_delta)
223226
enable_irq(sigma_delta->irq_line);
224227
}
225228

229+
#define AD_SD_CLEAR_DATA_BUFLEN 9
230+
231+
/* Called with `sigma_delta->bus_locked == true` only. */
232+
static int ad_sigma_delta_clear_pending_event(struct ad_sigma_delta *sigma_delta)
233+
{
234+
bool pending_event;
235+
unsigned int data_read_len = BITS_TO_BYTES(sigma_delta->info->num_resetclks);
236+
u8 *data;
237+
struct spi_transfer t[] = {
238+
{
239+
.len = 1,
240+
}, {
241+
.len = data_read_len,
242+
}
243+
};
244+
struct spi_message m;
245+
int ret;
246+
247+
/*
248+
* Read R̅D̅Y̅ pin (if possible) or status register to check if there is an
249+
* old event.
250+
*/
251+
if (sigma_delta->rdy_gpiod) {
252+
pending_event = gpiod_get_value(sigma_delta->rdy_gpiod);
253+
} else {
254+
unsigned status_reg;
255+
256+
ret = ad_sd_read_reg(sigma_delta, AD_SD_REG_STATUS, 1, &status_reg);
257+
if (ret)
258+
return ret;
259+
260+
pending_event = !(status_reg & AD_SD_REG_STATUS_RDY);
261+
}
262+
263+
if (!pending_event)
264+
return 0;
265+
266+
/*
267+
* In general the size of the data register is unknown. It varies from
268+
* device to device, might be one byte longer if CONTROL.DATA_STATUS is
269+
* set and even varies on some devices depending on which input is
270+
* selected. So send one byte to start reading the data register and
271+
* then just clock for some bytes with DIN (aka MOSI) high to not
272+
* confuse the register access state machine after the data register was
273+
* completely read. Note however that the sequence length must be
274+
* shorter than the reset procedure.
275+
*/
276+
277+
data = kzalloc(data_read_len + 1, GFP_KERNEL);
278+
if (!data)
279+
return -ENOMEM;
280+
281+
spi_message_init(&m);
282+
if (sigma_delta->info->has_registers) {
283+
unsigned int data_reg = sigma_delta->info->data_reg ?: AD_SD_REG_DATA;
284+
285+
data[0] = data_reg << sigma_delta->info->addr_shift;
286+
data[0] |= sigma_delta->info->read_mask;
287+
data[0] |= sigma_delta->comm;
288+
t[0].tx_buf = data;
289+
spi_message_add_tail(&t[0], &m);
290+
}
291+
292+
/*
293+
* The first transferred byte is part of the real data register,
294+
* so this doesn't need to be 0xff. In the remaining
295+
* `data_read_len - 1` bytes are less than $num_resetclks ones.
296+
*/
297+
t[1].tx_buf = data + 1;
298+
data[1] = 0x00;
299+
memset(data + 2, 0xff, data_read_len - 1);
300+
spi_message_add_tail(&t[1], &m);
301+
302+
ret = spi_sync_locked(sigma_delta->spi, &m);
303+
304+
kfree(data);
305+
306+
return ret;
307+
}
308+
226309
int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,
227310
unsigned int mode, unsigned int channel)
228311
{
@@ -238,6 +321,10 @@ int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,
238321
sigma_delta->keep_cs_asserted = true;
239322
reinit_completion(&sigma_delta->completion);
240323

324+
ret = ad_sigma_delta_clear_pending_event(sigma_delta);
325+
if (ret)
326+
goto out;
327+
241328
ret = ad_sigma_delta_set_mode(sigma_delta, mode);
242329
if (ret < 0)
243330
goto out;
@@ -311,6 +398,10 @@ int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
311398
sigma_delta->keep_cs_asserted = true;
312399
reinit_completion(&sigma_delta->completion);
313400

401+
ret = ad_sigma_delta_clear_pending_event(sigma_delta);
402+
if (ret)
403+
goto out_unlock;
404+
314405
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_SINGLE);
315406

316407
ad_sd_enable_irq(sigma_delta);
@@ -334,9 +425,11 @@ int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
334425
out:
335426
ad_sd_disable_irq(sigma_delta);
336427

337-
sigma_delta->keep_cs_asserted = false;
338428
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
339429
ad_sigma_delta_disable_one(sigma_delta, chan->address);
430+
431+
out_unlock:
432+
sigma_delta->keep_cs_asserted = false;
340433
sigma_delta->bus_locked = false;
341434
spi_bus_unlock(sigma_delta->spi->master);
342435
iio_device_release_direct_mode(indio_dev);
@@ -457,6 +550,10 @@ static int ad_sd_buffer_postenable(struct iio_dev *indio_dev)
457550
if (iio_device_get_current_mode(indio_dev) == INDIO_BUFFER_HARDWARE)
458551
ad_sd_prepare_and_enable_spi_engine_msg(sigma_delta, indio_dev);
459552

553+
ret = ad_sigma_delta_clear_pending_event(sigma_delta);
554+
if (ret)
555+
goto err_unlock;
556+
460557
ret = ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_CONTINUOUS);
461558
if (ret)
462559
goto err_unlock;

0 commit comments

Comments
 (0)