lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20240228122617.185814-5-alisa.roman@analog.com>
Date: Wed, 28 Feb 2024 14:26:17 +0200
From: Alisa-Dariana Roman <alisadariana@...il.com>
To: michael.hennerich@...log.com,
	linux-iio@...r.kernel.org,
	devicetree@...r.kernel.org,
	linux-kernel@...r.kernel.org
Cc: lars@...afoo.de,
	Michael.Hennerich@...log.com,
	jic23@...nel.org,
	robh+dt@...nel.org,
	krzysztof.kozlowski+dt@...aro.org,
	conor+dt@...nel.org,
	andriy.shevchenko@...ux.intel.com,
	nuno.sa@...log.com,
	alisa.roman@...log.com,
	dlechner@...libre.com
Subject: [PATCH v4 4/4] iio: adc: ad7192: Add AD7194 support

Unlike the other AD719Xs, AD7194 has configurable differential
channels. The configuration for the 16 differential channels can be
changed in the devicetree.

The default configuration includes 16 differential channels
corresponding to the voltage difference between each AINx input and
AINCOM input.

Also modify config AD7192 description for better scaling.

Moved ad7192_chip_info struct definition to allow use of callback
function parse_channels().

Signed-off-by: Alisa-Dariana Roman <alisa.roman@...log.com>
Reviewed-by: Nuno Sa <nuno.sa@...log.com>
Signed-off-by: romandariana <alisa.roman@...log.com>
---
 drivers/iio/adc/Kconfig  |  11 ++-
 drivers/iio/adc/ad7192.c | 143 ++++++++++++++++++++++++++++++++++++---
 2 files changed, 141 insertions(+), 13 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 0d9282fa67f5..6d8202d9f501 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -71,12 +71,17 @@ config AD7124
 	  called ad7124.
 
 config AD7192
-	tristate "Analog Devices AD7190 AD7192 AD7193 AD7195 ADC driver"
+	tristate "Analog Devices AD7192 and similar ADC driver"
 	depends on SPI
 	select AD_SIGMA_DELTA
 	help
-	  Say yes here to build support for Analog Devices AD7190,
-	  AD7192, AD7193 or AD7195 SPI analog to digital converters (ADC).
+	  Say yes here to build support for Analog Devices SPI analog to digital
+	  converters (ADC):
+	  - AD7190
+	  - AD7192
+	  - AD7193
+	  - AD7194
+	  - AD7195
 	  If unsure, say N (but it's safe to say "Y").
 
 	  To compile this driver as a module, choose M here: the
diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c
index e0f1c9eaf9ae..f8ba724bc143 100644
--- a/drivers/iio/adc/ad7192.c
+++ b/drivers/iio/adc/ad7192.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * AD7190 AD7192 AD7193 AD7195 SPI ADC driver
+ * AD7192 and similar SPI ADC driver
  *
  * Copyright 2011-2015 Analog Devices Inc.
  */
@@ -128,10 +128,39 @@
 #define AD7193_CH_AIN8		0x480 /* AIN7 - AINCOM */
 #define AD7193_CH_AINCOM	0x600 /* AINCOM - AINCOM */
 
+#define AD7194_CH_POS(x)	(((x) - 1) << 4)
+#define AD7194_CH_NEG(x)	((x) - 1)
+#define AD7194_CH_DIFF(pos, neg) \
+		(((neg) == 0 ? BIT(10) : AD7194_CH_NEG(neg)) | AD7194_CH_POS(pos))
+#define AD7194_CH_AIN1		AD7194_CH_DIFF(1, 0) /* AIN1 - AINCOM */
+#define AD7194_CH_AIN2		AD7194_CH_DIFF(2, 0) /* AIN2 - AINCOM */
+#define AD7194_CH_AIN3		AD7194_CH_DIFF(3, 0) /* AIN3 - AINCOM */
+#define AD7194_CH_AIN4		AD7194_CH_DIFF(4, 0) /* AIN4 - AINCOM */
+#define AD7194_CH_AIN5		AD7194_CH_DIFF(5, 0) /* AIN5 - AINCOM */
+#define AD7194_CH_AIN6		AD7194_CH_DIFF(6, 0) /* AIN6 - AINCOM */
+#define AD7194_CH_AIN7		AD7194_CH_DIFF(7, 0) /* AIN7 - AINCOM */
+#define AD7194_CH_AIN8		AD7194_CH_DIFF(8, 0) /* AIN8 - AINCOM */
+#define AD7194_CH_AIN9		AD7194_CH_DIFF(9, 0) /* AIN9 - AINCOM */
+#define AD7194_CH_AIN10		AD7194_CH_DIFF(10, 0) /* AIN10 - AINCOM */
+#define AD7194_CH_AIN11		AD7194_CH_DIFF(11, 0) /* AIN11 - AINCOM */
+#define AD7194_CH_AIN12		AD7194_CH_DIFF(12, 0) /* AIN12 - AINCOM */
+#define AD7194_CH_AIN13		AD7194_CH_DIFF(13, 0) /* AIN13 - AINCOM */
+#define AD7194_CH_AIN14		AD7194_CH_DIFF(14, 0) /* AIN14 - AINCOM */
+#define AD7194_CH_AIN15		AD7194_CH_DIFF(15, 0) /* AIN15 - AINCOM */
+#define AD7194_CH_AIN16		AD7194_CH_DIFF(16, 0) /* AIN16 - AINCOM */
+#define AD7194_CH_TEMP		0x100 /* Temp sensor */
+#define AD7194_CH_DIFF_START	1
+#define AD7194_CH_DIFF_NR	16
+#define AD7194_CH_AIN0_START	1
+#define AD7194_CH_AIN0_NR	16
+#define AD7194_CH_AIN1_START	0
+#define AD7194_CH_AIN1_NR	17
+
 /* ID Register Bit Designations (AD7192_REG_ID) */
 #define CHIPID_AD7190		0x4
 #define CHIPID_AD7192		0x0
 #define CHIPID_AD7193		0x2
+#define CHIPID_AD7194		0x3
 #define CHIPID_AD7195		0x6
 #define AD7192_ID_MASK		GENMASK(3, 0)
 
@@ -169,17 +198,10 @@ enum {
 	ID_AD7190,
 	ID_AD7192,
 	ID_AD7193,
+	ID_AD7194,
 	ID_AD7195,
 };
 
-struct ad7192_chip_info {
-	unsigned int			chip_id;
-	const char			*name;
-	const struct iio_chan_spec	*channels;
-	u8				num_channels;
-	const struct iio_info		*info;
-};
-
 struct ad7192_state {
 	const struct ad7192_chip_info	*chip_info;
 	struct regulator		*avdd;
@@ -200,6 +222,15 @@ struct ad7192_state {
 	struct ad_sigma_delta		sd;
 };
 
+struct ad7192_chip_info {
+	unsigned int			chip_id;
+	const char			*name;
+	const struct iio_chan_spec	*channels;
+	u8				num_channels;
+	const struct iio_info		*info;
+	int (*parse_channels)(struct ad7192_state *st);
+};
+
 static const char * const ad7192_syscalib_modes[] = {
 	[AD7192_SYSCALIB_ZERO_SCALE] = "zero_scale",
 	[AD7192_SYSCALIB_FULL_SCALE] = "full_scale",
@@ -921,6 +952,15 @@ static const struct iio_info ad7192_info = {
 	.update_scan_mode = ad7192_update_scan_mode,
 };
 
+static const struct iio_info ad7194_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,
+	.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,
@@ -1012,6 +1052,73 @@ static const struct iio_chan_spec ad7193_channels[] = {
 	IIO_CHAN_SOFT_TIMESTAMP(14),
 };
 
+static struct iio_chan_spec ad7194_channels[] = {
+	AD7193_DIFF_CHANNEL(0, 1, 0, AD7194_CH_AIN1),
+	AD7193_DIFF_CHANNEL(1, 2, 0, AD7194_CH_AIN2),
+	AD7193_DIFF_CHANNEL(2, 3, 0, AD7194_CH_AIN3),
+	AD7193_DIFF_CHANNEL(3, 4, 0, AD7194_CH_AIN4),
+	AD7193_DIFF_CHANNEL(4, 5, 0, AD7194_CH_AIN5),
+	AD7193_DIFF_CHANNEL(5, 6, 0, AD7194_CH_AIN6),
+	AD7193_DIFF_CHANNEL(6, 7, 0, AD7194_CH_AIN7),
+	AD7193_DIFF_CHANNEL(7, 8, 0, AD7194_CH_AIN8),
+	AD7193_DIFF_CHANNEL(8, 9, 0, AD7194_CH_AIN9),
+	AD7193_DIFF_CHANNEL(9, 10, 0, AD7194_CH_AIN10),
+	AD7193_DIFF_CHANNEL(10, 11, 0, AD7194_CH_AIN11),
+	AD7193_DIFF_CHANNEL(11, 12, 0, AD7194_CH_AIN12),
+	AD7193_DIFF_CHANNEL(12, 13, 0, AD7194_CH_AIN13),
+	AD7193_DIFF_CHANNEL(13, 14, 0, AD7194_CH_AIN14),
+	AD7193_DIFF_CHANNEL(14, 15, 0, AD7194_CH_AIN15),
+	AD7193_DIFF_CHANNEL(15, 16, 0, AD7194_CH_AIN16),
+	AD719x_TEMP_CHANNEL(16, AD7194_CH_TEMP),
+	IIO_CHAN_SOFT_TIMESTAMP(17),
+};
+
+static int ad7192_parse_channel(struct fwnode_handle *child)
+{
+	u32 reg, ain[2];
+	int ret;
+
+	ret = fwnode_property_read_u32(child, "reg", &reg);
+	if (ret)
+		return ret;
+
+	if (!in_range(reg, AD7194_CH_DIFF_START, AD7194_CH_DIFF_NR))
+		return -EINVAL;
+
+	ret = fwnode_property_read_u32_array(child, "diff-channels", ain,
+					     ARRAY_SIZE(ain));
+	if (ret)
+		return ret;
+
+	if (!in_range(ain[0], AD7194_CH_AIN0_START, AD7194_CH_AIN0_NR) ||
+	    !in_range(ain[1], AD7194_CH_AIN1_START, AD7194_CH_AIN1_NR))
+		return -EINVAL;
+
+	reg--;
+	ad7194_channels[reg].channel = ain[0];
+	ad7194_channels[reg].channel2 = ain[1];
+	ad7194_channels[reg].address = AD7194_CH_DIFF(ain[0], ain[1]);
+
+	return 0;
+}
+
+static int ad7192_parse_channels(struct ad7192_state *st)
+{
+	struct device *dev = &st->sd.spi->dev;
+	struct fwnode_handle *child;
+	int ret;
+
+	device_for_each_child_node(dev, child) {
+		ret = ad7192_parse_channel(child);
+		if (ret) {
+			fwnode_handle_put(child);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 static const struct ad7192_chip_info ad7192_chip_info_tbl[] = {
 	[ID_AD7190] = {
 		.chip_id = CHIPID_AD7190,
@@ -1034,6 +1141,14 @@ static const struct ad7192_chip_info ad7192_chip_info_tbl[] = {
 		.num_channels = ARRAY_SIZE(ad7193_channels),
 		.info = &ad7192_info,
 	},
+	[ID_AD7194] = {
+		.chip_id = CHIPID_AD7194,
+		.name = "ad7194",
+		.channels = ad7194_channels,
+		.num_channels = ARRAY_SIZE(ad7194_channels),
+		.info = &ad7194_info,
+		.parse_channels = ad7192_parse_channels,
+	},
 	[ID_AD7195] = {
 		.chip_id = CHIPID_AD7195,
 		.name = "ad7195",
@@ -1145,6 +1260,12 @@ static int ad7192_probe(struct spi_device *spi)
 		}
 	}
 
+	if (st->chip_info->parse_channels) {
+		ret = st->chip_info->parse_channels(st);
+		if (ret)
+			return ret;
+	}
+
 	ret = ad7192_setup(st);
 	if (ret)
 		return ret;
@@ -1156,6 +1277,7 @@ static const struct of_device_id ad7192_of_match[] = {
 	{ .compatible = "adi,ad7190", .data = &ad7192_chip_info_tbl[ID_AD7190] },
 	{ .compatible = "adi,ad7192", .data = &ad7192_chip_info_tbl[ID_AD7192] },
 	{ .compatible = "adi,ad7193", .data = &ad7192_chip_info_tbl[ID_AD7193] },
+	{ .compatible = "adi,ad7194", .data = &ad7192_chip_info_tbl[ID_AD7194] },
 	{ .compatible = "adi,ad7195", .data = &ad7192_chip_info_tbl[ID_AD7195] },
 	{}
 };
@@ -1165,6 +1287,7 @@ static const struct spi_device_id ad7192_ids[] = {
 	{ "ad7190", (kernel_ulong_t)&ad7192_chip_info_tbl[ID_AD7190] },
 	{ "ad7192", (kernel_ulong_t)&ad7192_chip_info_tbl[ID_AD7192] },
 	{ "ad7193", (kernel_ulong_t)&ad7192_chip_info_tbl[ID_AD7193] },
+	{ "ad7194", (kernel_ulong_t)&ad7192_chip_info_tbl[ID_AD7194] },
 	{ "ad7195", (kernel_ulong_t)&ad7192_chip_info_tbl[ID_AD7195] },
 	{}
 };
@@ -1181,6 +1304,6 @@ static struct spi_driver ad7192_driver = {
 module_spi_driver(ad7192_driver);
 
 MODULE_AUTHOR("Michael Hennerich <michael.hennerich@...log.com>");
-MODULE_DESCRIPTION("Analog Devices AD7190, AD7192, AD7193, AD7195 ADC");
+MODULE_DESCRIPTION("Analog Devices AD7192 and similar ADC");
 MODULE_LICENSE("GPL v2");
 MODULE_IMPORT_NS(IIO_AD_SIGMA_DELTA);
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ