[v3,2/2] iio: adc: ti-ads1298: Add driver

Message ID 20240206065818.2016910-2-mike.looijmans@topic.nl
State New
Headers
Series [v3,1/2] dt-bindings: iio: adc: ti-ads1298: Add bindings |

Commit Message

Mike Looijmans Feb. 6, 2024, 6:58 a.m. UTC
  Skeleton driver for the TI ADS1298 medical ADC. This device is
typically used for ECG and similar measurements. Supports data
acquisition at configurable scale and sampling frequency.

Signed-off-by: Mike Looijmans <mike.looijmans@topic.nl>

---

Changes in v3:
Indentation fixups
Remove unused headers
Remove #define leftovers
Use devm_get_clk_optional_enabled
Use ilog2 instead of fls()-1
Magic "23" replaced
Explain the extra "0" in read/write register
use guard() from cleanup.h
use REGCACHE_MAPLE

Changes in v2:
Remove accidental "default y" in Kconfig
Indentation and similar cosmetic fixes
Magic numbers into constants
Short return paths in read_raw and write_raw
DMA buffer alignment
Bounce buffer is u32 instead of u8
Avoid races using claim_direct_mode
Check errors on all register accesses
Immediate SPI restart to reduce underruns
"name" is chip name, not unique

 drivers/iio/adc/Kconfig      |  11 +
 drivers/iio/adc/Makefile     |   1 +
 drivers/iio/adc/ti-ads1298.c | 752 +++++++++++++++++++++++++++++++++++
 3 files changed, 764 insertions(+)
 create mode 100644 drivers/iio/adc/ti-ads1298.c
  

Comments

Mike Looijmans Feb. 6, 2024, 1:33 p.m. UTC | #1
On 06-02-2024 13:57, Andy Shevchenko wrote:
> On Tue, Feb 06, 2024 at 07:58:18AM +0100, Mike Looijmans wrote:
>> Skeleton driver for the TI ADS1298 medical ADC. This device is
>> typically used for ECG and similar measurements. Supports data
>> acquisition at configurable scale and sampling frequency.
> Thanks for an update, I have only a few style comments and a single one about
> comparison (see below). If you are going to address them as suggested, feel
> free to add
>
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
>
> to the next version.
>
> ...

Thanks for reviewing...


>> +/* Registers */
>> +#define ADS1298_REG_ID		0x00
>> +#define ADS1298_MASK_ID_FAMILY			GENMASK(7, 3)
>> +#define ADS1298_MASK_ID_CHANNELS		GENMASK(2, 0)
>> +#define ADS1298_ID_FAMILY_ADS129X		0x90
>> +#define ADS1298_ID_FAMILY_ADS129XR		0xd0
> + Blank line? (And so on for all registers that have bitfields defined)

Makes sense... Looks too cluttered as it is now.


>
>> +#define ADS1298_REG_CONFIG1	0x01
>> +#define ADS1298_MASK_CONFIG1_HR			BIT(7)
>> +#define ADS1298_MASK_CONFIG1_DR			GENMASK(2, 0)
>> +#define ADS1298_SHIFT_DR_HR			6
>> +#define ADS1298_SHIFT_DR_LP			7
>> +#define ADS1298_LOWEST_DR			0x06
> ...
>
>> +	factor = (rate >> ADS1298_SHIFT_DR_HR) / val;
>> +	if (factor >= 128)
> I just realized that this comparison is probably better in a form
>
> 	if (factor >= ADS1298_MASK_CONFIG1_HR)
>
> as it points out why this is a special case in comparison to 'if (factor)'
> below. What do you think?

The "HR" bit sets the device to high-res mode (which apparently doubles 
the internal sample rate).

But "128" could be written as "1 << ADS1298_SHIFT_DR_LP" which is the 
max oversampling factor.


> ...
>
>> +	wasbusy = --priv->rdata_xfer_busy;
> Why preincrement? How would it be different from postincrement?

Maybe better write this as:

--priv->rdata_xfer_busy;

wasbusy = priv->rdata_xfer_busy;

I want the value after decrementing it.


>> +	if (wasbusy) {
> To me more robust code would look like
>
> 	if (wasbusy < 1)
> 		return;
> 	...
> 	if (wasbusy > 1)
> 		...

wasbusy could have been unsigned.

This code will only ever execute with rdata_xfer_busy > 0 (or the SPI 
driver called our completion callback without us calling spi_async first)

>
>> +		/*
>> +		 * DRDY interrupt occurred before SPI completion. Start a new
>> +		 * SPI transaction now to retrieve the data that wasn't latched
>> +		 * into the ADS1298 chip's transfer buffer yet.
>> +		 */
>> +		spi_async(priv->spi, &priv->rdata_msg);
>> +		/*
>> +		 * If more than one DRDY took place, there was an overrun. Since
>> +		 * the sample is already lost, reset the counter to 1 so that
>> +		 * we will wait for a DRDY interrupt after this SPI transaction.
>> +		 */
>> +		if (wasbusy > 1)
>> +			priv->rdata_xfer_busy = 1;
>> +	}
> ...
>
>> +		/*
>> +		 * for a single transfer mode we're kept in direct_mode until
> For
>
>> +		 * completion, avoiding a race with buffered IO.
>> +		 */
> ...
>
>> +	wasbusy = priv->rdata_xfer_busy++;
> So, it starts from negative?
>
>> +	/* When no SPI transfer in transit, start one now */
>> +	if (!wasbusy)
> To be compatible with above perhaps
>
> 	if (wasbusy < 1)
>
> also makes it more robust (all negative numbers will be considered the same.
>
>> +		spi_async(priv->spi, &priv->rdata_msg);

The "rdata_xfer_busy" starts at 0.

Increments when a DRDY occurs.

Decrements when SPI completion is reported.

So the meaning of "rdata_xfer_busy" is:

0 = Waiting for DRDY interrupt

1 = SPI transfer in progress

2 = DRDY occured during SPI transfer, should start another on completion

 >2 = Multiple DRDY during SPI transfer, overflow, we 
lost rdata_xfer_busy - 2 samples


> ...
>
>
>> +	dev_dbg(dev, "Found %s, %u channels\n", ads1298_family_name(val),
>> +		(unsigned int)(4 + 2 * (val & ADS1298_MASK_ID_CHANNELS)));
> Castings in printf() is a big red flag usually (it's rarely we need them).
> Why is it here?

Compiler complains that the expression is "unsigned long". Probably 
because of ADS1298_MASK_ID_CHANNELS being so.


> ...
>
>> +	if (reset_gpio) {
>> +		/* Minimum reset pulsewidth is 2 clock cycles */
>> +		udelay(ADS1298_CLOCKS_TO_USECS(2));
>> +		gpiod_set_value(reset_gpio, 0);
> I would rewrite it as
>
> 		/* Minimum reset pulsewidth is 2 clock cycles */
> 		gpiod_set_value(reset_gpio, 1);
> 		udelay(ADS1298_CLOCKS_TO_USECS(2));
> 		gpiod_set_value(reset_gpio, 0);
>
> to be sure we have a reset done correctly, and the comment will make more
> sense.

If used, the reset must be asserted *before* the voltages and clocks are 
activated. This would obfuscate that, and add a redundant call to set_value.

I did forget to use "cansleep" here, will add that.
  
Mike Looijmans Feb. 6, 2024, 2:25 p.m. UTC | #2
On 06-02-2024 14:50, Andy Shevchenko wrote:
> On Tue, Feb 06, 2024 at 02:33:47PM +0100, Mike Looijmans wrote:
>> On 06-02-2024 13:57, Andy Shevchenko wrote:
>>> On Tue, Feb 06, 2024 at 07:58:18AM +0100, Mike Looijmans wrote:
> ...
>
>>>> +	factor = (rate >> ADS1298_SHIFT_DR_HR) / val;
>>>> +	if (factor >= 128)
>>> I just realized that this comparison is probably better in a form
>>>
>>> 	if (factor >= ADS1298_MASK_CONFIG1_HR)
>>>
>>> as it points out why this is a special case in comparison to 'if (factor)'
>>> below. What do you think?
>> The "HR" bit sets the device to high-res mode (which apparently doubles the
>> internal sample rate).
>>
>> But "128" could be written as "1 << ADS1298_SHIFT_DR_LP" which is the max
>> oversampling factor.
> Use BIT(..._DR_LP) and we are done here.

Ok.


> ...
>
>>>> +	wasbusy = --priv->rdata_xfer_busy;
>>> Why preincrement? How would it be different from postincrement?
>> Maybe better write this as:
>>
>> --priv->rdata_xfer_busy;
>>
>> wasbusy = priv->rdata_xfer_busy;
>>
>> I want the value after decrementing it.
> Yes, looks more obvious.

Having done that, and looking at it again, it's better to just eliminate 
the local "wasbusy" altogether. More concise.


>
>>>> +	if (wasbusy) {
>>> To me more robust code would look like
>>>
>>> 	if (wasbusy < 1)
>>> 		return;
>>> 	...
>>> 	if (wasbusy > 1)
>>> 		...
>> wasbusy could have been unsigned.
>>
>> This code will only ever execute with rdata_xfer_busy > 0 (or the SPI driver
>> called our completion callback without us calling spi_async first)
> You never know what may go wrong in the future :-) That said, I prefer robust
> code against non-robust.

Maybe: BUG_ON(!priv->rdata_xfer_busy)

Adds more code, dunno what weighs heavier... Haven't seen other drivers 
do this though.

I made rdata_xfer_busy unsigned as it should have been.


> ...
>
>>>> +	wasbusy = priv->rdata_xfer_busy++;
>>> So, it starts from negative?
>>>
>>>> +	/* When no SPI transfer in transit, start one now */
>>>> +	if (!wasbusy)
>>> To be compatible with above perhaps
>>>
>>> 	if (wasbusy < 1)
>>>
>>> also makes it more robust (all negative numbers will be considered the same.
>>>
>>>> +		spi_async(priv->spi, &priv->rdata_msg);
>> The "rdata_xfer_busy" starts at 0.
>>
>> Increments when a DRDY occurs.
>>
>> Decrements when SPI completion is reported.
>>
>> So the meaning of "rdata_xfer_busy" is:
>>
>> 0 = Waiting for DRDY interrupt
>>
>> 1 = SPI transfer in progress
>>
>> 2 = DRDY occured during SPI transfer, should start another on completion
>>
>>> 2 = Multiple DRDY during SPI transfer, overflow, we lost rdata_xfer_busy -
>> 2 samples
>
> Maybe another good comment is needed here as well?

I thought I had it covered with the comments... I'll add more.


>
> ...
>
>>>> +	dev_dbg(dev, "Found %s, %u channels\n", ads1298_family_name(val),
>>>> +		(unsigned int)(4 + 2 * (val & ADS1298_MASK_ID_CHANNELS)));
>>> Castings in printf() is a big red flag usually (it's rarely we need them).
>>> Why is it here?
>> Compiler complains that the expression is "unsigned long". Probably because
>>   of ADS1298_MASK_ID_CHANNELS being so.
> So, use the unsigned long specifier and drop casting.
>
> ...
>
>>>> +	if (reset_gpio) {
>>>> +		/* Minimum reset pulsewidth is 2 clock cycles */
>>>> +		udelay(ADS1298_CLOCKS_TO_USECS(2));
>>>> +		gpiod_set_value(reset_gpio, 0);
>>> I would rewrite it as
>>>
>>> 		/* Minimum reset pulsewidth is 2 clock cycles */
>>> 		gpiod_set_value(reset_gpio, 1);
>>> 		udelay(ADS1298_CLOCKS_TO_USECS(2));
>>> 		gpiod_set_value(reset_gpio, 0);
>>>
>>> to be sure we have a reset done correctly, and the comment will make more
>>> sense.
>> If used, the reset must be asserted *before* the voltages and clocks are
>> activated. This would obfuscate that, and add a redundant call to set_value.
> Then perhaps you want reset framework to be used instead?
>
> Dunno, but this comment seems confusing in a way that you somewhere asserted it
> and it's not obvious where and here is the delay out of a blue. Perhaps you may
> extend the comment?

Could use devm_reset_control_get_optional_shared() I guess, but that 
would change devicetree bindings as well...

And it wouldn't change the order, as it'd still be asserted at the start 
of probe()
  
Mike Looijmans Feb. 6, 2024, 2:47 p.m. UTC | #3
On 06-02-2024 15:25, Mike Looijmans wrote:
> On 06-02-2024 14:50, Andy Shevchenko wrote:
>> On Tue, Feb 06, 2024 at 02:33:47PM +0100, Mike Looijmans wrote:
>>> On 06-02-2024 13:57, Andy Shevchenko wrote:
>>>> On Tue, Feb 06, 2024 at 07:58:18AM +0100, Mike Looijmans wrote:
>>
>> ...
>>
>>>>> +    wasbusy = --priv->rdata_xfer_busy;
>>>> Why preincrement? How would it be different from postincrement?
>>> Maybe better write this as:
>>>
>>> --priv->rdata_xfer_busy;
>>>
>>> wasbusy = priv->rdata_xfer_busy;
>>>
>>> I want the value after decrementing it.
>> Yes, looks more obvious.
>
> Having done that, and looking at it again, it's better to just 
> eliminate the local "wasbusy" altogether. More concise.


This removes the decrement operator, so the method now looks like this:


static void ads1298_rdata_release_busy_or_restart(struct ads1298_private 
*priv)
{
     guard(spinlock_irqsave)(&priv->irq_busy_lock);

     if (priv->rdata_xfer_busy > 1) {
         /*
          * DRDY interrupt occurred before SPI completion. Start a new
          * SPI transaction now to retrieve the data that wasn't latched
          * into the ADS1298 chip's transfer buffer yet.
          */
         spi_async(priv->spi, &priv->rdata_msg);
         /*
          * If more than one DRDY took place, there was an overrun. Since
          * the sample is already lost, reset the counter to 1 so that
          * we will wait for a DRDY interrupt after this SPI transaction.
          */
         priv->rdata_xfer_busy = 1;
     } else {
         /* No pending data, wait for DRDY */
         priv->rdata_xfer_busy = 0;
     }
}
  
Mike Looijmans Feb. 6, 2024, 3:44 p.m. UTC | #4
On 06-02-2024 16:09, Andy Shevchenko wrote:
> On Tue, Feb 06, 2024 at 03:47:45PM +0100, Mike Looijmans wrote:
>> On 06-02-2024 15:25, Mike Looijmans wrote:
>>> On 06-02-2024 14:50, Andy Shevchenko wrote:
>>>> On Tue, Feb 06, 2024 at 02:33:47PM +0100, Mike Looijmans wrote:
>>>>> On 06-02-2024 13:57, Andy Shevchenko wrote:
>>>>>> On Tue, Feb 06, 2024 at 07:58:18AM +0100, Mike Looijmans wrote:
> ...
>
>>>>>>> +    wasbusy = --priv->rdata_xfer_busy;
>>>>>> Why preincrement? How would it be different from postincrement?
>>>>> Maybe better write this as:
>>>>>
>>>>> --priv->rdata_xfer_busy;
>>>>>
>>>>> wasbusy = priv->rdata_xfer_busy;
>>>>>
>>>>> I want the value after decrementing it.
>>>> Yes, looks more obvious.
>>> Having done that, and looking at it again, it's better to just eliminate
>>> the local "wasbusy" altogether. More concise.
>>
>> This removes the decrement operator, so the method now looks like this:
>>
>>
>> static void ads1298_rdata_release_busy_or_restart(struct ads1298_private
>> *priv)
>> {
>>      guard(spinlock_irqsave)(&priv->irq_busy_lock);
>>
>>      if (priv->rdata_xfer_busy > 1) {
>>          /*
>>           * DRDY interrupt occurred before SPI completion. Start a new
>>           * SPI transaction now to retrieve the data that wasn't latched
>>           * into the ADS1298 chip's transfer buffer yet.
>>           */
>>          spi_async(priv->spi, &priv->rdata_msg);
>>          /*
>>           * If more than one DRDY took place, there was an overrun. Since
>>           * the sample is already lost, reset the counter to 1 so that
>>           * we will wait for a DRDY interrupt after this SPI transaction.
>>           */
>>          priv->rdata_xfer_busy = 1;
>>      } else {
>>          /* No pending data, wait for DRDY */
>>          priv->rdata_xfer_busy = 0;
>>      }
>> }
> Yep and it looks like you reinvented atomics :-)
>
> 	atomic_t rdata_xfer_busy;
> 	...
>
> But it's up to you what to do with that.
> Maybe Jonathan can advice something different.
>
The spinlock also protects the call to spi_async().
  
Mike Looijmans Feb. 6, 2024, 5:38 p.m. UTC | #5
On 06-02-2024 17:32, Andy Shevchenko wrote:
> On Tue, Feb 06, 2024 at 04:44:03PM +0100, Mike Looijmans wrote:
>> On 06-02-2024 16:09, Andy Shevchenko wrote:
>>> On Tue, Feb 06, 2024 at 03:47:45PM +0100, Mike Looijmans wrote:
> ...
>
>>> But it's up to you what to do with that.
>>> Maybe Jonathan can advice something different.
>>>
>> The spinlock also protects the call to spi_async().
> I don't get this. Locks usually protect the data and not the code.
> Can you elaborate?
>
Either the DRDY or SPI completion handler will call spi_async(), the 
lock assures that it's only called by one.

Usually the DRDY handler will call spi_async(). If the next DRDY arrives 
before the spi_async transfer finishes, the SPI completion handler must 
call spi_async() a.s.a.p. to also read the newly arrived sample. There's 
no way to ask the chip whether there's data to read, so all the driver 
can do is use the ISR to remember that DRDY did trigger.

The lock protects that the "busy" counter matches the actual pending 
calls to spi_async, and also protects that only one handler will call 
spi_async (and update the counter).

Maybe this picture helps:

DRDY ---+-----+-----+-----+-

SPI ------+------------+-+--

busy 00001100011111112211101
  
Jonathan Cameron Feb. 10, 2024, 4:27 p.m. UTC | #6
On Tue, 6 Feb 2024 18:38:29 +0100
Mike Looijmans <mike.looijmans@topic.nl> wrote:

> On 06-02-2024 17:32, Andy Shevchenko wrote:
> > On Tue, Feb 06, 2024 at 04:44:03PM +0100, Mike Looijmans wrote:  
> >> On 06-02-2024 16:09, Andy Shevchenko wrote:  
> >>> On Tue, Feb 06, 2024 at 03:47:45PM +0100, Mike Looijmans wrote:  
> > ...
> >  
> >>> But it's up to you what to do with that.
> >>> Maybe Jonathan can advice something different.
> >>>  
> >> The spinlock also protects the call to spi_async().  
> > I don't get this. Locks usually protect the data and not the code.
> > Can you elaborate?
> >  
> Either the DRDY or SPI completion handler will call spi_async(), the 
> lock assures that it's only called by one.

Arguably it's protecting the destination buffer of the spi_async()
call.  We don't really care if we issue two reads (it's a waste
of time and we would store two sets of readings but meh), but we do
care about being sure that don't issue a second read into a buffer
that we are potentially simultaneously getting data back from.

There are comments where the release is to describe when it can 
be safely unlocked.

I'm not super keen on this whole structure but I don't really have a better
idea.  Who builds a device where you have no latched way of seeing
if there is new data? (some) Hardware folk love to assume they have a RTOS only
talking to their device and that no pulse signals will ever be missed.

We get to educate them when ever the opportunity arises :)

Jonathan

> 
> Usually the DRDY handler will call spi_async(). If the next DRDY arrives 
> before the spi_async transfer finishes, the SPI completion handler must 
> call spi_async() a.s.a.p. to also read the newly arrived sample. There's 
> no way to ask the chip whether there's data to read, so all the driver 
> can do is use the ISR to remember that DRDY did trigger.
> 
> The lock protects that the "busy" counter matches the actual pending 
> calls to spi_async, and also protects that only one handler will call 
> spi_async (and update the counter).
> 
> Maybe this picture helps:
> 
> DRDY ---+-----+-----+-----+-
> 
> SPI ------+------------+-+--
> 
> busy 00001100011111112211101
> 
>
  
Mike Looijmans Feb. 14, 2024, 6:48 a.m. UTC | #7
On 10-02-2024 17:27, Jonathan Cameron wrote:
> On Tue, 6 Feb 2024 18:38:29 +0100
> Mike Looijmans <mike.looijmans@topic.nl> wrote:
> 
>> On 06-02-2024 17:32, Andy Shevchenko wrote:
>>> On Tue, Feb 06, 2024 at 04:44:03PM +0100, Mike Looijmans wrote:
>>>> On 06-02-2024 16:09, Andy Shevchenko wrote:
>>>>> On Tue, Feb 06, 2024 at 03:47:45PM +0100, Mike Looijmans wrote:
>>> ...
>>>   
>>>>> But it's up to you what to do with that.
>>>>> Maybe Jonathan can advice something different.
>>>>>   
>>>> The spinlock also protects the call to spi_async().
>>> I don't get this. Locks usually protect the data and not the code.
>>> Can you elaborate?
>>>   
>> Either the DRDY or SPI completion handler will call spi_async(), the
>> lock assures that it's only called by one.
> 
> Arguably it's protecting the destination buffer of the spi_async()
> call.  We don't really care if we issue two reads (it's a waste
> of time and we would store two sets of readings but meh), but we do
> care about being sure that don't issue a second read into a buffer
> that we are potentially simultaneously getting data back from.

Indeed, that.

> 
> There are comments where the release is to describe when it can
> be safely unlocked.
> 
> I'm not super keen on this whole structure but I don't really have a better
> idea.  Who builds a device where you have no latched way of seeing
> if there is new data? (some) Hardware folk love to assume they have a RTOS only
> talking to their device and that no pulse signals will ever be missed.
> 
> We get to educate them when ever the opportunity arises :)

Even on RTOS this chip was a pain - to get it to work reliably I had to set up 
a DMA controller to run the SPI transactions, which took some smart 
daisy-chaining (I recall having the DMA controller write to its own control 
registers to avoid involving the CPU).

It's probably possible to trick audio hardware (I2S controller) into grabbing 
the data (my chip doesn't have that) without involving the CPU.

As the code is now, I can grab data and display it with the IIO oscilloscope 
over network at 4kHz without losing samples on an A9 at 600Mhz.
  

Patch

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 35f9867da12c..1d2d2eff15da 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -1318,6 +1318,17 @@  config TI_ADS8688
 	  This driver can also be built as a module. If so, the module will be
 	  called ti-ads8688.
 
+config TI_ADS1298
+	tristate "Texas Instruments ADS1298"
+	depends on SPI
+	select IIO_BUFFER
+	help
+	  If you say yes here you get support for Texas Instruments ADS1298
+	  medical ADC chips
+
+	  This driver can also be built as a module. If so, the module will be
+	  called ti-ads1298.
+
 config TI_ADS124S08
 	tristate "Texas Instruments ADS124S08"
 	depends on SPI
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index bee11d442af4..ff0e3633eded 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -117,6 +117,7 @@  obj-$(CONFIG_TI_ADS7924) += ti-ads7924.o
 obj-$(CONFIG_TI_ADS7950) += ti-ads7950.o
 obj-$(CONFIG_TI_ADS8344) += ti-ads8344.o
 obj-$(CONFIG_TI_ADS8688) += ti-ads8688.o
+obj-$(CONFIG_TI_ADS1298) += ti-ads1298.o
 obj-$(CONFIG_TI_ADS124S08) += ti-ads124s08.o
 obj-$(CONFIG_TI_ADS131E08) += ti-ads131e08.o
 obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
diff --git a/drivers/iio/adc/ti-ads1298.c b/drivers/iio/adc/ti-ads1298.c
new file mode 100644
index 000000000000..ac708f4fa3dc
--- /dev/null
+++ b/drivers/iio/adc/ti-ads1298.c
@@ -0,0 +1,752 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/* TI ADS1298 chip family driver
+ * Copyright (C) 2023 - 2024 Topic Embedded Products
+ */
+
+#include <linux/bitfield.h>
+#include <linux/cleanup.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/log2.h>
+#include <linux/math.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/units.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/kfifo_buf.h>
+
+#include <asm/unaligned.h>
+
+/* Commands */
+#define ADS1298_CMD_WAKEUP	0x02
+#define ADS1298_CMD_STANDBY	0x04
+#define ADS1298_CMD_RESET	0x06
+#define ADS1298_CMD_START	0x08
+#define ADS1298_CMD_STOP	0x0a
+#define ADS1298_CMD_RDATAC	0x10
+#define ADS1298_CMD_SDATAC	0x11
+#define ADS1298_CMD_RDATA	0x12
+#define ADS1298_CMD_RREG	0x20
+#define ADS1298_CMD_WREG	0x40
+
+/* Registers */
+#define ADS1298_REG_ID		0x00
+#define ADS1298_MASK_ID_FAMILY			GENMASK(7, 3)
+#define ADS1298_MASK_ID_CHANNELS		GENMASK(2, 0)
+#define ADS1298_ID_FAMILY_ADS129X		0x90
+#define ADS1298_ID_FAMILY_ADS129XR		0xd0
+#define ADS1298_REG_CONFIG1	0x01
+#define ADS1298_MASK_CONFIG1_HR			BIT(7)
+#define ADS1298_MASK_CONFIG1_DR			GENMASK(2, 0)
+#define ADS1298_SHIFT_DR_HR			6
+#define ADS1298_SHIFT_DR_LP			7
+#define ADS1298_LOWEST_DR			0x06
+#define ADS1298_REG_CONFIG2	0x02
+#define ADS1298_MASK_CONFIG2_RESERVED		BIT(6)
+#define ADS1298_MASK_CONFIG2_WCT_CHOP		BIT(5)
+#define ADS1298_MASK_CONFIG2_INT_TEST		BIT(4)
+#define ADS1298_MASK_CONFIG2_TEST_AMP		BIT(2)
+#define ADS1298_MASK_CONFIG2_TEST_FREQ_DC	GENMASK(1, 0)
+#define ADS1298_MASK_CONFIG2_TEST_FREQ_SLOW	0
+#define ADS1298_MASK_CONFIG2_TEST_FREQ_FAST	BIT(0)
+#define ADS1298_REG_CONFIG3	0x03
+#define ADS1298_MASK_CONFIG3_PWR_REFBUF		BIT(7)
+#define ADS1298_MASK_CONFIG3_RESERVED		BIT(6)
+#define ADS1298_MASK_CONFIG3_VREF_4V		BIT(5)
+#define ADS1298_REG_LOFF	0x04
+#define ADS1298_REG_CHnSET(n)	(0x05 + n)
+#define ADS1298_MASK_CH_PD		BIT(7)
+#define ADS1298_MASK_CH_PGA		GENMASK(6, 4)
+#define ADS1298_MASK_CH_MUX		GENMASK(2, 0)
+#define ADS1298_REG_LOFF_STATP	0x12
+#define ADS1298_REG_LOFF_STATN	0x13
+
+#define ADS1298_REG_CONFIG4	0x17
+#define ADS1298_MASK_CONFIG4_SINGLE_SHOT	BIT(3)
+#define ADS1298_REG_WCT1	0x18
+#define ADS1298_REG_WCT2	0x19
+
+#define ADS1298_MAX_CHANNELS	8
+#define ADS1298_BITS_PER_SAMPLE	24
+#define ADS1298_CLK_RATE_HZ	2048000
+#define ADS1298_CLOCKS_TO_USECS(x) \
+		(DIV_ROUND_UP((x) * MICROHZ_PER_HZ, ADS1298_CLK_RATE_HZ))
+/*
+ * Read/write register commands require 4 clocks to decode, for speeds above
+ * 2x the clock rate, this would require extra time between the command byte and
+ * the data. Much simpler is to just limit the SPI transfer speed while doing
+ * register access.
+ */
+#define ADS1298_SPI_BUS_SPEED_SLOW	ADS1298_CLK_RATE_HZ
+/* For reading and writing registers, we need a 3-byte buffer */
+#define ADS1298_SPI_CMD_BUFFER_SIZE	3
+/* Outputs status word and 8 24-bit samples, plus the command byte */
+#define ADS1298_SPI_RDATA_BUFFER_SIZE	((ADS1298_MAX_CHANNELS + 1) * 3 + 1)
+
+struct ads1298_private {
+	const struct ads1298_chip_info *chip_info;
+	struct spi_device *spi;
+	struct regulator *reg_avdd;
+	struct regulator *reg_vref;
+	struct clk *clk;
+	struct regmap *regmap;
+	struct completion completion;
+	struct iio_trigger *trig;
+	struct spi_transfer rdata_xfer;
+	struct spi_message rdata_msg;
+	spinlock_t irq_busy_lock; /* Handshake between SPI and DRDY irqs */
+	int rdata_xfer_busy;
+
+	/* Temporary storage for demuxing data after SPI transfer */
+	u32 bounce_buffer[ADS1298_MAX_CHANNELS];
+
+	/* For synchronous SPI exchanges (read/write registers) */
+	u8 cmd_buffer[ADS1298_SPI_CMD_BUFFER_SIZE] __aligned(IIO_DMA_MINALIGN);
+
+	/* Buffer used for incoming SPI data */
+	u8 rx_buffer[ADS1298_SPI_RDATA_BUFFER_SIZE];
+	/* Contains the RDATA command and zeroes to clock out */
+	u8 tx_buffer[ADS1298_SPI_RDATA_BUFFER_SIZE];
+};
+
+/* Three bytes per sample in RX buffer, starting at offset 4 */
+#define ADS1298_OFFSET_IN_RX_BUFFER(index)	(3 * (index) + 4)
+
+#define ADS1298_CHAN(index)				\
+{							\
+	.type = IIO_VOLTAGE,				\
+	.indexed = 1,					\
+	.channel = index,				\
+	.address = ADS1298_OFFSET_IN_RX_BUFFER(index),	\
+	.info_mask_separate =				\
+		BIT(IIO_CHAN_INFO_RAW) |		\
+		BIT(IIO_CHAN_INFO_SCALE),		\
+	.info_mask_shared_by_all =			\
+		BIT(IIO_CHAN_INFO_SAMP_FREQ) |		\
+		BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),	\
+	.scan_index = index,				\
+	.scan_type = {					\
+		.sign = 's',				\
+		.realbits = ADS1298_BITS_PER_SAMPLE,	\
+		.storagebits = 32,			\
+		.endianness = IIO_CPU,			\
+	},						\
+}
+
+static const struct iio_chan_spec ads1298_channels[] = {
+	ADS1298_CHAN(0),
+	ADS1298_CHAN(1),
+	ADS1298_CHAN(2),
+	ADS1298_CHAN(3),
+	ADS1298_CHAN(4),
+	ADS1298_CHAN(5),
+	ADS1298_CHAN(6),
+	ADS1298_CHAN(7),
+};
+
+static int ads1298_write_cmd(struct ads1298_private *priv, u8 command)
+{
+	struct spi_transfer xfer = {
+		.tx_buf = priv->cmd_buffer,
+		.rx_buf = priv->cmd_buffer,
+		.len = 1,
+		.speed_hz = ADS1298_SPI_BUS_SPEED_SLOW,
+		.delay = {
+			.value = 2,
+			.unit = SPI_DELAY_UNIT_USECS,
+		},
+	};
+
+	priv->cmd_buffer[0] = command;
+
+	return spi_sync_transfer(priv->spi, &xfer, 1);
+}
+
+static int ads1298_read_one(struct ads1298_private *priv, int chan_index)
+{
+	int ret;
+
+	/* Enable the channel */
+	ret = regmap_update_bits(priv->regmap, ADS1298_REG_CHnSET(chan_index),
+				 ADS1298_MASK_CH_PD, 0);
+	if (ret)
+		return ret;
+
+	/* Enable single-shot mode, so we don't need to send a STOP */
+	ret = regmap_update_bits(priv->regmap, ADS1298_REG_CONFIG4,
+				 ADS1298_MASK_CONFIG4_SINGLE_SHOT,
+				 ADS1298_MASK_CONFIG4_SINGLE_SHOT);
+	if (ret)
+		return ret;
+
+	reinit_completion(&priv->completion);
+
+	ret = ads1298_write_cmd(priv, ADS1298_CMD_START);
+	if (ret < 0) {
+		dev_err(&priv->spi->dev, "CMD_START error: %d\n", ret);
+		return ret;
+	}
+
+	/* Cannot take longer than 40ms (250Hz) */
+	ret = wait_for_completion_timeout(&priv->completion, msecs_to_jiffies(50));
+	if (!ret)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int ads1298_get_samp_freq(struct ads1298_private *priv, int *val)
+{
+	unsigned long rate;
+	int ret;
+	unsigned int cfg;
+
+	ret = regmap_read(priv->regmap, ADS1298_REG_CONFIG1, &cfg);
+	if (ret)
+		return ret;
+
+	if (priv->clk)
+		rate = clk_get_rate(priv->clk);
+	else
+		rate = ADS1298_CLK_RATE_HZ;
+	if (!rate)
+		return -EINVAL;
+
+	/* Data rate shift depends on HR/LP mode */
+	if (cfg & ADS1298_MASK_CONFIG1_HR)
+		rate >>= ADS1298_SHIFT_DR_HR;
+	else
+		rate >>= ADS1298_SHIFT_DR_LP;
+
+	*val = rate >> (cfg & ADS1298_MASK_CONFIG1_DR);
+
+	return IIO_VAL_INT;
+}
+
+static int ads1298_set_samp_freq(struct ads1298_private *priv, int val)
+{
+	unsigned long rate;
+	unsigned int factor;
+	unsigned int cfg;
+
+	if (priv->clk)
+		rate = clk_get_rate(priv->clk);
+	else
+		rate = ADS1298_CLK_RATE_HZ;
+	if (!rate)
+		return -EINVAL;
+
+	factor = (rate >> ADS1298_SHIFT_DR_HR) / val;
+	if (factor >= 128)
+		cfg = ADS1298_LOWEST_DR;
+	else if (factor)
+		cfg = ADS1298_MASK_CONFIG1_HR | ilog2(factor); /* Use HR mode */
+	else
+		cfg = ADS1298_MASK_CONFIG1_HR; /* Fastest possible */
+
+	return regmap_update_bits(priv->regmap, ADS1298_REG_CONFIG1,
+				  ADS1298_MASK_CONFIG1_HR | ADS1298_MASK_CONFIG1_DR,
+				  cfg);
+}
+
+static const u8 ads1298_pga_settings[] = { 6, 1, 2, 3, 4, 8, 12 };
+
+static int ads1298_get_scale(struct ads1298_private *priv,
+			     int channel, int *val, int *val2)
+{
+	int ret;
+	unsigned int regval;
+	u8 gain;
+
+	if (priv->reg_vref) {
+		ret = regulator_get_voltage(priv->reg_vref);
+		if (ret < 0)
+			return ret;
+
+		*val = ret / MILLI; /* Convert to millivolts */
+	} else {
+		ret = regmap_read(priv->regmap, ADS1298_REG_CONFIG3, &regval);
+		if (ret)
+			return ret;
+
+		/* Refererence in millivolts */
+		*val = regval & ADS1298_MASK_CONFIG3_VREF_4V ? 4000 : 2400;
+	}
+
+	ret = regmap_read(priv->regmap, ADS1298_REG_CHnSET(channel), &regval);
+	if (ret)
+		return ret;
+
+	gain = ads1298_pga_settings[FIELD_GET(ADS1298_MASK_CH_PGA, regval)];
+	*val /= gain; /* Full scale is VREF / gain */
+
+	*val2 = ADS1298_BITS_PER_SAMPLE - 1; /* Signed, hence the -1 */
+
+	return IIO_VAL_FRACTIONAL_LOG2;
+}
+
+static int ads1298_read_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int *val, int *val2, long mask)
+{
+	struct ads1298_private *priv = iio_priv(indio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = iio_device_claim_direct_mode(indio_dev);
+		if (ret)
+			return ret;
+
+		ret = ads1298_read_one(priv, chan->scan_index);
+
+		iio_device_release_direct_mode(indio_dev);
+
+		if (ret)
+			return ret;
+
+		*val = sign_extend32(get_unaligned_be24(priv->rx_buffer + chan->address),
+				     ADS1298_BITS_PER_SAMPLE - 1);
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		return ads1298_get_scale(priv, chan->channel, val, val2);
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		return ads1298_get_samp_freq(priv, val);
+	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+		ret = regmap_read(priv->regmap, ADS1298_REG_CONFIG1, val);
+		if (ret)
+			return ret;
+
+		*val = (16 << (*val & ADS1298_MASK_CONFIG1_DR));
+		return IIO_VAL_INT;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int ads1298_write_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan, int val,
+			     int val2, long mask)
+{
+	struct ads1298_private *priv = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		return ads1298_set_samp_freq(priv, val);
+	default:
+		return -EINVAL;
+	}
+}
+
+static int ads1298_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+	struct ads1298_private *priv = context;
+	struct spi_transfer reg_write_xfer = {
+		.tx_buf = priv->cmd_buffer,
+		.rx_buf = priv->cmd_buffer,
+		.len = 3,
+		.speed_hz = ADS1298_SPI_BUS_SPEED_SLOW,
+		.delay = {
+			.value = 2,
+			.unit = SPI_DELAY_UNIT_USECS,
+		},
+	};
+
+	priv->cmd_buffer[0] = ADS1298_CMD_WREG | reg;
+	priv->cmd_buffer[1] = 0; /* Number of registers to be written - 1 */
+	priv->cmd_buffer[2] = val;
+
+	return spi_sync_transfer(priv->spi, &reg_write_xfer, 1);
+}
+
+static int ads1298_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+	struct ads1298_private *priv = context;
+	struct spi_transfer reg_read_xfer = {
+		.tx_buf = priv->cmd_buffer,
+		.rx_buf = priv->cmd_buffer,
+		.len = 3,
+		.speed_hz = ADS1298_SPI_BUS_SPEED_SLOW,
+		.delay = {
+			.value = 2,
+			.unit = SPI_DELAY_UNIT_USECS,
+		},
+	};
+	int ret;
+
+	priv->cmd_buffer[0] = ADS1298_CMD_RREG | reg;
+	priv->cmd_buffer[1] = 0; /* Number of registers to be read - 1 */
+	priv->cmd_buffer[2] = 0;
+
+	ret = spi_sync_transfer(priv->spi, &reg_read_xfer, 1);
+	if (ret)
+		return ret;
+
+	*val = priv->cmd_buffer[2];
+
+	return 0;
+}
+
+static int ads1298_reg_access(struct iio_dev *indio_dev, unsigned int reg,
+			      unsigned int writeval, unsigned int *readval)
+{
+	struct ads1298_private *priv = iio_priv(indio_dev);
+
+	if (readval)
+		return regmap_read(priv->regmap, reg, readval);
+
+	return regmap_write(priv->regmap, reg, writeval);
+}
+
+static void ads1298_rdata_unmark_busy(struct ads1298_private *priv)
+{
+	/* Notify we're no longer waiting for the SPI transfer to complete */
+	guard(spinlock_irqsave)(&priv->irq_busy_lock);
+	priv->rdata_xfer_busy = 0;
+}
+
+static int ads1298_update_scan_mode(struct iio_dev *indio_dev,
+				    const unsigned long *scan_mask)
+{
+	struct ads1298_private *priv = iio_priv(indio_dev);
+	unsigned int val;
+	int ret;
+	int i;
+
+	/* Make the interrupt routines start with a clean slate */
+	ads1298_rdata_unmark_busy(priv);
+
+	/* Configure power-down bits to match scan mask */
+	for (i = 0; i < ADS1298_MAX_CHANNELS; i++) {
+		val = test_bit(i, scan_mask) ? 0 : ADS1298_MASK_CH_PD;
+		ret = regmap_update_bits(priv->regmap, ADS1298_REG_CHnSET(i),
+					 ADS1298_MASK_CH_PD, val);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct iio_info ads1298_info = {
+	.read_raw = &ads1298_read_raw,
+	.write_raw = &ads1298_write_raw,
+	.update_scan_mode = &ads1298_update_scan_mode,
+	.debugfs_reg_access = &ads1298_reg_access,
+};
+
+static void ads1298_rdata_release_busy_or_restart(struct ads1298_private *priv)
+{
+	int wasbusy;
+
+	guard(spinlock_irqsave)(&priv->irq_busy_lock);
+
+	wasbusy = --priv->rdata_xfer_busy;
+	if (wasbusy) {
+		/*
+		 * DRDY interrupt occurred before SPI completion. Start a new
+		 * SPI transaction now to retrieve the data that wasn't latched
+		 * into the ADS1298 chip's transfer buffer yet.
+		 */
+		spi_async(priv->spi, &priv->rdata_msg);
+		/*
+		 * If more than one DRDY took place, there was an overrun. Since
+		 * the sample is already lost, reset the counter to 1 so that
+		 * we will wait for a DRDY interrupt after this SPI transaction.
+		 */
+		if (wasbusy > 1)
+			priv->rdata_xfer_busy = 1;
+	}
+}
+
+/* Called from SPI completion interrupt handler */
+static void ads1298_rdata_complete(void *context)
+{
+	struct iio_dev *indio_dev = context;
+	struct ads1298_private *priv = iio_priv(indio_dev);
+	int scan_index;
+	u32 *bounce = priv->bounce_buffer;
+
+	if (!iio_buffer_enabled(indio_dev)) {
+		/*
+		 * for a single transfer mode we're kept in direct_mode until
+		 * completion, avoiding a race with buffered IO.
+		 */
+		ads1298_rdata_unmark_busy(priv);
+		complete(&priv->completion);
+		return;
+	}
+
+	/* Demux the channel data into our bounce buffer */
+	for_each_set_bit(scan_index, indio_dev->active_scan_mask,
+			 indio_dev->masklength) {
+		const struct iio_chan_spec *scan_chan =
+					&indio_dev->channels[scan_index];
+		const u8 *data = priv->rx_buffer + scan_chan->address;
+
+		*bounce++ = get_unaligned_be24(data);
+	}
+
+	/* rx_buffer can be overwritten from this point on */
+	ads1298_rdata_release_busy_or_restart(priv);
+
+	iio_push_to_buffers(indio_dev, priv->bounce_buffer);
+}
+
+static irqreturn_t ads1298_interrupt(int irq, void *dev_id)
+{
+	struct iio_dev *indio_dev = dev_id;
+	struct ads1298_private *priv = iio_priv(indio_dev);
+	int wasbusy;
+
+	guard(spinlock_irqsave)(&priv->irq_busy_lock);
+
+	wasbusy = priv->rdata_xfer_busy++;
+	/* When no SPI transfer in transit, start one now */
+	if (!wasbusy)
+		spi_async(priv->spi, &priv->rdata_msg);
+
+	return IRQ_HANDLED;
+};
+
+static int ads1298_buffer_postenable(struct iio_dev *indio_dev)
+{
+	struct ads1298_private *priv = iio_priv(indio_dev);
+	int ret;
+
+	/* Disable single-shot mode */
+	ret = regmap_update_bits(priv->regmap, ADS1298_REG_CONFIG4,
+				 ADS1298_MASK_CONFIG4_SINGLE_SHOT, 0);
+	if (ret)
+		return ret;
+
+	return ads1298_write_cmd(priv, ADS1298_CMD_START);
+}
+
+static int ads1298_buffer_predisable(struct iio_dev *indio_dev)
+{
+	struct ads1298_private *priv = iio_priv(indio_dev);
+
+	return ads1298_write_cmd(priv, ADS1298_CMD_STOP);
+}
+
+static const struct iio_buffer_setup_ops ads1298_setup_ops = {
+	.postenable = &ads1298_buffer_postenable,
+	.predisable = &ads1298_buffer_predisable,
+};
+
+static void ads1298_reg_disable(void *reg)
+{
+	regulator_disable(reg);
+}
+
+static const struct regmap_range ads1298_regmap_volatile_range[] = {
+	regmap_reg_range(ADS1298_REG_LOFF_STATP, ADS1298_REG_LOFF_STATN),
+};
+
+static const struct regmap_access_table ads1298_regmap_volatile = {
+	.yes_ranges = ads1298_regmap_volatile_range,
+	.n_yes_ranges = ARRAY_SIZE(ads1298_regmap_volatile_range),
+};
+
+static const struct regmap_config ads1298_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.reg_read = ads1298_reg_read,
+	.reg_write = ads1298_reg_write,
+	.max_register = ADS1298_REG_WCT2,
+	.volatile_table = &ads1298_regmap_volatile,
+	.cache_type = REGCACHE_MAPLE,
+};
+
+static const char *ads1298_family_name(unsigned int id)
+{
+	switch (id & ADS1298_MASK_ID_FAMILY) {
+	case ADS1298_ID_FAMILY_ADS129X:
+		return "ADS129x";
+	case ADS1298_ID_FAMILY_ADS129XR:
+		return "ADS129xR";
+	default:
+		return "(unknown)";
+	}
+}
+
+static int ads1298_init(struct ads1298_private *priv)
+{
+	struct device *dev = &priv->spi->dev;
+	int ret;
+	unsigned int val;
+
+	/* Device initializes into RDATAC mode, which we don't want. */
+	ret = ads1298_write_cmd(priv, ADS1298_CMD_SDATAC);
+	if (ret)
+		return ret;
+
+	ret = regmap_read(priv->regmap, ADS1298_REG_ID, &val);
+	if (ret)
+		return ret;
+
+	dev_dbg(dev, "Found %s, %u channels\n", ads1298_family_name(val),
+		(unsigned int)(4 + 2 * (val & ADS1298_MASK_ID_CHANNELS)));
+
+	/* Enable internal test signal, double amplitude, double frequency */
+	ret = regmap_write(priv->regmap, ADS1298_REG_CONFIG2,
+			   ADS1298_MASK_CONFIG2_RESERVED |
+			   ADS1298_MASK_CONFIG2_INT_TEST |
+			   ADS1298_MASK_CONFIG2_TEST_AMP |
+			   ADS1298_MASK_CONFIG2_TEST_FREQ_FAST);
+	if (ret)
+		return ret;
+
+	val = ADS1298_MASK_CONFIG3_RESERVED; /* Must write 1 always */
+	if (!priv->reg_vref) {
+		/* Enable internal reference */
+		val |= ADS1298_MASK_CONFIG3_PWR_REFBUF;
+		/* Use 4V VREF when power supply is at least 4.4V */
+		if (regulator_get_voltage(priv->reg_avdd) >= 4400000)
+			val |= ADS1298_MASK_CONFIG3_VREF_4V;
+	}
+	return regmap_write(priv->regmap, ADS1298_REG_CONFIG3, val);
+}
+
+static int ads1298_probe(struct spi_device *spi)
+{
+	struct ads1298_private *priv;
+	struct iio_dev *indio_dev;
+	struct device *dev = &spi->dev;
+	struct gpio_desc *reset_gpio;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	priv = iio_priv(indio_dev);
+
+	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(reset_gpio))
+		return dev_err_probe(dev, ret, "Cannot get reset GPIO\n");
+
+	/* VREF can be supplied externally. Otherwise use internal reference */
+	priv->reg_vref = devm_regulator_get_optional(dev, "vref");
+	if (IS_ERR(priv->reg_vref)) {
+		if (PTR_ERR(priv->reg_vref) != -ENODEV)
+			return dev_err_probe(dev, PTR_ERR(priv->reg_avdd),
+					     "Failed to get vref regulator\n");
+
+		priv->reg_vref = NULL;
+	} else {
+		ret = regulator_enable(priv->reg_vref);
+		if (ret)
+			return ret;
+
+		ret = devm_add_action_or_reset(dev, ads1298_reg_disable,
+					       priv->reg_vref);
+		if (ret)
+			return ret;
+	}
+
+	priv->clk = devm_clk_get_optional_enabled(dev, "clk");
+	if (IS_ERR(priv->clk))
+		return dev_err_probe(dev, PTR_ERR(priv->clk), "Failed to get clk\n");
+
+	priv->reg_avdd = devm_regulator_get(dev, "avdd");
+	if (IS_ERR(priv->reg_avdd))
+		return dev_err_probe(dev, PTR_ERR(priv->reg_avdd),
+				     "Failed to get avdd regulator\n");
+
+	ret = regulator_enable(priv->reg_avdd);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to enable avdd regulator\n");
+
+	ret = devm_add_action_or_reset(dev, ads1298_reg_disable,
+				       priv->reg_avdd);
+	if (ret)
+		return ret;
+
+	priv->spi = spi;
+	init_completion(&priv->completion);
+	spin_lock_init(&priv->irq_busy_lock);
+	priv->regmap = devm_regmap_init(dev, NULL, priv, &ads1298_regmap_config);
+	if (IS_ERR(priv->regmap))
+		return PTR_ERR(priv->regmap);
+
+	priv->tx_buffer[0] = ADS1298_CMD_RDATA;
+	priv->rdata_xfer.tx_buf = priv->tx_buffer;
+	priv->rdata_xfer.rx_buf = priv->rx_buffer;
+	priv->rdata_xfer.len = ADS1298_SPI_RDATA_BUFFER_SIZE;
+	/* Must keep CS low for 4 clocks */
+	priv->rdata_xfer.delay.value = 2;
+	priv->rdata_xfer.delay.unit = SPI_DELAY_UNIT_USECS;
+	spi_message_init_with_transfers(&priv->rdata_msg, &priv->rdata_xfer, 1);
+	priv->rdata_msg.complete = &ads1298_rdata_complete;
+	priv->rdata_msg.context = indio_dev;
+
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
+	indio_dev->channels = ads1298_channels;
+	indio_dev->num_channels = ADS1298_MAX_CHANNELS;
+	indio_dev->info = &ads1298_info;
+
+	if (reset_gpio) {
+		/* Minimum reset pulsewidth is 2 clock cycles */
+		udelay(ADS1298_CLOCKS_TO_USECS(2));
+		gpiod_set_value(reset_gpio, 0);
+	} else {
+		ret = ads1298_write_cmd(priv, ADS1298_CMD_RESET);
+		if (ret)
+			return dev_err_probe(dev, ret, "RESET failed\n");
+	}
+	/* Wait 18 clock cycles for reset command to complete */
+	udelay(ADS1298_CLOCKS_TO_USECS(18));
+
+	ret = ads1298_init(priv);
+	if (ret)
+		return dev_err_probe(dev, ret, "Init failed\n");
+
+	ret = devm_request_irq(dev, spi->irq, &ads1298_interrupt,
+			       IRQF_TRIGGER_FALLING, indio_dev->name,
+			       indio_dev);
+	if (ret)
+		return ret;
+
+	ret = devm_iio_kfifo_buffer_setup(dev, indio_dev, &ads1298_setup_ops);
+	if (ret)
+		return ret;
+
+	return devm_iio_device_register(dev, indio_dev);
+}
+
+static const struct spi_device_id ads1298_id[] = {
+	{ "ads1298" },
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, ads1298_id);
+
+static const struct of_device_id ads1298_of_table[] = {
+	{ .compatible = "ti,ads1298" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ads1298_of_table);
+
+static struct spi_driver ads1298_driver = {
+	.driver = {
+		.name	= "ads1298",
+		.of_match_table = ads1298_of_table,
+	},
+	.probe		= ads1298_probe,
+	.id_table	= ads1298_id,
+};
+module_spi_driver(ads1298_driver);
+
+MODULE_AUTHOR("Mike Looijmans <mike.looijmans@topic.nl>");
+MODULE_DESCRIPTION("TI ADS1298 ADC");
+MODULE_LICENSE("GPL");