[PATCH v1 3/3] iio: adc: ad7192: Add sync gpio

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add support for the SYNC pin of AD719x devices. This pin is controlled
through a GPIO. The pin allows synchronization of digital filters and
analog modulators when using multiple devices.

Signed-off-by: Alisa-Dariana Roman <alisa.roman@xxxxxxxxxx>
---
 drivers/iio/adc/ad7192.c | 112 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 111 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c
index 955e9eff0099..542db7280e99 100644
--- a/drivers/iio/adc/ad7192.c
+++ b/drivers/iio/adc/ad7192.c
@@ -10,6 +10,7 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/device.h>
+#include <linux/gpio/consumer.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/sysfs.h>
@@ -196,6 +197,7 @@ struct ad7192_chip_info {
 	u8				num_channels;
 	const struct ad_sigma_delta_info	*sigma_delta_info;
 	const struct iio_info		*info;
+	const struct iio_info		*info_sync;
 	int (*parse_channels)(struct iio_dev *indio_dev);
 };
 
@@ -216,6 +218,8 @@ struct ad7192_state {
 	struct mutex			lock;	/* protect sensor state */
 	u8				syscalib_mode[8];
 
+	struct gpio_desc		*sync_gpio;
+
 	struct ad_sigma_delta		sd;
 };
 
@@ -783,6 +787,36 @@ static void ad7192_update_filter_freq_avail(struct ad7192_state *st)
 	st->filter_freq_avail[3][0] = DIV_ROUND_CLOSEST(fadc * 272, 1024);
 }
 
+static ssize_t sync_gpio_show(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);
+
+	return sysfs_emit(buf, "%d\n", gpiod_get_value(st->sync_gpio));
+}
+
+static ssize_t sync_gpio_store(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf,
+			       size_t len)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct ad7192_state *st = iio_priv(indio_dev);
+	int val;
+	int ret;
+
+	ret = kstrtoint(buf, 0, &val);
+	if (ret < 0)
+		return ret;
+
+	if (st->sync_gpio)
+		gpiod_set_value(st->sync_gpio, val);
+
+	return len;
+}
+
 static IIO_DEVICE_ATTR(bridge_switch_en, 0644,
 		       ad7192_show_bridge_switch, ad7192_set,
 		       AD7192_REG_GPOCON);
@@ -791,25 +825,57 @@ static IIO_DEVICE_ATTR(ac_excitation_en, 0644,
 		       ad7192_show_ac_excitation, ad7192_set,
 		       AD7192_REG_CONF);
 
+static IIO_DEVICE_ATTR_RW(sync_gpio, 0);
+
 static struct attribute *ad7192_attributes[] = {
 	&iio_dev_attr_bridge_switch_en.dev_attr.attr,
 	NULL
 };
 
+static struct attribute *ad7192_attributes_sync[] = {
+	&iio_dev_attr_bridge_switch_en.dev_attr.attr,
+	&iio_dev_attr_sync_gpio.dev_attr.attr,
+	NULL
+};
+
 static const struct attribute_group ad7192_attribute_group = {
 	.attrs = ad7192_attributes,
 };
 
+static const struct attribute_group ad7192_attribute_group_sync = {
+	.attrs = ad7192_attributes_sync,
+};
+
+static struct attribute *ad7194_attributes_sync[] = {
+	&iio_dev_attr_sync_gpio.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group ad7194_attribute_group_sync = {
+	.attrs = ad7194_attributes_sync,
+};
+
 static struct attribute *ad7195_attributes[] = {
 	&iio_dev_attr_bridge_switch_en.dev_attr.attr,
 	&iio_dev_attr_ac_excitation_en.dev_attr.attr,
 	NULL
 };
 
+static struct attribute *ad7195_attributes_sync[] = {
+	&iio_dev_attr_bridge_switch_en.dev_attr.attr,
+	&iio_dev_attr_ac_excitation_en.dev_attr.attr,
+	&iio_dev_attr_sync_gpio.dev_attr.attr,
+	NULL
+};
+
 static const struct attribute_group ad7195_attribute_group = {
 	.attrs = ad7195_attributes,
 };
 
+static const struct attribute_group ad7195_attribute_group_sync = {
+	.attrs = ad7195_attributes_sync,
+};
+
 static unsigned int ad7192_get_temp_scale(bool unipolar)
 {
 	return unipolar ? 2815 * 2 : 2815;
@@ -1103,6 +1169,16 @@ static const struct iio_info ad7192_info = {
 	.update_scan_mode = ad7192_update_scan_mode,
 };
 
+static const struct iio_info ad7192_info_sync = {
+	.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 = &ad7192_attribute_group_sync,
+	.validate_trigger = ad_sd_validate_trigger,
+	.update_scan_mode = ad7192_update_scan_mode,
+};
+
 static const struct iio_info ad7194_info = {
 	.read_raw = ad7192_read_raw,
 	.write_raw = ad7192_write_raw,
@@ -1111,6 +1187,15 @@ static const struct iio_info ad7194_info = {
 	.validate_trigger = ad_sd_validate_trigger,
 };
 
+static const struct iio_info ad7194_info_sync = {
+	.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 = &ad7194_attribute_group_sync,
+	.validate_trigger = ad_sd_validate_trigger,
+};
+
 static const struct iio_info ad7195_info = {
 	.read_raw = ad7192_read_raw,
 	.write_raw = ad7192_write_raw,
@@ -1121,6 +1206,16 @@ static const struct iio_info ad7195_info = {
 	.update_scan_mode = ad7192_update_scan_mode,
 };
 
+static const struct iio_info ad7195_info_sync = {
+	.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 = &ad7195_attribute_group_sync,
+	.validate_trigger = ad_sd_validate_trigger,
+	.update_scan_mode = ad7192_update_scan_mode,
+};
+
 #define __AD719x_CHANNEL(_si, _channel1, _channel2, _address, _type, \
 	_mask_all, _mask_type_av, _mask_all_av, _ext_info) \
 	{ \
@@ -1292,6 +1387,7 @@ static const struct ad7192_chip_info ad7192_chip_info_tbl[] = {
 		.num_channels = ARRAY_SIZE(ad7192_channels),
 		.sigma_delta_info = &ad7192_sigma_delta_info,
 		.info = &ad7192_info,
+		.info_sync = &ad7192_info_sync,
 	},
 	[ID_AD7192] = {
 		.chip_id = CHIPID_AD7192,
@@ -1300,6 +1396,7 @@ static const struct ad7192_chip_info ad7192_chip_info_tbl[] = {
 		.num_channels = ARRAY_SIZE(ad7192_channels),
 		.sigma_delta_info = &ad7192_sigma_delta_info,
 		.info = &ad7192_info,
+		.info_sync = &ad7192_info_sync,
 	},
 	[ID_AD7193] = {
 		.chip_id = CHIPID_AD7193,
@@ -1308,11 +1405,13 @@ static const struct ad7192_chip_info ad7192_chip_info_tbl[] = {
 		.num_channels = ARRAY_SIZE(ad7193_channels),
 		.sigma_delta_info = &ad7192_sigma_delta_info,
 		.info = &ad7192_info,
+		.info_sync = &ad7192_info_sync,
 	},
 	[ID_AD7194] = {
 		.chip_id = CHIPID_AD7194,
 		.name = "ad7194",
 		.info = &ad7194_info,
+		.info_sync = &ad7194_info_sync,
 		.sigma_delta_info = &ad7194_sigma_delta_info,
 		.parse_channels = ad7194_parse_channels,
 	},
@@ -1323,6 +1422,7 @@ static const struct ad7192_chip_info ad7192_chip_info_tbl[] = {
 		.num_channels = ARRAY_SIZE(ad7192_channels),
 		.sigma_delta_info = &ad7192_sigma_delta_info,
 		.info = &ad7195_info,
+		.info_sync = &ad7195_info_sync,
 	},
 };
 
@@ -1344,6 +1444,11 @@ static int ad7192_probe(struct spi_device *spi)
 
 	mutex_init(&st->lock);
 
+	st->sync_gpio = devm_gpiod_get_optional(dev, "sync", GPIOD_OUT_HIGH);
+	if (IS_ERR(st->sync_gpio))
+		return dev_err_probe(dev, PTR_ERR(st->sync_gpio),
+				     "Failed to get sync gpio.\n");
+
 	/*
 	 * Regulator aincom is optional to maintain compatibility with older DT.
 	 * Newer firmware should provide a zero volt fixed supply if wired to
@@ -1399,7 +1504,12 @@ static int ad7192_probe(struct spi_device *spi)
 
 	indio_dev->name = st->chip_info->name;
 	indio_dev->modes = INDIO_DIRECT_MODE;
-	indio_dev->info = st->chip_info->info;
+
+	if (st->sync_gpio)
+		indio_dev->info = st->chip_info->info_sync;
+	else
+		indio_dev->info = st->chip_info->info;
+
 	if (st->chip_info->parse_channels) {
 		ret = st->chip_info->parse_channels(indio_dev);
 		if (ret)
-- 
2.43.0





[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux