summaryrefslogtreecommitdiff
path: root/drivers/iio/adc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/adc')
-rw-r--r--drivers/iio/adc/Kconfig15
-rw-r--r--drivers/iio/adc/Makefile1
-rw-r--r--drivers/iio/adc/ad4130.c131
-rw-r--r--drivers/iio/adc/ad7091r-base.c25
-rw-r--r--drivers/iio/adc/ad9467.c267
-rw-r--r--drivers/iio/adc/ad_sigma_delta.c7
-rw-r--r--drivers/iio/adc/adi-axi-adc.c385
-rw-r--r--drivers/iio/adc/max1363.c171
-rw-r--r--drivers/iio/adc/rtq6056.c275
-rw-r--r--drivers/iio/adc/ti-adc108s102.c4
-rw-r--r--drivers/iio/adc/ti-ads1015.c2
-rw-r--r--drivers/iio/adc/ti-ads1298.c769
12 files changed, 1458 insertions, 594 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 3b73c509bd68..d4462c202784 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -291,7 +291,7 @@ config AD799X
config AD9467
tristate "Analog Devices AD9467 High Speed ADC driver"
depends on SPI
- depends on ADI_AXI_ADC
+ select IIO_BACKEND
help
Say yes here to build support for Analog Devices:
* AD9467 16-Bit, 200 MSPS/250 MSPS Analog-to-Digital Converter
@@ -309,7 +309,7 @@ config ADI_AXI_ADC
select IIO_BUFFER_HW_CONSUMER
select IIO_BUFFER_DMAENGINE
select REGMAP_MMIO
- depends on OF
+ select IIO_BACKEND
help
Say yes here to build support for Analog Devices Generic
AXI ADC IP core. The IP core is used for interfacing with
@@ -1312,6 +1312,17 @@ config TI_ADS1100
This driver can also be built as a module. If so, the module will be
called ti-ads1100.
+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_ADS7950
tristate "Texas Instruments ADS7950 ADC driver"
depends on SPI && GPIOLIB
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index d2fda54a3259..a64326f40fcb 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -116,6 +116,7 @@ obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o
obj-$(CONFIG_TI_ADC161S626) += ti-adc161s626.o
obj-$(CONFIG_TI_ADS1015) += ti-ads1015.o
obj-$(CONFIG_TI_ADS1100) += ti-ads1100.o
+obj-$(CONFIG_TI_ADS1298) += ti-ads1298.o
obj-$(CONFIG_TI_ADS7924) += ti-ads7924.o
obj-$(CONFIG_TI_ADS7950) += ti-ads7950.o
obj-$(CONFIG_TI_ADS8344) += ti-ads8344.o
diff --git a/drivers/iio/adc/ad4130.c b/drivers/iio/adc/ad4130.c
index 62490424b6ae..febb64e67955 100644
--- a/drivers/iio/adc/ad4130.c
+++ b/drivers/iio/adc/ad4130.c
@@ -887,9 +887,9 @@ static int ad4130_set_filter_mode(struct iio_dev *indio_dev,
unsigned int old_fs;
int ret = 0;
- mutex_lock(&st->lock);
+ guard(mutex)(&st->lock);
if (setup_info->filter_mode == val)
- goto out;
+ return 0;
old_fs = setup_info->fs;
old_filter_mode = setup_info->filter_mode;
@@ -911,12 +911,10 @@ static int ad4130_set_filter_mode(struct iio_dev *indio_dev,
if (ret) {
setup_info->fs = old_fs;
setup_info->filter_mode = old_filter_mode;
+ return ret;
}
- out:
- mutex_unlock(&st->lock);
-
- return ret;
+ return 0;
}
static int ad4130_get_filter_mode(struct iio_dev *indio_dev,
@@ -927,9 +925,8 @@ static int ad4130_get_filter_mode(struct iio_dev *indio_dev,
struct ad4130_setup_info *setup_info = &st->chans_info[channel].setup;
enum ad4130_filter_mode filter_mode;
- mutex_lock(&st->lock);
+ guard(mutex)(&st->lock);
filter_mode = setup_info->filter_mode;
- mutex_unlock(&st->lock);
return filter_mode;
}
@@ -971,7 +968,7 @@ static int ad4130_set_channel_pga(struct ad4130_state *st, unsigned int channel,
struct ad4130_chan_info *chan_info = &st->chans_info[channel];
struct ad4130_setup_info *setup_info = &chan_info->setup;
unsigned int pga, old_pga;
- int ret = 0;
+ int ret;
for (pga = 0; pga < AD4130_MAX_PGA; pga++)
if (val == st->scale_tbls[setup_info->ref_sel][pga][0] &&
@@ -981,21 +978,20 @@ static int ad4130_set_channel_pga(struct ad4130_state *st, unsigned int channel,
if (pga == AD4130_MAX_PGA)
return -EINVAL;
- mutex_lock(&st->lock);
+ guard(mutex)(&st->lock);
if (pga == setup_info->pga)
- goto out;
+ return 0;
old_pga = setup_info->pga;
setup_info->pga = pga;
ret = ad4130_write_channel_setup(st, channel, false);
- if (ret)
+ if (ret) {
setup_info->pga = old_pga;
+ return ret;
+ }
-out:
- mutex_unlock(&st->lock);
-
- return ret;
+ return 0;
}
static int ad4130_set_channel_freq(struct ad4130_state *st,
@@ -1004,26 +1000,25 @@ static int ad4130_set_channel_freq(struct ad4130_state *st,
struct ad4130_chan_info *chan_info = &st->chans_info[channel];
struct ad4130_setup_info *setup_info = &chan_info->setup;
unsigned int fs, old_fs;
- int ret = 0;
+ int ret;
- mutex_lock(&st->lock);
+ guard(mutex)(&st->lock);
old_fs = setup_info->fs;
ad4130_freq_to_fs(setup_info->filter_mode, val, val2, &fs);
if (fs == setup_info->fs)
- goto out;
+ return 0;
setup_info->fs = fs;
ret = ad4130_write_channel_setup(st, channel, false);
- if (ret)
+ if (ret) {
setup_info->fs = old_fs;
+ return ret;
+ }
-out:
- mutex_unlock(&st->lock);
-
- return ret;
+ return 0;
}
static int _ad4130_read_sample(struct iio_dev *indio_dev, unsigned int channel,
@@ -1065,20 +1060,13 @@ static int _ad4130_read_sample(struct iio_dev *indio_dev, unsigned int channel,
static int ad4130_read_sample(struct iio_dev *indio_dev, unsigned int channel,
int *val)
{
- struct ad4130_state *st = iio_priv(indio_dev);
- int ret;
-
- ret = iio_device_claim_direct_mode(indio_dev);
- if (ret)
- return ret;
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ struct ad4130_state *st = iio_priv(indio_dev);
- mutex_lock(&st->lock);
- ret = _ad4130_read_sample(indio_dev, channel, val);
- mutex_unlock(&st->lock);
-
- iio_device_release_direct_mode(indio_dev);
-
- return ret;
+ guard(mutex)(&st->lock);
+ return _ad4130_read_sample(indio_dev, channel, val);
+ }
+ unreachable();
}
static int ad4130_read_raw(struct iio_dev *indio_dev,
@@ -1092,24 +1080,24 @@ static int ad4130_read_raw(struct iio_dev *indio_dev,
switch (info) {
case IIO_CHAN_INFO_RAW:
return ad4130_read_sample(indio_dev, channel, val);
- case IIO_CHAN_INFO_SCALE:
- mutex_lock(&st->lock);
+ case IIO_CHAN_INFO_SCALE: {
+ guard(mutex)(&st->lock);
*val = st->scale_tbls[setup_info->ref_sel][setup_info->pga][0];
*val2 = st->scale_tbls[setup_info->ref_sel][setup_info->pga][1];
- mutex_unlock(&st->lock);
return IIO_VAL_INT_PLUS_NANO;
+ }
case IIO_CHAN_INFO_OFFSET:
*val = st->bipolar ? -BIT(chan->scan_type.realbits - 1) : 0;
return IIO_VAL_INT;
- case IIO_CHAN_INFO_SAMP_FREQ:
- mutex_lock(&st->lock);
+ case IIO_CHAN_INFO_SAMP_FREQ: {
+ guard(mutex)(&st->lock);
ad4130_fs_to_freq(setup_info->filter_mode, setup_info->fs,
val, val2);
- mutex_unlock(&st->lock);
return IIO_VAL_INT_PLUS_NANO;
+ }
default:
return -EINVAL;
}
@@ -1134,9 +1122,9 @@ static int ad4130_read_avail(struct iio_dev *indio_dev,
return IIO_AVAIL_LIST;
case IIO_CHAN_INFO_SAMP_FREQ:
- mutex_lock(&st->lock);
- filter_config = &ad4130_filter_configs[setup_info->filter_mode];
- mutex_unlock(&st->lock);
+ scoped_guard(mutex, &st->lock) {
+ filter_config = &ad4130_filter_configs[setup_info->filter_mode];
+ }
*vals = (int *)filter_config->samp_freq_avail;
*length = filter_config->samp_freq_avail_len * 2;
@@ -1197,21 +1185,18 @@ static int ad4130_update_scan_mode(struct iio_dev *indio_dev,
unsigned int val = 0;
int ret;
- mutex_lock(&st->lock);
+ guard(mutex)(&st->lock);
for_each_set_bit(channel, scan_mask, indio_dev->num_channels) {
ret = ad4130_set_channel_enable(st, channel, true);
if (ret)
- goto out;
+ return ret;
val++;
}
st->num_enabled_channels = val;
-out:
- mutex_unlock(&st->lock);
-
return 0;
}
@@ -1232,22 +1217,19 @@ static int ad4130_set_fifo_watermark(struct iio_dev *indio_dev, unsigned int val
*/
eff = rounddown(AD4130_FIFO_SIZE, st->num_enabled_channels);
- mutex_lock(&st->lock);
+ guard(mutex)(&st->lock);
ret = regmap_update_bits(st->regmap, AD4130_FIFO_CONTROL_REG,
AD4130_FIFO_CONTROL_WM_MASK,
FIELD_PREP(AD4130_FIFO_CONTROL_WM_MASK,
ad4130_watermark_reg_val(eff)));
if (ret)
- goto out;
+ return ret;
st->effective_watermark = eff;
st->watermark = val;
-out:
- mutex_unlock(&st->lock);
-
- return ret;
+ return 0;
}
static const struct iio_info ad4130_info = {
@@ -1265,26 +1247,21 @@ static int ad4130_buffer_postenable(struct iio_dev *indio_dev)
struct ad4130_state *st = iio_priv(indio_dev);
int ret;
- mutex_lock(&st->lock);
+ guard(mutex)(&st->lock);
ret = ad4130_set_watermark_interrupt_en(st, true);
if (ret)
- goto out;
+ return ret;
ret = irq_set_irq_type(st->spi->irq, st->inv_irq_trigger);
if (ret)
- goto out;
+ return ret;
ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_WM);
if (ret)
- goto out;
-
- ret = ad4130_set_mode(st, AD4130_MODE_CONTINUOUS);
-
-out:
- mutex_unlock(&st->lock);
+ return ret;
- return ret;
+ return ad4130_set_mode(st, AD4130_MODE_CONTINUOUS);
}
static int ad4130_buffer_predisable(struct iio_dev *indio_dev)
@@ -1293,23 +1270,23 @@ static int ad4130_buffer_predisable(struct iio_dev *indio_dev)
unsigned int i;
int ret;
- mutex_lock(&st->lock);
+ guard(mutex)(&st->lock);
ret = ad4130_set_mode(st, AD4130_MODE_IDLE);
if (ret)
- goto out;
+ return ret;
ret = irq_set_irq_type(st->spi->irq, st->irq_trigger);
if (ret)
- goto out;
+ return ret;
ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_DISABLED);
if (ret)
- goto out;
+ return ret;
ret = ad4130_set_watermark_interrupt_en(st, false);
if (ret)
- goto out;
+ return ret;
/*
* update_scan_mode() is not called in the disable path, disable all
@@ -1318,13 +1295,10 @@ static int ad4130_buffer_predisable(struct iio_dev *indio_dev)
for (i = 0; i < indio_dev->num_channels; i++) {
ret = ad4130_set_channel_enable(st, i, false);
if (ret)
- goto out;
+ return ret;
}
-out:
- mutex_unlock(&st->lock);
-
- return ret;
+ return 0;
}
static const struct iio_buffer_setup_ops ad4130_buffer_ops = {
@@ -1338,9 +1312,8 @@ static ssize_t hwfifo_watermark_show(struct device *dev,
struct ad4130_state *st = iio_priv(dev_to_iio_dev(dev));
unsigned int val;
- mutex_lock(&st->lock);
+ guard(mutex)(&st->lock);
val = st->watermark;
- mutex_unlock(&st->lock);
return sysfs_emit(buf, "%d\n", val);
}
diff --git a/drivers/iio/adc/ad7091r-base.c b/drivers/iio/adc/ad7091r-base.c
index f4255b91acfc..d6876259ad14 100644
--- a/drivers/iio/adc/ad7091r-base.c
+++ b/drivers/iio/adc/ad7091r-base.c
@@ -86,28 +86,25 @@ static int ad7091r_read_raw(struct iio_dev *iio_dev,
unsigned int read_val;
int ret;
- mutex_lock(&st->lock);
+ guard(mutex)(&st->lock);
switch (m) {
case IIO_CHAN_INFO_RAW:
- if (st->mode != AD7091R_MODE_COMMAND) {
- ret = -EBUSY;
- goto unlock;
- }
+ if (st->mode != AD7091R_MODE_COMMAND)
+ return -EBUSY;
ret = ad7091r_read_one(iio_dev, chan->channel, &read_val);
if (ret)
- goto unlock;
+ return ret;
*val = read_val;
- ret = IIO_VAL_INT;
- break;
+ return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
if (st->vref) {
ret = regulator_get_voltage(st->vref);
if (ret < 0)
- goto unlock;
+ return ret;
*val = ret / 1000;
} else {
@@ -115,17 +112,11 @@ static int ad7091r_read_raw(struct iio_dev *iio_dev,
}
*val2 = chan->scan_type.realbits;
- ret = IIO_VAL_FRACTIONAL_LOG2;
- break;
+ return IIO_VAL_FRACTIONAL_LOG2;
default:
- ret = -EINVAL;
- break;
+ return -EINVAL;
}
-
-unlock:
- mutex_unlock(&st->lock);
- return ret;
}
static int ad7091r_read_event_config(struct iio_dev *indio_dev,
diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c
index 6581fce4ba95..7475ec2a56c7 100644
--- a/drivers/iio/adc/ad9467.c
+++ b/drivers/iio/adc/ad9467.c
@@ -17,13 +17,12 @@
#include <linux/of.h>
+#include <linux/iio/backend.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/clk.h>
-#include <linux/iio/adc/adi-axi-adc.h>
-
/*
* ADI High-Speed ADC common spi interface registers
* See Application-Note AN-877:
@@ -102,15 +101,20 @@
#define AD9467_REG_VREF_MASK 0x0F
struct ad9467_chip_info {
- struct adi_axi_adc_chip_info axi_adc_info;
- unsigned int default_output_mode;
- unsigned int vref_mask;
+ const char *name;
+ unsigned int id;
+ const struct iio_chan_spec *channels;
+ unsigned int num_channels;
+ const unsigned int (*scale_table)[2];
+ int num_scales;
+ unsigned long max_rate;
+ unsigned int default_output_mode;
+ unsigned int vref_mask;
};
-#define to_ad9467_chip_info(_info) \
- container_of(_info, struct ad9467_chip_info, axi_adc_info)
-
struct ad9467_state {
+ const struct ad9467_chip_info *info;
+ struct iio_backend *back;
struct spi_device *spi;
struct clk *clk;
unsigned int output_mode;
@@ -151,10 +155,10 @@ static int ad9467_spi_write(struct spi_device *spi, unsigned int reg,
return spi_write(spi, buf, ARRAY_SIZE(buf));
}
-static int ad9467_reg_access(struct adi_axi_adc_conv *conv, unsigned int reg,
+static int ad9467_reg_access(struct iio_dev *indio_dev, unsigned int reg,
unsigned int writeval, unsigned int *readval)
{
- struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
+ struct ad9467_state *st = iio_priv(indio_dev);
struct spi_device *spi = st->spi;
int ret;
@@ -191,10 +195,10 @@ static const unsigned int ad9467_scale_table[][2] = {
{2300, 8}, {2400, 9}, {2500, 10},
};
-static void __ad9467_get_scale(struct adi_axi_adc_conv *conv, int index,
+static void __ad9467_get_scale(struct ad9467_state *st, int index,
unsigned int *val, unsigned int *val2)
{
- const struct adi_axi_adc_chip_info *info = conv->chip_info;
+ const struct ad9467_chip_info *info = st->info;
const struct iio_chan_spec *chan = &info->channels[0];
unsigned int tmp;
@@ -229,52 +233,44 @@ static const struct iio_chan_spec ad9467_channels[] = {
};
static const struct ad9467_chip_info ad9467_chip_tbl = {
- .axi_adc_info = {
- .name = "ad9467",
- .id = CHIPID_AD9467,
- .max_rate = 250000000UL,
- .scale_table = ad9467_scale_table,
- .num_scales = ARRAY_SIZE(ad9467_scale_table),
- .channels = ad9467_channels,
- .num_channels = ARRAY_SIZE(ad9467_channels),
- },
+ .name = "ad9467",
+ .id = CHIPID_AD9467,
+ .max_rate = 250000000UL,
+ .scale_table = ad9467_scale_table,
+ .num_scales = ARRAY_SIZE(ad9467_scale_table),
+ .channels = ad9467_channels,
+ .num_channels = ARRAY_SIZE(ad9467_channels),
.default_output_mode = AD9467_DEF_OUTPUT_MODE,
.vref_mask = AD9467_REG_VREF_MASK,
};
static const struct ad9467_chip_info ad9434_chip_tbl = {
- .axi_adc_info = {
- .name = "ad9434",
- .id = CHIPID_AD9434,
- .max_rate = 500000000UL,
- .scale_table = ad9434_scale_table,
- .num_scales = ARRAY_SIZE(ad9434_scale_table),
- .channels = ad9434_channels,
- .num_channels = ARRAY_SIZE(ad9434_channels),
- },
+ .name = "ad9434",
+ .id = CHIPID_AD9434,
+ .max_rate = 500000000UL,
+ .scale_table = ad9434_scale_table,
+ .num_scales = ARRAY_SIZE(ad9434_scale_table),
+ .channels = ad9434_channels,
+ .num_channels = ARRAY_SIZE(ad9434_channels),
.default_output_mode = AD9434_DEF_OUTPUT_MODE,
.vref_mask = AD9434_REG_VREF_MASK,
};
static const struct ad9467_chip_info ad9265_chip_tbl = {
- .axi_adc_info = {
- .name = "ad9265",
- .id = CHIPID_AD9265,
- .max_rate = 125000000UL,
- .scale_table = ad9265_scale_table,
- .num_scales = ARRAY_SIZE(ad9265_scale_table),
- .channels = ad9467_channels,
- .num_channels = ARRAY_SIZE(ad9467_channels),
- },
+ .name = "ad9265",
+ .id = CHIPID_AD9265,
+ .max_rate = 125000000UL,
+ .scale_table = ad9265_scale_table,
+ .num_scales = ARRAY_SIZE(ad9265_scale_table),
+ .channels = ad9467_channels,
+ .num_channels = ARRAY_SIZE(ad9467_channels),
.default_output_mode = AD9265_DEF_OUTPUT_MODE,
.vref_mask = AD9265_REG_VREF_MASK,
};
-static int ad9467_get_scale(struct adi_axi_adc_conv *conv, int *val, int *val2)
+static int ad9467_get_scale(struct ad9467_state *st, int *val, int *val2)
{
- const struct adi_axi_adc_chip_info *info = conv->chip_info;
- const struct ad9467_chip_info *info1 = to_ad9467_chip_info(info);
- struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
+ const struct ad9467_chip_info *info = st->info;
unsigned int i, vref_val;
int ret;
@@ -282,7 +278,7 @@ static int ad9467_get_scale(struct adi_axi_adc_conv *conv, int *val, int *val2)
if (ret < 0)
return ret;
- vref_val = ret & info1->vref_mask;
+ vref_val = ret & info->vref_mask;
for (i = 0; i < info->num_scales; i++) {
if (vref_val == info->scale_table[i][1])
@@ -292,15 +288,14 @@ static int ad9467_get_scale(struct adi_axi_adc_conv *conv, int *val, int *val2)
if (i == info->num_scales)
return -ERANGE;
- __ad9467_get_scale(conv, i, val, val2);
+ __ad9467_get_scale(st, i, val, val2);
return IIO_VAL_INT_PLUS_MICRO;
}
-static int ad9467_set_scale(struct adi_axi_adc_conv *conv, int val, int val2)
+static int ad9467_set_scale(struct ad9467_state *st, int val, int val2)
{
- const struct adi_axi_adc_chip_info *info = conv->chip_info;
- struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
+ const struct ad9467_chip_info *info = st->info;
unsigned int scale_val[2];
unsigned int i;
int ret;
@@ -309,7 +304,7 @@ static int ad9467_set_scale(struct adi_axi_adc_conv *conv, int val, int val2)
return -EINVAL;
for (i = 0; i < info->num_scales; i++) {
- __ad9467_get_scale(conv, i, &scale_val[0], &scale_val[1]);
+ __ad9467_get_scale(st, i, &scale_val[0], &scale_val[1]);
if (scale_val[0] != val || scale_val[1] != val2)
continue;
@@ -326,15 +321,15 @@ static int ad9467_set_scale(struct adi_axi_adc_conv *conv, int val, int val2)
return -EINVAL;
}
-static int ad9467_read_raw(struct adi_axi_adc_conv *conv,
+static int ad9467_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long m)
{
- struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
+ struct ad9467_state *st = iio_priv(indio_dev);
switch (m) {
case IIO_CHAN_INFO_SCALE:
- return ad9467_get_scale(conv, val, val2);
+ return ad9467_get_scale(st, val, val2);
case IIO_CHAN_INFO_SAMP_FREQ:
*val = clk_get_rate(st->clk);
@@ -344,17 +339,17 @@ static int ad9467_read_raw(struct adi_axi_adc_conv *conv,
}
}
-static int ad9467_write_raw(struct adi_axi_adc_conv *conv,
+static int ad9467_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
- const struct adi_axi_adc_chip_info *info = conv->chip_info;
- struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
+ struct ad9467_state *st = iio_priv(indio_dev);
+ const struct ad9467_chip_info *info = st->info;
long r_clk;
switch (mask) {
case IIO_CHAN_INFO_SCALE:
- return ad9467_set_scale(conv, val, val2);
+ return ad9467_set_scale(st, val, val2);
case IIO_CHAN_INFO_SAMP_FREQ:
r_clk = clk_round_rate(st->clk, val);
if (r_clk < 0 || r_clk > info->max_rate) {
@@ -369,13 +364,13 @@ static int ad9467_write_raw(struct adi_axi_adc_conv *conv,
}
}
-static int ad9467_read_avail(struct adi_axi_adc_conv *conv,
+static int ad9467_read_avail(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
const int **vals, int *type, int *length,
long mask)
{
- const struct adi_axi_adc_chip_info *info = conv->chip_info;
- struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
+ struct ad9467_state *st = iio_priv(indio_dev);
+ const struct ad9467_chip_info *info = st->info;
switch (mask) {
case IIO_CHAN_INFO_SCALE:
@@ -389,6 +384,33 @@ static int ad9467_read_avail(struct adi_axi_adc_conv *conv,
}
}
+static int ad9467_update_scan_mode(struct iio_dev *indio_dev,
+ const unsigned long *scan_mask)
+{
+ struct ad9467_state *st = iio_priv(indio_dev);
+ unsigned int c;
+ int ret;
+
+ for (c = 0; c < st->info->num_channels; c++) {
+ if (test_bit(c, scan_mask))
+ ret = iio_backend_chan_enable(st->back, c);
+ else
+ ret = iio_backend_chan_disable(st->back, c);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct iio_info ad9467_info = {
+ .read_raw = ad9467_read_raw,
+ .write_raw = ad9467_write_raw,
+ .update_scan_mode = ad9467_update_scan_mode,
+ .debugfs_reg_access = ad9467_reg_access,
+ .read_avail = ad9467_read_avail,
+};
+
static int ad9467_outputmode_set(struct spi_device *spi, unsigned int mode)
{
int ret;
@@ -401,10 +423,9 @@ static int ad9467_outputmode_set(struct spi_device *spi, unsigned int mode)
AN877_ADC_TRANSFER_SYNC);
}
-static int ad9467_scale_fill(struct adi_axi_adc_conv *conv)
+static int ad9467_scale_fill(struct ad9467_state *st)
{
- const struct adi_axi_adc_chip_info *info = conv->chip_info;
- struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
+ const struct ad9467_chip_info *info = st->info;
unsigned int i, val1, val2;
st->scales = devm_kmalloc_array(&st->spi->dev, info->num_scales,
@@ -413,7 +434,7 @@ static int ad9467_scale_fill(struct adi_axi_adc_conv *conv)
return -ENOMEM;
for (i = 0; i < info->num_scales; i++) {
- __ad9467_get_scale(conv, i, &val1, &val2);
+ __ad9467_get_scale(st, i, &val1, &val2);
st->scales[i][0] = val1;
st->scales[i][1] = val2;
}
@@ -421,11 +442,27 @@ static int ad9467_scale_fill(struct adi_axi_adc_conv *conv)
return 0;
}
-static int ad9467_preenable_setup(struct adi_axi_adc_conv *conv)
+static int ad9467_setup(struct ad9467_state *st)
{
- struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
+ struct iio_backend_data_fmt data = {
+ .sign_extend = true,
+ .enable = true,
+ };
+ unsigned int c, mode;
+ int ret;
+
+ mode = st->info->default_output_mode | AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT;
+ ret = ad9467_outputmode_set(st->spi, mode);
+ if (ret)
+ return ret;
- return ad9467_outputmode_set(st->spi, st->output_mode);
+ for (c = 0; c < st->info->num_channels; c++) {
+ ret = iio_backend_data_format_set(st->back, c, &data);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
}
static int ad9467_reset(struct device *dev)
@@ -443,25 +480,65 @@ static int ad9467_reset(struct device *dev)
return 0;
}
+static int ad9467_iio_backend_get(struct ad9467_state *st)
+{
+ struct device *dev = &st->spi->dev;
+ struct device_node *__back;
+
+ st->back = devm_iio_backend_get(dev, NULL);
+ if (!IS_ERR(st->back))
+ return 0;
+ /* If not found, don't error out as we might have legacy DT property */
+ if (PTR_ERR(st->back) != -ENOENT)
+ return PTR_ERR(st->back);
+
+ /*
+ * if we don't get the backend using the normal API's, use the legacy
+ * 'adi,adc-dev' property. So we get all nodes with that property, and
+ * look for the one pointing at us. Then we directly lookup that fwnode
+ * on the backend list of registered devices. This is done so we don't
+ * make io-backends mandatory which would break DT ABI.
+ */
+ for_each_node_with_property(__back, "adi,adc-dev") {
+ struct device_node *__me;
+
+ __me = of_parse_phandle(__back, "adi,adc-dev", 0);
+ if (!__me)
+ continue;
+
+ if (!device_match_of_node(dev, __me)) {
+ of_node_put(__me);
+ continue;
+ }
+
+ of_node_put(__me);
+ st->back = __devm_iio_backend_get_from_fwnode_lookup(dev,
+ of_fwnode_handle(__back));
+ of_node_put(__back);
+ return PTR_ERR_OR_ZERO(st->back);
+ }
+
+ return -ENODEV;
+}
+
static int ad9467_probe(struct spi_device *spi)
{
- const struct ad9467_chip_info *info;
- struct adi_axi_adc_conv *conv;
+ struct iio_dev *indio_dev;
struct ad9467_state *st;
unsigned int id;
int ret;
- info = spi_get_device_match_data(spi);
- if (!info)
- return -ENODEV;
-
- conv = devm_adi_axi_adc_conv_register(&spi->dev, sizeof(*st));
- if (IS_ERR(conv))
- return PTR_ERR(conv);
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
- st = adi_axi_adc_conv_priv(conv);
+ st = iio_priv(indio_dev);
st->spi = spi;
+ st->info = spi_get_device_match_data(spi);
+ if (!st->info)
+ return -ENODEV;
+
st->clk = devm_clk_get_enabled(&spi->dev, "adc-clk");
if (IS_ERR(st->clk))
return PTR_ERR(st->clk);
@@ -475,29 +552,39 @@ static int ad9467_probe(struct spi_device *spi)
if (ret)
return ret;
- conv->chip_info = &info->axi_adc_info;
-
- ret = ad9467_scale_fill(conv);
+ ret = ad9467_scale_fill(st);
if (ret)
return ret;
id = ad9467_spi_read(spi, AN877_ADC_REG_CHIP_ID);
- if (id != conv->chip_info->id) {
+ if (id != st->info->id) {
dev_err(&spi->dev, "Mismatch CHIP_ID, got 0x%X, expected 0x%X\n",
- id, conv->chip_info->id);
+ id, st->info->id);
return -ENODEV;
}
- conv->reg_access = ad9467_reg_access;
- conv->write_raw = ad9467_write_raw;
- conv->read_raw = ad9467_read_raw;
- conv->read_avail = ad9467_read_avail;
- conv->preenable_setup = ad9467_preenable_setup;
+ indio_dev->name = st->info->name;
+ indio_dev->channels = st->info->channels;
+ indio_dev->num_channels = st->info->num_channels;
+ indio_dev->info = &ad9467_info;
- st->output_mode = info->default_output_mode |
- AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT;
+ ret = ad9467_iio_backend_get(st);
+ if (ret)
+ return ret;
- return 0;
+ ret = devm_iio_backend_request_buffer(&spi->dev, st->back, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_backend_enable(&spi->dev, st->back);
+ if (ret)
+ return ret;
+
+ ret = ad9467_setup(st);
+ if (ret)
+ return ret;
+
+ return devm_iio_device_register(&spi->dev, indio_dev);
}
static const struct of_device_id ad9467_of_match[] = {
@@ -529,4 +616,4 @@ module_spi_driver(ad9467_driver);
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD9467 ADC driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ADI_AXI);
+MODULE_IMPORT_NS(IIO_BACKEND);
diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
index 7e2192870743..fbba3f4a1189 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -568,6 +568,7 @@ EXPORT_SYMBOL_NS_GPL(ad_sd_validate_trigger, IIO_AD_SIGMA_DELTA);
static int devm_ad_sd_probe_trigger(struct device *dev, struct iio_dev *indio_dev)
{
struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
+ unsigned long irq_flags = irq_get_trigger_type(sigma_delta->spi->irq);
int ret;
if (dev != &sigma_delta->spi->dev) {
@@ -588,9 +589,13 @@ static int devm_ad_sd_probe_trigger(struct device *dev, struct iio_dev *indio_de
/* the IRQ core clears IRQ_DISABLE_UNLAZY flag when freeing an IRQ */
irq_set_status_flags(sigma_delta->spi->irq, IRQ_DISABLE_UNLAZY);
+ /* Allow overwriting the flags from firmware */
+ if (!irq_flags)
+ irq_flags = sigma_delta->info->irq_flags;
+
ret = devm_request_irq(dev, sigma_delta->spi->irq,
ad_sd_data_rdy_trig_poll,
- sigma_delta->info->irq_flags | IRQF_NO_AUTOEN,
+ irq_flags | IRQF_NO_AUTOEN,
indio_dev->name,
sigma_delta);
if (ret)
diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
index c247ff1541d2..4156639b3c8b 100644
--- a/drivers/iio/adc/adi-axi-adc.c
+++ b/drivers/iio/adc/adi-axi-adc.c
@@ -8,6 +8,7 @@
#include <linux/bitfield.h>
#include <linux/clk.h>
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/module.h>
@@ -17,13 +18,12 @@
#include <linux/regmap.h>
#include <linux/slab.h>
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-#include <linux/iio/buffer.h>
-#include <linux/iio/buffer-dmaengine.h>
-
#include <linux/fpga/adi-axi-common.h>
-#include <linux/iio/adc/adi-axi-adc.h>
+
+#include <linux/iio/backend.h>
+#include <linux/iio/buffer-dmaengine.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
/*
* Register definitions:
@@ -44,6 +44,7 @@
#define ADI_AXI_REG_CHAN_CTRL_PN_SEL_OWR BIT(10)
#define ADI_AXI_REG_CHAN_CTRL_IQCOR_EN BIT(9)
#define ADI_AXI_REG_CHAN_CTRL_DCFILT_EN BIT(8)
+#define ADI_AXI_REG_CHAN_CTRL_FMT_MASK GENMASK(6, 4)
#define ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT BIT(6)
#define ADI_AXI_REG_CHAN_CTRL_FMT_TYPE BIT(5)
#define ADI_AXI_REG_CHAN_CTRL_FMT_EN BIT(4)
@@ -55,286 +56,100 @@
ADI_AXI_REG_CHAN_CTRL_FMT_EN | \
ADI_AXI_REG_CHAN_CTRL_ENABLE)
-struct adi_axi_adc_core_info {
- unsigned int version;
-};
-
struct adi_axi_adc_state {
- struct mutex lock;
-
- struct adi_axi_adc_client *client;
struct regmap *regmap;
-};
-
-struct adi_axi_adc_client {
- struct list_head entry;
- struct adi_axi_adc_conv conv;
- struct adi_axi_adc_state *state;
struct device *dev;
- const struct adi_axi_adc_core_info *info;
};
-static LIST_HEAD(registered_clients);
-static DEFINE_MUTEX(registered_clients_lock);
-
-static struct adi_axi_adc_client *conv_to_client(struct adi_axi_adc_conv *conv)
-{
- return container_of(conv, struct adi_axi_adc_client, conv);
-}
-
-void *adi_axi_adc_conv_priv(struct adi_axi_adc_conv *conv)
-{
- struct adi_axi_adc_client *cl = conv_to_client(conv);
-
- return (char *)cl + ALIGN(sizeof(struct adi_axi_adc_client),
- IIO_DMA_MINALIGN);
-}
-EXPORT_SYMBOL_NS_GPL(adi_axi_adc_conv_priv, IIO_ADI_AXI);
-
-static int adi_axi_adc_config_dma_buffer(struct device *dev,
- struct iio_dev *indio_dev)
-{
- const char *dma_name;
-
- if (!device_property_present(dev, "dmas"))
- return 0;
-
- if (device_property_read_string(dev, "dma-names", &dma_name))
- dma_name = "rx";
-
- return devm_iio_dmaengine_buffer_setup(indio_dev->dev.parent,
- indio_dev, dma_name);
-}
-
-static int adi_axi_adc_read_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int *val, int *val2, long mask)
-{
- struct adi_axi_adc_state *st = iio_priv(indio_dev);
- struct adi_axi_adc_conv *conv = &st->client->conv;
-
- if (!conv->read_raw)
- return -EOPNOTSUPP;
-
- return conv->read_raw(conv, chan, val, val2, mask);
-}
-
-static int adi_axi_adc_write_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int val, int val2, long mask)
-{
- struct adi_axi_adc_state *st = iio_priv(indio_dev);
- struct adi_axi_adc_conv *conv = &st->client->conv;
-
- if (!conv->write_raw)
- return -EOPNOTSUPP;
-
- return conv->write_raw(conv, chan, val, val2, mask);
-}
-
-static int adi_axi_adc_read_avail(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- const int **vals, int *type, int *length,
- long mask)
-{
- struct adi_axi_adc_state *st = iio_priv(indio_dev);
- struct adi_axi_adc_conv *conv = &st->client->conv;
-
- if (!conv->read_avail)
- return -EOPNOTSUPP;
-
- return conv->read_avail(conv, chan, vals, type, length, mask);
-}
-
-static int adi_axi_adc_update_scan_mode(struct iio_dev *indio_dev,
- const unsigned long *scan_mask)
+static int axi_adc_enable(struct iio_backend *back)
{
- struct adi_axi_adc_state *st = iio_priv(indio_dev);
- struct adi_axi_adc_conv *conv = &st->client->conv;
- unsigned int i;
+ struct adi_axi_adc_state *st = iio_backend_get_priv(back);
int ret;
- for (i = 0; i < conv->chip_info->num_channels; i++) {
- if (test_bit(i, scan_mask))
- ret = regmap_set_bits(st->regmap,
- ADI_AXI_REG_CHAN_CTRL(i),
- ADI_AXI_REG_CHAN_CTRL_ENABLE);
- else
- ret = regmap_clear_bits(st->regmap,
- ADI_AXI_REG_CHAN_CTRL(i),
- ADI_AXI_REG_CHAN_CTRL_ENABLE);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-static struct adi_axi_adc_conv *adi_axi_adc_conv_register(struct device *dev,
- size_t sizeof_priv)
-{
- struct adi_axi_adc_client *cl;
- size_t alloc_size;
-
- alloc_size = ALIGN(sizeof(struct adi_axi_adc_client), IIO_DMA_MINALIGN);
- if (sizeof_priv)
- alloc_size += ALIGN(sizeof_priv, IIO_DMA_MINALIGN);
-
- cl = kzalloc(alloc_size, GFP_KERNEL);
- if (!cl)
- return ERR_PTR(-ENOMEM);
-
- mutex_lock(&registered_clients_lock);
-
- cl->dev = get_device(dev);
-
- list_add_tail(&cl->entry, &registered_clients);
-
- mutex_unlock(&registered_clients_lock);
+ ret = regmap_set_bits(st->regmap, ADI_AXI_REG_RSTN,
+ ADI_AXI_REG_RSTN_MMCM_RSTN);
+ if (ret)
+ return ret;
- return &cl->conv;
+ fsleep(10000);
+ return regmap_set_bits(st->regmap, ADI_AXI_REG_RSTN,
+ ADI_AXI_REG_RSTN_RSTN | ADI_AXI_REG_RSTN_MMCM_RSTN);
}
-static void adi_axi_adc_conv_unregister(struct adi_axi_adc_conv *conv)
+static void axi_adc_disable(struct iio_backend *back)
{
- struct adi_axi_adc_client *cl = conv_to_client(conv);
-
- mutex_lock(&registered_clients_lock);
-
- list_del(&cl->entry);
- put_device(cl->dev);
+ struct adi_axi_adc_state *st = iio_backend_get_priv(back);
- mutex_unlock(&registered_clients_lock);
-
- kfree(cl);
+ regmap_write(st->regmap, ADI_AXI_REG_RSTN, 0);
}
-static void devm_adi_axi_adc_conv_release(void *conv)
+static int axi_adc_data_format_set(struct iio_backend *back, unsigned int chan,
+ const struct iio_backend_data_fmt *data)
{
- adi_axi_adc_conv_unregister(conv);
+ struct adi_axi_adc_state *st = iio_backend_get_priv(back);
+ u32 val;
+
+ if (!data->enable)
+ return regmap_clear_bits(st->regmap,
+ ADI_AXI_REG_CHAN_CTRL(chan),
+ ADI_AXI_REG_CHAN_CTRL_FMT_EN);
+
+ val = FIELD_PREP(ADI_AXI_REG_CHAN_CTRL_FMT_EN, true);
+ if (data->sign_extend)
+ val |= FIELD_PREP(ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT, true);
+ if (data->type == IIO_BACKEND_OFFSET_BINARY)
+ val |= FIELD_PREP(ADI_AXI_REG_CHAN_CTRL_FMT_TYPE, true);
+
+ return regmap_update_bits(st->regmap, ADI_AXI_REG_CHAN_CTRL(chan),
+ ADI_AXI_REG_CHAN_CTRL_FMT_MASK, val);
}
-struct adi_axi_adc_conv *devm_adi_axi_adc_conv_register(struct device *dev,
- size_t sizeof_priv)
+static int axi_adc_chan_enable(struct iio_backend *back, unsigned int chan)
{
- struct adi_axi_adc_conv *conv;
- int ret;
-
- conv = adi_axi_adc_conv_register(dev, sizeof_priv);
- if (IS_ERR(conv))
- return conv;
+ struct adi_axi_adc_state *st = iio_backend_get_priv(back);
- ret = devm_add_action_or_reset(dev, devm_adi_axi_adc_conv_release,
- conv);
- if (ret)
- return ERR_PTR(ret);
-
- return conv;
+ return regmap_set_bits(st->regmap, ADI_AXI_REG_CHAN_CTRL(chan),
+ ADI_AXI_REG_CHAN_CTRL_ENABLE);
}
-EXPORT_SYMBOL_NS_GPL(devm_adi_axi_adc_conv_register, IIO_ADI_AXI);
-
-static const struct iio_info adi_axi_adc_info = {
- .read_raw = &adi_axi_adc_read_raw,
- .write_raw = &adi_axi_adc_write_raw,
- .update_scan_mode = &adi_axi_adc_update_scan_mode,
- .read_avail = &adi_axi_adc_read_avail,
-};
-
-static const struct adi_axi_adc_core_info adi_axi_adc_10_0_a_info = {
- .version = ADI_AXI_PCORE_VER(10, 0, 'a'),
-};
-static struct adi_axi_adc_client *adi_axi_adc_attach_client(struct device *dev)
+static int axi_adc_chan_disable(struct iio_backend *back, unsigned int chan)
{
- const struct adi_axi_adc_core_info *info;
- struct adi_axi_adc_client *cl;
- struct device_node *cln;
-
- info = of_device_get_match_data(dev);
- if (!info)
- return ERR_PTR(-ENODEV);
-
- cln = of_parse_phandle(dev->of_node, "adi,adc-dev", 0);
- if (!cln) {
- dev_err(dev, "No 'adi,adc-dev' node defined\n");
- return ERR_PTR(-ENODEV);
- }
-
- mutex_lock(&registered_clients_lock);
-
- list_for_each_entry(cl, &registered_clients, entry) {
- if (!cl->dev)
- continue;
-
- if (cl->dev->of_node != cln)
- continue;
-
- if (!try_module_get(cl->dev->driver->owner)) {
- mutex_unlock(&registered_clients_lock);
- of_node_put(cln);
- return ERR_PTR(-ENODEV);
- }
-
- get_device(cl->dev);
- cl->info = info;
- mutex_unlock(&registered_clients_lock);
- of_node_put(cln);
- return cl;
- }
+ struct adi_axi_adc_state *st = iio_backend_get_priv(back);
- mutex_unlock(&registered_clients_lock);
- of_node_put(cln);
-
- return ERR_PTR(-EPROBE_DEFER);
+ return regmap_clear_bits(st->regmap, ADI_AXI_REG_CHAN_CTRL(chan),
+ ADI_AXI_REG_CHAN_CTRL_ENABLE);
}
-static int adi_axi_adc_setup_channels(struct device *dev,
- struct adi_axi_adc_state *st)
+static struct iio_buffer *axi_adc_request_buffer(struct iio_backend *back,
+ struct iio_dev *indio_dev)
{
- struct adi_axi_adc_conv *conv = &st->client->conv;
- int i, ret;
+ struct adi_axi_adc_state *st = iio_backend_get_priv(back);
+ struct iio_buffer *buffer;
+ const char *dma_name;
+ int ret;
- if (conv->preenable_setup) {
- ret = conv->preenable_setup(conv);
- if (ret)
- return ret;
- }
+ if (device_property_read_string(st->dev, "dma-names", &dma_name))
+ dma_name = "rx";
- for (i = 0; i < conv->chip_info->num_channels; i++) {
- ret = regmap_write(st->regmap, ADI_AXI_REG_CHAN_CTRL(i),
- ADI_AXI_REG_CHAN_CTRL_DEFAULTS);
- if (ret)
- return ret;
+ buffer = iio_dmaengine_buffer_alloc(st->dev, dma_name);
+ if (IS_ERR(buffer)) {
+ dev_err(st->dev, "Could not get DMA buffer, %ld\n",
+ PTR_ERR(buffer));
+ return ERR_CAST(buffer);
}
- return 0;
-}
-
-static int axi_adc_reset(struct adi_axi_adc_state *st)
-{
- int ret;
-
- ret = regmap_write(st->regmap, ADI_AXI_REG_RSTN, 0);
- if (ret)
- return ret;
-
- mdelay(10);
- ret = regmap_write(st->regmap, ADI_AXI_REG_RSTN,
- ADI_AXI_REG_RSTN_MMCM_RSTN);
+ indio_dev->modes |= INDIO_BUFFER_HARDWARE;
+ ret = iio_device_attach_buffer(indio_dev, buffer);
if (ret)
- return ret;
+ return ERR_PTR(ret);
- mdelay(10);
- return regmap_write(st->regmap, ADI_AXI_REG_RSTN,
- ADI_AXI_REG_RSTN_RSTN | ADI_AXI_REG_RSTN_MMCM_RSTN);
+ return buffer;
}
-static void adi_axi_adc_cleanup(void *data)
+static void axi_adc_free_buffer(struct iio_backend *back,
+ struct iio_buffer *buffer)
{
- struct adi_axi_adc_client *cl = data;
-
- put_device(cl->dev);
- module_put(cl->dev->driver->owner);
+ iio_dmaengine_buffer_free(buffer);
}
static const struct regmap_config axi_adc_regmap_config = {
@@ -344,45 +159,47 @@ static const struct regmap_config axi_adc_regmap_config = {
.max_register = 0x0800,
};
+static const struct iio_backend_ops adi_axi_adc_generic = {
+ .enable = axi_adc_enable,
+ .disable = axi_adc_disable,
+ .data_format_set = axi_adc_data_format_set,
+ .chan_enable = axi_adc_chan_enable,
+ .chan_disable = axi_adc_chan_disable,
+ .request_buffer = axi_adc_request_buffer,
+ .free_buffer = axi_adc_free_buffer,
+};
+
static int adi_axi_adc_probe(struct platform_device *pdev)
{
- struct adi_axi_adc_conv *conv;
- struct iio_dev *indio_dev;
- struct adi_axi_adc_client *cl;
+ const unsigned int *expected_ver;
struct adi_axi_adc_state *st;
void __iomem *base;
unsigned int ver;
int ret;
- cl = adi_axi_adc_attach_client(&pdev->dev);
- if (IS_ERR(cl))
- return PTR_ERR(cl);
-
- ret = devm_add_action_or_reset(&pdev->dev, adi_axi_adc_cleanup, cl);
- if (ret)
- return ret;
-
- indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
- if (indio_dev == NULL)
+ st = devm_kzalloc(&pdev->dev, sizeof(*st), GFP_KERNEL);
+ if (!st)
return -ENOMEM;
- st = iio_priv(indio_dev);
- st->client = cl;
- cl->state = st;
- mutex_init(&st->lock);
-
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
+ st->dev = &pdev->dev;
st->regmap = devm_regmap_init_mmio(&pdev->dev, base,
&axi_adc_regmap_config);
if (IS_ERR(st->regmap))
return PTR_ERR(st->regmap);
- conv = &st->client->conv;
+ expected_ver = device_get_match_data(&pdev->dev);
+ if (!expected_ver)
+ return -ENODEV;
- ret = axi_adc_reset(st);
+ /*
+ * Force disable the core. Up to the frontend to enable us. And we can
+ * still read/write registers...
+ */
+ ret = regmap_write(st->regmap, ADI_AXI_REG_RSTN, 0);
if (ret)
return ret;
@@ -390,33 +207,19 @@ static int adi_axi_adc_probe(struct platform_device *pdev)
if (ret)
return ret;
- if (cl->info->version > ver) {
+ if (*expected_ver > ver) {
dev_err(&pdev->dev,
"IP core version is too old. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",
- ADI_AXI_PCORE_VER_MAJOR(cl->info->version),
- ADI_AXI_PCORE_VER_MINOR(cl->info->version),
- ADI_AXI_PCORE_VER_PATCH(cl->info->version),
+ ADI_AXI_PCORE_VER_MAJOR(*expected_ver),
+ ADI_AXI_PCORE_VER_MINOR(*expected_ver),
+ ADI_AXI_PCORE_VER_PATCH(*expected_ver),
ADI_AXI_PCORE_VER_MAJOR(ver),
ADI_AXI_PCORE_VER_MINOR(ver),
ADI_AXI_PCORE_VER_PATCH(ver));
return -ENODEV;
}
- indio_dev->info = &adi_axi_adc_info;
- indio_dev->name = "adi-axi-adc";
- indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->num_channels = conv->chip_info->num_channels;
- indio_dev->channels = conv->chip_info->channels;
-
- ret = adi_axi_adc_config_dma_buffer(&pdev->dev, indio_dev);
- if (ret)
- return ret;
-
- ret = adi_axi_adc_setup_channels(&pdev->dev, st);
- if (ret)
- return ret;
-
- ret = devm_iio_device_register(&pdev->dev, indio_dev);
+ ret = devm_iio_backend_register(&pdev->dev, &adi_axi_adc_generic, st);
if (ret)
return ret;
@@ -428,6 +231,8 @@ static int adi_axi_adc_probe(struct platform_device *pdev)
return 0;
}
+static unsigned int adi_axi_adc_10_0_a_info = ADI_AXI_PCORE_VER(10, 0, 'a');
+
/* Match table for of_platform binding */
static const struct of_device_id adi_axi_adc_of_match[] = {
{ .compatible = "adi,axi-adc-10.0.a", .data = &adi_axi_adc_10_0_a_info },
@@ -447,3 +252,5 @@ module_platform_driver(adi_axi_adc_driver);
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("Analog Devices Generic AXI ADC IP core driver");
MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS(IIO_DMAENGINE_BUFFER);
+MODULE_IMPORT_NS(IIO_BACKEND);
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c
index 7c2a98b8c3a9..8b5bc96cb9fb 100644
--- a/drivers/iio/adc/max1363.c
+++ b/drivers/iio/adc/max1363.c
@@ -357,62 +357,55 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev,
int *val,
long m)
{
- int ret = 0;
- s32 data;
- u8 rxbuf[2];
- struct max1363_state *st = iio_priv(indio_dev);
- struct i2c_client *client = st->client;
-
- ret = iio_device_claim_direct_mode(indio_dev);
- if (ret)
- return ret;
- mutex_lock(&st->lock);
-
- /*
- * If monitor mode is enabled, the method for reading a single
- * channel will have to be rather different and has not yet
- * been implemented.
- *
- * Also, cannot read directly if buffered capture enabled.
- */
- if (st->monitor_on) {
- ret = -EBUSY;
- goto error_ret;
- }
-
- /* Check to see if current scan mode is correct */
- if (st->current_mode != &max1363_mode_table[chan->address]) {
- /* Update scan mode if needed */
- st->current_mode = &max1363_mode_table[chan->address];
- ret = max1363_set_scan_mode(st);
- if (ret < 0)
- goto error_ret;
- }
- if (st->chip_info->bits != 8) {
- /* Get reading */
- data = st->recv(client, rxbuf, 2);
- if (data < 0) {
- ret = data;
- goto error_ret;
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ s32 data;
+ u8 rxbuf[2];
+ struct max1363_state *st = iio_priv(indio_dev);
+ struct i2c_client *client = st->client;
+
+ guard(mutex)(&st->lock);
+
+ /*
+ * If monitor mode is enabled, the method for reading a single
+ * channel will have to be rather different and has not yet
+ * been implemented.
+ *
+ * Also, cannot read directly if buffered capture enabled.
+ */
+ if (st->monitor_on)
+ return -EBUSY;
+
+ /* Check to see if current scan mode is correct */
+ if (st->current_mode != &max1363_mode_table[chan->address]) {
+ int ret;
+
+ /* Update scan mode if needed */
+ st->current_mode = &max1363_mode_table[chan->address];
+ ret = max1363_set_scan_mode(st);
+ if (ret < 0)
+ return ret;
}
- data = (rxbuf[1] | rxbuf[0] << 8) &
- ((1 << st->chip_info->bits) - 1);
- } else {
- /* Get reading */
- data = st->recv(client, rxbuf, 1);
- if (data < 0) {
- ret = data;
- goto error_ret;
+ if (st->chip_info->bits != 8) {
+ /* Get reading */
+ data = st->recv(client, rxbuf, 2);
+ if (data < 0)
+ return data;
+
+ data = (rxbuf[1] | rxbuf[0] << 8) &
+ ((1 << st->chip_info->bits) - 1);
+ } else {
+ /* Get reading */
+ data = st->recv(client, rxbuf, 1);
+ if (data < 0)
+ return data;
+
+ data = rxbuf[0];
}
- data = rxbuf[0];
- }
- *val = data;
-
-error_ret:
- mutex_unlock(&st->lock);
- iio_device_release_direct_mode(indio_dev);
- return ret;
+ *val = data;
+ return 0;
+ }
+ unreachable();
}
static int max1363_read_raw(struct iio_dev *indio_dev,
@@ -710,9 +703,8 @@ static ssize_t max1363_monitor_store_freq(struct device *dev,
if (!found)
return -EINVAL;
- mutex_lock(&st->lock);
- st->monitor_speed = i;
- mutex_unlock(&st->lock);
+ scoped_guard(mutex, &st->lock)
+ st->monitor_speed = i;
return 0;
}
@@ -815,12 +807,11 @@ static int max1363_read_event_config(struct iio_dev *indio_dev,
int val;
int number = chan->channel;
- mutex_lock(&st->lock);
+ guard(mutex)(&st->lock);
if (dir == IIO_EV_DIR_FALLING)
val = (1 << number) & st->mask_low;
else
val = (1 << number) & st->mask_high;
- mutex_unlock(&st->lock);
return val;
}
@@ -962,46 +953,42 @@ static int max1363_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir, int state)
{
- int ret = 0;
struct max1363_state *st = iio_priv(indio_dev);
- u16 unifiedmask;
- int number = chan->channel;
- ret = iio_device_claim_direct_mode(indio_dev);
- if (ret)
- return ret;
- mutex_lock(&st->lock);
-
- unifiedmask = st->mask_low | st->mask_high;
- if (dir == IIO_EV_DIR_FALLING) {
-
- if (state == 0)
- st->mask_low &= ~(1 << number);
- else {
- ret = __max1363_check_event_mask((1 << number),
- unifiedmask);
- if (ret)
- goto error_ret;
- st->mask_low |= (1 << number);
- }
- } else {
- if (state == 0)
- st->mask_high &= ~(1 << number);
- else {
- ret = __max1363_check_event_mask((1 << number),
- unifiedmask);
- if (ret)
- goto error_ret;
- st->mask_high |= (1 << number);
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ int number = chan->channel;
+ u16 unifiedmask;
+ int ret;
+
+ guard(mutex)(&st->lock);
+
+ unifiedmask = st->mask_low | st->mask_high;
+ if (dir == IIO_EV_DIR_FALLING) {
+
+ if (state == 0)
+ st->mask_low &= ~(1 << number);
+ else {
+ ret = __max1363_check_event_mask((1 << number),
+ unifiedmask);
+ if (ret)
+ return ret;
+ st->mask_low |= (1 << number);
+ }
+ } else {
+ if (state == 0)
+ st->mask_high &= ~(1 << number);
+ else {
+ ret = __max1363_check_event_mask((1 << number),
+ unifiedmask);
+ if (ret)
+ return ret;
+ st->mask_high |= (1 << number);
+ }
}
}
-
max1363_monitor_mode_update(st, !!(st->mask_high | st->mask_low));
-error_ret:
- mutex_unlock(&st->lock);
- iio_device_release_direct_mode(indio_dev);
- return ret;
+ return 0;
}
/*
diff --git a/drivers/iio/adc/rtq6056.c b/drivers/iio/adc/rtq6056.c
index ad4cea6839b2..a5464737e527 100644
--- a/drivers/iio/adc/rtq6056.c
+++ b/drivers/iio/adc/rtq6056.c
@@ -39,6 +39,10 @@
#define RTQ6056_DEFAULT_CONFIG 0x4127
#define RTQ6056_CONT_ALLON 7
+#define RTQ6059_DEFAULT_CONFIG 0x3C47
+#define RTQ6059_VBUS_LSB_OFFSET 3
+#define RTQ6059_AVG_BASE 8
+
enum {
RTQ6056_CH_VSHUNT = 0,
RTQ6056_CH_VBUS,
@@ -47,19 +51,46 @@ enum {
RTQ6056_MAX_CHANNEL
};
+/*
+ * The enum is to present the 0x00 CONFIG RG bitfield for the 16bit RG value
+ * field value order from LSB to MSB
+ * RTQ6053/6 is OPMODE->VSHUNTCT->VBUSCT->AVG->RESET
+ * RTQ6059 is OPMODE->SADC->BADC->PGA->RESET
+ */
enum {
F_OPMODE = 0,
F_VSHUNTCT,
+ F_RTQ6059_SADC = F_VSHUNTCT,
F_VBUSCT,
+ F_RTQ6059_BADC = F_VBUSCT,
F_AVG,
+ F_RTQ6059_PGA = F_AVG,
F_RESET,
F_MAX_FIELDS
};
+struct rtq6056_priv;
+
+struct richtek_dev_data {
+ bool fixed_samp_freq;
+ u8 vbus_offset;
+ int default_conv_time_us;
+ unsigned int default_config;
+ unsigned int calib_coefficient;
+ const int *avg_sample_list;
+ int avg_sample_list_length;
+ const struct reg_field *reg_fields;
+ const struct iio_chan_spec *channels;
+ int num_channels;
+ int (*read_scale)(struct iio_chan_spec const *ch, int *val, int *val2);
+ int (*set_average)(struct rtq6056_priv *priv, int val);
+};
+
struct rtq6056_priv {
struct device *dev;
struct regmap *regmap;
struct regmap_field *rm_fields[F_MAX_FIELDS];
+ const struct richtek_dev_data *devdata;
u32 shunt_resistor_uohm;
int vshuntct_us;
int vbusct_us;
@@ -74,6 +105,14 @@ static const struct reg_field rtq6056_reg_fields[F_MAX_FIELDS] = {
[F_RESET] = REG_FIELD(RTQ6056_REG_CONFIG, 15, 15),
};
+static const struct reg_field rtq6059_reg_fields[F_MAX_FIELDS] = {
+ [F_OPMODE] = REG_FIELD(RTQ6056_REG_CONFIG, 0, 2),
+ [F_RTQ6059_SADC] = REG_FIELD(RTQ6056_REG_CONFIG, 3, 6),
+ [F_RTQ6059_BADC] = REG_FIELD(RTQ6056_REG_CONFIG, 7, 10),
+ [F_RTQ6059_PGA] = REG_FIELD(RTQ6056_REG_CONFIG, 11, 12),
+ [F_RESET] = REG_FIELD(RTQ6056_REG_CONFIG, 15, 15),
+};
+
static const struct iio_chan_spec rtq6056_channels[RTQ6056_MAX_CHANNEL + 1] = {
{
.type = IIO_VOLTAGE,
@@ -151,10 +190,93 @@ static const struct iio_chan_spec rtq6056_channels[RTQ6056_MAX_CHANNEL + 1] = {
IIO_CHAN_SOFT_TIMESTAMP(RTQ6056_MAX_CHANNEL),
};
+/*
+ * Difference between RTQ6056 and RTQ6059
+ * - Fixed sampling conversion time
+ * - Average sample numbers
+ * - Channel scale
+ * - calibration coefficient
+ */
+static const struct iio_chan_spec rtq6059_channels[RTQ6056_MAX_CHANNEL + 1] = {
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 0,
+ .address = RTQ6056_REG_SHUNTVOLT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_CPU,
+ },
+ },
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 1,
+ .address = RTQ6056_REG_BUSVOLT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .scan_index = 1,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_CPU,
+ },
+ },
+ {
+ .type = IIO_POWER,
+ .indexed = 1,
+ .channel = 2,
+ .address = RTQ6056_REG_POWER,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .scan_index = 2,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_CPU,
+ },
+ },
+ {
+ .type = IIO_CURRENT,
+ .indexed = 1,
+ .channel = 3,
+ .address = RTQ6056_REG_CURRENT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .scan_index = 3,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_CPU,
+ },
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(RTQ6056_MAX_CHANNEL),
+};
+
static int rtq6056_adc_read_channel(struct rtq6056_priv *priv,
struct iio_chan_spec const *ch,
int *val)
{
+ const struct richtek_dev_data *devdata = priv->devdata;
struct device *dev = priv->dev;
unsigned int addr = ch->address;
unsigned int regval;
@@ -168,12 +290,21 @@ static int rtq6056_adc_read_channel(struct rtq6056_priv *priv,
return ret;
/* Power and VBUS is unsigned 16-bit, others are signed 16-bit */
- if (addr == RTQ6056_REG_BUSVOLT || addr == RTQ6056_REG_POWER)
+ switch (addr) {
+ case RTQ6056_REG_BUSVOLT:
+ regval >>= devdata->vbus_offset;
*val = regval;
- else
+ return IIO_VAL_INT;
+ case RTQ6056_REG_POWER:
+ *val = regval;
+ return IIO_VAL_INT;
+ case RTQ6056_REG_SHUNTVOLT:
+ case RTQ6056_REG_CURRENT:
*val = sign_extend32(regval, 16);
-
- return IIO_VAL_INT;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
}
static int rtq6056_adc_read_scale(struct iio_chan_spec const *ch, int *val,
@@ -199,6 +330,28 @@ static int rtq6056_adc_read_scale(struct iio_chan_spec const *ch, int *val,
}
}
+static int rtq6059_adc_read_scale(struct iio_chan_spec const *ch, int *val,
+ int *val2)
+{
+ switch (ch->address) {
+ case RTQ6056_REG_SHUNTVOLT:
+ /* VSHUNT lsb 10uV */
+ *val = 10000;
+ *val2 = 1000000;
+ return IIO_VAL_FRACTIONAL;
+ case RTQ6056_REG_BUSVOLT:
+ /* VBUS lsb 4mV */
+ *val = 4;
+ return IIO_VAL_INT;
+ case RTQ6056_REG_POWER:
+ /* Power lsb 20mW */
+ *val = 20;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
+
/*
* Sample frequency for channel VSHUNT and VBUS. The indices correspond
* with the bit value expected by the chip. And it can be found at
@@ -248,6 +401,10 @@ static const int rtq6056_avg_sample_list[] = {
1, 4, 16, 64, 128, 256, 512, 1024,
};
+static const int rtq6059_avg_sample_list[] = {
+ 1, 2, 4, 8, 16, 32, 64, 128,
+};
+
static int rtq6056_adc_set_average(struct rtq6056_priv *priv, int val)
{
unsigned int selector;
@@ -268,6 +425,30 @@ static int rtq6056_adc_set_average(struct rtq6056_priv *priv, int val)
return 0;
}
+static int rtq6059_adc_set_average(struct rtq6056_priv *priv, int val)
+{
+ unsigned int selector;
+ int ret;
+
+ if (val > 128 || val < 1)
+ return -EINVAL;
+
+ /* The supported average sample is 2^x (x from 0 to 7) */
+ selector = fls(val) - 1;
+
+ ret = regmap_field_write(priv->rm_fields[F_RTQ6059_BADC],
+ RTQ6059_AVG_BASE + selector);
+ if (ret)
+ return ret;
+
+ ret = regmap_field_write(priv->rm_fields[F_RTQ6059_SADC],
+ RTQ6059_AVG_BASE + selector);
+
+ priv->avg_sample = BIT(selector);
+
+ return 0;
+}
+
static int rtq6056_adc_get_sample_freq(struct rtq6056_priv *priv,
struct iio_chan_spec const *ch, int *val)
{
@@ -292,12 +473,13 @@ static int rtq6056_adc_read_raw(struct iio_dev *indio_dev,
int *val2, long mask)
{
struct rtq6056_priv *priv = iio_priv(indio_dev);
+ const struct richtek_dev_data *devdata = priv->devdata;
switch (mask) {
case IIO_CHAN_INFO_RAW:
return rtq6056_adc_read_channel(priv, chan, val);
case IIO_CHAN_INFO_SCALE:
- return rtq6056_adc_read_scale(chan, val, val2);
+ return devdata->read_scale(chan, val, val2);
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
*val = priv->avg_sample;
return IIO_VAL_INT;
@@ -313,6 +495,9 @@ static int rtq6056_adc_read_avail(struct iio_dev *indio_dev,
const int **vals, int *type, int *length,
long mask)
{
+ struct rtq6056_priv *priv = iio_priv(indio_dev);
+ const struct richtek_dev_data *devdata = priv->devdata;
+
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
*vals = rtq6056_samp_freq_list;
@@ -320,9 +505,9 @@ static int rtq6056_adc_read_avail(struct iio_dev *indio_dev,
*length = ARRAY_SIZE(rtq6056_samp_freq_list);
return IIO_AVAIL_LIST;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
- *vals = rtq6056_avg_sample_list;
+ *vals = devdata->avg_sample_list;
+ *length = devdata->avg_sample_list_length;
*type = IIO_VAL_INT;
- *length = ARRAY_SIZE(rtq6056_avg_sample_list);
return IIO_AVAIL_LIST;
default:
return -EINVAL;
@@ -334,6 +519,7 @@ static int rtq6056_adc_write_raw(struct iio_dev *indio_dev,
int val2, long mask)
{
struct rtq6056_priv *priv = iio_priv(indio_dev);
+ const struct richtek_dev_data *devdata = priv->devdata;
int ret;
ret = iio_device_claim_direct_mode(indio_dev);
@@ -342,10 +528,15 @@ static int rtq6056_adc_write_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
+ if (devdata->fixed_samp_freq) {
+ ret = -EINVAL;
+ break;
+ }
+
ret = rtq6056_adc_set_samp_freq(priv, chan, val);
break;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
- ret = rtq6056_adc_set_average(priv, val);
+ ret = devdata->set_average(priv, val);
break;
default:
ret = -EINVAL;
@@ -374,6 +565,7 @@ static int rtq6056_adc_read_label(struct iio_dev *indio_dev,
static int rtq6056_set_shunt_resistor(struct rtq6056_priv *priv,
int resistor_uohm)
{
+ const struct richtek_dev_data *devdata = priv->devdata;
unsigned int calib_val;
int ret;
@@ -382,8 +574,8 @@ static int rtq6056_set_shunt_resistor(struct rtq6056_priv *priv,
return -EINVAL;
}
- /* calibration = 5120000 / (Rshunt (uOhm) * current lsb (1mA)) */
- calib_val = 5120000 / resistor_uohm;
+ /* calibration = coefficient / (Rshunt (uOhm) * current lsb (1mA)) */
+ calib_val = devdata->calib_coefficient / resistor_uohm;
ret = regmap_write(priv->regmap, RTQ6056_REG_CALIBRATION, calib_val);
if (ret)
return ret;
@@ -450,6 +642,7 @@ static irqreturn_t rtq6056_buffer_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct rtq6056_priv *priv = iio_priv(indio_dev);
+ const struct richtek_dev_data *devdata = priv->devdata;
struct device *dev = priv->dev;
struct {
u16 vals[RTQ6056_MAX_CHANNEL];
@@ -469,6 +662,9 @@ static irqreturn_t rtq6056_buffer_trigger_handler(int irq, void *p)
if (ret)
goto out;
+ if (addr == RTQ6056_REG_BUSVOLT)
+ raw >>= devdata->vbus_offset;
+
data.vals[i++] = raw;
}
@@ -528,20 +724,26 @@ static int rtq6056_probe(struct i2c_client *i2c)
struct rtq6056_priv *priv;
struct device *dev = &i2c->dev;
struct regmap *regmap;
+ const struct richtek_dev_data *devdata;
unsigned int vendor_id, shunt_resistor_uohm;
int ret;
if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_WORD_DATA))
return -EOPNOTSUPP;
+ devdata = device_get_match_data(dev);
+ if (!devdata)
+ return dev_err_probe(dev, -EINVAL, "Invalid dev data\n");
+
indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
if (!indio_dev)
return -ENOMEM;
priv = iio_priv(indio_dev);
priv->dev = dev;
- priv->vshuntct_us = priv->vbusct_us = 1037;
+ priv->vshuntct_us = priv->vbusct_us = devdata->default_conv_time_us;
priv->avg_sample = 1;
+ priv->devdata = devdata;
i2c_set_clientdata(i2c, priv);
regmap = devm_regmap_init_i2c(i2c, &rtq6056_regmap_config);
@@ -561,15 +763,11 @@ static int rtq6056_probe(struct i2c_client *i2c)
"Invalid vendor id 0x%04x\n", vendor_id);
ret = devm_regmap_field_bulk_alloc(dev, regmap, priv->rm_fields,
- rtq6056_reg_fields, F_MAX_FIELDS);
+ devdata->reg_fields, F_MAX_FIELDS);
if (ret)
return dev_err_probe(dev, ret, "Failed to init regmap field\n");
- /*
- * By default, configure average sample as 1, bus and shunt conversion
- * time as 1037 microsecond, and operating mode to all on.
- */
- ret = regmap_write(regmap, RTQ6056_REG_CONFIG, RTQ6056_DEFAULT_CONFIG);
+ ret = regmap_write(regmap, RTQ6056_REG_CONFIG, devdata->default_config);
if (ret)
return dev_err_probe(dev, ret,
"Failed to enable continuous sensing\n");
@@ -598,8 +796,8 @@ static int rtq6056_probe(struct i2c_client *i2c)
indio_dev->name = "rtq6056";
indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->channels = rtq6056_channels;
- indio_dev->num_channels = ARRAY_SIZE(rtq6056_channels);
+ indio_dev->channels = devdata->channels;
+ indio_dev->num_channels = devdata->num_channels;
indio_dev->info = &rtq6056_info;
ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
@@ -640,8 +838,45 @@ static int rtq6056_runtime_resume(struct device *dev)
static DEFINE_RUNTIME_DEV_PM_OPS(rtq6056_pm_ops, rtq6056_runtime_suspend,
rtq6056_runtime_resume, NULL);
+static const struct richtek_dev_data rtq6056_devdata = {
+ .default_conv_time_us = 1037,
+ .calib_coefficient = 5120000,
+ /*
+ * By default, configure average sample as 1, bus and shunt conversion
+ * time as 1037 microsecond, and operating mode to all on.
+ */
+ .default_config = RTQ6056_DEFAULT_CONFIG,
+ .avg_sample_list = rtq6056_avg_sample_list,
+ .avg_sample_list_length = ARRAY_SIZE(rtq6056_avg_sample_list),
+ .reg_fields = rtq6056_reg_fields,
+ .channels = rtq6056_channels,
+ .num_channels = ARRAY_SIZE(rtq6056_channels),
+ .read_scale = rtq6056_adc_read_scale,
+ .set_average = rtq6056_adc_set_average,
+};
+
+static const struct richtek_dev_data rtq6059_devdata = {
+ .fixed_samp_freq = true,
+ .vbus_offset = RTQ6059_VBUS_LSB_OFFSET,
+ .default_conv_time_us = 532,
+ .calib_coefficient = 40960000,
+ /*
+ * By default, configure average sample as 1, bus and shunt conversion
+ * time as 532 microsecond, and operating mode to all on.
+ */
+ .default_config = RTQ6059_DEFAULT_CONFIG,
+ .avg_sample_list = rtq6059_avg_sample_list,
+ .avg_sample_list_length = ARRAY_SIZE(rtq6059_avg_sample_list),
+ .reg_fields = rtq6059_reg_fields,
+ .channels = rtq6059_channels,
+ .num_channels = ARRAY_SIZE(rtq6059_channels),
+ .read_scale = rtq6059_adc_read_scale,
+ .set_average = rtq6059_adc_set_average,
+};
+
static const struct of_device_id rtq6056_device_match[] = {
- { .compatible = "richtek,rtq6056" },
+ { .compatible = "richtek,rtq6056", .data = &rtq6056_devdata },
+ { .compatible = "richtek,rtq6059", .data = &rtq6059_devdata },
{}
};
MODULE_DEVICE_TABLE(of, rtq6056_device_match);
diff --git a/drivers/iio/adc/ti-adc108s102.c b/drivers/iio/adc/ti-adc108s102.c
index c82a161630e1..69fcbbc7e418 100644
--- a/drivers/iio/adc/ti-adc108s102.c
+++ b/drivers/iio/adc/ti-adc108s102.c
@@ -293,13 +293,11 @@ static const struct of_device_id adc108s102_of_match[] = {
};
MODULE_DEVICE_TABLE(of, adc108s102_of_match);
-#ifdef CONFIG_ACPI
static const struct acpi_device_id adc108s102_acpi_ids[] = {
{ "INT3495", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, adc108s102_acpi_ids);
-#endif
static const struct spi_device_id adc108s102_id[] = {
{ "adc108s102", 0 },
@@ -311,7 +309,7 @@ static struct spi_driver adc108s102_driver = {
.driver = {
.name = "adc108s102",
.of_match_table = adc108s102_of_match,
- .acpi_match_table = ACPI_PTR(adc108s102_acpi_ids),
+ .acpi_match_table = adc108s102_acpi_ids,
},
.probe = adc108s102_probe,
.id_table = adc108s102_id,
diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c
index 6799ea49dbc7..6ae967e4d8fa 100644
--- a/drivers/iio/adc/ti-ads1015.c
+++ b/drivers/iio/adc/ti-ads1015.c
@@ -925,7 +925,7 @@ static int ads1015_client_get_channels_config(struct i2c_client *client)
if (!fwnode_property_read_u32(node, "ti,gain", &pval)) {
pga = pval;
- if (pga > 6) {
+ if (pga > 5) {
dev_err(dev, "invalid gain on %pfw\n", node);
fwnode_handle_put(node);
return -EINVAL;
diff --git a/drivers/iio/adc/ti-ads1298.c b/drivers/iio/adc/ti-ads1298.c
new file mode 100644
index 000000000000..ed895a30beed
--- /dev/null
+++ b/drivers/iio/adc/ti-ads1298.c
@@ -0,0 +1,769 @@
+// 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 'n' 24-bit samples, plus the command byte */
+#define ADS1298_SPI_RDATA_BUFFER_SIZE(n) (((n) + 1) * 3 + 1)
+#define ADS1298_SPI_RDATA_BUFFER_SIZE_MAX \
+ ADS1298_SPI_RDATA_BUFFER_SIZE(ADS1298_MAX_CHANNELS)
+
+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 */
+ /*
+ * rdata_xfer_busy increments when a DRDY occurs and decrements when SPI
+ * completion is reported. Hence its meaning is:
+ * 0 = Waiting for DRDY interrupt
+ * 1 = SPI transfer in progress
+ * 2 = DRDY during SPI transfer, start another transfer on completion
+ * >2 = Multiple DRDY during transfer, lost rdata_xfer_busy - 2 samples
+ */
+ unsigned 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_MAX];
+ /* Contains the RDATA command and zeroes to clock out */
+ u8 tx_buffer[ADS1298_SPI_RDATA_BUFFER_SIZE_MAX];
+};
+
+/* 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;
+ unsigned int cfg;
+ int ret;
+
+ 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 >= BIT(ADS1298_SHIFT_DR_LP))
+ 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 < indio_dev->num_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)
+{
+ 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;
+ }
+}
+
+/* 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);
+ unsigned 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 int ads1298_init(struct iio_dev *indio_dev)
+{
+ struct ads1298_private *priv = iio_priv(indio_dev);
+ struct device *dev = &priv->spi->dev;
+ const char *suffix;
+ unsigned int val;
+ int ret;
+
+ /* 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;
+
+ /* Fill in name and channel count based on what the chip told us */
+ indio_dev->num_channels = 4 + 2 * (val & ADS1298_MASK_ID_CHANNELS);
+ switch (val & ADS1298_MASK_ID_FAMILY) {
+ case ADS1298_ID_FAMILY_ADS129X:
+ suffix = "";
+ break;
+ case ADS1298_ID_FAMILY_ADS129XR:
+ suffix = "r";
+ break;
+ default:
+ return dev_err_probe(dev, -ENODEV, "Unknown ID: 0x%x\n", val);
+ }
+ indio_dev->name = devm_kasprintf(dev, GFP_KERNEL, "ads129%u%s",
+ indio_dev->num_channels, suffix);
+
+ /* 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 to be asserted before enabling clock and power */
+ reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(reset_gpio),
+ "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);
+
+ indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
+ indio_dev->channels = ads1298_channels;
+ indio_dev->info = &ads1298_info;
+
+ if (reset_gpio) {
+ /*
+ * Deassert reset now that clock and power are active.
+ * Minimum reset pulsewidth is 2 clock cycles.
+ */
+ fsleep(ADS1298_CLOCKS_TO_USECS(2));
+ gpiod_set_value_cansleep(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 */
+ fsleep(ADS1298_CLOCKS_TO_USECS(18));
+
+ ret = ads1298_init(indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Init failed\n");
+
+ 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(indio_dev->num_channels);
+ /* 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;
+
+ 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");