All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] iio: adc: ad7192: Add improvements and new feature
@ 2023-09-18 21:48 alisadariana
  2023-09-18 21:48 ` [PATCH 1/3] iio: adc: ad7192: Use bitfield access macros alisadariana
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: alisadariana @ 2023-09-18 21:48 UTC (permalink / raw)
  Cc: Alisa-Dariana Roman, Lars-Peter Clausen, Michael Hennerich,
	Alexandru Tachici, Jonathan Cameron, linux-iio, linux-kernel

From: Alisa-Dariana Roman <alisadariana@gmail.com>

Dear maintainers,

I am submitting a series of patches to improve the ad7192 driver. I
would like to highlight that patch 3 is dependent on patch 2. For patch
3 to be applied, patch 2 needs to be applied beforehand. Also, patch 1
upgrades the driver to match the style of the last two patches.

Please consider applying these patches in order.

Thank you for your time and attention.

Sincerely,

Alisa-Dariana Roman (3):
  iio: adc: ad7192: Use bitfield access macros
  iio: adc: ad7192: Improve f_order computation
  iio: adc: ad7192: Add fast settling support

 .../ABI/testing/sysfs-bus-iio-adc-ad7192      |  18 ++
 drivers/iio/adc/ad7192.c                      | 230 +++++++++++++++---
 2 files changed, 208 insertions(+), 40 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] iio: adc: ad7192: Use bitfield access macros
  2023-09-18 21:48 [PATCH 0/3] iio: adc: ad7192: Add improvements and new feature alisadariana
@ 2023-09-18 21:48 ` alisadariana
  2023-09-19 12:24   ` Jonathan Cameron
  2023-09-18 21:48 ` [PATCH 2/3] iio: adc: ad7192: Improve f_order computation alisadariana
  2023-09-18 21:48 ` [PATCH 3/3] iio: adc: ad7192: Add fast settling support alisadariana
  2 siblings, 1 reply; 5+ messages in thread
From: alisadariana @ 2023-09-18 21:48 UTC (permalink / raw)
  Cc: Alisa-Dariana Roman, Alisa-Dariana Roman, Lars-Peter Clausen,
	Michael Hennerich, Alexandru Tachici, Jonathan Cameron, linux-iio,
	linux-kernel

From: Alisa-Dariana Roman <alisadariana@gmail.com>

Include bitfield.h and update driver to use bitfield access macros
GENMASK, FIELD_PREP and FIELD_GET.

Also simplify AD7192_CONF_GAIN(-1) to AD7192_CONF_GAIN_MASK and
AD7192_MODE_RATE(-1) to AD7192_MODE_RATE_MASK.

Signed-off-by: Alisa-Dariana Roman <alisa.roman@analog.com>
---
 drivers/iio/adc/ad7192.c | 50 +++++++++++++++++++++++++---------------
 1 file changed, 32 insertions(+), 18 deletions(-)

diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c
index 69d1103b9508..e83fecb63c1d 100644
--- a/drivers/iio/adc/ad7192.c
+++ b/drivers/iio/adc/ad7192.c
@@ -6,6 +6,7 @@
  */
 
 #include <linux/interrupt.h>
+#include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
@@ -43,7 +44,9 @@
 #define AD7192_COMM_WEN		BIT(7) /* Write Enable */
 #define AD7192_COMM_WRITE	0 /* Write Operation */
 #define AD7192_COMM_READ	BIT(6) /* Read Operation */
-#define AD7192_COMM_ADDR(x)	(((x) & 0x7) << 3) /* Register Address */
+#define AD7192_COMM_ADDR_MASK	GENMASK(5, 3) /* Register Address Mask */
+#define AD7192_COMM_ADDR(x)	FIELD_PREP(AD7192_COMM_ADDR_MASK, x)
+				  /* Register Address */
 #define AD7192_COMM_CREAD	BIT(2) /* Continuous Read of Data Register */
 
 /* Status Register Bit Designations (AD7192_REG_STAT) */
@@ -56,17 +59,24 @@
 #define AD7192_STAT_CH1		BIT(0) /* Channel 1 */
 
 /* Mode Register Bit Designations (AD7192_REG_MODE) */
-#define AD7192_MODE_SEL(x)	(((x) & 0x7) << 21) /* Operation Mode Select */
-#define AD7192_MODE_SEL_MASK	(0x7 << 21) /* Operation Mode Select Mask */
-#define AD7192_MODE_STA(x)	(((x) & 0x1) << 20) /* Status Register transmission */
+#define AD7192_MODE_SEL_MASK	GENMASK(23, 21) /* Operation Mode Select Mask */
+#define AD7192_MODE_SEL(x)	FIELD_PREP(AD7192_MODE_SEL_MASK, x)
+				  /* Operation Mode Select */
 #define AD7192_MODE_STA_MASK	BIT(20) /* Status Register transmission Mask */
-#define AD7192_MODE_CLKSRC(x)	(((x) & 0x3) << 18) /* Clock Source Select */
+#define AD7192_MODE_STA(x)	FIELD_PREP(AD7192_MODE_STA_MASK, x)
+				  /* Status Register transmission */
+#define AD7192_MODE_CLKSRC_MASK	GENMASK(19, 18) /* Clock Source Select Mask */
+#define AD7192_MODE_CLKSRC(x)	FIELD_PREP(AD7192_MODE_CLKSRC_MASK, x)
+				  /* Clock Source Select */
 #define AD7192_MODE_SINC3	BIT(15) /* SINC3 Filter Select */
 #define AD7192_MODE_ENPAR	BIT(13) /* Parity Enable */
 #define AD7192_MODE_CLKDIV	BIT(12) /* Clock divide by 2 (AD7190/2 only)*/
 #define AD7192_MODE_SCYCLE	BIT(11) /* Single cycle conversion */
 #define AD7192_MODE_REJ60	BIT(10) /* 50/60Hz notch filter */
-#define AD7192_MODE_RATE(x)	((x) & 0x3FF) /* Filter Update Rate Select */
+#define AD7192_MODE_RATE_MASK	GENMASK(9, 0)
+				  /* Filter Update Rate Select Mask */
+#define AD7192_MODE_RATE(x)	FIELD_PREP(AD7192_MODE_RATE_MASK, x)
+				  /* Filter Update Rate Select */
 
 /* Mode Register: AD7192_MODE_SEL options */
 #define AD7192_MODE_CONT		0 /* Continuous Conversion Mode */
@@ -92,13 +102,16 @@
 #define AD7192_CONF_CHOP	BIT(23) /* CHOP enable */
 #define AD7192_CONF_ACX		BIT(22) /* AC excitation enable(AD7195 only) */
 #define AD7192_CONF_REFSEL	BIT(20) /* REFIN1/REFIN2 Reference Select */
-#define AD7192_CONF_CHAN(x)	((x) << 8) /* Channel select */
-#define AD7192_CONF_CHAN_MASK	(0x7FF << 8) /* Channel select mask */
+#define AD7192_CONF_CHAN_MASK	GENMASK(18, 8) /* Channel select mask */
+#define AD7192_CONF_CHAN(x)	FIELD_PREP(AD7192_CONF_CHAN_MASK, x)
+				  /* Channel select */
 #define AD7192_CONF_BURN	BIT(7) /* Burnout current enable */
 #define AD7192_CONF_REFDET	BIT(6) /* Reference detect enable */
 #define AD7192_CONF_BUF		BIT(4) /* Buffered Mode Enable */
 #define AD7192_CONF_UNIPOLAR	BIT(3) /* Unipolar/Bipolar Enable */
-#define AD7192_CONF_GAIN(x)	((x) & 0x7) /* Gain Select */
+#define AD7192_CONF_GAIN_MASK	GENMASK(2, 0) /* Gain Select */
+#define AD7192_CONF_GAIN(x)	FIELD_PREP(AD7192_CONF_GAIN_MASK, x)
+				  /* Gain Select */
 
 #define AD7192_CH_AIN1P_AIN2M	BIT(0) /* AIN1(+) - AIN2(-) */
 #define AD7192_CH_AIN3P_AIN4M	BIT(1) /* AIN3(+) - AIN4(-) */
@@ -130,7 +143,7 @@
 #define CHIPID_AD7192		0x0
 #define CHIPID_AD7193		0x2
 #define CHIPID_AD7195		0x6
-#define AD7192_ID_MASK		0x0F
+#define AD7192_ID_MASK		GENMASK(3, 0)
 
 /* GPOCON Register Bit Designations (AD7192_REG_GPOCON) */
 #define AD7192_GPOCON_BPDSW	BIT(6) /* Bridge power-down switch enable */
@@ -399,7 +412,7 @@ static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np)
 	if (ret)
 		return ret;
 
-	id &= AD7192_ID_MASK;
+	id = FIELD_GET(AD7192_ID_MASK, id);
 
 	if (id != st->chip_info->chip_id)
 		dev_warn(&st->sd.spi->dev, "device ID query failed (0x%X != 0x%X)\n",
@@ -472,7 +485,7 @@ static ssize_t ad7192_show_ac_excitation(struct device *dev,
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct ad7192_state *st = iio_priv(indio_dev);
 
-	return sysfs_emit(buf, "%d\n", !!(st->conf & AD7192_CONF_ACX));
+	return sysfs_emit(buf, "%d\n", !!FIELD_GET(AD7192_CONF_ACX, st->conf));
 }
 
 static ssize_t ad7192_show_bridge_switch(struct device *dev,
@@ -482,7 +495,8 @@ static ssize_t ad7192_show_bridge_switch(struct device *dev,
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct ad7192_state *st = iio_priv(indio_dev);
 
-	return sysfs_emit(buf, "%d\n", !!(st->gpocon & AD7192_GPOCON_BPDSW));
+	return sysfs_emit(buf, "%d\n",
+			  !!FIELD_GET(AD7192_GPOCON_BPDSW, st->gpocon));
 }
 
 static ssize_t ad7192_set(struct device *dev,
@@ -667,9 +681,9 @@ static int ad7192_get_3db_filter_freq(struct ad7192_state *st)
 	fadc = DIV_ROUND_CLOSEST(st->fclk,
 				 st->f_order * AD7192_MODE_RATE(st->mode));
 
-	if (st->conf & AD7192_CONF_CHOP)
+	if (FIELD_GET(AD7192_CONF_CHOP, st->conf))
 		return DIV_ROUND_CLOSEST(fadc * 240, 1024);
-	if (st->mode & AD7192_MODE_SINC3)
+	if (FIELD_GET(AD7192_MODE_SINC3, st->mode))
 		return DIV_ROUND_CLOSEST(fadc * 272, 1024);
 	else
 		return DIV_ROUND_CLOSEST(fadc * 230, 1024);
@@ -682,7 +696,7 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,
 			   long m)
 {
 	struct ad7192_state *st = iio_priv(indio_dev);
-	bool unipolar = !!(st->conf & AD7192_CONF_UNIPOLAR);
+	bool unipolar = !!FIELD_GET(AD7192_CONF_UNIPOLAR, st->conf);
 
 	switch (m) {
 	case IIO_CHAN_INFO_RAW:
@@ -746,7 +760,7 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
 			if (val2 == st->scale_avail[i][1]) {
 				ret = 0;
 				tmp = st->conf;
-				st->conf &= ~AD7192_CONF_GAIN(-1);
+				st->conf &= ~AD7192_CONF_GAIN_MASK;
 				st->conf |= AD7192_CONF_GAIN(i);
 				if (tmp == st->conf)
 					break;
@@ -769,7 +783,7 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
 			break;
 		}
 
-		st->mode &= ~AD7192_MODE_RATE(-1);
+		st->mode &= ~AD7192_MODE_RATE_MASK;
 		st->mode |= AD7192_MODE_RATE(div);
 		ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
 		break;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/3] iio: adc: ad7192: Improve f_order computation
  2023-09-18 21:48 [PATCH 0/3] iio: adc: ad7192: Add improvements and new feature alisadariana
  2023-09-18 21:48 ` [PATCH 1/3] iio: adc: ad7192: Use bitfield access macros alisadariana
@ 2023-09-18 21:48 ` alisadariana
  2023-09-18 21:48 ` [PATCH 3/3] iio: adc: ad7192: Add fast settling support alisadariana
  2 siblings, 0 replies; 5+ messages in thread
From: alisadariana @ 2023-09-18 21:48 UTC (permalink / raw)
  Cc: Alisa-Dariana Roman, Alisa-Dariana Roman, Alexandru Tachici,
	Lars-Peter Clausen, Michael Hennerich, Jonathan Cameron,
	linux-iio, linux-kernel

From: Alisa-Dariana Roman <alisadariana@gmail.com>

Instead of using the f_order member of ad7192_state, a function that
computes the f_order coefficient makes more sense. This coefficient is a
function of the sinc filter and chop filter states.

Remove f_order member of ad7192_state structure. Instead use
ad7192_compute_f_order function to compute the f_order coefficient
according to the sinc filter and chop filter states passed as
parameters.

Add ad7192_get_f_order function that returns the current f_order
coefficient of the device.

Add ad7192_compute_f_adc function that computes the f_adc value
according to the sinc filter and chop filter states passed as
parameters.

Add ad7192_get_f_adc function that returns the current f_adc value of
the device.

Signed-off-by: Alisa-Dariana Roman <alisa.roman@analog.com>
---
 drivers/iio/adc/ad7192.c | 62 +++++++++++++++++++++++++++++-----------
 1 file changed, 46 insertions(+), 16 deletions(-)

diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c
index e83fecb63c1d..323e25c3ea30 100644
--- a/drivers/iio/adc/ad7192.c
+++ b/drivers/iio/adc/ad7192.c
@@ -193,7 +193,6 @@ struct ad7192_state {
 	struct clk			*mclk;
 	u16				int_vref_mv;
 	u32				fclk;
-	u32				f_order;
 	u32				mode;
 	u32				conf;
 	u32				scale_avail[8][2];
@@ -433,7 +432,6 @@ static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np)
 		st->conf |= AD7192_CONF_REFSEL;
 
 	st->conf &= ~AD7192_CONF_CHOP;
-	st->f_order = AD7192_NO_SYNC_FILTER;
 
 	buf_en = of_property_read_bool(np, "adi,buffer-enable");
 	if (buf_en)
@@ -544,22 +542,60 @@ static ssize_t ad7192_set(struct device *dev,
 	return ret ? ret : len;
 }
 
+static int ad7192_compute_f_order(bool sinc3_en, bool chop_en)
+{
+	if (!chop_en)
+		return 1;
+
+	if (sinc3_en)
+		return AD7192_SYNC3_FILTER;
+
+	return AD7192_SYNC4_FILTER;
+}
+
+static int ad7192_get_f_order(struct ad7192_state *st)
+{
+	bool sinc3_en, chop_en;
+
+	sinc3_en = FIELD_GET(AD7192_MODE_SINC3, st->mode);
+	chop_en = FIELD_GET(AD7192_CONF_CHOP, st->conf);
+
+	return ad7192_compute_f_order(sinc3_en, chop_en);
+}
+
+static int ad7192_compute_f_adc(struct ad7192_state *st, bool sinc3_en,
+				bool chop_en)
+{
+	unsigned int f_order = ad7192_compute_f_order(sinc3_en, chop_en);
+
+	return DIV_ROUND_CLOSEST(st->fclk,
+				 f_order * AD7192_MODE_RATE(st->mode));
+}
+
+static int ad7192_get_f_adc(struct ad7192_state *st)
+{
+	unsigned int f_order = ad7192_get_f_order(st);
+
+	return DIV_ROUND_CLOSEST(st->fclk,
+				 f_order * AD7192_MODE_RATE(st->mode));
+}
+
 static void ad7192_get_available_filter_freq(struct ad7192_state *st,
 						    int *freq)
 {
 	unsigned int fadc;
 
 	/* Formulas for filter at page 25 of the datasheet */
-	fadc = DIV_ROUND_CLOSEST(st->fclk,
-				 AD7192_SYNC4_FILTER * AD7192_MODE_RATE(st->mode));
+	fadc = ad7192_compute_f_adc(st, false, true);
 	freq[0] = DIV_ROUND_CLOSEST(fadc * 240, 1024);
 
-	fadc = DIV_ROUND_CLOSEST(st->fclk,
-				 AD7192_SYNC3_FILTER * AD7192_MODE_RATE(st->mode));
+	fadc = ad7192_compute_f_adc(st, true, true);
 	freq[1] = DIV_ROUND_CLOSEST(fadc * 240, 1024);
 
-	fadc = DIV_ROUND_CLOSEST(st->fclk, AD7192_MODE_RATE(st->mode));
+	fadc = ad7192_compute_f_adc(st, false, false);
 	freq[2] = DIV_ROUND_CLOSEST(fadc * 230, 1024);
+
+	fadc = ad7192_compute_f_adc(st, true, false);
 	freq[3] = DIV_ROUND_CLOSEST(fadc * 272, 1024);
 }
 
@@ -642,25 +678,21 @@ static int ad7192_set_3db_filter_freq(struct ad7192_state *st,
 
 	switch (idx) {
 	case 0:
-		st->f_order = AD7192_SYNC4_FILTER;
 		st->mode &= ~AD7192_MODE_SINC3;
 
 		st->conf |= AD7192_CONF_CHOP;
 		break;
 	case 1:
-		st->f_order = AD7192_SYNC3_FILTER;
 		st->mode |= AD7192_MODE_SINC3;
 
 		st->conf |= AD7192_CONF_CHOP;
 		break;
 	case 2:
-		st->f_order = AD7192_NO_SYNC_FILTER;
 		st->mode &= ~AD7192_MODE_SINC3;
 
 		st->conf &= ~AD7192_CONF_CHOP;
 		break;
 	case 3:
-		st->f_order = AD7192_NO_SYNC_FILTER;
 		st->mode |= AD7192_MODE_SINC3;
 
 		st->conf &= ~AD7192_CONF_CHOP;
@@ -678,8 +710,7 @@ static int ad7192_get_3db_filter_freq(struct ad7192_state *st)
 {
 	unsigned int fadc;
 
-	fadc = DIV_ROUND_CLOSEST(st->fclk,
-				 st->f_order * AD7192_MODE_RATE(st->mode));
+	fadc = ad7192_get_f_adc(st);
 
 	if (FIELD_GET(AD7192_CONF_CHOP, st->conf))
 		return DIV_ROUND_CLOSEST(fadc * 240, 1024);
@@ -726,8 +757,7 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,
 			*val -= 273 * ad7192_get_temp_scale(unipolar);
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SAMP_FREQ:
-		*val = st->fclk /
-			(st->f_order * 1024 * AD7192_MODE_RATE(st->mode));
+		*val = DIV_ROUND_CLOSEST(ad7192_get_f_adc(st), 1024);
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
 		*val = ad7192_get_3db_filter_freq(st);
@@ -777,7 +807,7 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
 			break;
 		}
 
-		div = st->fclk / (val * st->f_order * 1024);
+		div = st->fclk / (val * ad7192_get_f_order(st) * 1024);
 		if (div < 1 || div > 1023) {
 			ret = -EINVAL;
 			break;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/3] iio: adc: ad7192: Add fast settling support
  2023-09-18 21:48 [PATCH 0/3] iio: adc: ad7192: Add improvements and new feature alisadariana
  2023-09-18 21:48 ` [PATCH 1/3] iio: adc: ad7192: Use bitfield access macros alisadariana
  2023-09-18 21:48 ` [PATCH 2/3] iio: adc: ad7192: Improve f_order computation alisadariana
@ 2023-09-18 21:48 ` alisadariana
  2 siblings, 0 replies; 5+ messages in thread
From: alisadariana @ 2023-09-18 21:48 UTC (permalink / raw)
  Cc: Alisa-Dariana Roman, Alisa-Dariana Roman, Jonathan Cameron,
	Lars-Peter Clausen, Alexandru Tachici, Michael Hennerich,
	linux-iio, linux-kernel

From: Alisa-Dariana Roman <alisadariana@gmail.com>

Add fast settling mode support for AD7193.

Add fast_settling_average_factor attribute. Expose to user the current
value of the fast settling average factor. User can change the value by
writing a new one.

Add fast_settling_average_factor_available attribute. Expose to user
possible values for the fast settling average factor.

Signed-off-by: Alisa-Dariana Roman <alisa.roman@analog.com>
---
 .../ABI/testing/sysfs-bus-iio-adc-ad7192      |  18 +++
 drivers/iio/adc/ad7192.c                      | 130 ++++++++++++++++--
 2 files changed, 136 insertions(+), 12 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-bus-iio-adc-ad7192 b/Documentation/ABI/testing/sysfs-bus-iio-adc-ad7192
index f8315202c8f0..5790adbb1cc1 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio-adc-ad7192
+++ b/Documentation/ABI/testing/sysfs-bus-iio-adc-ad7192
@@ -19,6 +19,24 @@ Description:
 		the bridge can be disconnected (when it is not being used
 		using the bridge_switch_en attribute.
 
+What:		/sys/bus/iio/devices/iio:deviceX/fast_settling_average_factor
+KernelVersion:
+Contact:	linux-iio@vger.kernel.org
+Description:
+		This attribute, if available, is used to activate or deactivate
+		fast settling mode and set the value of the average factor to
+		1, 2, 8 or 16. If the average factor is set to 1, the fast
+		settling mode is disabled. The data from the sinc filter is
+		averaged by chosen value. The averaging reduces the output data
+		rate for a given FS word, however, the rms noise improves.
+
+What:		/sys/bus/iio/devices/iio:deviceX/fast_settling_average_factor_available
+KernelVersion:
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Reading returns a list with the possible values for the fast
+		settling average factor: 1, 2, 8, 16.
+
 What:		/sys/bus/iio/devices/iio:deviceX/in_voltagex_sys_calibration
 KernelVersion:
 Contact:	linux-iio@vger.kernel.org
diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c
index 323e25c3ea30..e2383a3bae87 100644
--- a/drivers/iio/adc/ad7192.c
+++ b/drivers/iio/adc/ad7192.c
@@ -68,6 +68,10 @@
 #define AD7192_MODE_CLKSRC_MASK	GENMASK(19, 18) /* Clock Source Select Mask */
 #define AD7192_MODE_CLKSRC(x)	FIELD_PREP(AD7192_MODE_CLKSRC_MASK, x)
 				  /* Clock Source Select */
+#define AD7192_MODE_AVG_MASK	GENMASK(17, 16)
+		  /* Fast Settling Filter Average Select Mask (AD7193 only) */
+#define AD7192_MODE_AVG(x)	FIELD_PREP(AD7192_MODE_AVG_MASK, x)
+		  /* Fast Settling Filter Average Select (AD7193 only) */
 #define AD7192_MODE_SINC3	BIT(15) /* SINC3 Filter Select */
 #define AD7192_MODE_ENPAR	BIT(13) /* Parity Enable */
 #define AD7192_MODE_CLKDIV	BIT(12) /* Clock divide by 2 (AD7190/2 only)*/
@@ -196,6 +200,7 @@ struct ad7192_state {
 	u32				mode;
 	u32				conf;
 	u32				scale_avail[8][2];
+	u8				avg_avail[4];
 	u8				gpocon;
 	u8				clock_sel;
 	struct mutex			lock;	/* protect sensor state */
@@ -473,6 +478,13 @@ static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np)
 		st->scale_avail[i][0] = scale_uv;
 	}
 
+	if (st->chip_info->chip_id == CHIPID_AD7193) {
+		st->avg_avail[0] = 1;
+		st->avg_avail[1] = 2;
+		st->avg_avail[2] = 8;
+		st->avg_avail[3] = 16;
+	}
+
 	return 0;
 }
 
@@ -497,6 +509,18 @@ static ssize_t ad7192_show_bridge_switch(struct device *dev,
 			  !!FIELD_GET(AD7192_GPOCON_BPDSW, st->gpocon));
 }
 
+static ssize_t ad7192_show_average_factor(struct device *dev,
+					  struct device_attribute *attr,
+					  char *buf)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct ad7192_state *st = iio_priv(indio_dev);
+	u8 avg_factor_index;
+
+	avg_factor_index = FIELD_GET(AD7192_MODE_AVG_MASK, st->mode);
+	return sysfs_emit(buf, "%d\n", st->avg_avail[avg_factor_index]);
+}
+
 static ssize_t ad7192_set(struct device *dev,
 			  struct device_attribute *attr,
 			  const char *buf,
@@ -505,12 +529,10 @@ static ssize_t ad7192_set(struct device *dev,
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct ad7192_state *st = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+	bool val, ret_einval;
+	u8 val_avg_factor;
+	unsigned int i;
 	int ret;
-	bool val;
-
-	ret = kstrtobool(buf, &val);
-	if (ret < 0)
-		return ret;
 
 	ret = iio_device_claim_direct_mode(indio_dev);
 	if (ret)
@@ -518,6 +540,10 @@ static ssize_t ad7192_set(struct device *dev,
 
 	switch ((u32)this_attr->address) {
 	case AD7192_REG_GPOCON:
+		ret = kstrtobool(buf, &val);
+		if (ret < 0)
+			return ret;
+
 		if (val)
 			st->gpocon |= AD7192_GPOCON_BPDSW;
 		else
@@ -526,6 +552,10 @@ static ssize_t ad7192_set(struct device *dev,
 		ad_sd_write_reg(&st->sd, AD7192_REG_GPOCON, 1, st->gpocon);
 		break;
 	case AD7192_REG_CONF:
+		ret = kstrtobool(buf, &val);
+		if (ret < 0)
+			return ret;
+
 		if (val)
 			st->conf |= AD7192_CONF_ACX;
 		else
@@ -533,6 +563,27 @@ static ssize_t ad7192_set(struct device *dev,
 
 		ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf);
 		break;
+	case AD7192_REG_MODE:
+		ret = kstrtou8(buf, 10, &val_avg_factor);
+		if (ret < 0)
+			return ret;
+
+		ret_einval = true;
+		for (i = 0; i < ARRAY_SIZE(st->avg_avail); i++) {
+			if (val_avg_factor == st->avg_avail[i]) {
+				st->mode &= ~AD7192_MODE_AVG_MASK;
+				st->mode |= AD7192_MODE_AVG(i);
+				ret_einval = false;
+			}
+		}
+
+		if (ret_einval)
+			return -EINVAL;
+
+		ret = ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
+		if (ret)
+			return ret;
+		break;
 	default:
 		ret = -EINVAL;
 	}
@@ -542,15 +593,22 @@ static ssize_t ad7192_set(struct device *dev,
 	return ret ? ret : len;
 }
 
-static int ad7192_compute_f_order(bool sinc3_en, bool chop_en)
+static int ad7192_compute_f_order(struct ad7192_state *st, bool sinc3_en, bool chop_en)
 {
-	if (!chop_en)
+	u8 avg_factor;
+	u8 avg_factor_selected;
+
+	avg_factor_selected = FIELD_GET(AD7192_MODE_AVG_MASK, st->mode);
+
+	if (!avg_factor_selected && !chop_en)
 		return 1;
 
+	avg_factor = st->avg_avail[avg_factor_selected];
+
 	if (sinc3_en)
-		return AD7192_SYNC3_FILTER;
+		return AD7192_SYNC3_FILTER + avg_factor - 1;
 
-	return AD7192_SYNC4_FILTER;
+	return AD7192_SYNC4_FILTER + avg_factor - 1;
 }
 
 static int ad7192_get_f_order(struct ad7192_state *st)
@@ -560,13 +618,13 @@ static int ad7192_get_f_order(struct ad7192_state *st)
 	sinc3_en = FIELD_GET(AD7192_MODE_SINC3, st->mode);
 	chop_en = FIELD_GET(AD7192_CONF_CHOP, st->conf);
 
-	return ad7192_compute_f_order(sinc3_en, chop_en);
+	return ad7192_compute_f_order(st, sinc3_en, chop_en);
 }
 
 static int ad7192_compute_f_adc(struct ad7192_state *st, bool sinc3_en,
 				bool chop_en)
 {
-	unsigned int f_order = ad7192_compute_f_order(sinc3_en, chop_en);
+	unsigned int f_order = ad7192_compute_f_order(st, sinc3_en, chop_en);
 
 	return DIV_ROUND_CLOSEST(st->fclk,
 				 f_order * AD7192_MODE_RATE(st->mode));
@@ -619,9 +677,29 @@ static ssize_t ad7192_show_filter_avail(struct device *dev,
 	return len;
 }
 
+static ssize_t ad7192_show_avg_factor_avail(struct device *dev,
+					    struct device_attribute *attr,
+					    char *buf)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct ad7192_state *st = iio_priv(indio_dev);
+	unsigned int i;
+	size_t len = 0;
+
+	for (i = 0; i < ARRAY_SIZE(st->avg_avail); i++)
+		len += sysfs_emit_at(buf, len, "%d ", st->avg_avail[i]);
+
+	buf[len - 1] = '\n';
+
+	return len;
+}
+
 static IIO_DEVICE_ATTR(filter_low_pass_3db_frequency_available,
 		       0444, ad7192_show_filter_avail, NULL, 0);
 
+static IIO_DEVICE_ATTR(fast_settling_average_factor_available,
+		       0444, ad7192_show_avg_factor_avail, NULL, 0);
+
 static IIO_DEVICE_ATTR(bridge_switch_en, 0644,
 		       ad7192_show_bridge_switch, ad7192_set,
 		       AD7192_REG_GPOCON);
@@ -630,6 +708,10 @@ static IIO_DEVICE_ATTR(ac_excitation_en, 0644,
 		       ad7192_show_ac_excitation, ad7192_set,
 		       AD7192_REG_CONF);
 
+static IIO_DEVICE_ATTR(fast_settling_average_factor, 0644,
+		       ad7192_show_average_factor, ad7192_set,
+		       AD7192_REG_MODE);
+
 static struct attribute *ad7192_attributes[] = {
 	&iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr,
 	&iio_dev_attr_bridge_switch_en.dev_attr.attr,
@@ -640,6 +722,18 @@ static const struct attribute_group ad7192_attribute_group = {
 	.attrs = ad7192_attributes,
 };
 
+static struct attribute *ad7193_attributes[] = {
+	&iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr,
+	&iio_dev_attr_bridge_switch_en.dev_attr.attr,
+	&iio_dev_attr_fast_settling_average_factor.dev_attr.attr,
+	&iio_dev_attr_fast_settling_average_factor_available.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group ad7193_attribute_group = {
+	.attrs = ad7193_attributes,
+};
+
 static struct attribute *ad7195_attributes[] = {
 	&iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr,
 	&iio_dev_attr_bridge_switch_en.dev_attr.attr,
@@ -895,6 +989,16 @@ static const struct iio_info ad7192_info = {
 	.update_scan_mode = ad7192_update_scan_mode,
 };
 
+static const struct iio_info ad7193_info = {
+	.read_raw = ad7192_read_raw,
+	.write_raw = ad7192_write_raw,
+	.write_raw_get_fmt = ad7192_write_raw_get_fmt,
+	.read_avail = ad7192_read_avail,
+	.attrs = &ad7193_attribute_group,
+	.validate_trigger = ad_sd_validate_trigger,
+	.update_scan_mode = ad7192_update_scan_mode,
+};
+
 static const struct iio_info ad7195_info = {
 	.read_raw = ad7192_read_raw,
 	.write_raw = ad7192_write_raw,
@@ -1069,7 +1173,9 @@ static int ad7192_probe(struct spi_device *spi)
 	if (ret < 0)
 		return ret;
 
-	if (st->chip_info->chip_id == CHIPID_AD7195)
+	if (st->chip_info->chip_id == CHIPID_AD7193)
+		indio_dev->info = &ad7193_info;
+	else if (st->chip_info->chip_id == CHIPID_AD7195)
 		indio_dev->info = &ad7195_info;
 	else
 		indio_dev->info = &ad7192_info;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/3] iio: adc: ad7192: Use bitfield access macros
  2023-09-18 21:48 ` [PATCH 1/3] iio: adc: ad7192: Use bitfield access macros alisadariana
@ 2023-09-19 12:24   ` Jonathan Cameron
  0 siblings, 0 replies; 5+ messages in thread
From: Jonathan Cameron @ 2023-09-19 12:24 UTC (permalink / raw)
  To: alisadariana
  Cc: Alisa-Dariana Roman, Lars-Peter Clausen, Michael Hennerich,
	Alexandru Tachici, Jonathan Cameron, linux-iio, linux-kernel

On Tue, 19 Sep 2023 00:48:52 +0300
alisadariana@gmail.com wrote:

> From: Alisa-Dariana Roman <alisadariana@gmail.com>
> 
> Include bitfield.h and update driver to use bitfield access macros
> GENMASK, FIELD_PREP and FIELD_GET.
> 
> Also simplify AD7192_CONF_GAIN(-1) to AD7192_CONF_GAIN_MASK and
> AD7192_MODE_RATE(-1) to AD7192_MODE_RATE_MASK.
> 
> Signed-off-by: Alisa-Dariana Roman <alisa.roman@analog.com>
> ---
>  drivers/iio/adc/ad7192.c | 50 +++++++++++++++++++++++++---------------
>  1 file changed, 32 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c
> index 69d1103b9508..e83fecb63c1d 100644
> --- a/drivers/iio/adc/ad7192.c
> +++ b/drivers/iio/adc/ad7192.c
> @@ -6,6 +6,7 @@
>   */
>  
>  #include <linux/interrupt.h>
> +#include <linux/bitfield.h>
>  #include <linux/clk.h>
>  #include <linux/device.h>
>  #include <linux/kernel.h>
> @@ -43,7 +44,9 @@
>  #define AD7192_COMM_WEN		BIT(7) /* Write Enable */
>  #define AD7192_COMM_WRITE	0 /* Write Operation */
>  #define AD7192_COMM_READ	BIT(6) /* Read Operation */
> -#define AD7192_COMM_ADDR(x)	(((x) & 0x7) << 3) /* Register Address */
> +#define AD7192_COMM_ADDR_MASK	GENMASK(5, 3) /* Register Address Mask */
> +#define AD7192_COMM_ADDR(x)	FIELD_PREP(AD7192_COMM_ADDR_MASK, x)
> +				  /* Register Address */
>  #define AD7192_COMM_CREAD	BIT(2) /* Continuous Read of Data Register */
>  
>  /* Status Register Bit Designations (AD7192_REG_STAT) */
> @@ -56,17 +59,24 @@
>  #define AD7192_STAT_CH1		BIT(0) /* Channel 1 */
>  
>  /* Mode Register Bit Designations (AD7192_REG_MODE) */
> -#define AD7192_MODE_SEL(x)	(((x) & 0x7) << 21) /* Operation Mode Select */
> -#define AD7192_MODE_SEL_MASK	(0x7 << 21) /* Operation Mode Select Mask */
> -#define AD7192_MODE_STA(x)	(((x) & 0x1) << 20) /* Status Register transmission */
> +#define AD7192_MODE_SEL_MASK	GENMASK(23, 21) /* Operation Mode Select Mask */
> +#define AD7192_MODE_SEL(x)	FIELD_PREP(AD7192_MODE_SEL_MASK, x)

Hi  Alisa-Dariana,

Whilst it is a bigger change, I'd ideally like all these XXX(x) calls to be replaced
inline with the FIELD_PREP(). It is just as clear to read and in many cases better
because you get patterns that go form

st->mode &= ~AD7192_MODE_SEL_MASK;
st->mode |= AD7192_MODE_SEL(mode);

which becomes the more visible and obvious
st->mode &= ~AD7192_MODE_SEL_MASK;
st->mode |= FIELD_PREP(AD7192_MODE_SEL_MASK, mode);
where you can clearly see the same bits were removed from st->mode, then
filled in with the new field value.

That's obscured with the additional macro.

Jonathan


> +				  /* Operation Mode Select */
>  #define AD7192_MODE_STA_MASK	BIT(20) /* Status Register transmission Mask */
> -#define AD7192_MODE_CLKSRC(x)	(((x) & 0x3) << 18) /* Clock Source Select */
> +#define AD7192_MODE_STA(x)	FIELD_PREP(AD7192_MODE_STA_MASK, x)
> +				  /* Status Register transmission */
> +#define AD7192_MODE_CLKSRC_MASK	GENMASK(19, 18) /* Clock Source Select Mask */
> +#define AD7192_MODE_CLKSRC(x)	FIELD_PREP(AD7192_MODE_CLKSRC_MASK, x)
> +				  /* Clock Source Select */
>  #define AD7192_MODE_SINC3	BIT(15) /* SINC3 Filter Select */
>  #define AD7192_MODE_ENPAR	BIT(13) /* Parity Enable */
>  #define AD7192_MODE_CLKDIV	BIT(12) /* Clock divide by 2 (AD7190/2 only)*/
>  #define AD7192_MODE_SCYCLE	BIT(11) /* Single cycle conversion */
>  #define AD7192_MODE_REJ60	BIT(10) /* 50/60Hz notch filter */
> -#define AD7192_MODE_RATE(x)	((x) & 0x3FF) /* Filter Update Rate Select */
> +#define AD7192_MODE_RATE_MASK	GENMASK(9, 0)
> +				  /* Filter Update Rate Select Mask */
> +#define AD7192_MODE_RATE(x)	FIELD_PREP(AD7192_MODE_RATE_MASK, x)
> +				  /* Filter Update Rate Select */
>  
>  /* Mode Register: AD7192_MODE_SEL options */
>  #define AD7192_MODE_CONT		0 /* Continuous Conversion Mode */
> @@ -92,13 +102,16 @@
>  #define AD7192_CONF_CHOP	BIT(23) /* CHOP enable */
>  #define AD7192_CONF_ACX		BIT(22) /* AC excitation enable(AD7195 only) */
>  #define AD7192_CONF_REFSEL	BIT(20) /* REFIN1/REFIN2 Reference Select */
> -#define AD7192_CONF_CHAN(x)	((x) << 8) /* Channel select */
> -#define AD7192_CONF_CHAN_MASK	(0x7FF << 8) /* Channel select mask */
> +#define AD7192_CONF_CHAN_MASK	GENMASK(18, 8) /* Channel select mask */
> +#define AD7192_CONF_CHAN(x)	FIELD_PREP(AD7192_CONF_CHAN_MASK, x)
> +				  /* Channel select */
>  #define AD7192_CONF_BURN	BIT(7) /* Burnout current enable */
>  #define AD7192_CONF_REFDET	BIT(6) /* Reference detect enable */
>  #define AD7192_CONF_BUF		BIT(4) /* Buffered Mode Enable */
>  #define AD7192_CONF_UNIPOLAR	BIT(3) /* Unipolar/Bipolar Enable */
> -#define AD7192_CONF_GAIN(x)	((x) & 0x7) /* Gain Select */
> +#define AD7192_CONF_GAIN_MASK	GENMASK(2, 0) /* Gain Select */
> +#define AD7192_CONF_GAIN(x)	FIELD_PREP(AD7192_CONF_GAIN_MASK, x)
> +				  /* Gain Select */
>  
>  #define AD7192_CH_AIN1P_AIN2M	BIT(0) /* AIN1(+) - AIN2(-) */
>  #define AD7192_CH_AIN3P_AIN4M	BIT(1) /* AIN3(+) - AIN4(-) */
> @@ -130,7 +143,7 @@
>  #define CHIPID_AD7192		0x0
>  #define CHIPID_AD7193		0x2
>  #define CHIPID_AD7195		0x6
> -#define AD7192_ID_MASK		0x0F
> +#define AD7192_ID_MASK		GENMASK(3, 0)
>  
>  /* GPOCON Register Bit Designations (AD7192_REG_GPOCON) */
>  #define AD7192_GPOCON_BPDSW	BIT(6) /* Bridge power-down switch enable */
> @@ -399,7 +412,7 @@ static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np)
>  	if (ret)
>  		return ret;
>  
> -	id &= AD7192_ID_MASK;
> +	id = FIELD_GET(AD7192_ID_MASK, id);
>  
>  	if (id != st->chip_info->chip_id)
>  		dev_warn(&st->sd.spi->dev, "device ID query failed (0x%X != 0x%X)\n",
> @@ -472,7 +485,7 @@ static ssize_t ad7192_show_ac_excitation(struct device *dev,
>  	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>  	struct ad7192_state *st = iio_priv(indio_dev);
>  
> -	return sysfs_emit(buf, "%d\n", !!(st->conf & AD7192_CONF_ACX));
> +	return sysfs_emit(buf, "%d\n", !!FIELD_GET(AD7192_CONF_ACX, st->conf));
>  }
>  
>  static ssize_t ad7192_show_bridge_switch(struct device *dev,
> @@ -482,7 +495,8 @@ static ssize_t ad7192_show_bridge_switch(struct device *dev,
>  	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>  	struct ad7192_state *st = iio_priv(indio_dev);
>  
> -	return sysfs_emit(buf, "%d\n", !!(st->gpocon & AD7192_GPOCON_BPDSW));
> +	return sysfs_emit(buf, "%d\n",
> +			  !!FIELD_GET(AD7192_GPOCON_BPDSW, st->gpocon));
>  }
>  
>  static ssize_t ad7192_set(struct device *dev,
> @@ -667,9 +681,9 @@ static int ad7192_get_3db_filter_freq(struct ad7192_state *st)
>  	fadc = DIV_ROUND_CLOSEST(st->fclk,
>  				 st->f_order * AD7192_MODE_RATE(st->mode));
>  
> -	if (st->conf & AD7192_CONF_CHOP)
> +	if (FIELD_GET(AD7192_CONF_CHOP, st->conf))
>  		return DIV_ROUND_CLOSEST(fadc * 240, 1024);
> -	if (st->mode & AD7192_MODE_SINC3)
> +	if (FIELD_GET(AD7192_MODE_SINC3, st->mode))
>  		return DIV_ROUND_CLOSEST(fadc * 272, 1024);
>  	else
>  		return DIV_ROUND_CLOSEST(fadc * 230, 1024);
> @@ -682,7 +696,7 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,
>  			   long m)
>  {
>  	struct ad7192_state *st = iio_priv(indio_dev);
> -	bool unipolar = !!(st->conf & AD7192_CONF_UNIPOLAR);
> +	bool unipolar = !!FIELD_GET(AD7192_CONF_UNIPOLAR, st->conf);
>  
>  	switch (m) {
>  	case IIO_CHAN_INFO_RAW:
> @@ -746,7 +760,7 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
>  			if (val2 == st->scale_avail[i][1]) {
>  				ret = 0;
>  				tmp = st->conf;
> -				st->conf &= ~AD7192_CONF_GAIN(-1);
> +				st->conf &= ~AD7192_CONF_GAIN_MASK;
>  				st->conf |= AD7192_CONF_GAIN(i);
>  				if (tmp == st->conf)
>  					break;
> @@ -769,7 +783,7 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
>  			break;
>  		}
>  
> -		st->mode &= ~AD7192_MODE_RATE(-1);
> +		st->mode &= ~AD7192_MODE_RATE_MASK;
>  		st->mode |= AD7192_MODE_RATE(div);
>  		ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
>  		break;


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2023-09-19 12:24 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-18 21:48 [PATCH 0/3] iio: adc: ad7192: Add improvements and new feature alisadariana
2023-09-18 21:48 ` [PATCH 1/3] iio: adc: ad7192: Use bitfield access macros alisadariana
2023-09-19 12:24   ` Jonathan Cameron
2023-09-18 21:48 ` [PATCH 2/3] iio: adc: ad7192: Improve f_order computation alisadariana
2023-09-18 21:48 ` [PATCH 3/3] iio: adc: ad7192: Add fast settling support alisadariana

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.