* [PATCH 00/11] iio: adc: ad7606: improvements and ad7606c parallel interface support
@ 2025-03-13 1:15 David Lechner
2025-03-13 1:15 ` [PATCH 01/11] iio: adc: ad7606_spi: check error in ad7606B_sw_mode_config() David Lechner
` (11 more replies)
0 siblings, 12 replies; 17+ messages in thread
From: David Lechner @ 2025-03-13 1:15 UTC (permalink / raw)
To: Jonathan Cameron, linux-iio
Cc: Michael Hennerich, Angelo Dureghello, Alexandru Ardelean,
Beniamin Bia, Stefan Popa, linux-kernel, David Lechner
The main purpose of this series is to add support for the AD7606C chips
using a parallel interface. Along the way quite a few improvements were
made to the driver which in the end made adding the additional chips
trivial.
The first 3 patches are fixes. The next 6 are some minor cleanups. The
2nd to last patch is the big one. As explained in the respective commit
message, the channel data structures were getting out of hand and only
going to get worse with the addition of SPI offload support. Instead, we
are opting to dynamically allocate the channel data structures to avoid
a bunch of the existing complexity in the driver.
I have limited access to hardware, so I was only able to test this with
ad7606c-18.
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
David Lechner (11):
iio: adc: ad7606_spi: check error in ad7606B_sw_mode_config()
iio: adc: ad7606: check for NULL before calling sw_mode_config()
iio: adc: ad7606: fix scales_available attributes
iio: adc: ad7606: add missing max sample rates
iio: adc: ad7606: use devm_mutex_init()
iio: adc: ad7606: fix kernel-doc comments
iio: adc: ad7606: use kernel identifier name style
iio: adc: ad7606: don't use address field
iio: adc: ad7606: drop ch param from ad7606_scale_setup_cb_t
iio: adc: ad7606: dynamically allocate channel info
iio: adc: ad7606_par: add ad7606c chips
drivers/iio/adc/ad7606.c | 313 ++++++++++++++++++++-----------------------
drivers/iio/adc/ad7606.h | 171 +++++++----------------
drivers/iio/adc/ad7606_par.c | 37 +----
drivers/iio/adc/ad7606_spi.c | 98 ++------------
4 files changed, 211 insertions(+), 408 deletions(-)
---
base-commit: 97fe5f8a4299e4b8601ecb62c9672c27f2d2ccce
change-id: 20250311-iio-adc-ad7606-improvements-997d7af218e3
Best regards,
--
David Lechner <dlechner@baylibre.com>
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 01/11] iio: adc: ad7606_spi: check error in ad7606B_sw_mode_config()
2025-03-13 1:15 [PATCH 00/11] iio: adc: ad7606: improvements and ad7606c parallel interface support David Lechner
@ 2025-03-13 1:15 ` David Lechner
2025-03-15 18:48 ` Jonathan Cameron
2025-03-13 1:15 ` [PATCH 02/11] iio: adc: ad7606: check for NULL before calling sw_mode_config() David Lechner
` (10 subsequent siblings)
11 siblings, 1 reply; 17+ messages in thread
From: David Lechner @ 2025-03-13 1:15 UTC (permalink / raw)
To: Jonathan Cameron, linux-iio
Cc: Michael Hennerich, Angelo Dureghello, Alexandru Ardelean,
Beniamin Bia, Stefan Popa, linux-kernel, David Lechner
Add missing error check in ad7606B_sw_mode_config().
Fixes: d2a415c86c6b ("iio: adc: ad7606: Add support for AD7606B ADC")
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
drivers/iio/adc/ad7606_spi.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c
index 885bf0b68e7775c5f4a12dfb827f502d5f782e8c..c028e08efe2c82cd97249f98eec50a9a9c06471f 100644
--- a/drivers/iio/adc/ad7606_spi.c
+++ b/drivers/iio/adc/ad7606_spi.c
@@ -174,11 +174,13 @@ static int ad7616_sw_mode_config(struct iio_dev *indio_dev)
static int ad7606B_sw_mode_config(struct iio_dev *indio_dev)
{
struct ad7606_state *st = iio_priv(indio_dev);
+ int ret;
/* Configure device spi to output on a single channel */
- st->bops->reg_write(st,
- AD7606_CONFIGURATION_REGISTER,
- AD7606_SINGLE_DOUT);
+ ret = st->bops->reg_write(st, AD7606_CONFIGURATION_REGISTER,
+ AD7606_SINGLE_DOUT);
+ if (ret)
+ return ret;
/*
* Scale can be configured individually for each channel
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 02/11] iio: adc: ad7606: check for NULL before calling sw_mode_config()
2025-03-13 1:15 [PATCH 00/11] iio: adc: ad7606: improvements and ad7606c parallel interface support David Lechner
2025-03-13 1:15 ` [PATCH 01/11] iio: adc: ad7606_spi: check error in ad7606B_sw_mode_config() David Lechner
@ 2025-03-13 1:15 ` David Lechner
2025-03-13 1:15 ` [PATCH 03/11] iio: adc: ad7606: fix scales_available attributes David Lechner
` (9 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: David Lechner @ 2025-03-13 1:15 UTC (permalink / raw)
To: Jonathan Cameron, linux-iio
Cc: Michael Hennerich, Angelo Dureghello, Alexandru Ardelean,
Beniamin Bia, Stefan Popa, linux-kernel, David Lechner
Check that the sw_mode_config function pointer is not NULL before
calling it. Not all buses define this callback, which resulted in a NULL
pointer dereference.
Fixes: e571c1902116 ("iio: adc: ad7606: move scale_setup as function pointer on chip-info")
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
drivers/iio/adc/ad7606.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c
index 631e837171679ad95e71cef2ce6c55c2c756881a..ec444aba25e89ced7b84b723aded3c9dbf2c738b 100644
--- a/drivers/iio/adc/ad7606.c
+++ b/drivers/iio/adc/ad7606.c
@@ -1236,9 +1236,11 @@ static int ad7616_sw_mode_setup(struct iio_dev *indio_dev)
st->write_scale = ad7616_write_scale_sw;
st->write_os = &ad7616_write_os_sw;
- ret = st->bops->sw_mode_config(indio_dev);
- if (ret)
- return ret;
+ if (st->bops->sw_mode_config) {
+ ret = st->bops->sw_mode_config(indio_dev);
+ if (ret)
+ return ret;
+ }
/* Activate Burst mode and SEQEN MODE */
return ad7606_write_mask(st, AD7616_CONFIGURATION_REGISTER,
@@ -1268,6 +1270,9 @@ static int ad7606b_sw_mode_setup(struct iio_dev *indio_dev)
st->write_scale = ad7606_write_scale_sw;
st->write_os = &ad7606_write_os_sw;
+ if (!st->bops->sw_mode_config)
+ return 0;
+
return st->bops->sw_mode_config(indio_dev);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 03/11] iio: adc: ad7606: fix scales_available attributes
2025-03-13 1:15 [PATCH 00/11] iio: adc: ad7606: improvements and ad7606c parallel interface support David Lechner
2025-03-13 1:15 ` [PATCH 01/11] iio: adc: ad7606_spi: check error in ad7606B_sw_mode_config() David Lechner
2025-03-13 1:15 ` [PATCH 02/11] iio: adc: ad7606: check for NULL before calling sw_mode_config() David Lechner
@ 2025-03-13 1:15 ` David Lechner
2025-03-13 1:15 ` [PATCH 04/11] iio: adc: ad7606: add missing max sample rates David Lechner
` (8 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: David Lechner @ 2025-03-13 1:15 UTC (permalink / raw)
To: Jonathan Cameron, linux-iio
Cc: Michael Hennerich, Angelo Dureghello, Alexandru Ardelean,
Beniamin Bia, Stefan Popa, linux-kernel, David Lechner
Fix the scales_available attributes to return all of the scales, not
just 1/2 of them. Also fix const correctness in the cast while we are
touching this.
Fixes: 94aab7a0f5c7 ("iio: adc: ad7606: rework available attributes for SW channels")
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
drivers/iio/adc/ad7606.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c
index ec444aba25e89ced7b84b723aded3c9dbf2c738b..79929bd24fa40bccfcdd88673107da4bf56e032b 100644
--- a/drivers/iio/adc/ad7606.c
+++ b/drivers/iio/adc/ad7606.c
@@ -1064,8 +1064,8 @@ static int ad7606_read_avail(struct iio_dev *indio_dev,
ch = chan->address;
cs = &st->chan_scales[ch];
- *vals = (int *)cs->scale_avail;
- *length = cs->num_scales;
+ *vals = (const int *)cs->scale_avail;
+ *length = cs->num_scales * 2;
*type = IIO_VAL_INT_PLUS_MICRO;
return IIO_AVAIL_LIST;
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 04/11] iio: adc: ad7606: add missing max sample rates
2025-03-13 1:15 [PATCH 00/11] iio: adc: ad7606: improvements and ad7606c parallel interface support David Lechner
` (2 preceding siblings ...)
2025-03-13 1:15 ` [PATCH 03/11] iio: adc: ad7606: fix scales_available attributes David Lechner
@ 2025-03-13 1:15 ` David Lechner
2025-03-13 1:15 ` [PATCH 05/11] iio: adc: ad7606: use devm_mutex_init() David Lechner
` (7 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: David Lechner @ 2025-03-13 1:15 UTC (permalink / raw)
To: Jonathan Cameron, linux-iio
Cc: Michael Hennerich, Angelo Dureghello, Alexandru Ardelean,
Beniamin Bia, Stefan Popa, linux-kernel, David Lechner
Add max sample rates for all of the chips. Previously, only one chip had
this field populated.
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
drivers/iio/adc/ad7606.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c
index 79929bd24fa40bccfcdd88673107da4bf56e032b..440e1e5a9b18570dc6441bff91afbc51d20cbc47 100644
--- a/drivers/iio/adc/ad7606.c
+++ b/drivers/iio/adc/ad7606.c
@@ -196,6 +196,7 @@ static int ad7616_sw_mode_setup(struct iio_dev *indio_dev);
static int ad7606b_sw_mode_setup(struct iio_dev *indio_dev);
const struct ad7606_chip_info ad7605_4_info = {
+ .max_samplerate = 300 * KILO,
.channels = ad7605_channels,
.name = "ad7605-4",
.num_adc_channels = 4,
@@ -205,6 +206,7 @@ const struct ad7606_chip_info ad7605_4_info = {
EXPORT_SYMBOL_NS_GPL(ad7605_4_info, "IIO_AD7606");
const struct ad7606_chip_info ad7606_8_info = {
+ .max_samplerate = 200 * KILO,
.channels = ad7606_channels_16bit,
.name = "ad7606-8",
.num_adc_channels = 8,
@@ -216,6 +218,7 @@ const struct ad7606_chip_info ad7606_8_info = {
EXPORT_SYMBOL_NS_GPL(ad7606_8_info, "IIO_AD7606");
const struct ad7606_chip_info ad7606_6_info = {
+ .max_samplerate = 200 * KILO,
.channels = ad7606_channels_16bit,
.name = "ad7606-6",
.num_adc_channels = 6,
@@ -227,6 +230,7 @@ const struct ad7606_chip_info ad7606_6_info = {
EXPORT_SYMBOL_NS_GPL(ad7606_6_info, "IIO_AD7606");
const struct ad7606_chip_info ad7606_4_info = {
+ .max_samplerate = 200 * KILO,
.channels = ad7606_channels_16bit,
.name = "ad7606-4",
.num_adc_channels = 4,
@@ -251,6 +255,7 @@ const struct ad7606_chip_info ad7606b_info = {
EXPORT_SYMBOL_NS_GPL(ad7606b_info, "IIO_AD7606");
const struct ad7606_chip_info ad7606c_16_info = {
+ .max_samplerate = 1 * MEGA,
.channels = ad7606_channels_16bit,
.name = "ad7606c16",
.num_adc_channels = 8,
@@ -263,6 +268,7 @@ const struct ad7606_chip_info ad7606c_16_info = {
EXPORT_SYMBOL_NS_GPL(ad7606c_16_info, "IIO_AD7606");
const struct ad7606_chip_info ad7607_info = {
+ .max_samplerate = 200 * KILO,
.channels = ad7607_channels,
.name = "ad7607",
.num_adc_channels = 8,
@@ -274,6 +280,7 @@ const struct ad7606_chip_info ad7607_info = {
EXPORT_SYMBOL_NS_GPL(ad7607_info, "IIO_AD7606");
const struct ad7606_chip_info ad7608_info = {
+ .max_samplerate = 200 * KILO,
.channels = ad7608_channels,
.name = "ad7608",
.num_adc_channels = 8,
@@ -285,6 +292,7 @@ const struct ad7606_chip_info ad7608_info = {
EXPORT_SYMBOL_NS_GPL(ad7608_info, "IIO_AD7606");
const struct ad7606_chip_info ad7609_info = {
+ .max_samplerate = 200 * KILO,
.channels = ad7608_channels,
.name = "ad7609",
.num_adc_channels = 8,
@@ -296,6 +304,7 @@ const struct ad7606_chip_info ad7609_info = {
EXPORT_SYMBOL_NS_GPL(ad7609_info, "IIO_AD7606");
const struct ad7606_chip_info ad7606c_18_info = {
+ .max_samplerate = 1 * MEGA,
.channels = ad7606_channels_18bit,
.name = "ad7606c18",
.num_adc_channels = 8,
@@ -308,6 +317,7 @@ const struct ad7606_chip_info ad7606c_18_info = {
EXPORT_SYMBOL_NS_GPL(ad7606c_18_info, "IIO_AD7606");
const struct ad7606_chip_info ad7616_info = {
+ .max_samplerate = 1 * MEGA,
.channels = ad7616_channels,
.init_delay_ms = 15,
.name = "ad7616",
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 05/11] iio: adc: ad7606: use devm_mutex_init()
2025-03-13 1:15 [PATCH 00/11] iio: adc: ad7606: improvements and ad7606c parallel interface support David Lechner
` (3 preceding siblings ...)
2025-03-13 1:15 ` [PATCH 04/11] iio: adc: ad7606: add missing max sample rates David Lechner
@ 2025-03-13 1:15 ` David Lechner
2025-03-15 18:52 ` Jonathan Cameron
2025-03-13 1:15 ` [PATCH 06/11] iio: adc: ad7606: fix kernel-doc comments David Lechner
` (6 subsequent siblings)
11 siblings, 1 reply; 17+ messages in thread
From: David Lechner @ 2025-03-13 1:15 UTC (permalink / raw)
To: Jonathan Cameron, linux-iio
Cc: Michael Hennerich, Angelo Dureghello, Alexandru Ardelean,
Beniamin Bia, Stefan Popa, linux-kernel, David Lechner
Use devm_mutex_init() in ad7606_probe(). Mutexes should be cleaned up
on driver removal.
Also add missing include while we are touching this.
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
drivers/iio/adc/ad7606.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c
index 440e1e5a9b18570dc6441bff91afbc51d20cbc47..f190269ac8ddd859e94eb24c26f5f010d0951646 100644
--- a/drivers/iio/adc/ad7606.c
+++ b/drivers/iio/adc/ad7606.c
@@ -13,6 +13,7 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/property.h>
#include <linux/pwm.h>
#include <linux/regulator/consumer.h>
@@ -1332,8 +1333,11 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
st = iio_priv(indio_dev);
dev_set_drvdata(dev, indio_dev);
+ ret = devm_mutex_init(dev, &st->lock);
+ if (ret)
+ return ret;
+
st->dev = dev;
- mutex_init(&st->lock);
st->bops = bops;
st->base_address = base_address;
st->oversampling = 1;
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 06/11] iio: adc: ad7606: fix kernel-doc comments
2025-03-13 1:15 [PATCH 00/11] iio: adc: ad7606: improvements and ad7606c parallel interface support David Lechner
` (4 preceding siblings ...)
2025-03-13 1:15 ` [PATCH 05/11] iio: adc: ad7606: use devm_mutex_init() David Lechner
@ 2025-03-13 1:15 ` David Lechner
2025-03-15 18:55 ` Jonathan Cameron
2025-03-13 1:15 ` [PATCH 07/11] iio: adc: ad7606: use kernel identifier name style David Lechner
` (5 subsequent siblings)
11 siblings, 1 reply; 17+ messages in thread
From: David Lechner @ 2025-03-13 1:15 UTC (permalink / raw)
To: Jonathan Cameron, linux-iio
Cc: Michael Hennerich, Angelo Dureghello, Alexandru Ardelean,
Beniamin Bia, Stefan Popa, linux-kernel, David Lechner
Fix several issues with kernel-doc comments in ad7606.h:
* Add missing ":" to @param names.
* Add some missing parameters.
* Remove some non-existent parameters.
* Fix alignment and wrapping.
* Fix some spelling.
`./scripts/kernel-doc -v -none drivers/iio/adc/ad7606*` is happy now.
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
drivers/iio/adc/ad7606.h | 90 ++++++++++++++++++++++++------------------------
1 file changed, 45 insertions(+), 45 deletions(-)
diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h
index 71a30525eaab512fa811f28fa79268a1a976bc8c..3da78488c8a247dccbff930023f98717d540081a 100644
--- a/drivers/iio/adc/ad7606.h
+++ b/drivers/iio/adc/ad7606.h
@@ -120,17 +120,17 @@ typedef int (*ad7606_sw_setup_cb_t)(struct iio_dev *indio_dev);
/**
* struct ad7606_chip_info - chip specific information
* @channels: channel specification
- * @max_samplerate: maximum supported samplerate
- * @name device name
+ * @max_samplerate: maximum supported sample rate
+ * @name: device name
* @num_channels: number of channels
- * @num_adc_channels the number of channels the ADC actually inputs.
+ * @num_adc_channels: the number of channels the ADC actually inputs.
* @scale_setup_cb: callback to setup the scales for each channel
* @sw_setup_cb: callback to setup the software mode if available.
- * @oversampling_avail pointer to the array which stores the available
+ * @oversampling_avail: pointer to the array which stores the available
* oversampling ratios.
- * @oversampling_num number of elements stored in oversampling_avail array
- * @os_req_reset some devices require a reset to update oversampling
- * @init_delay_ms required delay in milliseconds for initialization
+ * @oversampling_num: number of elements stored in oversampling_avail array
+ * @os_req_reset: some devices require a reset to update oversampling
+ * @init_delay_ms: required delay in milliseconds for initialization
* after a restart
*/
struct ad7606_chip_info {
@@ -149,10 +149,10 @@ struct ad7606_chip_info {
/**
* struct ad7606_chan_scale - channel scale configuration
- * @scale_avail pointer to the array which stores the available scales
- * @num_scales number of elements stored in the scale_avail array
- * @range voltage range selection, selects which scale to apply
- * @reg_offset offset for the register value, to be applied when
+ * @scale_avail: pointer to the array which stores the available scales
+ * @num_scales: number of elements stored in the scale_avail array
+ * @range: voltage range selection, selects which scale to apply
+ * @reg_offset: offset for the register value, to be applied when
* writing the value of 'range' to the register value
*/
struct ad7606_chan_scale {
@@ -165,32 +165,33 @@ struct ad7606_chan_scale {
/**
* struct ad7606_state - driver instance specific data
- * @dev pointer to kernel device
- * @chip_info entry in the table of chips that describes this device
- * @bops bus operations (SPI or parallel)
- * @chan_scales scale configuration for channels
- * @oversampling oversampling selection
- * @cnvst_pwm pointer to the PWM device connected to the cnvst pin
- * @base_address address from where to read data in parallel operation
- * @sw_mode_en software mode enabled
- * @oversampling_avail pointer to the array which stores the available
+ * @dev: pointer to kernel device
+ * @chip_info: entry in the table of chips that describes this device
+ * @bops: bus operations (SPI or parallel)
+ * @chan_scales: scale configuration for channels
+ * @oversampling: oversampling selection
+ * @cnvst_pwm: pointer to the PWM device connected to the cnvst pin
+ * @base_address: address from where to read data in parallel operation
+ * @sw_mode_en: software mode enabled
+ * @oversampling_avail: pointer to the array which stores the available
* oversampling ratios.
- * @num_os_ratios number of elements stored in oversampling_avail array
- * @write_scale pointer to the function which writes the scale
- * @write_os pointer to the function which writes the os
- * @lock protect sensor state from concurrent accesses to GPIOs
- * @gpio_convst GPIO descriptor for conversion start signal (CONVST)
- * @gpio_reset GPIO descriptor for device hard-reset
- * @gpio_range GPIO descriptor for range selection
- * @gpio_standby GPIO descriptor for stand-by signal (STBY),
+ * @num_os_ratios: number of elements stored in oversampling_avail array
+ * @back: pointer to the iio_backend structure, if used
+ * @write_scale: pointer to the function which writes the scale
+ * @write_os: pointer to the function which writes the os
+ * @lock: protect sensor state from concurrent accesses to GPIOs
+ * @gpio_convst: GPIO descriptor for conversion start signal (CONVST)
+ * @gpio_reset: GPIO descriptor for device hard-reset
+ * @gpio_range: GPIO descriptor for range selection
+ * @gpio_standby: GPIO descriptor for stand-by signal (STBY),
* controls power-down mode of device
- * @gpio_frstdata GPIO descriptor for reading from device when data
+ * @gpio_frstdata: GPIO descriptor for reading from device when data
* is being read on the first channel
- * @gpio_os GPIO descriptors to control oversampling on the device
- * @complete completion to indicate end of conversion
- * @trig The IIO trigger associated with the device.
- * @data buffer for reading data from the device
- * @d16 be16 buffer for reading data from the device
+ * @gpio_os: GPIO descriptors to control oversampling on the device
+ * @trig: The IIO trigger associated with the device.
+ * @completion: completion to indicate end of conversion
+ * @data: buffer for reading data from the device
+ * @d16: be16 buffer for reading data from the device
*/
struct ad7606_state {
struct device *dev;
@@ -232,17 +233,16 @@ struct ad7606_state {
/**
* struct ad7606_bus_ops - driver bus operations
- * @iio_backend_config function pointer for configuring the iio_backend for
+ * @iio_backend_config: function pointer for configuring the iio_backend for
* the compatibles that use it
- * @read_block function pointer for reading blocks of data
+ * @read_block: function pointer for reading blocks of data
* @sw_mode_config: pointer to a function which configured the device
* for software mode
- * @reg_read function pointer for reading spi register
- * @reg_write function pointer for writing spi register
- * @write_mask function pointer for write spi register with mask
- * @update_scan_mode function pointer for handling the calls to iio_info's update_scan
- * mode when enabling/disabling channels.
- * @rd_wr_cmd pointer to the function which calculates the spi address
+ * @reg_read: function pointer for reading spi register
+ * @reg_write: function pointer for writing spi register
+ * @update_scan_mode: function pointer for handling the calls to iio_info's
+ * update_scan mode when enabling/disabling channels.
+ * @rd_wr_cmd: pointer to the function which calculates the spi address
*/
struct ad7606_bus_ops {
/* more methods added in future? */
@@ -258,9 +258,9 @@ struct ad7606_bus_ops {
};
/**
- * struct ad7606_bus_info - agregate ad7606_chip_info and ad7606_bus_ops
- * @chip_info entry in the table of chips that describes this device
- * @bops bus operations (SPI or parallel)
+ * struct ad7606_bus_info - aggregate ad7606_chip_info and ad7606_bus_ops
+ * @chip_info: entry in the table of chips that describes this device
+ * @bops: bus operations (SPI or parallel)
*/
struct ad7606_bus_info {
const struct ad7606_chip_info *chip_info;
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 07/11] iio: adc: ad7606: use kernel identifier name style
2025-03-13 1:15 [PATCH 00/11] iio: adc: ad7606: improvements and ad7606c parallel interface support David Lechner
` (5 preceding siblings ...)
2025-03-13 1:15 ` [PATCH 06/11] iio: adc: ad7606: fix kernel-doc comments David Lechner
@ 2025-03-13 1:15 ` David Lechner
2025-03-13 1:15 ` [PATCH 08/11] iio: adc: ad7606: don't use address field David Lechner
` (4 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: David Lechner @ 2025-03-13 1:15 UTC (permalink / raw)
To: Jonathan Cameron, linux-iio
Cc: Michael Hennerich, Angelo Dureghello, Alexandru Ardelean,
Beniamin Bia, Stefan Popa, linux-kernel, David Lechner
Use lower_snake_case for the identifier names as that is the usual
kernel code style.
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
drivers/iio/adc/ad7606.h | 2 +-
drivers/iio/adc/ad7606_spi.c | 16 ++++++++--------
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h
index 3da78488c8a247dccbff930023f98717d540081a..01b0e2fcf343a77631fbf20c12ac9d02c80c3455 100644
--- a/drivers/iio/adc/ad7606.h
+++ b/drivers/iio/adc/ad7606.h
@@ -254,7 +254,7 @@ struct ad7606_bus_ops {
unsigned int addr,
unsigned int val);
int (*update_scan_mode)(struct iio_dev *indio_dev, const unsigned long *scan_mask);
- u16 (*rd_wr_cmd)(int addr, char isWriteOp);
+ u16 (*rd_wr_cmd)(int addr, char is_write_op);
};
/**
diff --git a/drivers/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c
index c028e08efe2c82cd97249f98eec50a9a9c06471f..1abaf8626206cb30e532cf9f82e0d050706aa1e0 100644
--- a/drivers/iio/adc/ad7606_spi.c
+++ b/drivers/iio/adc/ad7606_spi.c
@@ -59,16 +59,16 @@ static const struct iio_chan_spec ad7606c_18_sw_channels[] = {
AD7606_SW_CHANNEL(7, 18),
};
-static u16 ad7616_spi_rd_wr_cmd(int addr, char isWriteOp)
+static u16 ad7616_spi_rd_wr_cmd(int addr, char is_write_op)
{
/*
* The address of register consist of one w/r bit
* 6 bits of address followed by one reserved bit.
*/
- return ((addr & 0x7F) << 1) | ((isWriteOp & 0x1) << 7);
+ return ((addr & 0x7F) << 1) | ((is_write_op & 0x1) << 7);
}
-static u16 ad7606B_spi_rd_wr_cmd(int addr, char is_write_op)
+static u16 ad7606b_spi_rd_wr_cmd(int addr, char is_write_op)
{
/*
* The address of register consists of one bit which
@@ -171,7 +171,7 @@ static int ad7616_sw_mode_config(struct iio_dev *indio_dev)
return 0;
}
-static int ad7606B_sw_mode_config(struct iio_dev *indio_dev)
+static int ad7606b_sw_mode_config(struct iio_dev *indio_dev)
{
struct ad7606_state *st = iio_priv(indio_dev);
int ret;
@@ -195,7 +195,7 @@ static int ad7606c_18_sw_mode_config(struct iio_dev *indio_dev)
{
int ret;
- ret = ad7606B_sw_mode_config(indio_dev);
+ ret = ad7606b_sw_mode_config(indio_dev);
if (ret)
return ret;
@@ -228,15 +228,15 @@ static const struct ad7606_bus_ops ad7606b_spi_bops = {
.read_block = ad7606_spi_read_block,
.reg_read = ad7606_spi_reg_read,
.reg_write = ad7606_spi_reg_write,
- .rd_wr_cmd = ad7606B_spi_rd_wr_cmd,
- .sw_mode_config = ad7606B_sw_mode_config,
+ .rd_wr_cmd = ad7606b_spi_rd_wr_cmd,
+ .sw_mode_config = ad7606b_sw_mode_config,
};
static const struct ad7606_bus_ops ad7606c_18_spi_bops = {
.read_block = ad7606_spi_read_block18to32,
.reg_read = ad7606_spi_reg_read,
.reg_write = ad7606_spi_reg_write,
- .rd_wr_cmd = ad7606B_spi_rd_wr_cmd,
+ .rd_wr_cmd = ad7606b_spi_rd_wr_cmd,
.sw_mode_config = ad7606c_18_sw_mode_config,
};
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 08/11] iio: adc: ad7606: don't use address field
2025-03-13 1:15 [PATCH 00/11] iio: adc: ad7606: improvements and ad7606c parallel interface support David Lechner
` (6 preceding siblings ...)
2025-03-13 1:15 ` [PATCH 07/11] iio: adc: ad7606: use kernel identifier name style David Lechner
@ 2025-03-13 1:15 ` David Lechner
2025-03-13 1:15 ` [PATCH 09/11] iio: adc: ad7606: drop ch param from ad7606_scale_setup_cb_t David Lechner
` (3 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: David Lechner @ 2025-03-13 1:15 UTC (permalink / raw)
To: Jonathan Cameron, linux-iio
Cc: Michael Hennerich, Angelo Dureghello, Alexandru Ardelean,
Beniamin Bia, Stefan Popa, linux-kernel, David Lechner
Drop use of the address field in the ad7606 driver. This field was
duplicating the same info that was already in the channel and scan_index
fields. This is one less thing to have to hold in your mind when reading
the code.
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
drivers/iio/adc/ad7606.c | 8 ++++----
drivers/iio/adc/ad7606.h | 1 -
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c
index f190269ac8ddd859e94eb24c26f5f010d0951646..02ff4be3545d45f0e10bbea7251862f4e3daf97f 100644
--- a/drivers/iio/adc/ad7606.c
+++ b/drivers/iio/adc/ad7606.c
@@ -776,14 +776,14 @@ static int ad7606_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_RAW:
if (!iio_device_claim_direct(indio_dev))
return -EBUSY;
- ret = ad7606_scan_direct(indio_dev, chan->address, val);
+ ret = ad7606_scan_direct(indio_dev, chan->scan_index, val);
iio_device_release_direct(indio_dev);
if (ret < 0)
return ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
if (st->sw_mode_en)
- ch = chan->address;
+ ch = chan->scan_index;
cs = &st->chan_scales[ch];
*val = cs->scale_avail[cs->range][0];
*val2 = cs->scale_avail[cs->range][1];
@@ -865,7 +865,7 @@ static int ad7606_write_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_SCALE:
if (st->sw_mode_en)
- ch = chan->address;
+ ch = chan->scan_index;
cs = &st->chan_scales[ch];
for (i = 0; i < cs->num_scales; i++) {
scale_avail_uv[i] = cs->scale_avail[i][0] * MICRO +
@@ -1072,7 +1072,7 @@ static int ad7606_read_avail(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
if (st->sw_mode_en)
- ch = chan->address;
+ ch = chan->scan_index;
cs = &st->chan_scales[ch];
*vals = (const int *)cs->scale_avail;
diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h
index 01b0e2fcf343a77631fbf20c12ac9d02c80c3455..f6a6c89dbdc708f4e25e3c9ade9e9e614a7f99b1 100644
--- a/drivers/iio/adc/ad7606.h
+++ b/drivers/iio/adc/ad7606.h
@@ -45,7 +45,6 @@
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = num, \
- .address = num, \
.info_mask_separate = mask_sep, \
.info_mask_separate_available = \
mask_sep_avail, \
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 09/11] iio: adc: ad7606: drop ch param from ad7606_scale_setup_cb_t
2025-03-13 1:15 [PATCH 00/11] iio: adc: ad7606: improvements and ad7606c parallel interface support David Lechner
` (7 preceding siblings ...)
2025-03-13 1:15 ` [PATCH 08/11] iio: adc: ad7606: don't use address field David Lechner
@ 2025-03-13 1:15 ` David Lechner
2025-03-13 1:15 ` [PATCH 10/11] iio: adc: ad7606: dynamically allocate channel info David Lechner
` (2 subsequent siblings)
11 siblings, 0 replies; 17+ messages in thread
From: David Lechner @ 2025-03-13 1:15 UTC (permalink / raw)
To: Jonathan Cameron, linux-iio
Cc: Michael Hennerich, Angelo Dureghello, Alexandru Ardelean,
Beniamin Bia, Stefan Popa, linux-kernel, David Lechner
Drop the ch parameter from the ad7606_scale_setup_cb_t functions. The
same info is already available from the chan param via chan->scan_type
and chan->channel, so the parameter is redundant.
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
drivers/iio/adc/ad7606.c | 44 +++++++++++++++++++++++---------------------
drivers/iio/adc/ad7606.h | 2 +-
2 files changed, 24 insertions(+), 22 deletions(-)
diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c
index 02ff4be3545d45f0e10bbea7251862f4e3daf97f..12871134b22f5ebcb66e9b57cefb8affa523685e 100644
--- a/drivers/iio/adc/ad7606.c
+++ b/drivers/iio/adc/ad7606.c
@@ -182,17 +182,17 @@ static const struct iio_chan_spec ad7616_channels[] = {
};
static int ad7606c_18bit_chan_scale_setup(struct iio_dev *indio_dev,
- struct iio_chan_spec *chan, int ch);
+ struct iio_chan_spec *chan);
static int ad7606c_16bit_chan_scale_setup(struct iio_dev *indio_dev,
- struct iio_chan_spec *chan, int ch);
+ struct iio_chan_spec *chan);
static int ad7606_16bit_chan_scale_setup(struct iio_dev *indio_dev,
- struct iio_chan_spec *chan, int ch);
+ struct iio_chan_spec *chan);
static int ad7607_chan_scale_setup(struct iio_dev *indio_dev,
- struct iio_chan_spec *chan, int ch);
+ struct iio_chan_spec *chan);
static int ad7608_chan_scale_setup(struct iio_dev *indio_dev,
- struct iio_chan_spec *chan, int ch);
+ struct iio_chan_spec *chan);
static int ad7609_chan_scale_setup(struct iio_dev *indio_dev,
- struct iio_chan_spec *chan, int ch);
+ struct iio_chan_spec *chan);
static int ad7616_sw_mode_setup(struct iio_dev *indio_dev);
static int ad7606b_sw_mode_setup(struct iio_dev *indio_dev);
@@ -346,10 +346,10 @@ int ad7606_reset(struct ad7606_state *st)
EXPORT_SYMBOL_NS_GPL(ad7606_reset, "IIO_AD7606");
static int ad7606_16bit_chan_scale_setup(struct iio_dev *indio_dev,
- struct iio_chan_spec *chan, int ch)
+ struct iio_chan_spec *chan)
{
struct ad7606_state *st = iio_priv(indio_dev);
- struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+ struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index];
if (!st->sw_mode_en) {
/* tied to logic low, analog input range is +/- 5V */
@@ -425,10 +425,10 @@ static int ad7606_get_chan_config(struct iio_dev *indio_dev, int ch,
}
static int ad7606c_18bit_chan_scale_setup(struct iio_dev *indio_dev,
- struct iio_chan_spec *chan, int ch)
+ struct iio_chan_spec *chan)
{
struct ad7606_state *st = iio_priv(indio_dev);
- struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+ struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index];
bool bipolar, differential;
int ret;
@@ -439,7 +439,8 @@ static int ad7606c_18bit_chan_scale_setup(struct iio_dev *indio_dev,
return 0;
}
- ret = ad7606_get_chan_config(indio_dev, ch, &bipolar, &differential);
+ ret = ad7606_get_chan_config(indio_dev, chan->scan_index, &bipolar,
+ &differential);
if (ret)
return ret;
@@ -482,10 +483,10 @@ static int ad7606c_18bit_chan_scale_setup(struct iio_dev *indio_dev,
}
static int ad7606c_16bit_chan_scale_setup(struct iio_dev *indio_dev,
- struct iio_chan_spec *chan, int ch)
+ struct iio_chan_spec *chan)
{
struct ad7606_state *st = iio_priv(indio_dev);
- struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+ struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index];
bool bipolar, differential;
int ret;
@@ -496,7 +497,8 @@ static int ad7606c_16bit_chan_scale_setup(struct iio_dev *indio_dev,
return 0;
}
- ret = ad7606_get_chan_config(indio_dev, ch, &bipolar, &differential);
+ ret = ad7606_get_chan_config(indio_dev, chan->scan_index, &bipolar,
+ &differential);
if (ret)
return ret;
@@ -540,10 +542,10 @@ static int ad7606c_16bit_chan_scale_setup(struct iio_dev *indio_dev,
}
static int ad7607_chan_scale_setup(struct iio_dev *indio_dev,
- struct iio_chan_spec *chan, int ch)
+ struct iio_chan_spec *chan)
{
struct ad7606_state *st = iio_priv(indio_dev);
- struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+ struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index];
cs->range = 0;
cs->scale_avail = ad7607_hw_scale_avail;
@@ -552,10 +554,10 @@ static int ad7607_chan_scale_setup(struct iio_dev *indio_dev,
}
static int ad7608_chan_scale_setup(struct iio_dev *indio_dev,
- struct iio_chan_spec *chan, int ch)
+ struct iio_chan_spec *chan)
{
struct ad7606_state *st = iio_priv(indio_dev);
- struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+ struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index];
cs->range = 0;
cs->scale_avail = ad7606_18bit_hw_scale_avail;
@@ -564,10 +566,10 @@ static int ad7608_chan_scale_setup(struct iio_dev *indio_dev,
}
static int ad7609_chan_scale_setup(struct iio_dev *indio_dev,
- struct iio_chan_spec *chan, int ch)
+ struct iio_chan_spec *chan)
{
struct ad7606_state *st = iio_priv(indio_dev);
- struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+ struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index];
cs->range = 0;
cs->scale_avail = ad7609_hw_scale_avail;
@@ -1305,7 +1307,7 @@ static int ad7606_chan_scales_setup(struct iio_dev *indio_dev)
indio_dev->channels = chans;
for (ch = 0; ch < st->chip_info->num_adc_channels; ch++) {
- ret = st->chip_info->scale_setup_cb(indio_dev, &chans[ch + offset], ch);
+ ret = st->chip_info->scale_setup_cb(indio_dev, &chans[ch + offset]);
if (ret)
return ret;
}
diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h
index f6a6c89dbdc708f4e25e3c9ade9e9e614a7f99b1..fd4c0d615a880ac6fdcaad213d4843329c3bd7fe 100644
--- a/drivers/iio/adc/ad7606.h
+++ b/drivers/iio/adc/ad7606.h
@@ -113,7 +113,7 @@
struct ad7606_state;
typedef int (*ad7606_scale_setup_cb_t)(struct iio_dev *indio_dev,
- struct iio_chan_spec *chan, int ch);
+ struct iio_chan_spec *chan);
typedef int (*ad7606_sw_setup_cb_t)(struct iio_dev *indio_dev);
/**
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 10/11] iio: adc: ad7606: dynamically allocate channel info
2025-03-13 1:15 [PATCH 00/11] iio: adc: ad7606: improvements and ad7606c parallel interface support David Lechner
` (8 preceding siblings ...)
2025-03-13 1:15 ` [PATCH 09/11] iio: adc: ad7606: drop ch param from ad7606_scale_setup_cb_t David Lechner
@ 2025-03-13 1:15 ` David Lechner
2025-03-15 19:02 ` Jonathan Cameron
2025-03-13 1:15 ` [PATCH 11/11] iio: adc: ad7606_par: add ad7606c chips David Lechner
2025-03-13 21:11 ` [PATCH 00/11] iio: adc: ad7606: improvements and ad7606c parallel interface support Nuno Sá
11 siblings, 1 reply; 17+ messages in thread
From: David Lechner @ 2025-03-13 1:15 UTC (permalink / raw)
To: Jonathan Cameron, linux-iio
Cc: Michael Hennerich, Angelo Dureghello, Alexandru Ardelean,
Beniamin Bia, Stefan Popa, linux-kernel, David Lechner
Refactor the ad7606 drivers to dynamically allocate the channel info.
The channel info was getting a bit unwieldy. In some cases, the
indio_dev->channels field was getting assigned up to 3 different times,
each in a different function, making it difficult to see where the info
was coming from. This problem stemps from the number of permutations of
the channel array needed to support various modes of operation and data
buses. We already have 4 per chip (hardware mode, software mode, AXI ADC
backend and AXI ADC backend with software mode) and we intend to add two
more per chip when adding SPI offload support.
To make it easier to read and maintain, move all of the channel setup
to a single function that dynamically allocates and fills in the channel
info.
Additionally, this lets us remove some hacks where we had to compute an
offset due to the fact that sometimes there was a soft timestamp channel
at the start of the array. Now the timestamp channel is always at the
end of the array as is typical in other drivers.
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
drivers/iio/adc/ad7606.c | 232 ++++++++++++++++++-------------------------
drivers/iio/adc/ad7606.h | 76 +-------------
drivers/iio/adc/ad7606_par.c | 33 ------
drivers/iio/adc/ad7606_spi.c | 86 +---------------
4 files changed, 102 insertions(+), 325 deletions(-)
diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c
index 12871134b22f5ebcb66e9b57cefb8affa523685e..e6eb82b4de09dc35753f9ca363f619ff93884e56 100644
--- a/drivers/iio/adc/ad7606.c
+++ b/drivers/iio/adc/ad7606.c
@@ -95,92 +95,6 @@ static const unsigned int ad7616_oversampling_avail[8] = {
1, 2, 4, 8, 16, 32, 64, 128,
};
-static const struct iio_chan_spec ad7605_channels[] = {
- IIO_CHAN_SOFT_TIMESTAMP(4),
- AD7605_CHANNEL(0),
- AD7605_CHANNEL(1),
- AD7605_CHANNEL(2),
- AD7605_CHANNEL(3),
-};
-
-static const struct iio_chan_spec ad7606_channels_16bit[] = {
- IIO_CHAN_SOFT_TIMESTAMP(8),
- AD7606_CHANNEL(0, 16),
- AD7606_CHANNEL(1, 16),
- AD7606_CHANNEL(2, 16),
- AD7606_CHANNEL(3, 16),
- AD7606_CHANNEL(4, 16),
- AD7606_CHANNEL(5, 16),
- AD7606_CHANNEL(6, 16),
- AD7606_CHANNEL(7, 16),
-};
-
-static const struct iio_chan_spec ad7606_channels_18bit[] = {
- IIO_CHAN_SOFT_TIMESTAMP(8),
- AD7606_CHANNEL(0, 18),
- AD7606_CHANNEL(1, 18),
- AD7606_CHANNEL(2, 18),
- AD7606_CHANNEL(3, 18),
- AD7606_CHANNEL(4, 18),
- AD7606_CHANNEL(5, 18),
- AD7606_CHANNEL(6, 18),
- AD7606_CHANNEL(7, 18),
-};
-
-static const struct iio_chan_spec ad7607_channels[] = {
- IIO_CHAN_SOFT_TIMESTAMP(8),
- AD7606_CHANNEL(0, 14),
- AD7606_CHANNEL(1, 14),
- AD7606_CHANNEL(2, 14),
- AD7606_CHANNEL(3, 14),
- AD7606_CHANNEL(4, 14),
- AD7606_CHANNEL(5, 14),
- AD7606_CHANNEL(6, 14),
- AD7606_CHANNEL(7, 14),
-};
-
-static const struct iio_chan_spec ad7608_channels[] = {
- IIO_CHAN_SOFT_TIMESTAMP(8),
- AD7606_CHANNEL(0, 18),
- AD7606_CHANNEL(1, 18),
- AD7606_CHANNEL(2, 18),
- AD7606_CHANNEL(3, 18),
- AD7606_CHANNEL(4, 18),
- AD7606_CHANNEL(5, 18),
- AD7606_CHANNEL(6, 18),
- AD7606_CHANNEL(7, 18),
-};
-
-/*
- * The current assumption that this driver makes for AD7616, is that it's
- * working in Hardware Mode with Serial, Burst and Sequencer modes activated.
- * To activate them, following pins must be pulled high:
- * -SER/PAR
- * -SEQEN
- * And following pins must be pulled low:
- * -WR/BURST
- * -DB4/SER1W
- */
-static const struct iio_chan_spec ad7616_channels[] = {
- IIO_CHAN_SOFT_TIMESTAMP(16),
- AD7606_CHANNEL(0, 16),
- AD7606_CHANNEL(1, 16),
- AD7606_CHANNEL(2, 16),
- AD7606_CHANNEL(3, 16),
- AD7606_CHANNEL(4, 16),
- AD7606_CHANNEL(5, 16),
- AD7606_CHANNEL(6, 16),
- AD7606_CHANNEL(7, 16),
- AD7606_CHANNEL(8, 16),
- AD7606_CHANNEL(9, 16),
- AD7606_CHANNEL(10, 16),
- AD7606_CHANNEL(11, 16),
- AD7606_CHANNEL(12, 16),
- AD7606_CHANNEL(13, 16),
- AD7606_CHANNEL(14, 16),
- AD7606_CHANNEL(15, 16),
-};
-
static int ad7606c_18bit_chan_scale_setup(struct iio_dev *indio_dev,
struct iio_chan_spec *chan);
static int ad7606c_16bit_chan_scale_setup(struct iio_dev *indio_dev,
@@ -198,20 +112,18 @@ static int ad7606b_sw_mode_setup(struct iio_dev *indio_dev);
const struct ad7606_chip_info ad7605_4_info = {
.max_samplerate = 300 * KILO,
- .channels = ad7605_channels,
.name = "ad7605-4",
+ .bits = 16,
.num_adc_channels = 4,
- .num_channels = 5,
.scale_setup_cb = ad7606_16bit_chan_scale_setup,
};
EXPORT_SYMBOL_NS_GPL(ad7605_4_info, "IIO_AD7606");
const struct ad7606_chip_info ad7606_8_info = {
.max_samplerate = 200 * KILO,
- .channels = ad7606_channels_16bit,
.name = "ad7606-8",
+ .bits = 16,
.num_adc_channels = 8,
- .num_channels = 9,
.oversampling_avail = ad7606_oversampling_avail,
.oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
.scale_setup_cb = ad7606_16bit_chan_scale_setup,
@@ -220,10 +132,9 @@ EXPORT_SYMBOL_NS_GPL(ad7606_8_info, "IIO_AD7606");
const struct ad7606_chip_info ad7606_6_info = {
.max_samplerate = 200 * KILO,
- .channels = ad7606_channels_16bit,
.name = "ad7606-6",
+ .bits = 16,
.num_adc_channels = 6,
- .num_channels = 7,
.oversampling_avail = ad7606_oversampling_avail,
.oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
.scale_setup_cb = ad7606_16bit_chan_scale_setup,
@@ -232,10 +143,9 @@ EXPORT_SYMBOL_NS_GPL(ad7606_6_info, "IIO_AD7606");
const struct ad7606_chip_info ad7606_4_info = {
.max_samplerate = 200 * KILO,
- .channels = ad7606_channels_16bit,
.name = "ad7606-4",
+ .bits = 16,
.num_adc_channels = 4,
- .num_channels = 5,
.oversampling_avail = ad7606_oversampling_avail,
.oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
.scale_setup_cb = ad7606_16bit_chan_scale_setup,
@@ -243,11 +153,10 @@ const struct ad7606_chip_info ad7606_4_info = {
EXPORT_SYMBOL_NS_GPL(ad7606_4_info, "IIO_AD7606");
const struct ad7606_chip_info ad7606b_info = {
- .channels = ad7606_channels_16bit,
.max_samplerate = 800 * KILO,
.name = "ad7606b",
+ .bits = 16,
.num_adc_channels = 8,
- .num_channels = 9,
.oversampling_avail = ad7606_oversampling_avail,
.oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
.scale_setup_cb = ad7606_16bit_chan_scale_setup,
@@ -257,10 +166,9 @@ EXPORT_SYMBOL_NS_GPL(ad7606b_info, "IIO_AD7606");
const struct ad7606_chip_info ad7606c_16_info = {
.max_samplerate = 1 * MEGA,
- .channels = ad7606_channels_16bit,
.name = "ad7606c16",
+ .bits = 16,
.num_adc_channels = 8,
- .num_channels = 9,
.oversampling_avail = ad7606_oversampling_avail,
.oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
.scale_setup_cb = ad7606c_16bit_chan_scale_setup,
@@ -270,10 +178,9 @@ EXPORT_SYMBOL_NS_GPL(ad7606c_16_info, "IIO_AD7606");
const struct ad7606_chip_info ad7607_info = {
.max_samplerate = 200 * KILO,
- .channels = ad7607_channels,
.name = "ad7607",
+ .bits = 14,
.num_adc_channels = 8,
- .num_channels = 9,
.oversampling_avail = ad7606_oversampling_avail,
.oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
.scale_setup_cb = ad7607_chan_scale_setup,
@@ -282,10 +189,9 @@ EXPORT_SYMBOL_NS_GPL(ad7607_info, "IIO_AD7606");
const struct ad7606_chip_info ad7608_info = {
.max_samplerate = 200 * KILO,
- .channels = ad7608_channels,
.name = "ad7608",
+ .bits = 18,
.num_adc_channels = 8,
- .num_channels = 9,
.oversampling_avail = ad7606_oversampling_avail,
.oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
.scale_setup_cb = ad7608_chan_scale_setup,
@@ -294,10 +200,9 @@ EXPORT_SYMBOL_NS_GPL(ad7608_info, "IIO_AD7606");
const struct ad7606_chip_info ad7609_info = {
.max_samplerate = 200 * KILO,
- .channels = ad7608_channels,
.name = "ad7609",
+ .bits = 18,
.num_adc_channels = 8,
- .num_channels = 9,
.oversampling_avail = ad7606_oversampling_avail,
.oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
.scale_setup_cb = ad7609_chan_scale_setup,
@@ -306,10 +211,9 @@ EXPORT_SYMBOL_NS_GPL(ad7609_info, "IIO_AD7606");
const struct ad7606_chip_info ad7606c_18_info = {
.max_samplerate = 1 * MEGA,
- .channels = ad7606_channels_18bit,
.name = "ad7606c18",
+ .bits = 18,
.num_adc_channels = 8,
- .num_channels = 9,
.oversampling_avail = ad7606_oversampling_avail,
.oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
.scale_setup_cb = ad7606c_18bit_chan_scale_setup,
@@ -319,11 +223,10 @@ EXPORT_SYMBOL_NS_GPL(ad7606c_18_info, "IIO_AD7606");
const struct ad7606_chip_info ad7616_info = {
.max_samplerate = 1 * MEGA,
- .channels = ad7616_channels,
.init_delay_ms = 15,
.name = "ad7616",
+ .bits = 16,
.num_adc_channels = 16,
- .num_channels = 17,
.oversampling_avail = ad7616_oversampling_avail,
.oversampling_num = ARRAY_SIZE(ad7616_oversampling_avail),
.os_req_reset = true,
@@ -373,7 +276,6 @@ static int ad7606_get_chan_config(struct iio_dev *indio_dev, int ch,
{
struct ad7606_state *st = iio_priv(indio_dev);
unsigned int num_channels = st->chip_info->num_adc_channels;
- unsigned int offset = indio_dev->num_channels - st->chip_info->num_adc_channels;
struct device *dev = st->dev;
int ret;
@@ -389,7 +291,7 @@ static int ad7606_get_chan_config(struct iio_dev *indio_dev, int ch,
continue;
/* channel number (here) is from 1 to num_channels */
- if (reg < offset || reg > num_channels) {
+ if (reg < 1 || reg > num_channels) {
dev_warn(dev,
"Invalid channel number (ignoring): %d\n", reg);
continue;
@@ -706,8 +608,8 @@ static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch,
int *val)
{
struct ad7606_state *st = iio_priv(indio_dev);
- unsigned int realbits = st->chip_info->channels[1].scan_type.realbits;
const struct iio_chan_spec *chan;
+ unsigned int realbits;
int ret;
if (st->gpio_convst) {
@@ -739,7 +641,9 @@ static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch,
if (ret)
goto error_ret;
- chan = &indio_dev->channels[ch + 1];
+ chan = &indio_dev->channels[ch];
+ realbits = chan->scan_type.realbits;
+
if (chan->scan_type.sign == 'u') {
if (realbits > 16)
*val = st->data.buf32[ch];
@@ -1289,29 +1193,84 @@ static int ad7606b_sw_mode_setup(struct iio_dev *indio_dev)
return st->bops->sw_mode_config(indio_dev);
}
-static int ad7606_chan_scales_setup(struct iio_dev *indio_dev)
+static int ad7606_probe_channels(struct iio_dev *indio_dev)
{
struct ad7606_state *st = iio_priv(indio_dev);
- unsigned int offset = indio_dev->num_channels - st->chip_info->num_adc_channels;
- struct iio_chan_spec *chans;
- size_t size;
- int ch, ret;
-
- /* Clone IIO channels, since some may be differential */
- size = indio_dev->num_channels * sizeof(*indio_dev->channels);
- chans = devm_kzalloc(st->dev, size, GFP_KERNEL);
- if (!chans)
+ struct device *dev = indio_dev->dev.parent;
+ struct iio_chan_spec *channels;
+ bool slow_bus;
+ int ret, i;
+
+ slow_bus = !st->bops->iio_backend_config;
+ indio_dev->num_channels = st->chip_info->num_adc_channels;
+
+ /* Slow buses also get 1 more channel for soft timestamp */
+ if (slow_bus)
+ indio_dev->num_channels++;
+
+ channels = devm_kcalloc(dev, indio_dev->num_channels, sizeof(*channels),
+ GFP_KERNEL);
+ if (!channels)
return -ENOMEM;
- memcpy(chans, indio_dev->channels, size);
- indio_dev->channels = chans;
+ for (i = 0; i < indio_dev->num_channels; i++) {
+ struct iio_chan_spec *chan = &channels[i];
- for (ch = 0; ch < st->chip_info->num_adc_channels; ch++) {
- ret = st->chip_info->scale_setup_cb(indio_dev, &chans[ch + offset]);
+ chan->type = IIO_VOLTAGE;
+ chan->indexed = 1;
+ chan->channel = i;
+ chan->scan_index = i;
+ chan->scan_type.sign = 's';
+ chan->scan_type.realbits = st->chip_info->bits;
+ chan->scan_type.storagebits = st->chip_info->bits > 16 ? 32 : 16;
+ chan->scan_type.endianness = IIO_CPU;
+
+ if (indio_dev->modes & INDIO_DIRECT_MODE)
+ chan->info_mask_separate |= BIT(IIO_CHAN_INFO_RAW);
+
+ if (st->sw_mode_en) {
+ chan->info_mask_separate |= BIT(IIO_CHAN_INFO_SCALE);
+ chan->info_mask_separate_available |=
+ BIT(IIO_CHAN_INFO_SCALE);
+
+ /**
+ * All chips with software mode support oversampling,
+ * so we skip the oversampling_available check. And the
+ * shared_by_type instead of shared_by_all on slow
+ * buses is for backward compatibility.
+ */
+ if (slow_bus)
+ chan->info_mask_shared_by_type |=
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO);
+ else
+ chan->info_mask_shared_by_all |=
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO);
+
+ chan->info_mask_shared_by_all_available |=
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO);
+ } else {
+ chan->info_mask_shared_by_type |=
+ BIT(IIO_CHAN_INFO_SCALE);
+
+ if (st->chip_info->oversampling_avail)
+ chan->info_mask_shared_by_all |=
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO);
+ }
+
+ if (!slow_bus)
+ chan->info_mask_shared_by_all |=
+ BIT(IIO_CHAN_INFO_SAMP_FREQ);
+
+ ret = st->chip_info->scale_setup_cb(indio_dev, chan);
if (ret)
return ret;
}
+ if (slow_bus)
+ channels[i] = (struct iio_chan_spec)IIO_CHAN_SOFT_TIMESTAMP(i);
+
+ indio_dev->channels = channels;
+
return 0;
}
@@ -1343,6 +1302,11 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
st->bops = bops;
st->base_address = base_address;
st->oversampling = 1;
+ st->sw_mode_en = device_property_read_bool(dev, "adi,sw-mode");
+
+ if (st->sw_mode_en && !chip_info->sw_setup_cb)
+ return dev_err_probe(dev, -EINVAL,
+ "Software mode is not supported for this chip\n");
ret = devm_regulator_get_enable(dev, "avcc");
if (ret)
@@ -1371,10 +1335,14 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
else
indio_dev->info = &ad7606_info_no_os_or_range;
}
- indio_dev->modes = INDIO_DIRECT_MODE;
+
+ /* AXI ADC backend doesn't support single read. */
+ indio_dev->modes = st->bops->iio_backend_config ? 0 : INDIO_DIRECT_MODE;
indio_dev->name = chip_info->name;
- indio_dev->channels = st->chip_info->channels;
- indio_dev->num_channels = st->chip_info->num_channels;
+
+ ret = ad7606_probe_channels(indio_dev);
+ if (ret)
+ return ret;
ret = ad7606_reset(st);
if (ret)
@@ -1466,17 +1434,11 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
st->write_scale = ad7606_write_scale_hw;
st->write_os = ad7606_write_os_hw;
- st->sw_mode_en = st->chip_info->sw_setup_cb &&
- device_property_present(st->dev, "adi,sw-mode");
if (st->sw_mode_en) {
indio_dev->info = &ad7606_info_sw_mode;
st->chip_info->sw_setup_cb(indio_dev);
}
- ret = ad7606_chan_scales_setup(indio_dev);
- if (ret)
- return ret;
-
return devm_iio_device_register(dev, indio_dev);
}
EXPORT_SYMBOL_NS_GPL(ad7606_probe, "IIO_AD7606");
diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h
index fd4c0d615a880ac6fdcaad213d4843329c3bd7fe..b67058cd021a3d00ff0f461766d51e46d7998f32 100644
--- a/drivers/iio/adc/ad7606.h
+++ b/drivers/iio/adc/ad7606.h
@@ -40,76 +40,6 @@
#define AD7606_RANGE_CH_ADDR(ch) (0x03 + ((ch) >> 1))
#define AD7606_OS_MODE 0x08
-#define AD760X_CHANNEL(num, mask_sep, mask_type, mask_all, \
- mask_sep_avail, mask_all_avail, bits) { \
- .type = IIO_VOLTAGE, \
- .indexed = 1, \
- .channel = num, \
- .info_mask_separate = mask_sep, \
- .info_mask_separate_available = \
- mask_sep_avail, \
- .info_mask_shared_by_type = mask_type, \
- .info_mask_shared_by_all = mask_all, \
- .info_mask_shared_by_all_available = \
- mask_all_avail, \
- .scan_index = num, \
- .scan_type = { \
- .sign = 's', \
- .realbits = (bits), \
- .storagebits = (bits) > 16 ? 32 : 16, \
- .endianness = IIO_CPU, \
- }, \
-}
-
-#define AD7606_SW_CHANNEL(num, bits) \
- AD760X_CHANNEL(num, \
- /* mask separate */ \
- BIT(IIO_CHAN_INFO_RAW) | \
- BIT(IIO_CHAN_INFO_SCALE), \
- /* mask type */ \
- BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
- /* mask all */ \
- 0, \
- /* mask separate available */ \
- BIT(IIO_CHAN_INFO_SCALE), \
- /* mask all available */ \
- BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
- bits)
-
-#define AD7605_CHANNEL(num) \
- AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \
- BIT(IIO_CHAN_INFO_SCALE), 0, 0, 0, 16)
-
-#define AD7606_CHANNEL(num, bits) \
- AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \
- BIT(IIO_CHAN_INFO_SCALE), \
- BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
- 0, 0, bits)
-
-#define AD7616_CHANNEL(num) AD7606_SW_CHANNEL(num, 16)
-
-#define AD7606_BI_CHANNEL(num) \
- AD760X_CHANNEL(num, 0, \
- BIT(IIO_CHAN_INFO_SCALE), \
- BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
- BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
- 0, 0, 16)
-
-#define AD7606_BI_SW_CHANNEL(num) \
- AD760X_CHANNEL(num, \
- /* mask separate */ \
- BIT(IIO_CHAN_INFO_SCALE), \
- /* mask type */ \
- 0, \
- /* mask all */ \
- BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
- BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
- /* mask separate available */ \
- BIT(IIO_CHAN_INFO_SCALE), \
- /* mask all available */ \
- BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
- 16)
-
struct ad7606_state;
typedef int (*ad7606_scale_setup_cb_t)(struct iio_dev *indio_dev,
@@ -118,10 +48,9 @@ typedef int (*ad7606_sw_setup_cb_t)(struct iio_dev *indio_dev);
/**
* struct ad7606_chip_info - chip specific information
- * @channels: channel specification
* @max_samplerate: maximum supported sample rate
* @name: device name
- * @num_channels: number of channels
+ * @bits: data width in bits
* @num_adc_channels: the number of channels the ADC actually inputs.
* @scale_setup_cb: callback to setup the scales for each channel
* @sw_setup_cb: callback to setup the software mode if available.
@@ -133,11 +62,10 @@ typedef int (*ad7606_sw_setup_cb_t)(struct iio_dev *indio_dev);
* after a restart
*/
struct ad7606_chip_info {
- const struct iio_chan_spec *channels;
unsigned int max_samplerate;
const char *name;
+ unsigned int bits;
unsigned int num_adc_channels;
- unsigned int num_channels;
ad7606_scale_setup_cb_t scale_setup_cb;
ad7606_sw_setup_cb_t sw_setup_cb;
const unsigned int *oversampling_avail;
diff --git a/drivers/iio/adc/ad7606_par.c b/drivers/iio/adc/ad7606_par.c
index 335fb481bfde15b79331eabdcbc970d70880338c..e33b07ab5eace4b78e7cf39ee7e8d9379c9f73e7 100644
--- a/drivers/iio/adc/ad7606_par.c
+++ b/drivers/iio/adc/ad7606_par.c
@@ -21,28 +21,6 @@
#include "ad7606.h"
#include "ad7606_bus_iface.h"
-static const struct iio_chan_spec ad7606b_bi_channels[] = {
- AD7606_BI_CHANNEL(0),
- AD7606_BI_CHANNEL(1),
- AD7606_BI_CHANNEL(2),
- AD7606_BI_CHANNEL(3),
- AD7606_BI_CHANNEL(4),
- AD7606_BI_CHANNEL(5),
- AD7606_BI_CHANNEL(6),
- AD7606_BI_CHANNEL(7),
-};
-
-static const struct iio_chan_spec ad7606b_bi_sw_channels[] = {
- AD7606_BI_SW_CHANNEL(0),
- AD7606_BI_SW_CHANNEL(1),
- AD7606_BI_SW_CHANNEL(2),
- AD7606_BI_SW_CHANNEL(3),
- AD7606_BI_SW_CHANNEL(4),
- AD7606_BI_SW_CHANNEL(5),
- AD7606_BI_SW_CHANNEL(6),
- AD7606_BI_SW_CHANNEL(7),
-};
-
static int ad7606_par_bus_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *scan_mask)
{
@@ -94,9 +72,6 @@ static int ad7606_par_bus_setup_iio_backend(struct device *dev,
return ret;
}
- indio_dev->channels = ad7606b_bi_channels;
- indio_dev->num_channels = 8;
-
return 0;
}
@@ -120,19 +95,11 @@ static int ad7606_par_bus_reg_write(struct ad7606_state *st, unsigned int addr,
return pdata->bus_reg_write(st->back, addr, val);
}
-static int ad7606_par_bus_sw_mode_config(struct iio_dev *indio_dev)
-{
- indio_dev->channels = ad7606b_bi_sw_channels;
-
- return 0;
-}
-
static const struct ad7606_bus_ops ad7606_bi_bops = {
.iio_backend_config = ad7606_par_bus_setup_iio_backend,
.update_scan_mode = ad7606_par_bus_update_scan_mode,
.reg_read = ad7606_par_bus_reg_read,
.reg_write = ad7606_par_bus_reg_write,
- .sw_mode_config = ad7606_par_bus_sw_mode_config,
};
static int ad7606_par16_read_block(struct device *dev,
diff --git a/drivers/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c
index 1abaf8626206cb30e532cf9f82e0d050706aa1e0..b2b975fb7fea4d1af6caef59e75ca495501bc140 100644
--- a/drivers/iio/adc/ad7606_spi.c
+++ b/drivers/iio/adc/ad7606_spi.c
@@ -15,50 +15,6 @@
#define MAX_SPI_FREQ_HZ 23500000 /* VDRIVE above 4.75 V */
-static const struct iio_chan_spec ad7616_sw_channels[] = {
- IIO_CHAN_SOFT_TIMESTAMP(16),
- AD7616_CHANNEL(0),
- AD7616_CHANNEL(1),
- AD7616_CHANNEL(2),
- AD7616_CHANNEL(3),
- AD7616_CHANNEL(4),
- AD7616_CHANNEL(5),
- AD7616_CHANNEL(6),
- AD7616_CHANNEL(7),
- AD7616_CHANNEL(8),
- AD7616_CHANNEL(9),
- AD7616_CHANNEL(10),
- AD7616_CHANNEL(11),
- AD7616_CHANNEL(12),
- AD7616_CHANNEL(13),
- AD7616_CHANNEL(14),
- AD7616_CHANNEL(15),
-};
-
-static const struct iio_chan_spec ad7606b_sw_channels[] = {
- IIO_CHAN_SOFT_TIMESTAMP(8),
- AD7606_SW_CHANNEL(0, 16),
- AD7606_SW_CHANNEL(1, 16),
- AD7606_SW_CHANNEL(2, 16),
- AD7606_SW_CHANNEL(3, 16),
- AD7606_SW_CHANNEL(4, 16),
- AD7606_SW_CHANNEL(5, 16),
- AD7606_SW_CHANNEL(6, 16),
- AD7606_SW_CHANNEL(7, 16),
-};
-
-static const struct iio_chan_spec ad7606c_18_sw_channels[] = {
- IIO_CHAN_SOFT_TIMESTAMP(8),
- AD7606_SW_CHANNEL(0, 18),
- AD7606_SW_CHANNEL(1, 18),
- AD7606_SW_CHANNEL(2, 18),
- AD7606_SW_CHANNEL(3, 18),
- AD7606_SW_CHANNEL(4, 18),
- AD7606_SW_CHANNEL(5, 18),
- AD7606_SW_CHANNEL(6, 18),
- AD7606_SW_CHANNEL(7, 18),
-};
-
static u16 ad7616_spi_rd_wr_cmd(int addr, char is_write_op)
{
/*
@@ -160,48 +116,13 @@ static int ad7606_spi_reg_write(struct ad7606_state *st,
return spi_write(spi, &st->d16[0], sizeof(st->d16[0]));
}
-static int ad7616_sw_mode_config(struct iio_dev *indio_dev)
-{
- /*
- * Scale can be configured individually for each channel
- * in software mode.
- */
- indio_dev->channels = ad7616_sw_channels;
-
- return 0;
-}
-
static int ad7606b_sw_mode_config(struct iio_dev *indio_dev)
{
struct ad7606_state *st = iio_priv(indio_dev);
- int ret;
/* Configure device spi to output on a single channel */
- ret = st->bops->reg_write(st, AD7606_CONFIGURATION_REGISTER,
- AD7606_SINGLE_DOUT);
- if (ret)
- return ret;
-
- /*
- * Scale can be configured individually for each channel
- * in software mode.
- */
- indio_dev->channels = ad7606b_sw_channels;
-
- return 0;
-}
-
-static int ad7606c_18_sw_mode_config(struct iio_dev *indio_dev)
-{
- int ret;
-
- ret = ad7606b_sw_mode_config(indio_dev);
- if (ret)
- return ret;
-
- indio_dev->channels = ad7606c_18_sw_channels;
-
- return 0;
+ return st->bops->reg_write(st, AD7606_CONFIGURATION_REGISTER,
+ AD7606_SINGLE_DOUT);
}
static const struct ad7606_bus_ops ad7606_spi_bops = {
@@ -221,7 +142,6 @@ static const struct ad7606_bus_ops ad7616_spi_bops = {
.reg_read = ad7606_spi_reg_read,
.reg_write = ad7606_spi_reg_write,
.rd_wr_cmd = ad7616_spi_rd_wr_cmd,
- .sw_mode_config = ad7616_sw_mode_config,
};
static const struct ad7606_bus_ops ad7606b_spi_bops = {
@@ -237,7 +157,7 @@ static const struct ad7606_bus_ops ad7606c_18_spi_bops = {
.reg_read = ad7606_spi_reg_read,
.reg_write = ad7606_spi_reg_write,
.rd_wr_cmd = ad7606b_spi_rd_wr_cmd,
- .sw_mode_config = ad7606c_18_sw_mode_config,
+ .sw_mode_config = ad7606b_sw_mode_config,
};
static const struct ad7606_bus_info ad7605_4_bus_info = {
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 11/11] iio: adc: ad7606_par: add ad7606c chips
2025-03-13 1:15 [PATCH 00/11] iio: adc: ad7606: improvements and ad7606c parallel interface support David Lechner
` (9 preceding siblings ...)
2025-03-13 1:15 ` [PATCH 10/11] iio: adc: ad7606: dynamically allocate channel info David Lechner
@ 2025-03-13 1:15 ` David Lechner
2025-03-13 21:11 ` [PATCH 00/11] iio: adc: ad7606: improvements and ad7606c parallel interface support Nuno Sá
11 siblings, 0 replies; 17+ messages in thread
From: David Lechner @ 2025-03-13 1:15 UTC (permalink / raw)
To: Jonathan Cameron, linux-iio
Cc: Michael Hennerich, Angelo Dureghello, Alexandru Ardelean,
Beniamin Bia, Stefan Popa, linux-kernel, David Lechner
Add lookup table entries for ad7606c-16 and ad7606c-18 chips.
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
drivers/iio/adc/ad7606_par.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/iio/adc/ad7606_par.c b/drivers/iio/adc/ad7606_par.c
index e33b07ab5eace4b78e7cf39ee7e8d9379c9f73e7..634852c4bbd2c531d6c0e02d2f1e62db9008cad9 100644
--- a/drivers/iio/adc/ad7606_par.c
+++ b/drivers/iio/adc/ad7606_par.c
@@ -222,6 +222,8 @@ static const struct platform_device_id ad7606_driver_ids[] = {
{ .name = "ad7606-6", .driver_data = (kernel_ulong_t)&ad7606_6_info, },
{ .name = "ad7606-8", .driver_data = (kernel_ulong_t)&ad7606_8_info, },
{ .name = "ad7606b", .driver_data = (kernel_ulong_t)&ad7606b_info, },
+ { .name = "ad7606c-16", .driver_data = (kernel_ulong_t)&ad7606c_16_info },
+ { .name = "ad7606c-18", .driver_data = (kernel_ulong_t)&ad7606c_18_info },
{ .name = "ad7607", .driver_data = (kernel_ulong_t)&ad7607_info, },
{ .name = "ad7608", .driver_data = (kernel_ulong_t)&ad7608_info, },
{ .name = "ad7609", .driver_data = (kernel_ulong_t)&ad7609_info, },
@@ -235,6 +237,8 @@ static const struct of_device_id ad7606_of_match[] = {
{ .compatible = "adi,ad7606-6", .data = &ad7606_6_info },
{ .compatible = "adi,ad7606-8", .data = &ad7606_8_info },
{ .compatible = "adi,ad7606b", .data = &ad7606b_info },
+ { .compatible = "adi,ad7606c-16", .data = &ad7606c_16_info },
+ { .compatible = "adi,ad7606c-18", .data = &ad7606c_18_info },
{ .compatible = "adi,ad7607", .data = &ad7607_info },
{ .compatible = "adi,ad7608", .data = &ad7608_info },
{ .compatible = "adi,ad7609", .data = &ad7609_info },
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 00/11] iio: adc: ad7606: improvements and ad7606c parallel interface support
2025-03-13 1:15 [PATCH 00/11] iio: adc: ad7606: improvements and ad7606c parallel interface support David Lechner
` (10 preceding siblings ...)
2025-03-13 1:15 ` [PATCH 11/11] iio: adc: ad7606_par: add ad7606c chips David Lechner
@ 2025-03-13 21:11 ` Nuno Sá
11 siblings, 0 replies; 17+ messages in thread
From: Nuno Sá @ 2025-03-13 21:11 UTC (permalink / raw)
To: David Lechner, Jonathan Cameron, linux-iio
Cc: Michael Hennerich, Angelo Dureghello, Alexandru Ardelean,
Beniamin Bia, Stefan Popa, linux-kernel
On Wed, 2025-03-12 at 20:15 -0500, David Lechner wrote:
> The main purpose of this series is to add support for the AD7606C chips
> using a parallel interface. Along the way quite a few improvements were
> made to the driver which in the end made adding the additional chips
> trivial.
>
> The first 3 patches are fixes. The next 6 are some minor cleanups. The
> 2nd to last patch is the big one. As explained in the respective commit
> message, the channel data structures were getting out of hand and only
> going to get worse with the addition of SPI offload support. Instead, we
> are opting to dynamically allocate the channel data structures to avoid
> a bunch of the existing complexity in the driver.
>
> I have limited access to hardware, so I was only able to test this with
> ad7606c-18.
>
> Signed-off-by: David Lechner <dlechner@baylibre.com>
> ---
Reviewed-by: Nuno Sá <nuno.sa@analog.com>
> David Lechner (11):
> iio: adc: ad7606_spi: check error in ad7606B_sw_mode_config()
> iio: adc: ad7606: check for NULL before calling sw_mode_config()
> iio: adc: ad7606: fix scales_available attributes
> iio: adc: ad7606: add missing max sample rates
> iio: adc: ad7606: use devm_mutex_init()
> iio: adc: ad7606: fix kernel-doc comments
> iio: adc: ad7606: use kernel identifier name style
> iio: adc: ad7606: don't use address field
> iio: adc: ad7606: drop ch param from ad7606_scale_setup_cb_t
> iio: adc: ad7606: dynamically allocate channel info
> iio: adc: ad7606_par: add ad7606c chips
>
> drivers/iio/adc/ad7606.c | 313 ++++++++++++++++++++-----------------------
> drivers/iio/adc/ad7606.h | 171 +++++++----------------
> drivers/iio/adc/ad7606_par.c | 37 +----
> drivers/iio/adc/ad7606_spi.c | 98 ++------------
> 4 files changed, 211 insertions(+), 408 deletions(-)
> ---
> base-commit: 97fe5f8a4299e4b8601ecb62c9672c27f2d2ccce
> change-id: 20250311-iio-adc-ad7606-improvements-997d7af218e3
>
> Best regards,
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 01/11] iio: adc: ad7606_spi: check error in ad7606B_sw_mode_config()
2025-03-13 1:15 ` [PATCH 01/11] iio: adc: ad7606_spi: check error in ad7606B_sw_mode_config() David Lechner
@ 2025-03-15 18:48 ` Jonathan Cameron
0 siblings, 0 replies; 17+ messages in thread
From: Jonathan Cameron @ 2025-03-15 18:48 UTC (permalink / raw)
To: David Lechner
Cc: linux-iio, Michael Hennerich, Angelo Dureghello,
Alexandru Ardelean, Beniamin Bia, Stefan Popa, linux-kernel
On Wed, 12 Mar 2025 20:15:39 -0500
David Lechner <dlechner@baylibre.com> wrote:
> Add missing error check in ad7606B_sw_mode_config().
>
> Fixes: d2a415c86c6b ("iio: adc: ad7606: Add support for AD7606B ADC")
Nice to have, but is there a path in which this happens other than
in hardware failure? If not probably not worth a fixes tag (which
tends to make people start backporting things).
> Signed-off-by: David Lechner <dlechner@baylibre.com>
> ---
> drivers/iio/adc/ad7606_spi.c | 8 +++++---
> 1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c
> index 885bf0b68e7775c5f4a12dfb827f502d5f782e8c..c028e08efe2c82cd97249f98eec50a9a9c06471f 100644
> --- a/drivers/iio/adc/ad7606_spi.c
> +++ b/drivers/iio/adc/ad7606_spi.c
> @@ -174,11 +174,13 @@ static int ad7616_sw_mode_config(struct iio_dev *indio_dev)
> static int ad7606B_sw_mode_config(struct iio_dev *indio_dev)
> {
> struct ad7606_state *st = iio_priv(indio_dev);
> + int ret;
>
> /* Configure device spi to output on a single channel */
> - st->bops->reg_write(st,
> - AD7606_CONFIGURATION_REGISTER,
> - AD7606_SINGLE_DOUT);
> + ret = st->bops->reg_write(st, AD7606_CONFIGURATION_REGISTER,
> + AD7606_SINGLE_DOUT);
> + if (ret)
> + return ret;
>
> /*
> * Scale can be configured individually for each channel
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 05/11] iio: adc: ad7606: use devm_mutex_init()
2025-03-13 1:15 ` [PATCH 05/11] iio: adc: ad7606: use devm_mutex_init() David Lechner
@ 2025-03-15 18:52 ` Jonathan Cameron
0 siblings, 0 replies; 17+ messages in thread
From: Jonathan Cameron @ 2025-03-15 18:52 UTC (permalink / raw)
To: David Lechner
Cc: linux-iio, Michael Hennerich, Angelo Dureghello,
Alexandru Ardelean, Beniamin Bia, Stefan Popa, linux-kernel
On Wed, 12 Mar 2025 20:15:43 -0500
David Lechner <dlechner@baylibre.com> wrote:
> Use devm_mutex_init() in ad7606_probe(). Mutexes should be cleaned up
> on driver removal.
>
> Also add missing include while we are touching this.
>
> Signed-off-by: David Lechner <dlechner@baylibre.com>
Just for the record (in case anyone other than us two is watching ;)
I'm not keen to have large numbers of patches doing this at this
point as the benefit in debug ability this brings is pretty tiny.
I'm absolutely fine with it in a series making other cleanup
type changes to a driver though - so fine here!
Note I will probably pick up the fixes soon after rc1 given
some look pretty important. That means stuff like this may have
to wait a while for the fixes to circulate around to the char-misc-next branch.
Jonathan
> ---
> drivers/iio/adc/ad7606.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c
> index 440e1e5a9b18570dc6441bff91afbc51d20cbc47..f190269ac8ddd859e94eb24c26f5f010d0951646 100644
> --- a/drivers/iio/adc/ad7606.c
> +++ b/drivers/iio/adc/ad7606.c
> @@ -13,6 +13,7 @@
> #include <linux/interrupt.h>
> #include <linux/kernel.h>
> #include <linux/module.h>
> +#include <linux/mutex.h>
> #include <linux/property.h>
> #include <linux/pwm.h>
> #include <linux/regulator/consumer.h>
> @@ -1332,8 +1333,11 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
> st = iio_priv(indio_dev);
> dev_set_drvdata(dev, indio_dev);
>
> + ret = devm_mutex_init(dev, &st->lock);
> + if (ret)
> + return ret;
> +
> st->dev = dev;
> - mutex_init(&st->lock);
> st->bops = bops;
> st->base_address = base_address;
> st->oversampling = 1;
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 06/11] iio: adc: ad7606: fix kernel-doc comments
2025-03-13 1:15 ` [PATCH 06/11] iio: adc: ad7606: fix kernel-doc comments David Lechner
@ 2025-03-15 18:55 ` Jonathan Cameron
0 siblings, 0 replies; 17+ messages in thread
From: Jonathan Cameron @ 2025-03-15 18:55 UTC (permalink / raw)
To: David Lechner
Cc: linux-iio, Michael Hennerich, Angelo Dureghello,
Alexandru Ardelean, Beniamin Bia, Stefan Popa, linux-kernel
On Wed, 12 Mar 2025 20:15:44 -0500
David Lechner <dlechner@baylibre.com> wrote:
> Fix several issues with kernel-doc comments in ad7606.h:
> * Add missing ":" to @param names.
> * Add some missing parameters.
> * Remove some non-existent parameters.
> * Fix alignment and wrapping.
> * Fix some spelling.
>
> `./scripts/kernel-doc -v -none drivers/iio/adc/ad7606*` is happy now.
>
> Signed-off-by: David Lechner <dlechner@baylibre.com>
> ---
> drivers/iio/adc/ad7606.h | 90 ++++++++++++++++++++++++------------------------
> 1 file changed, 45 insertions(+), 45 deletions(-)
>
> diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h
> index 71a30525eaab512fa811f28fa79268a1a976bc8c..3da78488c8a247dccbff930023f98717d540081a 100644
> --- a/drivers/iio/adc/ad7606.h
> +++ b/drivers/iio/adc/ad7606.h
> @@ -120,17 +120,17 @@ typedef int (*ad7606_sw_setup_cb_t)(struct iio_dev *indio_dev);
> /**
> * struct ad7606_chip_info - chip specific information
> * @channels: channel specification
> - * @max_samplerate: maximum supported samplerate
> - * @name device name
> + * @max_samplerate: maximum supported sample rate
> + * @name: device name
> * @num_channels: number of channels
> - * @num_adc_channels the number of channels the ADC actually inputs.
> + * @num_adc_channels: the number of channels the ADC actually inputs.
What does that mean? ADCs don't input channels, they have channels which
are inputs. Turns out I don't read the docs closely enough whilst reviewing ;)
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 10/11] iio: adc: ad7606: dynamically allocate channel info
2025-03-13 1:15 ` [PATCH 10/11] iio: adc: ad7606: dynamically allocate channel info David Lechner
@ 2025-03-15 19:02 ` Jonathan Cameron
0 siblings, 0 replies; 17+ messages in thread
From: Jonathan Cameron @ 2025-03-15 19:02 UTC (permalink / raw)
To: David Lechner
Cc: linux-iio, Michael Hennerich, Angelo Dureghello,
Alexandru Ardelean, Beniamin Bia, Stefan Popa, linux-kernel
On Wed, 12 Mar 2025 20:15:48 -0500
David Lechner <dlechner@baylibre.com> wrote:
> Refactor the ad7606 drivers to dynamically allocate the channel info.
>
> The channel info was getting a bit unwieldy. In some cases, the
> indio_dev->channels field was getting assigned up to 3 different times,
> each in a different function, making it difficult to see where the info
> was coming from. This problem stemps from the number of permutations of
> the channel array needed to support various modes of operation and data
> buses. We already have 4 per chip (hardware mode, software mode, AXI ADC
> backend and AXI ADC backend with software mode) and we intend to add two
> more per chip when adding SPI offload support.
>
> To make it easier to read and maintain, move all of the channel setup
> to a single function that dynamically allocates and fills in the channel
> info.
>
> Additionally, this lets us remove some hacks where we had to compute an
> offset due to the fact that sometimes there was a soft timestamp channel
> at the start of the array. Now the timestamp channel is always at the
> end of the array as is typical in other drivers.
>
> Signed-off-by: David Lechner <dlechner@baylibre.com>
whilst I like static const channel arrays it is hard to argue with the logic
that it got too complex here so fair enough.
A few trivial things inline.
Jonathan
> @@ -1289,29 +1193,84 @@ static int ad7606b_sw_mode_setup(struct iio_dev *indio_dev)
> return st->bops->sw_mode_config(indio_dev);
> }
>
> -static int ad7606_chan_scales_setup(struct iio_dev *indio_dev)
> +static int ad7606_probe_channels(struct iio_dev *indio_dev)
> {
> struct ad7606_state *st = iio_priv(indio_dev);
> - unsigned int offset = indio_dev->num_channels - st->chip_info->num_adc_channels;
> - struct iio_chan_spec *chans;
> - size_t size;
> - int ch, ret;
> -
> - /* Clone IIO channels, since some may be differential */
> - size = indio_dev->num_channels * sizeof(*indio_dev->channels);
> - chans = devm_kzalloc(st->dev, size, GFP_KERNEL);
> - if (!chans)
> + struct device *dev = indio_dev->dev.parent;
> + struct iio_chan_spec *channels;
> + bool slow_bus;
> + int ret, i;
> +
> + slow_bus = !st->bops->iio_backend_config;
Maybe inline with declaration?
bool slow_bus = !st->...
> + indio_dev->num_channels = st->chip_info->num_adc_channels;
> +
> + /* Slow buses also get 1 more channel for soft timestamp */
> + if (slow_bus)
> + indio_dev->num_channels++;
> +
> + channels = devm_kcalloc(dev, indio_dev->num_channels, sizeof(*channels),
> + GFP_KERNEL);
> + if (!channels)
> return -ENOMEM;
>
> - memcpy(chans, indio_dev->channels, size);
> - indio_dev->channels = chans;
> + for (i = 0; i < indio_dev->num_channels; i++) {
> + struct iio_chan_spec *chan = &channels[i];
>
> - for (ch = 0; ch < st->chip_info->num_adc_channels; ch++) {
> - ret = st->chip_info->scale_setup_cb(indio_dev, &chans[ch + offset]);
> + chan->type = IIO_VOLTAGE;
> + chan->indexed = 1;
> + chan->channel = i;
> + chan->scan_index = i;
> + chan->scan_type.sign = 's';
> + chan->scan_type.realbits = st->chip_info->bits;
> + chan->scan_type.storagebits = st->chip_info->bits > 16 ? 32 : 16;
> + chan->scan_type.endianness = IIO_CPU;
> +
> + if (indio_dev->modes & INDIO_DIRECT_MODE)
> + chan->info_mask_separate |= BIT(IIO_CHAN_INFO_RAW);
> +
> + if (st->sw_mode_en) {
> + chan->info_mask_separate |= BIT(IIO_CHAN_INFO_SCALE);
> + chan->info_mask_separate_available |=
> + BIT(IIO_CHAN_INFO_SCALE);
> +
> + /**
/* probably more appropriate here.
> + * All chips with software mode support oversampling,
> + * so we skip the oversampling_available check. And the
> + * shared_by_type instead of shared_by_all on slow
> + * buses is for backward compatibility.
> + */
> + if (slow_bus)
> + chan->info_mask_shared_by_type |=
> + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO);
> + else
> + chan->info_mask_shared_by_all |=
> + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO);
> +
> + chan->info_mask_shared_by_all_available |=
> + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO);
> + } else {
> + chan->info_mask_shared_by_type |=
> + BIT(IIO_CHAN_INFO_SCALE);
> +
> + if (st->chip_info->oversampling_avail)
> + chan->info_mask_shared_by_all |=
> + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO);
> + }
> +
> + if (!slow_bus)
> + chan->info_mask_shared_by_all |=
> + BIT(IIO_CHAN_INFO_SAMP_FREQ);
> +
> + ret = st->chip_info->scale_setup_cb(indio_dev, chan);
> if (ret)
> return ret;
> }
>
> + if (slow_bus)
> + channels[i] = (struct iio_chan_spec)IIO_CHAN_SOFT_TIMESTAMP(i);
> +
> + indio_dev->channels = channels;
> +
> return 0;
> }
> diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h
> index fd4c0d615a880ac6fdcaad213d4843329c3bd7fe..b67058cd021a3d00ff0f461766d51e46d7998f32 100644
> --- a/drivers/iio/adc/ad7606.h
> +++ b/drivers/iio/adc/ad7606.h
> typedef int (*ad7606_scale_setup_cb_t)(struct iio_dev *indio_dev,
> @@ -118,10 +48,9 @@ typedef int (*ad7606_sw_setup_cb_t)(struct iio_dev *indio_dev);
>
> /**
> * struct ad7606_chip_info - chip specific information
> - * @channels: channel specification
> * @max_samplerate: maximum supported sample rate
> * @name: device name
> - * @num_channels: number of channels
> + * @bits: data width in bits
Hmm. Was previously in the wrong order. Maybe fix that in your
earlier cleanup then this will look more natural.
> * @num_adc_channels: the number of channels the ADC actually inputs.
> * @scale_setup_cb: callback to setup the scales for each channel
> * @sw_setup_cb: callback to setup the software mode if available.
> @@ -133,11 +62,10 @@ typedef int (*ad7606_sw_setup_cb_t)(struct iio_dev *indio_dev);
> * after a restart
> */
> struct ad7606_chip_info {
> - const struct iio_chan_spec *channels;
> unsigned int max_samplerate;
> const char *name;
> + unsigned int bits;
> unsigned int num_adc_channels;
> - unsigned int num_channels;
> ad7606_scale_setup_cb_t scale_setup_cb;
> ad7606_sw_setup_cb_t sw_setup_cb;
> const unsigned int *oversampling_avail;
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2025-03-15 19:02 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-13 1:15 [PATCH 00/11] iio: adc: ad7606: improvements and ad7606c parallel interface support David Lechner
2025-03-13 1:15 ` [PATCH 01/11] iio: adc: ad7606_spi: check error in ad7606B_sw_mode_config() David Lechner
2025-03-15 18:48 ` Jonathan Cameron
2025-03-13 1:15 ` [PATCH 02/11] iio: adc: ad7606: check for NULL before calling sw_mode_config() David Lechner
2025-03-13 1:15 ` [PATCH 03/11] iio: adc: ad7606: fix scales_available attributes David Lechner
2025-03-13 1:15 ` [PATCH 04/11] iio: adc: ad7606: add missing max sample rates David Lechner
2025-03-13 1:15 ` [PATCH 05/11] iio: adc: ad7606: use devm_mutex_init() David Lechner
2025-03-15 18:52 ` Jonathan Cameron
2025-03-13 1:15 ` [PATCH 06/11] iio: adc: ad7606: fix kernel-doc comments David Lechner
2025-03-15 18:55 ` Jonathan Cameron
2025-03-13 1:15 ` [PATCH 07/11] iio: adc: ad7606: use kernel identifier name style David Lechner
2025-03-13 1:15 ` [PATCH 08/11] iio: adc: ad7606: don't use address field David Lechner
2025-03-13 1:15 ` [PATCH 09/11] iio: adc: ad7606: drop ch param from ad7606_scale_setup_cb_t David Lechner
2025-03-13 1:15 ` [PATCH 10/11] iio: adc: ad7606: dynamically allocate channel info David Lechner
2025-03-15 19:02 ` Jonathan Cameron
2025-03-13 1:15 ` [PATCH 11/11] iio: adc: ad7606_par: add ad7606c chips David Lechner
2025-03-13 21:11 ` [PATCH 00/11] iio: adc: ad7606: improvements and ad7606c parallel interface support Nuno Sá
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).