* [PATCH v6 0/8] *** Add support for AD485x DAS Family ***
@ 2024-11-11 12:11 Antoniu Miclaus
2024-11-11 12:11 ` [PATCH v6 1/8] iio: backend: add API for interface get Antoniu Miclaus
` (7 more replies)
0 siblings, 8 replies; 19+ messages in thread
From: Antoniu Miclaus @ 2024-11-11 12:11 UTC (permalink / raw)
To: jic23, robh, conor+dt, dlechner, linux-iio, devicetree,
linux-kernel, linux-pwm
Cc: Antoniu Miclaus
Add support for AD485X fully buffered, 8-channel simultaneous sampling,
16/20-bit, 1 MSPS data acquisition system (DAS) with differential, wide
common-mode range inputs.
Some particularities:
1. softspan - the devices support multiple softspans which are represented in iio
through offset/scale. The current handling implies changing both
the scale and the offset separately via IIO, therefore in order to
properly set the softspan, each time the offset changes the softspan
is set to the default value. And only after changing also the scale
the desired softspan is set. This is the approach we are suggesting
since we need the softspan configurable from userspace and not from
devicetree.
2. packet format - Data provided on the CMOS and LVDS conversion data output buses
are packaged into eight channel packets. This is currently handled
as extended info.
Antoniu Miclaus (8):
iio: backend: add API for interface get
iio: backend: add support for data size set
iio: backend: add API for oversampling
iio: adc: adi-axi-adc: add interface type
iio: adc: adi-axi-adc: set data format
iio: adc: adi-axi-adc: add oversampling
dt-bindings: iio: adc: add ad4851
iio: adc: ad4851: add ad485x driver
.../bindings/iio/adc/adi,ad4851.yaml | 103 ++
drivers/iio/adc/Kconfig | 13 +
drivers/iio/adc/Makefile | 1 +
drivers/iio/adc/ad4851.c | 1190 +++++++++++++++++
drivers/iio/adc/adi-axi-adc.c | 63 +
drivers/iio/industrialio-backend.c | 59 +
include/linux/iio/backend.h | 17 +
7 files changed, 1446 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ad4851.yaml
create mode 100644 drivers/iio/adc/ad4851.c
--
2.47.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v6 1/8] iio: backend: add API for interface get
2024-11-11 12:11 [PATCH v6 0/8] *** Add support for AD485x DAS Family *** Antoniu Miclaus
@ 2024-11-11 12:11 ` Antoniu Miclaus
2024-11-11 12:11 ` [PATCH v6 2/8] iio: backend: add support for data size set Antoniu Miclaus
` (6 subsequent siblings)
7 siblings, 0 replies; 19+ messages in thread
From: Antoniu Miclaus @ 2024-11-11 12:11 UTC (permalink / raw)
To: jic23, robh, conor+dt, dlechner, linux-iio, devicetree,
linux-kernel, linux-pwm
Cc: Antoniu Miclaus
Add backend support for obtaining the interface type used.
Reviewed-by: David Lechner <dlechner@baylibre.com>
Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
---
no changes in v6.
drivers/iio/industrialio-backend.c | 24 ++++++++++++++++++++++++
include/linux/iio/backend.h | 11 +++++++++++
2 files changed, 35 insertions(+)
diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c
index 20b3b5212da7..c792cd1e24e8 100644
--- a/drivers/iio/industrialio-backend.c
+++ b/drivers/iio/industrialio-backend.c
@@ -636,6 +636,30 @@ ssize_t iio_backend_ext_info_set(struct iio_dev *indio_dev, uintptr_t private,
}
EXPORT_SYMBOL_NS_GPL(iio_backend_ext_info_set, IIO_BACKEND);
+/**
+ * iio_backend_interface_type_get - get the interface type used.
+ * @back: Backend device
+ * @type: Interface type
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_interface_type_get(struct iio_backend *back,
+ enum iio_backend_interface_type *type)
+{
+ int ret;
+
+ ret = iio_backend_op_call(back, interface_type_get, type);
+ if (ret)
+ return ret;
+
+ if (*type >= IIO_BACKEND_INTERFACE_MAX)
+ return -EINVAL;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_interface_type_get, IIO_BACKEND);
+
/**
* iio_backend_extend_chan_spec - Extend an IIO channel
* @back: Backend device
diff --git a/include/linux/iio/backend.h b/include/linux/iio/backend.h
index 37d56914d485..e5ea90f1c3e0 100644
--- a/include/linux/iio/backend.h
+++ b/include/linux/iio/backend.h
@@ -68,6 +68,12 @@ enum iio_backend_sample_trigger {
IIO_BACKEND_SAMPLE_TRIGGER_MAX
};
+enum iio_backend_interface_type {
+ IIO_BACKEND_INTERFACE_SERIAL_LVDS,
+ IIO_BACKEND_INTERFACE_SERIAL_CMOS,
+ IIO_BACKEND_INTERFACE_MAX
+};
+
/**
* struct iio_backend_ops - operations structure for an iio_backend
* @enable: Enable backend.
@@ -86,6 +92,7 @@ enum iio_backend_sample_trigger {
* @extend_chan_spec: Extend an IIO channel.
* @ext_info_set: Extended info setter.
* @ext_info_get: Extended info getter.
+ * @interface_type_get: Interface type.
* @read_raw: Read a channel attribute from a backend device
* @debugfs_print_chan_status: Print channel status into a buffer.
* @debugfs_reg_access: Read or write register value of backend.
@@ -121,6 +128,8 @@ struct iio_backend_ops {
const char *buf, size_t len);
int (*ext_info_get)(struct iio_backend *back, uintptr_t private,
const struct iio_chan_spec *chan, char *buf);
+ int (*interface_type_get)(struct iio_backend *back,
+ enum iio_backend_interface_type *type);
int (*read_raw)(struct iio_backend *back,
struct iio_chan_spec const *chan, int *val, int *val2,
long mask);
@@ -169,6 +178,8 @@ ssize_t iio_backend_ext_info_set(struct iio_dev *indio_dev, uintptr_t private,
const char *buf, size_t len);
ssize_t iio_backend_ext_info_get(struct iio_dev *indio_dev, uintptr_t private,
const struct iio_chan_spec *chan, char *buf);
+int iio_backend_interface_type_get(struct iio_backend *back,
+ enum iio_backend_interface_type *type);
int iio_backend_read_raw(struct iio_backend *back,
struct iio_chan_spec const *chan, int *val, int *val2,
long mask);
--
2.47.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v6 2/8] iio: backend: add support for data size set
2024-11-11 12:11 [PATCH v6 0/8] *** Add support for AD485x DAS Family *** Antoniu Miclaus
2024-11-11 12:11 ` [PATCH v6 1/8] iio: backend: add API for interface get Antoniu Miclaus
@ 2024-11-11 12:11 ` Antoniu Miclaus
2024-11-11 12:11 ` [PATCH v6 3/8] iio: backend: add API for oversampling Antoniu Miclaus
` (5 subsequent siblings)
7 siblings, 0 replies; 19+ messages in thread
From: Antoniu Miclaus @ 2024-11-11 12:11 UTC (permalink / raw)
To: jic23, robh, conor+dt, dlechner, linux-iio, devicetree,
linux-kernel, linux-pwm
Cc: Antoniu Miclaus
Add backend support for setting the data size used.
This setting can be adjusted within the IP cores interfacing devices.
Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
---
changes in v6:
- drop size_t
drivers/iio/industrialio-backend.c | 21 +++++++++++++++++++++
include/linux/iio/backend.h | 3 +++
2 files changed, 24 insertions(+)
diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c
index c792cd1e24e8..ea184fc2c838 100644
--- a/drivers/iio/industrialio-backend.c
+++ b/drivers/iio/industrialio-backend.c
@@ -660,6 +660,27 @@ int iio_backend_interface_type_get(struct iio_backend *back,
}
EXPORT_SYMBOL_NS_GPL(iio_backend_interface_type_get, IIO_BACKEND);
+/**
+ * iio_backend_data_size_set - set the data width/size in the data bus.
+ * @back: Backend device
+ * @size: Size in bits
+ *
+ * Some frontend devices can dynamically control the word/data size on the
+ * interface/data bus. Hence, the backend device needs to be aware of it so
+ * data can be correctly transferred.
+ *
+ * Return:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_data_size_set(struct iio_backend *back, unsigned int size)
+{
+ if (!size)
+ return -EINVAL;
+
+ return iio_backend_op_call(back, data_size_set, size);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_data_size_set, IIO_BACKEND);
+
/**
* iio_backend_extend_chan_spec - Extend an IIO channel
* @back: Backend device
diff --git a/include/linux/iio/backend.h b/include/linux/iio/backend.h
index e5ea90f1c3e0..59b6651b7eaf 100644
--- a/include/linux/iio/backend.h
+++ b/include/linux/iio/backend.h
@@ -93,6 +93,7 @@ enum iio_backend_interface_type {
* @ext_info_set: Extended info setter.
* @ext_info_get: Extended info getter.
* @interface_type_get: Interface type.
+ * @data_size_set: Data size.
* @read_raw: Read a channel attribute from a backend device
* @debugfs_print_chan_status: Print channel status into a buffer.
* @debugfs_reg_access: Read or write register value of backend.
@@ -130,6 +131,7 @@ struct iio_backend_ops {
const struct iio_chan_spec *chan, char *buf);
int (*interface_type_get)(struct iio_backend *back,
enum iio_backend_interface_type *type);
+ int (*data_size_set)(struct iio_backend *back, unsigned int size);
int (*read_raw)(struct iio_backend *back,
struct iio_chan_spec const *chan, int *val, int *val2,
long mask);
@@ -180,6 +182,7 @@ ssize_t iio_backend_ext_info_get(struct iio_dev *indio_dev, uintptr_t private,
const struct iio_chan_spec *chan, char *buf);
int iio_backend_interface_type_get(struct iio_backend *back,
enum iio_backend_interface_type *type);
+int iio_backend_data_size_set(struct iio_backend *back, unsigned int size);
int iio_backend_read_raw(struct iio_backend *back,
struct iio_chan_spec const *chan, int *val, int *val2,
long mask);
--
2.47.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v6 3/8] iio: backend: add API for oversampling
2024-11-11 12:11 [PATCH v6 0/8] *** Add support for AD485x DAS Family *** Antoniu Miclaus
2024-11-11 12:11 ` [PATCH v6 1/8] iio: backend: add API for interface get Antoniu Miclaus
2024-11-11 12:11 ` [PATCH v6 2/8] iio: backend: add support for data size set Antoniu Miclaus
@ 2024-11-11 12:11 ` Antoniu Miclaus
2024-11-11 15:41 ` Nuno Sá
2024-11-11 12:11 ` [PATCH v6 4/8] iio: adc: adi-axi-adc: add interface type Antoniu Miclaus
` (4 subsequent siblings)
7 siblings, 1 reply; 19+ messages in thread
From: Antoniu Miclaus @ 2024-11-11 12:11 UTC (permalink / raw)
To: jic23, robh, conor+dt, dlechner, linux-iio, devicetree,
linux-kernel, linux-pwm
Cc: Antoniu Miclaus
Add backend support for enabling/disabling oversampling.
Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
---
changes in v6:
- add iio backend commit for oversampling enable/disable
drivers/iio/industrialio-backend.c | 14 ++++++++++++++
include/linux/iio/backend.h | 3 +++
2 files changed, 17 insertions(+)
diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c
index ea184fc2c838..6ba445ba3dd0 100644
--- a/drivers/iio/industrialio-backend.c
+++ b/drivers/iio/industrialio-backend.c
@@ -681,6 +681,20 @@ int iio_backend_data_size_set(struct iio_backend *back, unsigned int size)
}
EXPORT_SYMBOL_NS_GPL(iio_backend_data_size_set, IIO_BACKEND);
+/**
+ * iio_backend_oversampling_en - set the data width/size in the data bus.
+ * @back: Backend device
+ * @en: oversampling enabled/disabled.
+ *
+ * Return:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_oversampling_en(struct iio_backend *back, bool en)
+{
+ return iio_backend_op_call(back, oversampling_en, en);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_oversampling_en, IIO_BACKEND);
+
/**
* iio_backend_extend_chan_spec - Extend an IIO channel
* @back: Backend device
diff --git a/include/linux/iio/backend.h b/include/linux/iio/backend.h
index 59b6651b7eaf..b8f63823b3db 100644
--- a/include/linux/iio/backend.h
+++ b/include/linux/iio/backend.h
@@ -94,6 +94,7 @@ enum iio_backend_interface_type {
* @ext_info_get: Extended info getter.
* @interface_type_get: Interface type.
* @data_size_set: Data size.
+ * @oversampling_en: Oversampling.
* @read_raw: Read a channel attribute from a backend device
* @debugfs_print_chan_status: Print channel status into a buffer.
* @debugfs_reg_access: Read or write register value of backend.
@@ -132,6 +133,7 @@ struct iio_backend_ops {
int (*interface_type_get)(struct iio_backend *back,
enum iio_backend_interface_type *type);
int (*data_size_set)(struct iio_backend *back, unsigned int size);
+ int (*oversampling_en)(struct iio_backend *back, bool en);
int (*read_raw)(struct iio_backend *back,
struct iio_chan_spec const *chan, int *val, int *val2,
long mask);
@@ -183,6 +185,7 @@ ssize_t iio_backend_ext_info_get(struct iio_dev *indio_dev, uintptr_t private,
int iio_backend_interface_type_get(struct iio_backend *back,
enum iio_backend_interface_type *type);
int iio_backend_data_size_set(struct iio_backend *back, unsigned int size);
+int iio_backend_oversampling_en(struct iio_backend *back, bool en);
int iio_backend_read_raw(struct iio_backend *back,
struct iio_chan_spec const *chan, int *val, int *val2,
long mask);
--
2.47.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v6 4/8] iio: adc: adi-axi-adc: add interface type
2024-11-11 12:11 [PATCH v6 0/8] *** Add support for AD485x DAS Family *** Antoniu Miclaus
` (2 preceding siblings ...)
2024-11-11 12:11 ` [PATCH v6 3/8] iio: backend: add API for oversampling Antoniu Miclaus
@ 2024-11-11 12:11 ` Antoniu Miclaus
2024-11-11 12:12 ` [PATCH v6 5/8] iio: adc: adi-axi-adc: set data format Antoniu Miclaus
` (3 subsequent siblings)
7 siblings, 0 replies; 19+ messages in thread
From: Antoniu Miclaus @ 2024-11-11 12:11 UTC (permalink / raw)
To: jic23, robh, conor+dt, dlechner, linux-iio, devicetree,
linux-kernel, linux-pwm
Cc: Antoniu Miclaus
Add support for getting the interface (CMOS or LVDS) used by the AXI ADC
IP.
Reviewed-by: David Lechner <dlechner@baylibre.com>
Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
---
no changes in v6.
drivers/iio/adc/adi-axi-adc.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
index 5c8c87eb36d1..f6475bc93796 100644
--- a/drivers/iio/adc/adi-axi-adc.c
+++ b/drivers/iio/adc/adi-axi-adc.c
@@ -39,6 +39,9 @@
#define ADI_AXI_REG_RSTN_MMCM_RSTN BIT(1)
#define ADI_AXI_REG_RSTN_RSTN BIT(0)
+#define ADI_AXI_ADC_REG_CONFIG 0x000c
+#define ADI_AXI_ADC_REG_CONFIG_CMOS_OR_LVDS_N BIT(7)
+
#define ADI_AXI_ADC_REG_CTRL 0x0044
#define ADI_AXI_ADC_CTRL_DDR_EDGESEL_MASK BIT(1)
@@ -290,6 +293,25 @@ static int axi_adc_chan_disable(struct iio_backend *back, unsigned int chan)
ADI_AXI_REG_CHAN_CTRL_ENABLE);
}
+static int axi_adc_interface_type_get(struct iio_backend *back,
+ enum iio_backend_interface_type *type)
+{
+ struct adi_axi_adc_state *st = iio_backend_get_priv(back);
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(st->regmap, ADI_AXI_ADC_REG_CONFIG, &val);
+ if (ret)
+ return ret;
+
+ if (val & ADI_AXI_ADC_REG_CONFIG_CMOS_OR_LVDS_N)
+ *type = IIO_BACKEND_INTERFACE_SERIAL_CMOS;
+ else
+ *type = IIO_BACKEND_INTERFACE_SERIAL_LVDS;
+
+ return 0;
+}
+
static struct iio_buffer *axi_adc_request_buffer(struct iio_backend *back,
struct iio_dev *indio_dev)
{
@@ -337,6 +359,7 @@ static const struct iio_backend_ops adi_axi_adc_ops = {
.iodelay_set = axi_adc_iodelays_set,
.test_pattern_set = axi_adc_test_pattern_set,
.chan_status = axi_adc_chan_status,
+ .interface_type_get = axi_adc_interface_type_get,
.debugfs_reg_access = iio_backend_debugfs_ptr(axi_adc_reg_access),
.debugfs_print_chan_status = iio_backend_debugfs_ptr(axi_adc_debugfs_print_chan_status),
};
--
2.47.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v6 5/8] iio: adc: adi-axi-adc: set data format
2024-11-11 12:11 [PATCH v6 0/8] *** Add support for AD485x DAS Family *** Antoniu Miclaus
` (3 preceding siblings ...)
2024-11-11 12:11 ` [PATCH v6 4/8] iio: adc: adi-axi-adc: add interface type Antoniu Miclaus
@ 2024-11-11 12:12 ` Antoniu Miclaus
2024-11-12 20:11 ` David Lechner
2024-11-11 12:12 ` [PATCH v6 6/8] iio: adc: adi-axi-adc: add oversampling Antoniu Miclaus
` (2 subsequent siblings)
7 siblings, 1 reply; 19+ messages in thread
From: Antoniu Miclaus @ 2024-11-11 12:12 UTC (permalink / raw)
To: jic23, robh, conor+dt, dlechner, linux-iio, devicetree,
linux-kernel, linux-pwm
Cc: Antoniu Miclaus
Add support for selecting the data format within the AXI ADC ip.
Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
---
changes in v6:
- use switch case
- add macro definition for packet format mask and sizes
drivers/iio/adc/adi-axi-adc.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
index f6475bc93796..9bf967d5b730 100644
--- a/drivers/iio/adc/adi-axi-adc.c
+++ b/drivers/iio/adc/adi-axi-adc.c
@@ -45,6 +45,12 @@
#define ADI_AXI_ADC_REG_CTRL 0x0044
#define ADI_AXI_ADC_CTRL_DDR_EDGESEL_MASK BIT(1)
+#define ADI_AXI_ADC_REG_CNTRL_3 0x004c
+#define AD485X_CNTRL_3_CUSTOM_CTRL_PACKET_FORMAT_MSK GENMASK(1, 0)
+#define AD485X_PACKET_FORMAT_20BIT 0x0
+#define AD485X_PACKET_FORMAT_24BIT 0x1
+#define AD485X_PACKET_FORMAT_32BIT 0x2
+
#define ADI_AXI_ADC_REG_DRP_STATUS 0x0074
#define ADI_AXI_ADC_DRP_LOCKED BIT(17)
@@ -312,6 +318,29 @@ static int axi_adc_interface_type_get(struct iio_backend *back,
return 0;
}
+static int axi_adc_data_size_set(struct iio_backend *back, unsigned int size)
+{
+ struct adi_axi_adc_state *st = iio_backend_get_priv(back);
+ unsigned int val;
+
+ switch (size) {
+ case 20:
+ val = AD485X_PACKET_FORMAT_20BIT;
+ break;
+ case 24:
+ val = AD485X_PACKET_FORMAT_24BIT;
+ break;
+ case 32:
+ val = AD485X_PACKET_FORMAT_32BIT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(st->regmap, ADI_AXI_ADC_REG_CNTRL_3,
+ AD485X_CNTRL_3_CUSTOM_CTRL_PACKET_FORMAT_MSK, val);
+}
+
static struct iio_buffer *axi_adc_request_buffer(struct iio_backend *back,
struct iio_dev *indio_dev)
{
@@ -360,6 +389,7 @@ static const struct iio_backend_ops adi_axi_adc_ops = {
.test_pattern_set = axi_adc_test_pattern_set,
.chan_status = axi_adc_chan_status,
.interface_type_get = axi_adc_interface_type_get,
+ .data_size_set = axi_adc_data_size_set,
.debugfs_reg_access = iio_backend_debugfs_ptr(axi_adc_reg_access),
.debugfs_print_chan_status = iio_backend_debugfs_ptr(axi_adc_debugfs_print_chan_status),
};
--
2.47.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v6 6/8] iio: adc: adi-axi-adc: add oversampling
2024-11-11 12:11 [PATCH v6 0/8] *** Add support for AD485x DAS Family *** Antoniu Miclaus
` (4 preceding siblings ...)
2024-11-11 12:12 ` [PATCH v6 5/8] iio: adc: adi-axi-adc: set data format Antoniu Miclaus
@ 2024-11-11 12:12 ` Antoniu Miclaus
2024-11-12 20:12 ` David Lechner
2024-11-23 16:04 ` Jonathan Cameron
2024-11-11 12:12 ` [PATCH v6 7/8] dt-bindings: iio: adc: add ad4851 Antoniu Miclaus
2024-11-11 12:12 ` [PATCH v6 8/8] iio: adc: ad4851: add ad485x driver Antoniu Miclaus
7 siblings, 2 replies; 19+ messages in thread
From: Antoniu Miclaus @ 2024-11-11 12:12 UTC (permalink / raw)
To: jic23, robh, conor+dt, dlechner, linux-iio, devicetree,
linux-kernel, linux-pwm
Cc: Antoniu Miclaus
Add support for enabling/disabling oversampling.
Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
---
changes in v6:
- add support for oversampling enable/disable.
drivers/iio/adc/adi-axi-adc.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
index 9bf967d5b730..8ec668f59c88 100644
--- a/drivers/iio/adc/adi-axi-adc.c
+++ b/drivers/iio/adc/adi-axi-adc.c
@@ -46,6 +46,7 @@
#define ADI_AXI_ADC_CTRL_DDR_EDGESEL_MASK BIT(1)
#define ADI_AXI_ADC_REG_CNTRL_3 0x004c
+#define AD485X_CNTRL_3_CUSTOM_CTRL_OS_EN_MSK BIT(2)
#define AD485X_CNTRL_3_CUSTOM_CTRL_PACKET_FORMAT_MSK GENMASK(1, 0)
#define AD485X_PACKET_FORMAT_20BIT 0x0
#define AD485X_PACKET_FORMAT_24BIT 0x1
@@ -341,6 +342,14 @@ static int axi_adc_data_size_set(struct iio_backend *back, unsigned int size)
AD485X_CNTRL_3_CUSTOM_CTRL_PACKET_FORMAT_MSK, val);
}
+static int axi_adc_oversampling_en(struct iio_backend *back, bool en)
+{
+ struct adi_axi_adc_state *st = iio_backend_get_priv(back);
+
+ return regmap_update_bits(st->regmap, ADI_AXI_ADC_REG_CNTRL_3,
+ AD485X_CNTRL_3_CUSTOM_CTRL_OS_EN_MSK, en);
+}
+
static struct iio_buffer *axi_adc_request_buffer(struct iio_backend *back,
struct iio_dev *indio_dev)
{
@@ -390,6 +399,7 @@ static const struct iio_backend_ops adi_axi_adc_ops = {
.chan_status = axi_adc_chan_status,
.interface_type_get = axi_adc_interface_type_get,
.data_size_set = axi_adc_data_size_set,
+ .oversampling_en = axi_adc_oversampling_en,
.debugfs_reg_access = iio_backend_debugfs_ptr(axi_adc_reg_access),
.debugfs_print_chan_status = iio_backend_debugfs_ptr(axi_adc_debugfs_print_chan_status),
};
--
2.47.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v6 7/8] dt-bindings: iio: adc: add ad4851
2024-11-11 12:11 [PATCH v6 0/8] *** Add support for AD485x DAS Family *** Antoniu Miclaus
` (5 preceding siblings ...)
2024-11-11 12:12 ` [PATCH v6 6/8] iio: adc: adi-axi-adc: add oversampling Antoniu Miclaus
@ 2024-11-11 12:12 ` Antoniu Miclaus
2024-11-11 12:12 ` [PATCH v6 8/8] iio: adc: ad4851: add ad485x driver Antoniu Miclaus
7 siblings, 0 replies; 19+ messages in thread
From: Antoniu Miclaus @ 2024-11-11 12:12 UTC (permalink / raw)
To: jic23, robh, conor+dt, dlechner, linux-iio, devicetree,
linux-kernel, linux-pwm
Cc: Antoniu Miclaus, Conor Dooley
Add devicetree bindings for ad485x family.
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
---
no changes in v6.
.../bindings/iio/adc/adi,ad4851.yaml | 103 ++++++++++++++++++
1 file changed, 103 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ad4851.yaml
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4851.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4851.yaml
new file mode 100644
index 000000000000..9e9439fed3ef
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4851.yaml
@@ -0,0 +1,103 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright 2024 Analog Devices Inc.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/adi,ad4851.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD485X family
+
+maintainers:
+ - Sergiu Cuciurean <sergiu.cuciurean@analog.com>
+ - Dragos Bogdan <dragos.bogdan@analog.com>
+ - Antoniu Miclaus <antoniu.miclaus@analog.com>
+
+description: |
+ Analog Devices AD485X fully buffered, 8-channel simultaneous sampling,
+ 16/20-bit, 1 MSPS data acquisition system (DAS) with differential, wide
+ common-mode range inputs.
+
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad4855.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad4856.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad4857.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad4858.pdf
+
+$ref: /schemas/spi/spi-peripheral-props.yaml#
+
+properties:
+ compatible:
+ enum:
+ - adi,ad4851
+ - adi,ad4852
+ - adi,ad4853
+ - adi,ad4854
+ - adi,ad4855
+ - adi,ad4856
+ - adi,ad4857
+ - adi,ad4858
+ - adi,ad4858i
+
+ reg:
+ maxItems: 1
+
+ vcc-supply: true
+
+ vee-supply: true
+
+ vdd-supply: true
+
+ vddh-supply: true
+
+ vddl-supply: true
+
+ vio-supply: true
+
+ vrefbuf-supply: true
+
+ vrefio-supply: true
+
+ pwms:
+ description: PWM connected to the CNV pin.
+ maxItems: 1
+
+ io-backends:
+ maxItems: 1
+
+ pd-gpios:
+ maxItems: 1
+
+ spi-max-frequency:
+ maximum: 25000000
+
+required:
+ - compatible
+ - reg
+ - vcc-supply
+ - vee-supply
+ - vdd-supply
+ - vio-supply
+ - pwms
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ adc@0{
+ compatible = "adi,ad4858";
+ reg = <0>;
+ spi-max-frequency = <10000000>;
+ vcc-supply = <&vcc>;
+ vdd-supply = <&vdd>;
+ vee-supply = <&vee>;
+ vddh-supply = <&vddh>;
+ vddl-supply = <&vddl>;
+ vio-supply = <&vio>;
+ pwms = <&pwm_gen 0 0>;
+ io-backends = <&iio_backend>;
+ };
+ };
+...
--
2.47.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v6 8/8] iio: adc: ad4851: add ad485x driver
2024-11-11 12:11 [PATCH v6 0/8] *** Add support for AD485x DAS Family *** Antoniu Miclaus
` (6 preceding siblings ...)
2024-11-11 12:12 ` [PATCH v6 7/8] dt-bindings: iio: adc: add ad4851 Antoniu Miclaus
@ 2024-11-11 12:12 ` Antoniu Miclaus
2024-11-12 20:02 ` David Lechner
7 siblings, 1 reply; 19+ messages in thread
From: Antoniu Miclaus @ 2024-11-11 12:12 UTC (permalink / raw)
To: jic23, robh, conor+dt, dlechner, linux-iio, devicetree,
linux-kernel, linux-pwm
Cc: Antoniu Miclaus
Add support for the AD485X a fully buffered, 8-channel simultaneous
sampling, 16/20-bit, 1 MSPS data acquisition system (DAS) with
differential, wide common-mode range inputs.
Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
---
changes in v6 (implemented most of the review comments in v5):
- fix zero size array
- remove leftover offset members
- remove unused structure members
- DIV_ROUND_UP_ULL
- check ad4851_osr_to_regval before OS enable.
- user regmap_clear_bits/regmap_set_bits where applicable.
- drop resoluton boost for 16-bit chips
- use mutex in ad4851_get_oversampling_ratio.
- drop GPIOD_OUT_* macros.
- rearrange operations inside ad4851_setup
- drop kmalloc for scales and use array instead.
- drop unreachable return
- add devm_add_action_and_reset to call pwm_disable.
- add comment for the PD sequence.
- lane_num->num_lanes
- add blank line after return ret.
- don't wrap early.
- add structure for scale_table.
- use dev = &spi->dev to shorten code.
- fix regulator messages
- indio_dev->modes = INDIO_DIRECT_MODE;
drivers/iio/adc/Kconfig | 13 +
drivers/iio/adc/Makefile | 1 +
drivers/iio/adc/ad4851.c | 1190 ++++++++++++++++++++++++++++++++++++++
3 files changed, 1204 insertions(+)
create mode 100644 drivers/iio/adc/ad4851.c
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 6c4e74420fd2..0d97cd760d90 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -61,6 +61,19 @@ config AD4695
To compile this driver as a module, choose M here: the module will be
called ad4695.
+config AD4851
+ tristate "Analog Device AD4851 DAS Driver"
+ depends on SPI
+ select REGMAP_SPI
+ select IIO_BACKEND
+ help
+ Say yes here to build support for Analog Devices AD4851, AD4852,
+ AD4853, AD4854, AD4855, AD4856, AD4857, AD4858, AD4858I high speed
+ data acquisition system (DAS).
+
+ To compile this driver as a module, choose M here: the module will be
+ called ad4851.
+
config AD7091R
tristate
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 7b91cd98c0e0..d83df8b5925d 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
obj-$(CONFIG_AD4000) += ad4000.o
obj-$(CONFIG_AD4130) += ad4130.o
obj-$(CONFIG_AD4695) += ad4695.o
+obj-$(CONFIG_AD4851) += ad4851.o
obj-$(CONFIG_AD7091R) += ad7091r-base.o
obj-$(CONFIG_AD7091R5) += ad7091r5.o
obj-$(CONFIG_AD7091R8) += ad7091r8.o
diff --git a/drivers/iio/adc/ad4851.c b/drivers/iio/adc/ad4851.c
new file mode 100644
index 000000000000..6c66477a05b7
--- /dev/null
+++ b/drivers/iio/adc/ad4851.c
@@ -0,0 +1,1190 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Analog Devices AD4851 DAS driver
+ *
+ * Copyright 2024 Analog Devices Inc.
+ */
+
+#include <linux/array_size.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/minmax.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/pwm.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+#include <linux/types.h>
+#include <linux/unaligned.h>
+#include <linux/units.h>
+
+#include <linux/iio/backend.h>
+#include <linux/iio/iio.h>
+
+#define AD4851_REG_INTERFACE_CONFIG_A 0x00
+#define AD4851_REG_INTERFACE_CONFIG_B 0x01
+#define AD4851_REG_PRODUCT_ID_L 0x04
+#define AD4851_REG_PRODUCT_ID_H 0x05
+#define AD4851_REG_DEVICE_CTRL 0x25
+#define AD4851_REG_PACKET 0x26
+#define AD4851_REG_OVERSAMPLE 0x27
+
+#define AD4851_REG_CH_CONFIG_BASE 0x2A
+#define AD4851_REG_CHX_SOFTSPAN(ch) ((0x12 * (ch)) + AD4851_REG_CH_CONFIG_BASE)
+#define AD4851_REG_CHX_OFFSET(ch) (AD4851_REG_CHX_SOFTSPAN(ch) + 0x01)
+#define AD4851_REG_CHX_OFFSET_LSB(ch) AD4851_REG_CHX_OFFSET(ch)
+#define AD4851_REG_CHX_OFFSET_MID(ch) (AD4851_REG_CHX_OFFSET_LSB(ch) + 0x01)
+#define AD4851_REG_CHX_OFFSET_MSB(ch) (AD4851_REG_CHX_OFFSET_MID(ch) + 0x01)
+#define AD4851_REG_CHX_GAIN(ch) (AD4851_REG_CHX_OFFSET(ch) + 0x03)
+#define AD4851_REG_CHX_GAIN_LSB(ch) AD4851_REG_CHX_GAIN(ch)
+#define AD4851_REG_CHX_GAIN_MSB(ch) (AD4851_REG_CHX_GAIN(ch) + 0x01)
+#define AD4851_REG_CHX_PHASE(ch) (AD4851_REG_CHX_GAIN(ch) + 0x02)
+#define AD4851_REG_CHX_PHASE_LSB(ch) AD4851_REG_CHX_PHASE(ch)
+#define AD4851_REG_CHX_PHASE_MSB(ch) (AD4851_REG_CHX_PHASE_LSB(ch) + 0x01)
+
+#define AD4851_REG_TESTPAT_0(c) (0x38 + (c) * 0x12)
+#define AD4851_REG_TESTPAT_1(c) (0x39 + (c) * 0x12)
+#define AD4851_REG_TESTPAT_2(c) (0x3A + (c) * 0x12)
+#define AD4851_REG_TESTPAT_3(c) (0x3B + (c) * 0x12)
+
+#define AD4851_SW_RESET (BIT(7) | BIT(0))
+#define AD4851_SDO_ENABLE BIT(4)
+#define AD4851_SINGLE_INSTRUCTION BIT(7)
+#define AD4851_REFBUF_PD BIT(2)
+#define AD4851_REFSEL_PD BIT(1)
+#define AD4851_ECHO_CLOCK_MODE BIT(0)
+
+#define AD4851_PACKET_FORMAT_0 0
+#define AD4851_PACKET_FORMAT_1 1
+#define AD4851_PACKET_FORMAT_MASK GENMASK(1, 0)
+
+#define AD4851_OS_EN_MSK BIT(7)
+#define AD4851_OS_RATIO_MSK GENMASK(3, 0)
+
+#define AD4851_TEST_PAT BIT(2)
+
+#define AD4858_PACKET_SIZE_20 0
+#define AD4858_PACKET_SIZE_24 1
+#define AD4858_PACKET_SIZE_32 2
+
+#define AD4857_PACKET_SIZE_16 0
+#define AD4857_PACKET_SIZE_24 1
+
+#define AD4851_TESTPAT_0_DEFAULT 0x2A
+#define AD4851_TESTPAT_1_DEFAULT 0x3C
+#define AD4851_TESTPAT_2_DEFAULT 0xCE
+#define AD4851_TESTPAT_3_DEFAULT(c) (0x0A + (0x10 * (c)))
+
+#define AD4851_SOFTSPAN_0V_2V5 0
+#define AD4851_SOFTSPAN_N2V5_2V5 1
+#define AD4851_SOFTSPAN_0V_5V 2
+#define AD4851_SOFTSPAN_N5V_5V 3
+#define AD4851_SOFTSPAN_0V_6V25 4
+#define AD4851_SOFTSPAN_N6V25_6V25 5
+#define AD4851_SOFTSPAN_0V_10V 6
+#define AD4851_SOFTSPAN_N10V_10V 7
+#define AD4851_SOFTSPAN_0V_12V5 8
+#define AD4851_SOFTSPAN_N12V5_12V5 9
+#define AD4851_SOFTSPAN_0V_20V 10
+#define AD4851_SOFTSPAN_N20V_20V 11
+#define AD4851_SOFTSPAN_0V_25V 12
+#define AD4851_SOFTSPAN_N25V_25V 13
+#define AD4851_SOFTSPAN_0V_40V 14
+#define AD4851_SOFTSPAN_N40V_40V 15
+
+#define AD4851_MAX_LANES 8
+#define AD4851_MAX_IODELAY 32
+
+#define AD4851_T_CNVH_NS 40
+
+#define AD4841_MAX_SCALE_AVAIL 10
+
+struct ad4851_scale {
+ unsigned int scale_val;
+ u8 reg_val;
+};
+
+static const struct ad4851_scale ad4851_scale_table[] = {
+ { 2500, 0x0 },
+ { 5000, 0x1 },
+ { 5000, 0x2 },
+ { 10000, 0x3 },
+ { 6250, 0x4 },
+ { 12500, 0x5 },
+ { 10000, 0x6 },
+ { 20000, 0x7 },
+ { 12500, 0x8 },
+ { 25000, 0x9 },
+ { 20000, 0xA },
+ { 40000, 0xB },
+ { 25000, 0xC },
+ { 50000, 0xD },
+ { 40000, 0xE },
+ { 80000, 0xF },
+};
+
+static const unsigned int ad4851_scale_avail[] = {
+ 2500, 5000,
+ 10000, 6250,
+ 12500, 20000,
+ 25000, 40000,
+ 50000, 80000,
+};
+
+struct ad4851_chip_info {
+ const char *name;
+ unsigned int product_id;
+ const unsigned int (*scale_table)[2];
+ int num_scales;
+ const struct iio_chan_spec *channels;
+ unsigned int num_channels;
+ unsigned long max_sample_rate_hz;
+ unsigned int resolution;
+};
+
+enum {
+ AD4851_SCAN_TYPE_NORMAL,
+ AD4851_SCAN_TYPE_RESOLUTION_BOOST,
+};
+
+struct ad4851_state {
+ struct spi_device *spi;
+ struct pwm_device *cnv;
+ struct iio_backend *back;
+ /*
+ * Synchronize access to members the of driver state, and ensure
+ * atomicity of consecutive regmap operations.
+ */
+ struct mutex lock;
+ struct regmap *regmap;
+ struct regulator *vrefbuf;
+ struct regulator *vrefio;
+ const struct ad4851_chip_info *info;
+ struct gpio_desc *pd_gpio;
+ bool resolution_boost_enabled;
+ unsigned long sampling_freq;
+ unsigned int scales[AD4841_MAX_SCALE_AVAIL][2];
+};
+
+static int ad4851_reg_access(struct iio_dev *indio_dev,
+ unsigned int reg,
+ unsigned int writeval,
+ unsigned int *readval)
+{
+ struct ad4851_state *st = iio_priv(indio_dev);
+
+ guard(mutex)(&st->lock);
+
+ if (readval)
+ return regmap_read(st->regmap, reg, readval);
+
+ return regmap_write(st->regmap, reg, writeval);
+}
+
+static int ad4851_set_sampling_freq(struct ad4851_state *st, unsigned int freq)
+{
+ struct pwm_state cnv_state = {
+ .duty_cycle = AD4851_T_CNVH_NS,
+ .enabled = true,
+ };
+ int ret;
+
+ freq = clamp(freq, 1, st->info->max_sample_rate_hz);
+
+ cnv_state.period = DIV_ROUND_UP_ULL(NSEC_PER_SEC, freq);
+
+ ret = pwm_apply_might_sleep(st->cnv, &cnv_state);
+ if (ret)
+ return ret;
+
+ st->sampling_freq = freq;
+
+ return 0;
+}
+
+static const int ad4851_oversampling_ratios[] = {
+ 1, 2, 4, 8, 16, 32, 64, 128,
+ 256, 512, 1024, 2048, 4096, 8192, 16384, 32768,
+ 65536,
+};
+
+static int ad4851_osr_to_regval(int ratio)
+{
+ int i;
+
+ for (i = 1; i < ARRAY_SIZE(ad4851_oversampling_ratios); i++)
+ if (ratio == ad4851_oversampling_ratios[i])
+ return i - 1;
+
+ return -EINVAL;
+}
+
+static int ad4851_set_oversampling_ratio(struct ad4851_state *st,
+ const struct iio_chan_spec *chan,
+ unsigned int osr)
+{
+ unsigned int val;
+ int ret;
+
+ guard(mutex)(&st->lock);
+
+ if (osr == 1) {
+ ret = regmap_clear_bits(st->regmap, AD4851_REG_OVERSAMPLE,
+ AD4851_OS_EN_MSK);
+ if (ret)
+ return ret;
+
+ ret = iio_backend_oversampling_en(st->back, false);
+ if (ret)
+ return ret;
+ } else {
+ val = ad4851_osr_to_regval(osr);
+ if (val < 0)
+ return -EINVAL;
+
+ ret = regmap_set_bits(st->regmap, AD4851_REG_OVERSAMPLE,
+ AD4851_OS_EN_MSK);
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(st->regmap, AD4851_REG_OVERSAMPLE,
+ AD4851_OS_RATIO_MSK, val);
+ if (ret)
+ return ret;
+
+ ret = iio_backend_oversampling_en(st->back, true);
+ if (ret)
+ return ret;
+ }
+
+ switch (chan->scan_type.realbits) {
+ case 20:
+ switch (osr) {
+ case 0:
+ return -EINVAL;
+ case 1:
+ val = 20;
+ break;
+ default:
+ val = 24;
+ break;
+ }
+ break;
+ case 16:
+ val = 16;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = iio_backend_data_size_set(st->back, val);
+ if (ret)
+ return ret;
+
+ if (osr == 1 || chan->scan_type.realbits == 16) {
+ ret = regmap_clear_bits(st->regmap, AD4851_REG_PACKET,
+ AD4851_PACKET_FORMAT_MASK);
+ if (ret)
+ return ret;
+
+ st->resolution_boost_enabled = false;
+ } else {
+ ret = regmap_update_bits(st->regmap, AD4851_REG_PACKET,
+ AD4851_PACKET_FORMAT_MASK,
+ FIELD_PREP(AD4851_PACKET_FORMAT_MASK, 1);
+ if (ret)
+ return ret;
+
+ st->resolution_boost_enabled = true;
+ }
+
+ return 0;
+}
+
+static int ad4851_get_oversampling_ratio(struct ad4851_state *st, unsigned int *val)
+{
+ unsigned int osr;
+ int ret;
+
+ guard(mutex)(&st->lock);
+
+ ret = regmap_read(st->regmap, AD4851_REG_OVERSAMPLE, &osr);
+ if (ret)
+ return ret;
+
+ if (!FIELD_GET(AD4851_OS_EN_MSK, osr))
+ *val = 1;
+ else
+ *val = ad4851_oversampling_ratios[FIELD_GET(AD4851_OS_RATIO_MSK, osr)];
+
+ return IIO_VAL_INT;
+}
+
+static void ad4851_reg_disable(void *data)
+{
+ regulator_disable(data);
+}
+
+static void ad4851_pwm_disable(void *data)
+{
+ pwm_disable(data);
+}
+
+static int ad4851_setup(struct ad4851_state *st)
+{
+ unsigned int product_id;
+ int ret;
+
+ if (!IS_ERR(st->vrefbuf)) {
+ ret = regmap_set_bits(st->regmap, AD4851_REG_DEVICE_CTRL,
+ AD4851_REFBUF_PD);
+ if (ret)
+ return ret;
+
+ ret = regulator_enable(st->vrefbuf);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(&st->spi->dev, ad4851_reg_disable,
+ st->vrefbuf);
+ if (ret)
+ return ret;
+ }
+
+ if (!IS_ERR(st->vrefio)) {
+ ret = regmap_set_bits(st->regmap, AD4851_REG_DEVICE_CTRL,
+ AD4851_REFSEL_PD);
+ if (ret)
+ return ret;
+
+ ret = regulator_enable(st->vrefio);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(&st->spi->dev, ad4851_reg_disable,
+ st->vrefio);
+ if (ret)
+ return ret;
+ }
+
+ if (st->pd_gpio) {
+ /* To initiate a global reset, bring the PD pin high twice */
+ gpiod_set_value(st->pd_gpio, 1);
+ fsleep(1);
+ gpiod_set_value(st->pd_gpio, 0);
+ fsleep(1);
+ gpiod_set_value(st->pd_gpio, 1);
+ fsleep(1);
+ gpiod_set_value(st->pd_gpio, 0);
+ fsleep(1000);
+ } else {
+ ret = regmap_set_bits(st->regmap, AD4851_REG_INTERFACE_CONFIG_A,
+ AD4851_SW_RESET);
+ if (ret)
+ return ret;
+ }
+
+ ret = regmap_write(st->regmap, AD4851_REG_INTERFACE_CONFIG_B,
+ AD4851_SINGLE_INSTRUCTION);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(st->regmap, AD4851_REG_INTERFACE_CONFIG_A,
+ AD4851_SDO_ENABLE);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(st->regmap, AD4851_REG_PRODUCT_ID_L, &product_id);
+ if (ret)
+ return ret;
+
+ if (product_id != st->info->product_id)
+ dev_info(&st->spi->dev, "Unknown product ID: 0x%02X\n",
+ product_id);
+
+ ret = regmap_set_bits(st->regmap, AD4851_REG_DEVICE_CTRL,
+ AD4851_ECHO_CLOCK_MODE);
+ if (ret)
+ return ret;
+
+ return regmap_write(st->regmap, AD4851_REG_PACKET, 0);
+}
+
+static int ad4851_find_opt(bool *field, u32 size, u32 *ret_start)
+{
+ unsigned int i, cnt = 0, max_cnt = 0, max_start = 0;
+ int start;
+
+ for (i = 0, start = -1; i < size; i++) {
+ if (field[i] == 0) {
+ if (start == -1)
+ start = i;
+ cnt++;
+ } else {
+ if (cnt > max_cnt) {
+ max_cnt = cnt;
+ max_start = start;
+ }
+ start = -1;
+ cnt = 0;
+ }
+ }
+ /*
+ * Find the longest consecutive sequence of false values from field
+ * and return starting index.
+ */
+ if (cnt > max_cnt) {
+ max_cnt = cnt;
+ max_start = start;
+ }
+
+ if (!max_cnt)
+ return -ENOENT;
+
+ *ret_start = max_start;
+
+ return max_cnt;
+}
+
+static int ad4851_calibrate(struct ad4851_state *st)
+{
+ unsigned int opt_delay, num_lanes, delay, i, s, c;
+ enum iio_backend_interface_type interface_type;
+ DECLARE_BITMAP(pn_status, AD4851_MAX_LANES * AD4851_MAX_IODELAY);
+ bool status;
+ int ret;
+
+ ret = iio_backend_interface_type_get(st->back, &interface_type);
+ if (ret)
+ return ret;
+
+ switch (interface_type) {
+ case IIO_BACKEND_INTERFACE_SERIAL_CMOS:
+ num_lanes = st->info->num_channels;
+ break;
+ case IIO_BACKEND_INTERFACE_SERIAL_LVDS:
+ num_lanes = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (st->info->resolution == 16) {
+ ret = iio_backend_data_size_set(st->back, 24);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(st->regmap, AD4851_REG_PACKET,
+ AD4851_TEST_PAT | AD4857_PACKET_SIZE_24);
+ if (ret)
+ return ret;
+ } else {
+ ret = iio_backend_data_size_set(st->back, 32);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(st->regmap, AD4851_REG_PACKET,
+ AD4851_TEST_PAT | AD4858_PACKET_SIZE_32);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < st->info->num_channels; i++) {
+ ret = regmap_write(st->regmap, AD4851_REG_TESTPAT_0(i),
+ AD4851_TESTPAT_0_DEFAULT);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(st->regmap, AD4851_REG_TESTPAT_1(i),
+ AD4851_TESTPAT_1_DEFAULT);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(st->regmap, AD4851_REG_TESTPAT_2(i),
+ AD4851_TESTPAT_2_DEFAULT);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(st->regmap, AD4851_REG_TESTPAT_3(i),
+ AD4851_TESTPAT_3_DEFAULT(i));
+ if (ret)
+ return ret;
+
+ ret = iio_backend_chan_enable(st->back, i);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < num_lanes; i++) {
+ for (delay = 0; delay < AD4851_MAX_IODELAY; delay++) {
+ ret = iio_backend_iodelay_set(st->back, i, delay);
+ if (ret)
+ return ret;
+
+ ret = iio_backend_chan_status(st->back, i, &status);
+ if (ret)
+ return ret;
+
+ if (status)
+ set_bit(i * AD4851_MAX_IODELAY + delay, pn_status);
+ else
+ clear_bit(i * AD4851_MAX_IODELAY + delay, pn_status);
+ }
+ }
+
+ for (i = 0; i < num_lanes; i++) {
+ status = test_bit(i * AD4851_MAX_IODELAY, pn_status);
+ c = ad4851_find_opt(&status, AD4851_MAX_IODELAY, &s);
+ if (c < 0)
+ return c;
+
+ opt_delay = s + c / 2;
+ ret = iio_backend_iodelay_set(st->back, i, opt_delay);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < st->info->num_channels; i++) {
+ ret = iio_backend_chan_disable(st->back, i);
+ if (ret)
+ return ret;
+ }
+
+ ret = iio_backend_data_size_set(st->back, 20);
+ if (ret)
+ return ret;
+
+ return regmap_write(st->regmap, AD4851_REG_PACKET, 0);
+}
+
+static int ad4851_get_calibscale(struct ad4851_state *st, int ch, int *val, int *val2)
+{
+ unsigned int reg_val;
+ int gain;
+ int ret;
+
+ guard(mutex)(&st->lock);
+
+ ret = regmap_read(st->regmap, AD4851_REG_CHX_GAIN_MSB(ch), ®_val);
+ if (ret)
+ return ret;
+
+ gain = reg_val << 8;
+
+ ret = regmap_read(st->regmap, AD4851_REG_CHX_GAIN_LSB(ch), ®_val);
+ if (ret)
+ return ret;
+
+ gain |= reg_val;
+
+ *val = gain;
+ *val2 = 32768;
+
+ return IIO_VAL_FRACTIONAL;
+}
+
+static int ad4851_set_calibscale(struct ad4851_state *st, int ch, int val,
+ int val2)
+{
+ u64 gain;
+ u8 buf[2];
+ int ret;
+
+ if (val < 0 || val2 < 0)
+ return -EINVAL;
+
+ gain = val * MICRO + val2;
+ gain = DIV_U64_ROUND_CLOSEST(gain * 32768, MICRO);
+
+ put_unaligned_be16(gain, buf);
+
+ guard(mutex)(&st->lock);
+
+ ret = regmap_write(st->regmap, AD4851_REG_CHX_GAIN_MSB(ch), buf[0]);
+ if (ret)
+ return ret;
+
+ return regmap_write(st->regmap, AD4851_REG_CHX_GAIN_LSB(ch), buf[1]);
+}
+
+static int ad4851_get_calibbias(struct ad4851_state *st, int ch, int *val)
+{
+ unsigned int lsb, mid, msb;
+ int ret;
+
+ guard(mutex)(&st->lock);
+
+ ret = regmap_read(st->regmap, AD4851_REG_CHX_OFFSET_MSB(ch),
+ &msb);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(st->regmap, AD4851_REG_CHX_OFFSET_MID(ch),
+ &mid);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(st->regmap, AD4851_REG_CHX_OFFSET_LSB(ch),
+ &lsb);
+ if (ret)
+ return ret;
+
+ if (st->info->resolution == 16) {
+ *val = msb << 8;
+ *val |= mid;
+ *val = sign_extend32(*val, 15);
+ } else {
+ *val = msb << 12;
+ *val |= mid << 4;
+ *val |= lsb >> 4;
+ *val = sign_extend32(*val, 19);
+ }
+
+ return IIO_VAL_INT;
+}
+
+static int ad4851_set_calibbias(struct ad4851_state *st, int ch, int val)
+{
+ u8 buf[3] = { 0 };
+ int ret;
+
+ if (val < 0)
+ return -EINVAL;
+
+ if (st->info->resolution == 16)
+ put_unaligned_be16(val, buf);
+ else
+ put_unaligned_be24(val << 4, buf);
+
+ guard(mutex)(&st->lock);
+
+ ret = regmap_write(st->regmap, AD4851_REG_CHX_OFFSET_LSB(ch), buf[2]);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(st->regmap, AD4851_REG_CHX_OFFSET_MID(ch), buf[1]);
+ if (ret)
+ return ret;
+
+ return regmap_write(st->regmap, AD4851_REG_CHX_OFFSET_MSB(ch), buf[0]);
+}
+
+static void __ad4851_get_scale(struct ad4851_state *st, int scale_tbl,
+ unsigned int *val, unsigned int *val2)
+{
+ const struct ad4851_chip_info *info = st->info;
+ const struct iio_chan_spec *chan = &info->channels[0];
+ unsigned int tmp;
+
+ tmp = ((unsigned long long)scale_tbl * MICRO) >> chan->scan_type.realbits;
+ *val = tmp / MICRO;
+ *val2 = tmp % MICRO;
+}
+
+static int ad4851_set_scale(struct ad4851_state *st,
+ const struct iio_chan_spec *chan, int val, int val2)
+{
+ unsigned int scale_val[2];
+ unsigned int i;
+ bool single_ended = false;
+
+ for (i = 0; i < ARRAY_SIZE(ad4851_scale_table); i++) {
+ __ad4851_get_scale(st, ad4851_scale_table[i].scale_val,
+ &scale_val[0], &scale_val[1]);
+ if (scale_val[0] != val || scale_val[1] != val2)
+ continue;
+
+ /*
+ * Adjust the softspan value (differential or single ended)
+ * based on the scale value selected channel type.
+ *
+ * If the channel is not differential then continue iterations
+ * until the next matching scale value which always corresponds
+ * to the single ended mode.
+ */
+ if (!chan->differential && !single_ended) {
+ single_ended = true;
+ continue;
+ }
+
+ return regmap_write(st->regmap,
+ AD4851_REG_CHX_SOFTSPAN(chan->channel),
+ ad4851_scale_table[i].reg_val);
+ }
+
+ return -EINVAL;
+}
+
+static int ad4851_get_scale(struct ad4851_state *st,
+ const struct iio_chan_spec *chan, int *val,
+ int *val2)
+{
+ int i, softspan_val;
+ int ret;
+
+ ret = regmap_read(st->regmap, AD4851_REG_CHX_SOFTSPAN(chan->channel),
+ &softspan_val);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < ARRAY_SIZE(ad4851_scale_table); i++) {
+ if (softspan_val == ad4851_scale_table[i].reg_val)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(ad4851_scale_table))
+ return -EIO;
+
+ __ad4851_get_scale(st, ad4851_scale_table[i].scale_val, val, val2);
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int ad4851_scale_fill(struct ad4851_state *st)
+{
+ unsigned int i, val1, val2;
+
+ for (i = 0; i < ARRAY_SIZE(ad4851_scale_avail); i++) {
+ __ad4851_get_scale(st, ad4851_scale_avail[i], &val1, &val2);
+ st->scales[i][0] = val1;
+ st->scales[i][1] = val2;
+ }
+
+ return 0;
+}
+
+static int ad4851_read_raw(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ int *val, int *val2, long info)
+{
+ struct ad4851_state *st = iio_priv(indio_dev);
+
+ switch (info) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = st->sampling_freq;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_CALIBSCALE:
+ return ad4851_get_calibscale(st, chan->channel, val, val2);
+ case IIO_CHAN_INFO_SCALE:
+ return ad4851_get_scale(st, chan, val, val2);
+ case IIO_CHAN_INFO_CALIBBIAS:
+ return ad4851_get_calibbias(st, chan->channel, val);
+ case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+ return ad4851_get_oversampling_ratio(st, val);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad4851_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long info)
+{
+ struct ad4851_state *st = iio_priv(indio_dev);
+
+ switch (info) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return ad4851_set_sampling_freq(st, val);
+ case IIO_CHAN_INFO_SCALE:
+ return ad4851_set_scale(st, chan, val, val2);
+ case IIO_CHAN_INFO_CALIBSCALE:
+ return ad4851_set_calibscale(st, chan->channel, val, val2);
+ case IIO_CHAN_INFO_CALIBBIAS:
+ return ad4851_set_calibbias(st, chan->channel, val);
+ case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+ return ad4851_set_oversampling_ratio(st, chan, val);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad4851_update_scan_mode(struct iio_dev *indio_dev,
+ const unsigned long *scan_mask)
+{
+ struct ad4851_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 int ad4851_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long mask)
+{
+ struct ad4851_state *st = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ *vals = (const int *)st->scales;
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ /* Values are stored in a 2D matrix */
+ *length = ARRAY_SIZE(ad4851_scale_avail) * 2;
+ return IIO_AVAIL_LIST;
+ case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+ *vals = ad4851_oversampling_ratios;
+ *length = ARRAY_SIZE(ad4851_oversampling_ratios);
+ *type = IIO_VAL_INT;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_scan_type ad4851_scan_type_16[] = {
+ [AD4851_SCAN_TYPE_NORMAL] = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 16,
+ },
+ [AD4851_SCAN_TYPE_RESOLUTION_BOOST] = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 16,
+ },
+};
+
+static const struct iio_scan_type ad4851_scan_type_20[] = {
+ [AD4851_SCAN_TYPE_NORMAL] = {
+ .sign = 's',
+ .realbits = 20,
+ .storagebits = 32,
+ },
+ [AD4851_SCAN_TYPE_RESOLUTION_BOOST] = {
+ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ },
+};
+
+static int ad4851_get_current_scan_type(const struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan)
+{
+ struct ad4851_state *st = iio_priv(indio_dev);
+
+ return st->resolution_boost_enabled ? AD4851_SCAN_TYPE_RESOLUTION_BOOST
+ : AD4851_SCAN_TYPE_NORMAL;
+}
+
+#define AD4851_IIO_CHANNEL(index, diff, bits) \
+{ \
+ .type = IIO_VOLTAGE, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_CALIBSCALE) | \
+ BIT(IIO_CHAN_INFO_CALIBBIAS) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
+ .info_mask_shared_by_type_available = \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
+ .indexed = 1, \
+ .differential = diff, \
+ .channel = index, \
+ .channel2 = index + diff * 8, \
+ .scan_index = index + diff * 8, \
+ .ext_scan_type = ad4851_scan_type_##bits, \
+ .num_ext_scan_type = \
+ ARRAY_SIZE(ad4851_scan_type_##bits), \
+}
+
+static const struct iio_chan_spec ad4858_channels[] = {
+ AD4851_IIO_CHANNEL(0, 0, 20),
+ AD4851_IIO_CHANNEL(1, 0, 20),
+ AD4851_IIO_CHANNEL(2, 0, 20),
+ AD4851_IIO_CHANNEL(3, 0, 20),
+ AD4851_IIO_CHANNEL(4, 0, 20),
+ AD4851_IIO_CHANNEL(5, 0, 20),
+ AD4851_IIO_CHANNEL(6, 0, 20),
+ AD4851_IIO_CHANNEL(7, 0, 20),
+ AD4851_IIO_CHANNEL(0, 1, 20),
+ AD4851_IIO_CHANNEL(1, 1, 20),
+ AD4851_IIO_CHANNEL(2, 1, 20),
+ AD4851_IIO_CHANNEL(3, 1, 20),
+ AD4851_IIO_CHANNEL(4, 1, 20),
+ AD4851_IIO_CHANNEL(5, 1, 20),
+ AD4851_IIO_CHANNEL(6, 1, 20),
+ AD4851_IIO_CHANNEL(7, 1, 20),
+};
+
+static const struct iio_chan_spec ad4857_channels[] = {
+ AD4851_IIO_CHANNEL(0, 0, 16),
+ AD4851_IIO_CHANNEL(1, 0, 16),
+ AD4851_IIO_CHANNEL(2, 0, 16),
+ AD4851_IIO_CHANNEL(3, 0, 16),
+ AD4851_IIO_CHANNEL(4, 0, 16),
+ AD4851_IIO_CHANNEL(5, 0, 16),
+ AD4851_IIO_CHANNEL(6, 0, 16),
+ AD4851_IIO_CHANNEL(7, 0, 16),
+ AD4851_IIO_CHANNEL(0, 1, 16),
+ AD4851_IIO_CHANNEL(1, 1, 16),
+ AD4851_IIO_CHANNEL(2, 1, 16),
+ AD4851_IIO_CHANNEL(3, 1, 16),
+ AD4851_IIO_CHANNEL(4, 1, 16),
+ AD4851_IIO_CHANNEL(5, 1, 16),
+ AD4851_IIO_CHANNEL(6, 1, 16),
+ AD4851_IIO_CHANNEL(7, 1, 16),
+};
+
+static const struct ad4851_chip_info ad4851_info = {
+ .name = "ad4851",
+ .product_id = 0x67,
+ .channels = ad4857_channels,
+ .num_channels = ARRAY_SIZE(ad4857_channels),
+ .max_sample_rate_hz = 250 * KILO,
+ .resolution = 16,
+};
+
+static const struct ad4851_chip_info ad4852_info = {
+ .name = "ad4852",
+ .product_id = 0x66,
+ .channels = ad4858_channels,
+ .num_channels = ARRAY_SIZE(ad4858_channels),
+ .max_sample_rate_hz = 250 * KILO,
+ .resolution = 20,
+};
+
+static const struct ad4851_chip_info ad4853_info = {
+ .name = "ad4853",
+ .product_id = 0x65,
+ .channels = ad4857_channels,
+ .num_channels = ARRAY_SIZE(ad4857_channels),
+ .max_sample_rate_hz = 1 * MEGA,
+ .resolution = 16,
+};
+
+static const struct ad4851_chip_info ad4854_info = {
+ .name = "ad4854",
+ .product_id = 0x64,
+ .channels = ad4858_channels,
+ .num_channels = ARRAY_SIZE(ad4858_channels),
+ .max_sample_rate_hz = 1 * MEGA,
+ .resolution = 20,
+};
+
+static const struct ad4851_chip_info ad4855_info = {
+ .name = "ad4855",
+ .product_id = 0x63,
+ .channels = ad4857_channels,
+ .num_channels = ARRAY_SIZE(ad4857_channels),
+ .max_sample_rate_hz = 250 * KILO,
+ .resolution = 16,
+};
+
+static const struct ad4851_chip_info ad4856_info = {
+ .name = "ad4856",
+ .product_id = 0x62,
+ .channels = ad4858_channels,
+ .num_channels = ARRAY_SIZE(ad4858_channels),
+ .max_sample_rate_hz = 250 * KILO,
+ .resolution = 20,
+};
+
+static const struct ad4851_chip_info ad4857_info = {
+ .name = "ad4857",
+ .product_id = 0x61,
+ .channels = ad4857_channels,
+ .num_channels = ARRAY_SIZE(ad4857_channels),
+ .max_sample_rate_hz = 1 * MEGA,
+ .resolution = 16,
+};
+
+static const struct ad4851_chip_info ad4858_info = {
+ .name = "ad4858",
+ .product_id = 0x60,
+ .channels = ad4858_channels,
+ .num_channels = ARRAY_SIZE(ad4858_channels),
+ .max_sample_rate_hz = 1 * MEGA,
+ .resolution = 20,
+};
+
+static const struct ad4851_chip_info ad4858i_info = {
+ .name = "ad4858i",
+ .product_id = 0x6F,
+ .channels = ad4858_channels,
+ .num_channels = ARRAY_SIZE(ad4858_channels),
+ .max_sample_rate_hz = 1 * MEGA,
+ .resolution = 20,
+};
+
+static const struct iio_info ad4851_iio_info = {
+ .debugfs_reg_access = ad4851_reg_access,
+ .read_raw = ad4851_read_raw,
+ .write_raw = ad4851_write_raw,
+ .update_scan_mode = ad4851_update_scan_mode,
+ .get_current_scan_type = &ad4851_get_current_scan_type,
+ .read_avail = ad4851_read_avail,
+};
+
+static const struct regmap_config regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 8,
+ .read_flag_mask = BIT(7),
+};
+
+static const char * const ad4851_power_supplies[] = {
+ "vcc", "vdd", "vee", "vio",
+};
+
+static int ad4851_probe(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev;
+ struct device *dev = &spi->dev;
+ struct ad4851_state *st;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+ st->spi = spi;
+
+ ret = devm_mutex_init(dev, &st->lock);
+ if (ret)
+ return ret;
+
+ ret = devm_regulator_bulk_get_enable(dev,
+ ARRAY_SIZE(ad4851_power_supplies),
+ ad4851_power_supplies);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to get and enable supplies\n");
+
+ ret = devm_regulator_get_enable_optional(dev, "vddh");
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(dev, ret, "failed to enable vddh voltage\n");
+
+ ret = devm_regulator_get_enable_optional(dev, "vddl");
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(dev, ret, "failed to enable vddl voltage\n");
+
+ st->vrefbuf = devm_regulator_get_optional(dev, "vrefbuf");
+ if (IS_ERR(st->vrefbuf)) {
+ if (PTR_ERR(st->vrefbuf) != -ENODEV)
+ return dev_err_probe(dev, PTR_ERR(st->vrefbuf),
+ "Failed to get vrefbuf regulator\n");
+ }
+
+ st->vrefio = devm_regulator_get_optional(dev, "vrefio");
+ if (IS_ERR(st->vrefio)) {
+ if (PTR_ERR(st->vrefio) != -ENODEV)
+ return dev_err_probe(dev, PTR_ERR(st->vrefio),
+ "Failed to get vrefio regulator\n");
+ }
+
+ st->pd_gpio = devm_gpiod_get_optional(dev, "pd", GPIOD_OUT_LOW);
+ if (IS_ERR(st->pd_gpio))
+ return dev_err_probe(dev, PTR_ERR(st->pd_gpio),
+ "Error on requesting pd GPIO\n");
+
+ st->cnv = devm_pwm_get(dev, NULL);
+ if (IS_ERR(st->cnv))
+ return dev_err_probe(dev, PTR_ERR(st->cnv),
+ "Error on requesting pwm\n");
+
+ ret = ad4851_set_sampling_freq(st, HZ_PER_MHZ);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(&st->spi->dev, ad4851_pwm_disable,
+ st->cnv);
+ if (ret)
+ return ret;
+
+ st->info = spi_get_device_match_data(spi);
+ if (!st->info)
+ return -ENODEV;
+
+ st->regmap = devm_regmap_init_spi(spi, ®map_config);
+ if (IS_ERR(st->regmap))
+ return PTR_ERR(st->regmap);
+
+ ret = ad4851_scale_fill(st);
+ if (ret)
+ return ret;
+
+ ret = ad4851_setup(st);
+ if (ret)
+ return ret;
+
+ indio_dev->name = st->info->name;
+ indio_dev->channels = st->info->channels;
+ indio_dev->num_channels = st->info->num_channels;
+ indio_dev->info = &ad4851_iio_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ st->back = devm_iio_backend_get(dev, NULL);
+ if (IS_ERR(st->back))
+ return PTR_ERR(st->back);
+
+ ret = devm_iio_backend_request_buffer(dev, st->back, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_backend_enable(dev, st->back);
+ if (ret)
+ return ret;
+
+ ret = ad4851_calibrate(st);
+ if (ret)
+ return ret;
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static const struct of_device_id ad4851_of_match[] = {
+ { .compatible = "adi,ad4851", .data = &ad4851_info, },
+ { .compatible = "adi,ad4852", .data = &ad4852_info, },
+ { .compatible = "adi,ad4853", .data = &ad4853_info, },
+ { .compatible = "adi,ad4854", .data = &ad4854_info, },
+ { .compatible = "adi,ad4855", .data = &ad4855_info, },
+ { .compatible = "adi,ad4856", .data = &ad4856_info, },
+ { .compatible = "adi,ad4857", .data = &ad4857_info, },
+ { .compatible = "adi,ad4858", .data = &ad4858_info, },
+ { .compatible = "adi,ad4858i", .data = &ad4858i_info, },
+ { }
+};
+
+static const struct spi_device_id ad4851_spi_id[] = {
+ { "ad4851", (kernel_ulong_t)&ad4851_info },
+ { "ad4852", (kernel_ulong_t)&ad4852_info },
+ { "ad4853", (kernel_ulong_t)&ad4853_info },
+ { "ad4854", (kernel_ulong_t)&ad4854_info },
+ { "ad4855", (kernel_ulong_t)&ad4855_info },
+ { "ad4856", (kernel_ulong_t)&ad4856_info },
+ { "ad4857", (kernel_ulong_t)&ad4857_info },
+ { "ad4858", (kernel_ulong_t)&ad4858_info },
+ { "ad4858i", (kernel_ulong_t)&ad4858i_info },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, ad4851_spi_id);
+
+static struct spi_driver ad4851_driver = {
+ .probe = ad4851_probe,
+ .driver = {
+ .name = "ad4851",
+ .of_match_table = ad4851_of_match,
+ },
+ .id_table = ad4851_spi_id,
+};
+module_spi_driver(ad4851_driver);
+
+MODULE_AUTHOR("Sergiu Cuciurean <sergiu.cuciurean@analog.com>");
+MODULE_AUTHOR("Dragos Bogdan <dragos.bogdan@analog.com>");
+MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com>");
+MODULE_DESCRIPTION("Analog Devices AD4851 DAS driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(IIO_BACKEND);
--
2.47.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH v6 3/8] iio: backend: add API for oversampling
2024-11-11 12:11 ` [PATCH v6 3/8] iio: backend: add API for oversampling Antoniu Miclaus
@ 2024-11-11 15:41 ` Nuno Sá
2024-11-23 16:02 ` Jonathan Cameron
0 siblings, 1 reply; 19+ messages in thread
From: Nuno Sá @ 2024-11-11 15:41 UTC (permalink / raw)
To: Antoniu Miclaus, jic23, robh, conor+dt, dlechner, linux-iio,
devicetree, linux-kernel, linux-pwm
On Mon, 2024-11-11 at 14:11 +0200, Antoniu Miclaus wrote:
> Add backend support for enabling/disabling oversampling.
>
> Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
> ---
> changes in v6:
> - add iio backend commit for oversampling enable/disable
> drivers/iio/industrialio-backend.c | 14 ++++++++++++++
> include/linux/iio/backend.h | 3 +++
> 2 files changed, 17 insertions(+)
>
> diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-
> backend.c
> index ea184fc2c838..6ba445ba3dd0 100644
> --- a/drivers/iio/industrialio-backend.c
> +++ b/drivers/iio/industrialio-backend.c
> @@ -681,6 +681,20 @@ int iio_backend_data_size_set(struct iio_backend *back,
> unsigned int size)
> }
> EXPORT_SYMBOL_NS_GPL(iio_backend_data_size_set, IIO_BACKEND);
>
> +/**
> + * iio_backend_oversampling_en - set the data width/size in the data bus.
Seems unrelated?
> + * @back: Backend device
> + * @en: oversampling enabled/disabled.
> + *
> + * Return:
> + * 0 on success, negative error number on failure.
> + */
> +int iio_backend_oversampling_en(struct iio_backend *back, bool en)
> +{
> + return iio_backend_op_call(back, oversampling_en, en);
> +}
> +EXPORT_SYMBOL_NS_GPL(iio_backend_oversampling_en, IIO_BACKEND);
> +
There was some discussion around having APIs with a boolean parameter (actually
even improving - in terms of callbacks - further with some generic
getter/setter's) or having two callbacks:
iio_backend_oversampling_enable()
iio_backend_oversampling_disable()
I'm guessing you don't really want to do any major conversion/refactoring at
this point in your series so I have a slight preference for just keeping the
current style of dedicated enable and disable APIs (irrespective of being the
better approach or not). Please consider it, if you have to re-spin the series.
- Nuno Sá
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v6 8/8] iio: adc: ad4851: add ad485x driver
2024-11-11 12:12 ` [PATCH v6 8/8] iio: adc: ad4851: add ad485x driver Antoniu Miclaus
@ 2024-11-12 20:02 ` David Lechner
2024-11-14 10:39 ` Miclaus, Antoniu
0 siblings, 1 reply; 19+ messages in thread
From: David Lechner @ 2024-11-12 20:02 UTC (permalink / raw)
To: Antoniu Miclaus, jic23, robh, conor+dt, linux-iio, devicetree,
linux-kernel, linux-pwm
On 11/11/24 6:12 AM, Antoniu Miclaus wrote:
> Add support for the AD485X a fully buffered, 8-channel simultaneous
> sampling, 16/20-bit, 1 MSPS data acquisition system (DAS) with
> differential, wide common-mode range inputs.
>
> Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
> ---
> changes in v6 (implemented most of the review comments in v5):
What is the plan for addressing the rest of the comments?
I don't want to keep making the same comments over and over again.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v6 5/8] iio: adc: adi-axi-adc: set data format
2024-11-11 12:12 ` [PATCH v6 5/8] iio: adc: adi-axi-adc: set data format Antoniu Miclaus
@ 2024-11-12 20:11 ` David Lechner
0 siblings, 0 replies; 19+ messages in thread
From: David Lechner @ 2024-11-12 20:11 UTC (permalink / raw)
To: Antoniu Miclaus, jic23, robh, conor+dt, linux-iio, devicetree,
linux-kernel, linux-pwm
On 11/11/24 6:12 AM, Antoniu Miclaus wrote:
> Add support for selecting the data format within the AXI ADC ip.
>
> Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
> ---
> changes in v6:
> - use switch case
> - add macro definition for packet format mask and sizes
> drivers/iio/adc/adi-axi-adc.c | 30 ++++++++++++++++++++++++++++++
> 1 file changed, 30 insertions(+)
>
> diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
> index f6475bc93796..9bf967d5b730 100644
> --- a/drivers/iio/adc/adi-axi-adc.c
> +++ b/drivers/iio/adc/adi-axi-adc.c
> @@ -45,6 +45,12 @@
> #define ADI_AXI_ADC_REG_CTRL 0x0044
> #define ADI_AXI_ADC_CTRL_DDR_EDGESEL_MASK BIT(1)
>
> +#define ADI_AXI_ADC_REG_CNTRL_3 0x004c
> +#define AD485X_CNTRL_3_CUSTOM_CTRL_PACKET_FORMAT_MSK GENMASK(1, 0)
> +#define AD485X_PACKET_FORMAT_20BIT 0x0
> +#define AD485X_PACKET_FORMAT_24BIT 0x1
> +#define AD485X_PACKET_FORMAT_32BIT 0x2
> +
> #define ADI_AXI_ADC_REG_DRP_STATUS 0x0074
> #define ADI_AXI_ADC_DRP_LOCKED BIT(17)
>
> @@ -312,6 +318,29 @@ static int axi_adc_interface_type_get(struct iio_backend *back,
> return 0;
> }
>
> +static int axi_adc_data_size_set(struct iio_backend *back, unsigned int size)
> +{
> + struct adi_axi_adc_state *st = iio_backend_get_priv(back);
> + unsigned int val;
> +
> + switch (size) {
What happened to 16 bit for 16-bit chips?
Ideally there should be an identification register we can read or
a compatible string from the devicetree that says if the HDL was
compiled for a 16-bit or 20-bit chip and we would have two different
versions of this function and pick one based on what HDL is being
used.
> + case 20:
> + val = AD485X_PACKET_FORMAT_20BIT;
> + break;
> + case 24:
> + val = AD485X_PACKET_FORMAT_24BIT;
> + break;
> + case 32:
> + val = AD485X_PACKET_FORMAT_32BIT;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return regmap_update_bits(st->regmap, ADI_AXI_ADC_REG_CNTRL_3,
> + AD485X_CNTRL_3_CUSTOM_CTRL_PACKET_FORMAT_MSK, val);
> +}
> +
> static struct iio_buffer *axi_adc_request_buffer(struct iio_backend *back,
> struct iio_dev *indio_dev)
> {
> @@ -360,6 +389,7 @@ static const struct iio_backend_ops adi_axi_adc_ops = {
> .test_pattern_set = axi_adc_test_pattern_set,
> .chan_status = axi_adc_chan_status,
> .interface_type_get = axi_adc_interface_type_get,
> + .data_size_set = axi_adc_data_size_set,
> .debugfs_reg_access = iio_backend_debugfs_ptr(axi_adc_reg_access),
> .debugfs_print_chan_status = iio_backend_debugfs_ptr(axi_adc_debugfs_print_chan_status),
> };
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v6 6/8] iio: adc: adi-axi-adc: add oversampling
2024-11-11 12:12 ` [PATCH v6 6/8] iio: adc: adi-axi-adc: add oversampling Antoniu Miclaus
@ 2024-11-12 20:12 ` David Lechner
2024-11-23 16:04 ` Jonathan Cameron
1 sibling, 0 replies; 19+ messages in thread
From: David Lechner @ 2024-11-12 20:12 UTC (permalink / raw)
To: Antoniu Miclaus, jic23, robh, conor+dt, linux-iio, devicetree,
linux-kernel, linux-pwm
On 11/11/24 6:12 AM, Antoniu Miclaus wrote:
> Add support for enabling/disabling oversampling.
>
> Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
> ---
> changes in v6:
> - add support for oversampling enable/disable.
> drivers/iio/adc/adi-axi-adc.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
> index 9bf967d5b730..8ec668f59c88 100644
> --- a/drivers/iio/adc/adi-axi-adc.c
> +++ b/drivers/iio/adc/adi-axi-adc.c
> @@ -46,6 +46,7 @@
> #define ADI_AXI_ADC_CTRL_DDR_EDGESEL_MASK BIT(1)
>
> #define ADI_AXI_ADC_REG_CNTRL_3 0x004c
> +#define AD485X_CNTRL_3_CUSTOM_CTRL_OS_EN_MSK BIT(2)
> #define AD485X_CNTRL_3_CUSTOM_CTRL_PACKET_FORMAT_MSK GENMASK(1, 0)
> #define AD485X_PACKET_FORMAT_20BIT 0x0
> #define AD485X_PACKET_FORMAT_24BIT 0x1
> @@ -341,6 +342,14 @@ static int axi_adc_data_size_set(struct iio_backend *back, unsigned int size)
> AD485X_CNTRL_3_CUSTOM_CTRL_PACKET_FORMAT_MSK, val);
> }
>
> +static int axi_adc_oversampling_en(struct iio_backend *back, bool en)
> +{
> + struct adi_axi_adc_state *st = iio_backend_get_priv(back);
> +
> + return regmap_update_bits(st->regmap, ADI_AXI_ADC_REG_CNTRL_3,
> + AD485X_CNTRL_3_CUSTOM_CTRL_OS_EN_MSK, en);
This needs FIELD_PREP() to apply the correct shift to en.
> +}
> +
> static struct iio_buffer *axi_adc_request_buffer(struct iio_backend *back,
> struct iio_dev *indio_dev)
> {
> @@ -390,6 +399,7 @@ static const struct iio_backend_ops adi_axi_adc_ops = {
> .chan_status = axi_adc_chan_status,
> .interface_type_get = axi_adc_interface_type_get,
> .data_size_set = axi_adc_data_size_set,
> + .oversampling_en = axi_adc_oversampling_en,
> .debugfs_reg_access = iio_backend_debugfs_ptr(axi_adc_reg_access),
> .debugfs_print_chan_status = iio_backend_debugfs_ptr(axi_adc_debugfs_print_chan_status),
> };
^ permalink raw reply [flat|nested] 19+ messages in thread
* RE: [PATCH v6 8/8] iio: adc: ad4851: add ad485x driver
2024-11-12 20:02 ` David Lechner
@ 2024-11-14 10:39 ` Miclaus, Antoniu
2024-11-14 14:47 ` David Lechner
0 siblings, 1 reply; 19+ messages in thread
From: Miclaus, Antoniu @ 2024-11-14 10:39 UTC (permalink / raw)
To: David Lechner, jic23@kernel.org, robh@kernel.org,
conor+dt@kernel.org, linux-iio@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-pwm@vger.kernel.org
> On 11/11/24 6:12 AM, Antoniu Miclaus wrote:
> > Add support for the AD485X a fully buffered, 8-channel simultaneous
> > sampling, 16/20-bit, 1 MSPS data acquisition system (DAS) with
> > differential, wide common-mode range inputs.
> >
> > Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
> > ---
> > changes in v6 (implemented most of the review comments in v5):
> What is the plan for addressing the rest of the comments?
For the rest of the comments I think I replied inline in the previous series.
> I don't want to keep making the same comments over and over again.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v6 8/8] iio: adc: ad4851: add ad485x driver
2024-11-14 10:39 ` Miclaus, Antoniu
@ 2024-11-14 14:47 ` David Lechner
2024-11-15 10:59 ` Miclaus, Antoniu
0 siblings, 1 reply; 19+ messages in thread
From: David Lechner @ 2024-11-14 14:47 UTC (permalink / raw)
To: Miclaus, Antoniu, jic23@kernel.org, robh@kernel.org,
conor+dt@kernel.org, linux-iio@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-pwm@vger.kernel.org
On 11/14/24 4:39 AM, Miclaus, Antoniu wrote:
>> On 11/11/24 6:12 AM, Antoniu Miclaus wrote:
>>> Add support for the AD485X a fully buffered, 8-channel simultaneous
>>> sampling, 16/20-bit, 1 MSPS data acquisition system (DAS) with
>>> differential, wide common-mode range inputs.
>>>
>>> Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
>>> ---
>>> changes in v6 (implemented most of the review comments in v5):
>> What is the plan for addressing the rest of the comments?
> For the rest of the comments I think I replied inline in the previous series.
>
I didn't look very close yet, but at a quick glance, I saw that all
scan_type are still only signed, there is no unsigned for when the
channels are used as single-ended. And the scan_index ordering is
still wrong. This makes me doubt that buffered reads are working
correctly for all configurations.
^ permalink raw reply [flat|nested] 19+ messages in thread
* RE: [PATCH v6 8/8] iio: adc: ad4851: add ad485x driver
2024-11-14 14:47 ` David Lechner
@ 2024-11-15 10:59 ` Miclaus, Antoniu
0 siblings, 0 replies; 19+ messages in thread
From: Miclaus, Antoniu @ 2024-11-15 10:59 UTC (permalink / raw)
To: David Lechner, jic23@kernel.org, robh@kernel.org,
conor+dt@kernel.org, linux-iio@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-pwm@vger.kernel.org
> On 11/14/24 4:39 AM, Miclaus, Antoniu wrote:
> >> On 11/11/24 6:12 AM, Antoniu Miclaus wrote:
> >>> Add support for the AD485X a fully buffered, 8-channel simultaneous
> >>> sampling, 16/20-bit, 1 MSPS data acquisition system (DAS) with
> >>> differential, wide common-mode range inputs.
> >>>
> >>> Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
> >>> ---
> >>> changes in v6 (implemented most of the review comments in v5):
> >> What is the plan for addressing the rest of the comments?
> > For the rest of the comments I think I replied inline in the previous series.
> >
> I didn't look very close yet, but at a quick glance, I saw that all
> scan_type are still only signed, there is no unsigned for when the
> channels are used as single-ended. And the scan_index ordering is
> still wrong. This makes me doubt that buffered reads are working
> correctly for all configurations.
Sure, will implement the scan_type as you suggested in the next series.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v6 3/8] iio: backend: add API for oversampling
2024-11-11 15:41 ` Nuno Sá
@ 2024-11-23 16:02 ` Jonathan Cameron
2024-11-23 16:05 ` Jonathan Cameron
0 siblings, 1 reply; 19+ messages in thread
From: Jonathan Cameron @ 2024-11-23 16:02 UTC (permalink / raw)
To: Nuno Sá
Cc: Antoniu Miclaus, robh, conor+dt, dlechner, linux-iio, devicetree,
linux-kernel, linux-pwm
On Mon, 11 Nov 2024 16:41:02 +0100
Nuno Sá <noname.nuno@gmail.com> wrote:
> On Mon, 2024-11-11 at 14:11 +0200, Antoniu Miclaus wrote:
> > Add backend support for enabling/disabling oversampling.
> >
> > Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
> > ---
> > changes in v6:
> > - add iio backend commit for oversampling enable/disable
> > drivers/iio/industrialio-backend.c | 14 ++++++++++++++
> > include/linux/iio/backend.h | 3 +++
> > 2 files changed, 17 insertions(+)
> >
> > diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-
> > backend.c
> > index ea184fc2c838..6ba445ba3dd0 100644
> > --- a/drivers/iio/industrialio-backend.c
> > +++ b/drivers/iio/industrialio-backend.c
> > @@ -681,6 +681,20 @@ int iio_backend_data_size_set(struct iio_backend *back,
> > unsigned int size)
> > }
> > EXPORT_SYMBOL_NS_GPL(iio_backend_data_size_set, IIO_BACKEND);
> >
> > +/**
> > + * iio_backend_oversampling_en - set the data width/size in the data bus.
>
> Seems unrelated?
>
> > + * @back: Backend device
> > + * @en: oversampling enabled/disabled.
> > + *
> > + * Return:
> > + * 0 on success, negative error number on failure.
> > + */
> > +int iio_backend_oversampling_en(struct iio_backend *back, bool en)
Odd to just be on or off vs a count of how much to oversample by
with 1 meaning don't oversample, 2,4,8 etc saying how much to oversample by.
> > +{
> > + return iio_backend_op_call(back, oversampling_en, en);
> > +}
> > +EXPORT_SYMBOL_NS_GPL(iio_backend_oversampling_en, IIO_BACKEND);
> > +
>
> There was some discussion around having APIs with a boolean parameter (actually
> even improving - in terms of callbacks - further with some generic
> getter/setter's) or having two callbacks:
>
> iio_backend_oversampling_enable()
> iio_backend_oversampling_disable()
>
> I'm guessing you don't really want to do any major conversion/refactoring at
> this point in your series so I have a slight preference for just keeping the
> current style of dedicated enable and disable APIs (irrespective of being the
> better approach or not). Please consider it, if you have to re-spin the series.
Agreed. Keep it consistent for now. I don't mind a proposal to refactor
the lot (though not yet convinced either way on it being a good idea)
but I don't want to see it inconsistent.
>
> - Nuno Sá
>
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v6 6/8] iio: adc: adi-axi-adc: add oversampling
2024-11-11 12:12 ` [PATCH v6 6/8] iio: adc: adi-axi-adc: add oversampling Antoniu Miclaus
2024-11-12 20:12 ` David Lechner
@ 2024-11-23 16:04 ` Jonathan Cameron
1 sibling, 0 replies; 19+ messages in thread
From: Jonathan Cameron @ 2024-11-23 16:04 UTC (permalink / raw)
To: Antoniu Miclaus
Cc: robh, conor+dt, dlechner, linux-iio, devicetree, linux-kernel,
linux-pwm
On Mon, 11 Nov 2024 14:12:01 +0200
Antoniu Miclaus <antoniu.miclaus@analog.com> wrote:
> Add support for enabling/disabling oversampling.
As earlier, this is usually an oversample by N, not just a boolean.
If it is boolean for this device, then I assume there is a fixed
ratio. Make the interface controlling between 1 and whatever that
ratio is.
Jonathan
>
> Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
> ---
> changes in v6:
> - add support for oversampling enable/disable.
> drivers/iio/adc/adi-axi-adc.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
> index 9bf967d5b730..8ec668f59c88 100644
> --- a/drivers/iio/adc/adi-axi-adc.c
> +++ b/drivers/iio/adc/adi-axi-adc.c
> @@ -46,6 +46,7 @@
> #define ADI_AXI_ADC_CTRL_DDR_EDGESEL_MASK BIT(1)
>
> #define ADI_AXI_ADC_REG_CNTRL_3 0x004c
> +#define AD485X_CNTRL_3_CUSTOM_CTRL_OS_EN_MSK BIT(2)
> #define AD485X_CNTRL_3_CUSTOM_CTRL_PACKET_FORMAT_MSK GENMASK(1, 0)
> #define AD485X_PACKET_FORMAT_20BIT 0x0
> #define AD485X_PACKET_FORMAT_24BIT 0x1
> @@ -341,6 +342,14 @@ static int axi_adc_data_size_set(struct iio_backend *back, unsigned int size)
> AD485X_CNTRL_3_CUSTOM_CTRL_PACKET_FORMAT_MSK, val);
> }
>
> +static int axi_adc_oversampling_en(struct iio_backend *back, bool en)
> +{
> + struct adi_axi_adc_state *st = iio_backend_get_priv(back);
> +
> + return regmap_update_bits(st->regmap, ADI_AXI_ADC_REG_CNTRL_3,
> + AD485X_CNTRL_3_CUSTOM_CTRL_OS_EN_MSK, en);
> +}
> +
> static struct iio_buffer *axi_adc_request_buffer(struct iio_backend *back,
> struct iio_dev *indio_dev)
> {
> @@ -390,6 +399,7 @@ static const struct iio_backend_ops adi_axi_adc_ops = {
> .chan_status = axi_adc_chan_status,
> .interface_type_get = axi_adc_interface_type_get,
> .data_size_set = axi_adc_data_size_set,
> + .oversampling_en = axi_adc_oversampling_en,
> .debugfs_reg_access = iio_backend_debugfs_ptr(axi_adc_reg_access),
> .debugfs_print_chan_status = iio_backend_debugfs_ptr(axi_adc_debugfs_print_chan_status),
> };
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v6 3/8] iio: backend: add API for oversampling
2024-11-23 16:02 ` Jonathan Cameron
@ 2024-11-23 16:05 ` Jonathan Cameron
0 siblings, 0 replies; 19+ messages in thread
From: Jonathan Cameron @ 2024-11-23 16:05 UTC (permalink / raw)
To: Nuno Sá
Cc: Antoniu Miclaus, robh, conor+dt, dlechner, linux-iio, devicetree,
linux-kernel, linux-pwm
On Sat, 23 Nov 2024 16:02:49 +0000
Jonathan Cameron <jic23@kernel.org> wrote:
> On Mon, 11 Nov 2024 16:41:02 +0100
> Nuno Sá <noname.nuno@gmail.com> wrote:
>
> > On Mon, 2024-11-11 at 14:11 +0200, Antoniu Miclaus wrote:
> > > Add backend support for enabling/disabling oversampling.
> > >
> > > Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
> > > ---
> > > changes in v6:
> > > - add iio backend commit for oversampling enable/disable
> > > drivers/iio/industrialio-backend.c | 14 ++++++++++++++
> > > include/linux/iio/backend.h | 3 +++
> > > 2 files changed, 17 insertions(+)
> > >
> > > diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-
> > > backend.c
> > > index ea184fc2c838..6ba445ba3dd0 100644
> > > --- a/drivers/iio/industrialio-backend.c
> > > +++ b/drivers/iio/industrialio-backend.c
> > > @@ -681,6 +681,20 @@ int iio_backend_data_size_set(struct iio_backend *back,
> > > unsigned int size)
> > > }
> > > EXPORT_SYMBOL_NS_GPL(iio_backend_data_size_set, IIO_BACKEND);
> > >
> > > +/**
> > > + * iio_backend_oversampling_en - set the data width/size in the data bus.
> >
> > Seems unrelated?
> >
> > > + * @back: Backend device
> > > + * @en: oversampling enabled/disabled.
> > > + *
> > > + * Return:
> > > + * 0 on success, negative error number on failure.
> > > + */
> > > +int iio_backend_oversampling_en(struct iio_backend *back, bool en)
> Odd to just be on or off vs a count of how much to oversample by
> with 1 meaning don't oversample, 2,4,8 etc saying how much to oversample by.
Looking at the code, why does the backend care? Seems you only set the ratio
on the ADC, not the in the FPGA IP. So I don't follow how that is useful
Jonathan
>
> > > +{
> > > + return iio_backend_op_call(back, oversampling_en, en);
> > > +}
> > > +EXPORT_SYMBOL_NS_GPL(iio_backend_oversampling_en, IIO_BACKEND);
> > > +
> >
> > There was some discussion around having APIs with a boolean parameter (actually
> > even improving - in terms of callbacks - further with some generic
> > getter/setter's) or having two callbacks:
> >
> > iio_backend_oversampling_enable()
> > iio_backend_oversampling_disable()
> >
> > I'm guessing you don't really want to do any major conversion/refactoring at
> > this point in your series so I have a slight preference for just keeping the
> > current style of dedicated enable and disable APIs (irrespective of being the
> > better approach or not). Please consider it, if you have to re-spin the series.
> Agreed. Keep it consistent for now. I don't mind a proposal to refactor
> the lot (though not yet convinced either way on it being a good idea)
> but I don't want to see it inconsistent.
>
> >
> > - Nuno Sá
> >
> >
>
>
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2024-11-23 16:06 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-11-11 12:11 [PATCH v6 0/8] *** Add support for AD485x DAS Family *** Antoniu Miclaus
2024-11-11 12:11 ` [PATCH v6 1/8] iio: backend: add API for interface get Antoniu Miclaus
2024-11-11 12:11 ` [PATCH v6 2/8] iio: backend: add support for data size set Antoniu Miclaus
2024-11-11 12:11 ` [PATCH v6 3/8] iio: backend: add API for oversampling Antoniu Miclaus
2024-11-11 15:41 ` Nuno Sá
2024-11-23 16:02 ` Jonathan Cameron
2024-11-23 16:05 ` Jonathan Cameron
2024-11-11 12:11 ` [PATCH v6 4/8] iio: adc: adi-axi-adc: add interface type Antoniu Miclaus
2024-11-11 12:12 ` [PATCH v6 5/8] iio: adc: adi-axi-adc: set data format Antoniu Miclaus
2024-11-12 20:11 ` David Lechner
2024-11-11 12:12 ` [PATCH v6 6/8] iio: adc: adi-axi-adc: add oversampling Antoniu Miclaus
2024-11-12 20:12 ` David Lechner
2024-11-23 16:04 ` Jonathan Cameron
2024-11-11 12:12 ` [PATCH v6 7/8] dt-bindings: iio: adc: add ad4851 Antoniu Miclaus
2024-11-11 12:12 ` [PATCH v6 8/8] iio: adc: ad4851: add ad485x driver Antoniu Miclaus
2024-11-12 20:02 ` David Lechner
2024-11-14 10:39 ` Miclaus, Antoniu
2024-11-14 14:47 ` David Lechner
2024-11-15 10:59 ` Miclaus, Antoniu
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).