aboutsummaryrefslogtreecommitdiff
path: root/drivers/iio/adc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/adc')
-rw-r--r--drivers/iio/adc/Kconfig27
-rw-r--r--drivers/iio/adc/Makefile2
-rw-r--r--drivers/iio/adc/ab8500-gpadc.c8
-rw-r--r--drivers/iio/adc/ad4130.c7
-rw-r--r--drivers/iio/adc/ad7124.c55
-rw-r--r--drivers/iio/adc/ad7173.c1180
-rw-r--r--drivers/iio/adc/ad7192.c38
-rw-r--r--drivers/iio/adc/ad7292.c13
-rw-r--r--drivers/iio/adc/ad7944.c524
-rw-r--r--drivers/iio/adc/ad_sigma_delta.c23
-rw-r--r--drivers/iio/adc/adi-axi-adc.c20
-rw-r--r--drivers/iio/adc/fsl-imx25-gcq.c140
-rw-r--r--drivers/iio/adc/hx711.c5
-rw-r--r--drivers/iio/adc/max11410.c27
-rw-r--r--drivers/iio/adc/pac1934.c77
-rw-r--r--drivers/iio/adc/qcom-spmi-adc5.c7
-rw-r--r--drivers/iio/adc/rcar-gyroadc.c21
-rw-r--r--drivers/iio/adc/rzg2l_adc.c11
-rw-r--r--drivers/iio/adc/spear_adc.c25
-rw-r--r--drivers/iio/adc/stm32-adc.c61
-rw-r--r--drivers/iio/adc/ti-ads131e08.c12
-rw-r--r--drivers/iio/adc/twl4030-madc.c19
22 files changed, 1957 insertions, 345 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 0d9282fa67f5..8db68b80b391 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -70,6 +70,23 @@ config AD7124
To compile this driver as a module, choose M here: the module will be
called ad7124.
+config AD7173
+ tristate "Analog Devices AD7173 driver"
+ depends on SPI_MASTER
+ select AD_SIGMA_DELTA
+ select GPIO_REGMAP if GPIOLIB
+ select REGMAP_SPI if GPIOLIB
+ help
+ Say yes here to build support for Analog Devices AD7173 and similar ADC
+ Currently supported models:
+ - AD7172-2
+ - AD7173-8
+ - AD7175-2
+ - AD7176-2
+
+ To compile this driver as a module, choose M here: the module will be
+ called ad7173.
+
config AD7192
tristate "Analog Devices AD7190 AD7192 AD7193 AD7195 ADC driver"
depends on SPI
@@ -264,6 +281,16 @@ config AD7923
To compile this driver as a module, choose M here: the
module will be called ad7923.
+config AD7944
+ tristate "Analog Devices AD7944 and similar ADCs driver"
+ depends on SPI
+ help
+ Say yes here to build support for Analog Devices
+ AD7944, AD7985, AD7986 ADCs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad7944
+
config AD7949
tristate "Analog Devices AD7949 and similar ADCs driver"
depends on SPI
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index b3c434722364..edb32ce2af02 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_AD7091R) += ad7091r-base.o
obj-$(CONFIG_AD7091R5) += ad7091r5.o
obj-$(CONFIG_AD7091R8) += ad7091r8.o
obj-$(CONFIG_AD7124) += ad7124.o
+obj-$(CONFIG_AD7173) += ad7173.o
obj-$(CONFIG_AD7192) += ad7192.o
obj-$(CONFIG_AD7266) += ad7266.o
obj-$(CONFIG_AD7280) += ad7280a.o
@@ -28,6 +29,7 @@ obj-$(CONFIG_AD7780) += ad7780.o
obj-$(CONFIG_AD7791) += ad7791.o
obj-$(CONFIG_AD7793) += ad7793.o
obj-$(CONFIG_AD7887) += ad7887.o
+obj-$(CONFIG_AD7944) += ad7944.o
obj-$(CONFIG_AD7949) += ad7949.o
obj-$(CONFIG_AD799X) += ad799x.o
obj-$(CONFIG_AD9467) += ad9467.o
diff --git a/drivers/iio/adc/ab8500-gpadc.c b/drivers/iio/adc/ab8500-gpadc.c
index 80645fee79a4..59f66e9cb0e8 100644
--- a/drivers/iio/adc/ab8500-gpadc.c
+++ b/drivers/iio/adc/ab8500-gpadc.c
@@ -1021,14 +1021,13 @@ static int ab8500_gpadc_parse_channel(struct device *dev,
/**
* ab8500_gpadc_parse_channels() - Parse the GPADC channels from DT
* @gpadc: the GPADC to configure the channels for
- * @chans: the IIO channels we parsed
- * @nchans: the number of IIO channels we parsed
+ * @chans_parsed: the IIO channels we parsed
+ * @nchans_parsed: the number of IIO channels we parsed
*/
static int ab8500_gpadc_parse_channels(struct ab8500_gpadc *gpadc,
struct iio_chan_spec **chans_parsed,
unsigned int *nchans_parsed)
{
- struct fwnode_handle *child;
struct ab8500_gpadc_chan_info *ch;
struct iio_chan_spec *iio_chans;
unsigned int nchans;
@@ -1052,7 +1051,7 @@ static int ab8500_gpadc_parse_channels(struct ab8500_gpadc *gpadc,
return -ENOMEM;
i = 0;
- device_for_each_child_node(gpadc->dev, child) {
+ device_for_each_child_node_scoped(gpadc->dev, child) {
struct iio_chan_spec *iio_chan;
int ret;
@@ -1062,7 +1061,6 @@ static int ab8500_gpadc_parse_channels(struct ab8500_gpadc *gpadc,
ret = ab8500_gpadc_parse_channel(gpadc->dev, child, ch,
iio_chan);
if (ret) {
- fwnode_handle_put(child);
return ret;
}
i++;
diff --git a/drivers/iio/adc/ad4130.c b/drivers/iio/adc/ad4130.c
index febb64e67955..aaf1fb0ac447 100644
--- a/drivers/iio/adc/ad4130.c
+++ b/drivers/iio/adc/ad4130.c
@@ -1600,17 +1600,14 @@ static int ad4130_parse_fw_children(struct iio_dev *indio_dev)
{
struct ad4130_state *st = iio_priv(indio_dev);
struct device *dev = &st->spi->dev;
- struct fwnode_handle *child;
int ret;
indio_dev->channels = st->chans;
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
ret = ad4130_parse_fw_channel(indio_dev, child);
- if (ret) {
- fwnode_handle_put(child);
+ if (ret)
return ret;
- }
}
return 0;
diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c
index b9b206fcd748..e7b1d517d3de 100644
--- a/drivers/iio/adc/ad7124.c
+++ b/drivers/iio/adc/ad7124.c
@@ -14,7 +14,8 @@
#include <linux/kernel.h>
#include <linux/kfifo.h>
#include <linux/module.h>
-#include <linux/of.h>
+#include <linux/mod_devicetable.h>
+#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
@@ -807,22 +808,19 @@ static int ad7124_check_chip_id(struct ad7124_state *st)
return 0;
}
-static int ad7124_of_parse_channel_config(struct iio_dev *indio_dev,
- struct device_node *np)
+static int ad7124_parse_channel_config(struct iio_dev *indio_dev,
+ struct device *dev)
{
struct ad7124_state *st = iio_priv(indio_dev);
struct ad7124_channel_config *cfg;
struct ad7124_channel *channels;
- struct device_node *child;
struct iio_chan_spec *chan;
unsigned int ain[2], channel = 0, tmp;
int ret;
- st->num_channels = of_get_available_child_count(np);
- if (!st->num_channels) {
- dev_err(indio_dev->dev.parent, "no channel children\n");
- return -ENODEV;
- }
+ st->num_channels = device_get_child_node_count(dev);
+ if (!st->num_channels)
+ return dev_err_probe(dev, -ENODEV, "no channel children\n");
chan = devm_kcalloc(indio_dev->dev.parent, st->num_channels,
sizeof(*chan), GFP_KERNEL);
@@ -838,39 +836,38 @@ static int ad7124_of_parse_channel_config(struct iio_dev *indio_dev,
indio_dev->num_channels = st->num_channels;
st->channels = channels;
- for_each_available_child_of_node(np, child) {
+ device_for_each_child_node_scoped(dev, child) {
cfg = &st->channels[channel].cfg;
- ret = of_property_read_u32(child, "reg", &channel);
+ ret = fwnode_property_read_u32(child, "reg", &channel);
if (ret)
- goto err;
+ return ret;
- if (channel >= indio_dev->num_channels) {
- dev_err(indio_dev->dev.parent,
+ if (channel >= indio_dev->num_channels)
+ return dev_err_probe(dev, -EINVAL,
"Channel index >= number of channels\n");
- ret = -EINVAL;
- goto err;
- }
- ret = of_property_read_u32_array(child, "diff-channels",
- ain, 2);
+ ret = fwnode_property_read_u32_array(child, "diff-channels",
+ ain, 2);
if (ret)
- goto err;
+ return ret;
st->channels[channel].nr = channel;
st->channels[channel].ain = AD7124_CHANNEL_AINP(ain[0]) |
AD7124_CHANNEL_AINM(ain[1]);
- cfg->bipolar = of_property_read_bool(child, "bipolar");
+ cfg->bipolar = fwnode_property_read_bool(child, "bipolar");
- ret = of_property_read_u32(child, "adi,reference-select", &tmp);
+ ret = fwnode_property_read_u32(child, "adi,reference-select", &tmp);
if (ret)
cfg->refsel = AD7124_INT_REF;
else
cfg->refsel = tmp;
- cfg->buf_positive = of_property_read_bool(child, "adi,buffered-positive");
- cfg->buf_negative = of_property_read_bool(child, "adi,buffered-negative");
+ cfg->buf_positive =
+ fwnode_property_read_bool(child, "adi,buffered-positive");
+ cfg->buf_negative =
+ fwnode_property_read_bool(child, "adi,buffered-negative");
chan[channel] = ad7124_channel_template;
chan[channel].address = channel;
@@ -880,10 +877,6 @@ static int ad7124_of_parse_channel_config(struct iio_dev *indio_dev,
}
return 0;
-err:
- of_node_put(child);
-
- return ret;
}
static int ad7124_setup(struct ad7124_state *st)
@@ -943,9 +936,7 @@ static int ad7124_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
int i, ret;
- info = of_device_get_match_data(&spi->dev);
- if (!info)
- info = (void *)spi_get_device_id(spi)->driver_data;
+ info = spi_get_device_match_data(spi);
if (!info)
return -ENODEV;
@@ -965,7 +956,7 @@ static int ad7124_probe(struct spi_device *spi)
if (ret < 0)
return ret;
- ret = ad7124_of_parse_channel_config(indio_dev, spi->dev.of_node);
+ ret = ad7124_parse_channel_config(indio_dev, &spi->dev);
if (ret < 0)
return ret;
diff --git a/drivers/iio/adc/ad7173.c b/drivers/iio/adc/ad7173.c
new file mode 100644
index 000000000000..a7826bba0852
--- /dev/null
+++ b/drivers/iio/adc/ad7173.c
@@ -0,0 +1,1180 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * AD717x family SPI ADC driver
+ *
+ * Supported devices:
+ * AD7172-2/AD7172-4/AD7173-8/AD7175-2
+ * AD7175-8/AD7176-2/AD7177-2
+ *
+ * Copyright (C) 2015, 2024 Analog Devices, Inc.
+ */
+
+#include <linux/array_size.h>
+#include <linux/bitfield.h>
+#include <linux/bitmap.h>
+#include <linux/container_of.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio/driver.h>
+#include <linux/gpio/regmap.h>
+#include <linux/idr.h>
+#include <linux/interrupt.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/types.h>
+#include <linux/units.h>
+
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#include <linux/iio/adc/ad_sigma_delta.h>
+
+#define AD7173_REG_COMMS 0x00
+#define AD7173_REG_ADC_MODE 0x01
+#define AD7173_REG_INTERFACE_MODE 0x02
+#define AD7173_REG_CRC 0x03
+#define AD7173_REG_DATA 0x04
+#define AD7173_REG_GPIO 0x06
+#define AD7173_REG_ID 0x07
+#define AD7173_REG_CH(x) (0x10 + (x))
+#define AD7173_REG_SETUP(x) (0x20 + (x))
+#define AD7173_REG_FILTER(x) (0x28 + (x))
+#define AD7173_REG_OFFSET(x) (0x30 + (x))
+#define AD7173_REG_GAIN(x) (0x38 + (x))
+
+#define AD7173_RESET_LENGTH BITS_TO_BYTES(64)
+
+#define AD7173_CH_ENABLE BIT(15)
+#define AD7173_CH_SETUP_SEL_MASK GENMASK(14, 12)
+#define AD7173_CH_SETUP_AINPOS_MASK GENMASK(9, 5)
+#define AD7173_CH_SETUP_AINNEG_MASK GENMASK(4, 0)
+
+#define AD7173_CH_ADDRESS(pos, neg) \
+ (FIELD_PREP(AD7173_CH_SETUP_AINPOS_MASK, pos) | \
+ FIELD_PREP(AD7173_CH_SETUP_AINNEG_MASK, neg))
+#define AD7173_AIN_TEMP_POS 17
+#define AD7173_AIN_TEMP_NEG 18
+
+#define AD7172_2_ID 0x00d0
+#define AD7175_ID 0x0cd0
+#define AD7176_ID 0x0c90
+#define AD7175_2_ID 0x0cd0
+#define AD7172_4_ID 0x2050
+#define AD7173_ID 0x30d0
+#define AD7175_8_ID 0x3cd0
+#define AD7177_ID 0x4fd0
+#define AD7173_ID_MASK GENMASK(15, 4)
+
+#define AD7173_ADC_MODE_REF_EN BIT(15)
+#define AD7173_ADC_MODE_SING_CYC BIT(13)
+#define AD7173_ADC_MODE_MODE_MASK GENMASK(6, 4)
+#define AD7173_ADC_MODE_CLOCKSEL_MASK GENMASK(3, 2)
+#define AD7173_ADC_MODE_CLOCKSEL_INT 0x0
+#define AD7173_ADC_MODE_CLOCKSEL_INT_OUTPUT 0x1
+#define AD7173_ADC_MODE_CLOCKSEL_EXT 0x2
+#define AD7173_ADC_MODE_CLOCKSEL_XTAL 0x3
+
+#define AD7173_GPIO_PDSW BIT(14)
+#define AD7173_GPIO_OP_EN2_3 BIT(13)
+#define AD7173_GPIO_MUX_IO BIT(12)
+#define AD7173_GPIO_SYNC_EN BIT(11)
+#define AD7173_GPIO_ERR_EN BIT(10)
+#define AD7173_GPIO_ERR_DAT BIT(9)
+#define AD7173_GPIO_GP_DATA3 BIT(7)
+#define AD7173_GPIO_GP_DATA2 BIT(6)
+#define AD7173_GPIO_IP_EN1 BIT(5)
+#define AD7173_GPIO_IP_EN0 BIT(4)
+#define AD7173_GPIO_OP_EN1 BIT(3)
+#define AD7173_GPIO_OP_EN0 BIT(2)
+#define AD7173_GPIO_GP_DATA1 BIT(1)
+#define AD7173_GPIO_GP_DATA0 BIT(0)
+
+#define AD7173_GPO12_DATA(x) BIT((x) + 0)
+#define AD7173_GPO23_DATA(x) BIT((x) + 4)
+#define AD7173_GPO_DATA(x) ((x) < 2 ? AD7173_GPO12_DATA(x) : AD7173_GPO23_DATA(x))
+
+#define AD7173_INTERFACE_DATA_STAT BIT(6)
+#define AD7173_INTERFACE_DATA_STAT_EN(x) \
+ FIELD_PREP(AD7173_INTERFACE_DATA_STAT, x)
+
+#define AD7173_SETUP_BIPOLAR BIT(12)
+#define AD7173_SETUP_AREF_BUF_MASK GENMASK(11, 10)
+#define AD7173_SETUP_AIN_BUF_MASK GENMASK(9, 8)
+
+#define AD7173_SETUP_REF_SEL_MASK GENMASK(5, 4)
+#define AD7173_SETUP_REF_SEL_AVDD1_AVSS 0x3
+#define AD7173_SETUP_REF_SEL_INT_REF 0x2
+#define AD7173_SETUP_REF_SEL_EXT_REF2 0x1
+#define AD7173_SETUP_REF_SEL_EXT_REF 0x0
+#define AD7173_VOLTAGE_INT_REF_uV 2500000
+#define AD7173_TEMP_SENSIIVITY_uV_per_C 477
+#define AD7177_ODR_START_VALUE 0x07
+
+#define AD7173_FILTER_ODR0_MASK GENMASK(5, 0)
+#define AD7173_MAX_CONFIGS 8
+
+enum ad7173_ids {
+ ID_AD7172_2,
+ ID_AD7172_4,
+ ID_AD7173_8,
+ ID_AD7175_2,
+ ID_AD7175_8,
+ ID_AD7176_2,
+ ID_AD7177_2,
+};
+
+struct ad7173_device_info {
+ const unsigned int *sinc5_data_rates;
+ unsigned int num_sinc5_data_rates;
+ unsigned int odr_start_value;
+ unsigned int num_channels;
+ unsigned int num_configs;
+ unsigned int num_inputs;
+ unsigned int clock;
+ unsigned int id;
+ char *name;
+ bool has_temp;
+ bool has_int_ref;
+ bool has_ref2;
+ u8 num_gpios;
+};
+
+struct ad7173_channel_config {
+ u8 cfg_slot;
+ bool live;
+
+ /* Following fields are used to compare equality. */
+ struct_group(config_props,
+ bool bipolar;
+ bool input_buf;
+ u8 odr;
+ u8 ref_sel;
+ );
+};
+
+struct ad7173_channel {
+ unsigned int chan_reg;
+ unsigned int ain;
+ struct ad7173_channel_config cfg;
+};
+
+struct ad7173_state {
+ struct ad_sigma_delta sd;
+ const struct ad7173_device_info *info;
+ struct ad7173_channel *channels;
+ struct regulator_bulk_data regulators[3];
+ unsigned int adc_mode;
+ unsigned int interface_mode;
+ unsigned int num_channels;
+ struct ida cfg_slots_status;
+ unsigned long long config_usage_counter;
+ unsigned long long *config_cnts;
+ struct clk *ext_clk;
+ struct clk_hw int_clk_hw;
+#if IS_ENABLED(CONFIG_GPIOLIB)
+ struct regmap *reg_gpiocon_regmap;
+ struct gpio_regmap *gpio_regmap;
+#endif
+};
+
+static const unsigned int ad7173_sinc5_data_rates[] = {
+ 6211000, 6211000, 6211000, 6211000, 6211000, 6211000, 5181000, 4444000, /* 0-7 */
+ 3115000, 2597000, 1007000, 503800, 381000, 200300, 100500, 59520, /* 8-15 */
+ 49680, 20010, 16333, 10000, 5000, 2500, 1250, /* 16-22 */
+};
+
+static const unsigned int ad7175_sinc5_data_rates[] = {
+ 50000000, 41667000, 31250000, 27778000, /* 0-3 */
+ 20833000, 17857000, 12500000, 10000000, /* 4-7 */
+ 5000000, 2500000, 1000000, 500000, /* 8-11 */
+ 397500, 200000, 100000, 59920, /* 12-15 */
+ 49960, 20000, 16666, 10000, /* 16-19 */
+ 5000, /* 20 */
+};
+
+static const struct ad7173_device_info ad7173_device_info[] = {
+ [ID_AD7172_2] = {
+ .name = "ad7172-2",
+ .id = AD7172_2_ID,
+ .num_inputs = 5,
+ .num_channels = 4,
+ .num_configs = 4,
+ .num_gpios = 2,
+ .has_temp = true,
+ .has_int_ref = true,
+ .clock = 2 * HZ_PER_MHZ,
+ .sinc5_data_rates = ad7173_sinc5_data_rates,
+ .num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates),
+ },
+ [ID_AD7172_4] = {
+ .id = AD7172_4_ID,
+ .num_inputs = 9,
+ .num_channels = 8,
+ .num_configs = 8,
+ .num_gpios = 4,
+ .has_temp = false,
+ .has_ref2 = true,
+ .clock = 2 * HZ_PER_MHZ,
+ .sinc5_data_rates = ad7173_sinc5_data_rates,
+ .num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates),
+ },
+ [ID_AD7173_8] = {
+ .name = "ad7173-8",
+ .id = AD7173_ID,
+ .num_inputs = 17,
+ .num_channels = 16,
+ .num_configs = 8,
+ .num_gpios = 4,
+ .has_temp = true,
+ .has_int_ref = true,
+ .has_ref2 = true,
+ .clock = 2 * HZ_PER_MHZ,
+ .sinc5_data_rates = ad7173_sinc5_data_rates,
+ .num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates),
+ },
+ [ID_AD7175_2] = {
+ .name = "ad7175-2",
+ .id = AD7175_2_ID,
+ .num_inputs = 5,
+ .num_channels = 4,
+ .num_configs = 4,
+ .num_gpios = 2,
+ .has_temp = true,
+ .has_int_ref = true,
+ .clock = 16 * HZ_PER_MHZ,
+ .sinc5_data_rates = ad7175_sinc5_data_rates,
+ .num_sinc5_data_rates = ARRAY_SIZE(ad7175_sinc5_data_rates),
+ },
+ [ID_AD7175_8] = {
+ .id = AD7175_8_ID,
+ .num_inputs = 17,
+ .num_channels = 16,
+ .num_configs = 8,
+ .num_gpios = 4,
+ .has_temp = true,
+ .has_int_ref = true,
+ .has_ref2 = true,
+ .clock = 16 * HZ_PER_MHZ,
+ .sinc5_data_rates = ad7175_sinc5_data_rates,
+ .num_sinc5_data_rates = ARRAY_SIZE(ad7175_sinc5_data_rates),
+ },
+ [ID_AD7176_2] = {
+ .name = "ad7176-2",
+ .id = AD7176_ID,
+ .num_inputs = 5,
+ .num_channels = 4,
+ .num_configs = 4,
+ .num_gpios = 2,
+ .has_temp = false,
+ .has_int_ref = true,
+ .clock = 16 * HZ_PER_MHZ,
+ .sinc5_data_rates = ad7175_sinc5_data_rates,
+ .num_sinc5_data_rates = ARRAY_SIZE(ad7175_sinc5_data_rates),
+ },
+ [ID_AD7177_2] = {
+ .id = AD7177_ID,
+ .num_inputs = 5,
+ .num_channels = 4,
+ .num_configs = 4,
+ .num_gpios = 2,
+ .has_temp = true,
+ .has_int_ref = true,
+ .clock = 16 * HZ_PER_MHZ,
+ .odr_start_value = AD7177_ODR_START_VALUE,
+ .sinc5_data_rates = ad7175_sinc5_data_rates,
+ .num_sinc5_data_rates = ARRAY_SIZE(ad7175_sinc5_data_rates),
+ },
+};
+
+static const char *const ad7173_ref_sel_str[] = {
+ [AD7173_SETUP_REF_SEL_EXT_REF] = "vref",
+ [AD7173_SETUP_REF_SEL_EXT_REF2] = "vref2",
+ [AD7173_SETUP_REF_SEL_INT_REF] = "refout-avss",
+ [AD7173_SETUP_REF_SEL_AVDD1_AVSS] = "avdd",
+};
+
+static const char *const ad7173_clk_sel[] = {
+ "ext-clk", "xtal"
+};
+
+#if IS_ENABLED(CONFIG_GPIOLIB)
+
+static const struct regmap_range ad7173_range_gpio[] = {
+ regmap_reg_range(AD7173_REG_GPIO, AD7173_REG_GPIO),
+};
+
+static const struct regmap_access_table ad7173_access_table = {
+ .yes_ranges = ad7173_range_gpio,
+ .n_yes_ranges = ARRAY_SIZE(ad7173_range_gpio),
+};
+
+static const struct regmap_config ad7173_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .rd_table = &ad7173_access_table,
+ .wr_table = &ad7173_access_table,
+ .read_flag_mask = BIT(6),
+};
+
+static int ad7173_mask_xlate(struct gpio_regmap *gpio, unsigned int base,
+ unsigned int offset, unsigned int *reg,
+ unsigned int *mask)
+{
+ *mask = AD7173_GPO_DATA(offset);
+ *reg = base;
+ return 0;
+}
+
+static void ad7173_gpio_disable(void *data)
+{
+ struct ad7173_state *st = data;
+ unsigned int mask;
+
+ mask = AD7173_GPIO_OP_EN0 | AD7173_GPIO_OP_EN1 | AD7173_GPIO_OP_EN2_3;
+ regmap_update_bits(st->reg_gpiocon_regmap, AD7173_REG_GPIO, mask, ~mask);
+}
+
+static int ad7173_gpio_init(struct ad7173_state *st)
+{
+ struct gpio_regmap_config gpio_regmap = {};
+ struct device *dev = &st->sd.spi->dev;
+ unsigned int mask;
+ int ret;
+
+ st->reg_gpiocon_regmap = devm_regmap_init_spi(st->sd.spi, &ad7173_regmap_config);
+ ret = PTR_ERR_OR_ZERO(st->reg_gpiocon_regmap);
+ if (ret)
+ return dev_err_probe(dev, ret, "Unable to init regmap\n");
+
+ mask = AD7173_GPIO_OP_EN0 | AD7173_GPIO_OP_EN1 | AD7173_GPIO_OP_EN2_3;
+ regmap_update_bits(st->reg_gpiocon_regmap, AD7173_REG_GPIO, mask, mask);
+
+ ret = devm_add_action_or_reset(dev, ad7173_gpio_disable, st);
+ if (ret)
+ return ret;
+
+ gpio_regmap.parent = dev;
+ gpio_regmap.regmap = st->reg_gpiocon_regmap;
+ gpio_regmap.ngpio = st->info->num_gpios;
+ gpio_regmap.reg_set_base = AD7173_REG_GPIO;
+ gpio_regmap.reg_mask_xlate = ad7173_mask_xlate;
+
+ st->gpio_regmap = devm_gpio_regmap_register(dev, &gpio_regmap);
+ ret = PTR_ERR_OR_ZERO(st->gpio_regmap);
+ if (ret)
+ return dev_err_probe(dev, ret, "Unable to init gpio-regmap\n");
+
+ return 0;
+}
+#else
+static int ad7173_gpio_init(struct ad7173_state *st)
+{
+ return 0;
+}
+#endif /* CONFIG_GPIOLIB */
+
+static struct ad7173_state *ad_sigma_delta_to_ad7173(struct ad_sigma_delta *sd)
+{
+ return container_of(sd, struct ad7173_state, sd);
+}
+
+static struct ad7173_state *clk_hw_to_ad7173(struct clk_hw *hw)
+{
+ return container_of(hw, struct ad7173_state, int_clk_hw);
+}
+
+static void ad7173_ida_destroy(void *data)
+{
+ struct ad7173_state *st = data;
+
+ ida_destroy(&st->cfg_slots_status);
+}
+
+static void ad7173_reset_usage_cnts(struct ad7173_state *st)
+{
+ memset64(st->config_cnts, 0, st->info->num_configs);
+ st->config_usage_counter = 0;
+}
+
+static struct ad7173_channel_config *
+ad7173_find_live_config(struct ad7173_state *st, struct ad7173_channel_config *cfg)
+{
+ struct ad7173_channel_config *cfg_aux;
+ ptrdiff_t cmp_size;
+ int i;
+
+ cmp_size = sizeof_field(struct ad7173_channel_config, config_props);
+ for (i = 0; i < st->num_channels; i++) {
+ cfg_aux = &st->channels[i].cfg;
+
+ if (cfg_aux->live &&
+ !memcmp(&cfg->config_props, &cfg_aux->config_props, cmp_size))
+ return cfg_aux;
+ }
+ return NULL;
+}
+
+/* Could be replaced with a generic LRU implementation */
+static int ad7173_free_config_slot_lru(struct ad7173_state *st)
+{
+ int i, lru_position = 0;
+
+ for (i = 1; i < st->info->num_configs; i++)
+ if (st->config_cnts[i] < st->config_cnts[lru_position])
+ lru_position = i;
+
+ for (i = 0; i < st->num_channels; i++)
+ if (st->channels[i].cfg.cfg_slot == lru_position)
+ st->channels[i].cfg.live = false;
+
+ ida_free(&st->cfg_slots_status, lru_position);
+ return ida_alloc(&st->cfg_slots_status, GFP_KERNEL);
+}
+
+/* Could be replaced with a generic LRU implementation */
+static int ad7173_load_config(struct ad7173_state *st,
+ struct ad7173_channel_config *cfg)
+{
+ unsigned int config;
+ int free_cfg_slot, ret;
+
+ free_cfg_slot = ida_alloc_range(&st->cfg_slots_status, 0,
+ st->info->num_configs - 1, GFP_KERNEL);
+ if (free_cfg_slot < 0)
+ free_cfg_slot = ad7173_free_config_slot_lru(st);
+
+ cfg->cfg_slot = free_cfg_slot;
+ config = FIELD_PREP(AD7173_SETUP_REF_SEL_MASK, cfg->ref_sel);
+
+ if (cfg->bipolar)
+ config |= AD7173_SETUP_BIPOLAR;
+
+ if (cfg->input_buf)
+ config |= AD7173_SETUP_AIN_BUF_MASK;
+
+ ret = ad_sd_write_reg(&st->sd, AD7173_REG_SETUP(free_cfg_slot), 2, config);
+ if (ret)
+ return ret;
+
+ return ad_sd_write_reg(&st->sd, AD7173_REG_FILTER(free_cfg_slot), 2,
+ AD7173_FILTER_ODR0_MASK & cfg->odr);
+}
+
+static int ad7173_config_channel(struct ad7173_state *st, int addr)
+{
+ struct ad7173_channel_config *cfg = &st->channels[addr].cfg;
+ struct ad7173_channel_config *live_cfg;
+ int ret;
+
+ if (!cfg->live) {
+ live_cfg = ad7173_find_live_config(st, cfg);
+ if (live_cfg) {
+ cfg->cfg_slot = live_cfg->cfg_slot;
+ } else {
+ ret = ad7173_load_config(st, cfg);
+ if (ret)
+ return ret;
+ cfg->live = true;
+ }
+ }
+
+ if (st->config_usage_counter == U64_MAX)
+ ad7173_reset_usage_cnts(st);
+
+ st->config_usage_counter++;
+ st->config_cnts[cfg->cfg_slot] = st->config_usage_counter;
+
+ return 0;
+}
+
+static int ad7173_set_channel(struct ad_sigma_delta *sd, unsigned int channel)
+{
+ struct ad7173_state *st = ad_sigma_delta_to_ad7173(sd);
+ unsigned int val;
+ int ret;
+
+ ret = ad7173_config_channel(st, channel);
+ if (ret)
+ return ret;
+
+ val = AD7173_CH_ENABLE |
+ FIELD_PREP(AD7173_CH_SETUP_SEL_MASK, st->channels[channel].cfg.cfg_slot) |
+ st->channels[channel].ain;
+
+ return ad_sd_write_reg(&st->sd, AD7173_REG_CH(channel), 2, val);
+}
+
+static int ad7173_set_mode(struct ad_sigma_delta *sd,
+ enum ad_sigma_delta_mode mode)
+{
+ struct ad7173_state *st = ad_sigma_delta_to_ad7173(sd);
+
+ st->adc_mode &= ~AD7173_ADC_MODE_MODE_MASK;
+ st->adc_mode |= FIELD_PREP(AD7173_ADC_MODE_MODE_MASK, mode);
+
+ return ad_sd_write_reg(&st->sd, AD7173_REG_ADC_MODE, 2, st->adc_mode);
+}
+
+static int ad7173_append_status(struct ad_sigma_delta *sd, bool append)
+{
+ struct ad7173_state *st = ad_sigma_delta_to_ad7173(sd);
+ unsigned int interface_mode = st->interface_mode;
+ int ret;
+
+ interface_mode |= AD7173_INTERFACE_DATA_STAT_EN(append);
+ ret = ad_sd_write_reg(&st->sd, AD7173_REG_INTERFACE_MODE, 2, interface_mode);
+ if (ret)
+ return ret;
+
+ st->interface_mode = interface_mode;
+
+ return 0;
+}
+
+static int ad7173_disable_all(struct ad_sigma_delta *sd)
+{
+ struct ad7173_state *st = ad_sigma_delta_to_ad7173(sd);
+ int ret;
+ int i;
+
+ for (i = 0; i < st->num_channels; i++) {
+ ret = ad_sd_write_reg(sd, AD7173_REG_CH(i), 2, 0);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct ad_sigma_delta_info ad7173_sigma_delta_info = {
+ .set_channel = ad7173_set_channel,
+ .append_status = ad7173_append_status,
+ .disable_all = ad7173_disable_all,
+ .set_mode = ad7173_set_mode,
+ .has_registers = true,
+ .addr_shift = 0,
+ .read_mask = BIT(6),
+ .status_ch_mask = GENMASK(3, 0),
+ .data_reg = AD7173_REG_DATA,
+};
+
+static int ad7173_setup(struct iio_dev *indio_dev)
+{
+ struct ad7173_state *st = iio_priv(indio_dev);
+ struct device *dev = &st->sd.spi->dev;
+ u8 buf[AD7173_RESET_LENGTH];
+ unsigned int id;
+ int ret;
+
+ /* reset the serial interface */
+ memset(buf, 0xff, AD7173_RESET_LENGTH);
+ ret = spi_write_then_read(st->sd.spi, buf, sizeof(buf), NULL, 0);
+ if (ret < 0)
+ return ret;
+
+ /* datasheet recommends a delay of at least 500us after reset */
+ fsleep(500);
+
+ ret = ad_sd_read_reg(&st->sd, AD7173_REG_ID, 2, &id);
+ if (ret)
+ return ret;
+
+ id &= AD7173_ID_MASK;
+ if (id != st->info->id)
+ dev_warn(dev, "Unexpected device id: 0x%04X, expected: 0x%04X\n",
+ id, st->info->id);
+
+ st->adc_mode |= AD7173_ADC_MODE_SING_CYC;
+ st->interface_mode = 0x0;
+
+ st->config_usage_counter = 0;
+ st->config_cnts = devm_kcalloc(dev, st->info->num_configs,
+ sizeof(*st->config_cnts), GFP_KERNEL);
+ if (!st->config_cnts)
+ return -ENOMEM;
+
+ /* All channels are enabled by default after a reset */
+ return ad7173_disable_all(&st->sd);
+}
+
+static unsigned int ad7173_get_ref_voltage_milli(struct ad7173_state *st,
+ u8 reference_select)
+{
+ int vref;
+
+ switch (reference_select) {
+ case AD7173_SETUP_REF_SEL_EXT_REF:
+ vref = regulator_get_voltage(st->regulators[0].consumer);
+ break;
+
+ case AD7173_SETUP_REF_SEL_EXT_REF2:
+ vref = regulator_get_voltage(st->regulators[1].consumer);
+ break;
+
+ case AD7173_SETUP_REF_SEL_INT_REF:
+ vref = AD7173_VOLTAGE_INT_REF_uV;
+ break;
+
+ case AD7173_SETUP_REF_SEL_AVDD1_AVSS:
+ vref = regulator_get_voltage(st->regulators[2].consumer);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if (vref < 0)
+ return vref;
+
+ return vref / (MICRO / MILLI);
+}
+
+static int ad7173_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long info)
+{
+ struct ad7173_state *st = iio_priv(indio_dev);
+ struct ad7173_channel *ch = &st->channels[chan->address];
+ unsigned int reg;
+ u64 temp;
+ int ret;
+
+ switch (info) {
+ case IIO_CHAN_INFO_RAW:
+ ret = ad_sigma_delta_single_conversion(indio_dev, chan, val);
+ if (ret < 0)
+ return ret;
+
+ /* disable channel after single conversion */
+ ret = ad_sd_write_reg(&st->sd, AD7173_REG_CH(chan->address), 2, 0);
+ if (ret < 0)
+ return ret;
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ if (chan->type == IIO_TEMP) {
+ temp = AD7173_VOLTAGE_INT_REF_uV * MILLI;
+ temp /= AD7173_TEMP_SENSIIVITY_uV_per_C;
+ *val = temp;
+ *val2 = chan->scan_type.realbits;
+ } else {
+ *val = ad7173_get_ref_voltage_milli(st, ch->cfg.ref_sel);
+ *val2 = chan->scan_type.realbits - !!(ch->cfg.bipolar);
+ }
+ return IIO_VAL_FRACTIONAL_LOG2;
+ case IIO_CHAN_INFO_OFFSET:
+ if (chan->type == IIO_TEMP) {
+ /* 0 Kelvin -> raw sample */
+ temp = -ABSOLUTE_ZERO_MILLICELSIUS;
+ temp *= AD7173_TEMP_SENSIIVITY_uV_per_C;
+ temp <<= chan->scan_type.realbits;
+ temp = DIV_U64_ROUND_CLOSEST(temp,
+ AD7173_VOLTAGE_INT_REF_uV *
+ MILLI);
+ *val = -temp;
+ } else {
+ *val = -BIT(chan->scan_type.realbits - 1);
+ }
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ reg = st->channels[chan->address].cfg.odr;
+
+ *val = st->info->sinc5_data_rates[reg] / MILLI;
+ *val2 = (st->info->sinc5_data_rates[reg] % MILLI) * (MICRO / MILLI);
+
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad7173_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long info)
+{
+ struct ad7173_state *st = iio_priv(indio_dev);
+ struct ad7173_channel_config *cfg;
+ unsigned int freq, i, reg;
+ int ret;
+
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
+ switch (info) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ freq = val * MILLI + val2 / MILLI;
+ for (i = st->info->odr_start_value; i < st->info->num_sinc5_data_rates - 1; i++)
+ if (freq >= st->info->sinc5_data_rates[i])
+ break;
+
+ cfg = &st->channels[chan->address].cfg;
+ cfg->odr = i;
+
+ if (!cfg->live)
+ break;
+
+ ret = ad_sd_read_reg(&st->sd, AD7173_REG_FILTER(cfg->cfg_slot), 2, &reg);
+ if (ret)
+ break;
+ reg &= ~AD7173_FILTER_ODR0_MASK;
+ reg |= FIELD_PREP(AD7173_FILTER_ODR0_MASK, i);
+ ret = ad_sd_write_reg(&st->sd, AD7173_REG_FILTER(cfg->cfg_slot), 2, reg);
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ iio_device_release_direct_mode(indio_dev);
+ return ret;
+}
+
+static int ad7173_update_scan_mode(struct iio_dev *indio_dev,
+ const unsigned long *scan_mask)
+{
+ struct ad7173_state *st = iio_priv(indio_dev);
+ int i, ret;
+
+ for (i = 0; i < indio_dev->num_channels; i++) {
+ if (test_bit(i, scan_mask))
+ ret = ad7173_set_channel(&st->sd, i);
+ else
+ ret = ad_sd_write_reg(&st->sd, AD7173_REG_CH(i), 2, 0);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ad7173_debug_reg_access(struct iio_dev *indio_dev, unsigned int reg,
+ unsigned int writeval, unsigned int *readval)
+{
+ struct ad7173_state *st = iio_priv(indio_dev);
+ u8 reg_size;
+
+ if (reg == AD7173_REG_COMMS)
+ reg_size = 1;
+ else if (reg == AD7173_REG_CRC || reg == AD7173_REG_DATA ||
+ reg >= AD7173_REG_OFFSET(0))
+ reg_size = 3;
+ else
+ reg_size = 2;
+
+ if (readval)
+ return ad_sd_read_reg(&st->sd, reg, reg_size, readval);
+
+ return ad_sd_write_reg(&st->sd, reg, reg_size, writeval);
+}
+
+static const struct iio_info ad7173_info = {
+ .read_raw = &ad7173_read_raw,
+ .write_raw = &ad7173_write_raw,
+ .debugfs_reg_access = &ad7173_debug_reg_access,
+ .validate_trigger = ad_sd_validate_trigger,
+ .update_scan_mode = ad7173_update_scan_mode,
+};
+
+static const struct iio_chan_spec ad7173_channel_template = {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 24,
+ .storagebits = 32,
+ .endianness = IIO_BE,
+ },
+};
+
+static const struct iio_chan_spec ad7173_temp_iio_channel_template = {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .channel = AD7173_AIN_TEMP_POS,
+ .channel2 = AD7173_AIN_TEMP_NEG,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 24,
+ .storagebits = 32,
+ .endianness = IIO_BE,
+ },
+};
+
+static void ad7173_disable_regulators(void *data)
+{
+ struct ad7173_state *st = data;
+
+ regulator_bulk_disable(ARRAY_SIZE(st->regulators), st->regulators);
+}
+
+static void ad7173_clk_disable_unprepare(void *clk)
+{
+ clk_disable_unprepare(clk);
+}
+
+static unsigned long ad7173_sel_clk(struct ad7173_state *st,
+ unsigned int clk_sel)
+{
+ int ret;
+
+ st->adc_mode &= ~AD7173_ADC_MODE_CLOCKSEL_MASK;
+ st->adc_mode |= FIELD_PREP(AD7173_ADC_MODE_CLOCKSEL_MASK, clk_sel);
+ ret = ad_sd_write_reg(&st->sd, AD7173_REG_ADC_MODE, 0x2, st->adc_mode);
+
+ return ret;
+}
+
+static unsigned long ad7173_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct ad7173_state *st = clk_hw_to_ad7173(hw);
+
+ return st->info->clock / HZ_PER_KHZ;
+}
+
+static int ad7173_clk_output_is_enabled(struct clk_hw *hw)
+{
+ struct ad7173_state *st = clk_hw_to_ad7173(hw);
+ u32 clk_sel;
+
+ clk_sel = FIELD_GET(AD7173_ADC_MODE_CLOCKSEL_MASK, st->adc_mode);
+ return clk_sel == AD7173_ADC_MODE_CLOCKSEL_INT_OUTPUT;
+}
+
+static int ad7173_clk_output_prepare(struct clk_hw *hw)
+{
+ struct ad7173_state *st = clk_hw_to_ad7173(hw);
+
+ return ad7173_sel_clk(st, AD7173_ADC_MODE_CLOCKSEL_INT_OUTPUT);
+}
+
+static void ad7173_clk_output_unprepare(struct clk_hw *hw)
+{
+ struct ad7173_state *st = clk_hw_to_ad7173(hw);
+
+ ad7173_sel_clk(st, AD7173_ADC_MODE_CLOCKSEL_INT);
+}
+
+static const struct clk_ops ad7173_int_clk_ops = {
+ .recalc_rate = ad7173_clk_recalc_rate,
+ .is_enabled = ad7173_clk_output_is_enabled,
+ .prepare = ad7173_clk_output_prepare,
+ .unprepare = ad7173_clk_output_unprepare,
+};
+
+static int ad7173_register_clk_provider(struct iio_dev *indio_dev)
+{
+ struct ad7173_state *st = iio_priv(indio_dev);
+ struct device *dev = indio_dev->dev.parent;
+ struct fwnode_handle *fwnode = dev_fwnode(dev);
+ struct clk_init_data init = {};
+ int ret;
+
+ if (!IS_ENABLED(CONFIG_COMMON_CLK))
+ return 0;
+
+ init.name = fwnode_get_name(fwnode);
+ init.ops = &ad7173_int_clk_ops;
+
+ st->int_clk_hw.init = &init;
+ ret = devm_clk_hw_register(dev, &st->int_clk_hw);
+ if (ret)
+ return ret;
+
+ return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
+ &st->int_clk_hw);
+}
+
+static int ad7173_fw_parse_channel_config(struct iio_dev *indio_dev)
+{
+ struct ad7173_channel *chans_st_arr, *chan_st_priv;
+ struct ad7173_state *st = iio_priv(indio_dev);
+ struct device *dev = indio_dev->dev.parent;
+ struct iio_chan_spec *chan_arr, *chan;
+ unsigned int ain[2], chan_index = 0;
+ int ref_sel, ret;
+
+ chan_arr = devm_kcalloc(dev, sizeof(*indio_dev->channels),
+ st->num_channels, GFP_KERNEL);
+ if (!chan_arr)
+ return -ENOMEM;
+
+ chans_st_arr = devm_kcalloc(dev, st->num_channels, sizeof(*st->channels),
+ GFP_KERNEL);
+ if (!chans_st_arr)
+ return -ENOMEM;
+
+ indio_dev->channels = chan_arr;
+ st->channels = chans_st_arr;
+
+ if (st->info->has_temp) {
+ chan_arr[chan_index] = ad7173_temp_iio_channel_template;
+ chan_st_priv = &chans_st_arr[chan_index];
+ chan_st_priv->ain =
+ AD7173_CH_ADDRESS(chan_arr[chan_index].channel,
+ chan_arr[chan_index].channel2);
+ chan_st_priv->cfg.bipolar = false;
+ chan_st_priv->cfg.input_buf = true;
+ chan_st_priv->cfg.ref_sel = AD7173_SETUP_REF_SEL_INT_REF;
+ st->adc_mode |= AD7173_ADC_MODE_REF_EN;
+
+ chan_index++;
+ }
+
+ device_for_each_child_node_scoped(dev, child) {
+ chan = &chan_arr[chan_index];
+ chan_st_priv = &chans_st_arr[chan_index];
+ ret = fwnode_property_read_u32_array(child, "diff-channels",
+ ain, ARRAY_SIZE(ain));
+ if (ret)
+ return ret;
+
+ if (ain[0] >= st->info->num_inputs ||
+ ain[1] >= st->info->num_inputs)
+ return dev_err_probe(dev, -EINVAL,
+ "Input pin number out of range for pair (%d %d).\n",
+ ain[0], ain[1]);
+
+ ret = fwnode_property_match_property_string(child,
+ "adi,reference-select",
+ ad7173_ref_sel_str,
+ ARRAY_SIZE(ad7173_ref_sel_str));
+ if (ret < 0)
+ ref_sel = AD7173_SETUP_REF_SEL_INT_REF;
+ else
+ ref_sel = ret;
+
+ if (ref_sel == AD7173_SETUP_REF_SEL_INT_REF &&
+ !st->info->has_int_ref)
+ return dev_err_probe(dev, -EINVAL,
+ "Internal reference is not available on current model.\n");
+
+ if (ref_sel == AD7173_SETUP_REF_SEL_EXT_REF2 && !st->info->has_ref2)
+ return dev_err_probe(dev, -EINVAL,
+ "External reference 2 is not available on current model.\n");
+
+ ret = ad7173_get_ref_voltage_milli(st, ref_sel);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "Cannot use reference %u\n", ref_sel);
+
+ if (ref_sel == AD7173_SETUP_REF_SEL_INT_REF)
+ st->adc_mode |= AD7173_ADC_MODE_REF_EN;
+ chan_st_priv->cfg.ref_sel = ref_sel;
+
+ *chan = ad7173_channel_template;
+ chan->address = chan_index;
+ chan->scan_index = chan_index;
+ chan->channel = ain[0];
+ chan->channel2 = ain[1];
+ chan->differential = true;
+
+ chan_st_priv->ain = AD7173_CH_ADDRESS(ain[0], ain[1]);
+ chan_st_priv->chan_reg = chan_index;
+ chan_st_priv->cfg.input_buf = true;
+ chan_st_priv->cfg.odr = 0;
+
+ chan_st_priv->cfg.bipolar = fwnode_property_read_bool(child, "bipolar");
+ if (chan_st_priv->cfg.bipolar)
+ chan->info_mask_separate |= BIT(IIO_CHAN_INFO_OFFSET);
+
+ chan_index++;
+ }
+ return 0;
+}
+
+static int ad7173_fw_parse_device_config(struct iio_dev *indio_dev)
+{
+ struct ad7173_state *st = iio_priv(indio_dev);
+ struct device *dev = indio_dev->dev.parent;
+ unsigned int num_channels;
+ int ret;
+
+ st->regulators[0].supply = ad7173_ref_sel_str[AD7173_SETUP_REF_SEL_EXT_REF];
+ st->regulators[1].supply = ad7173_ref_sel_str[AD7173_SETUP_REF_SEL_EXT_REF2];
+ st->regulators[2].supply = ad7173_ref_sel_str[AD7173_SETUP_REF_SEL_AVDD1_AVSS];
+
+ /*
+ * If a regulator is not available, it will be set to a dummy regulator.
+ * Each channel reference is checked with regulator_get_voltage() before
+ * setting attributes so if any channel uses a dummy supply the driver
+ * probe will fail.
+ */
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(st->regulators),
+ st->regulators);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get regulators\n");
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(st->regulators), st->regulators);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable regulators\n");
+
+ ret = devm_add_action_or_reset(dev, ad7173_disable_regulators, st);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to add regulators disable action\n");
+
+ ret = device_property_match_property_string(dev, "clock-names",
+ ad7173_clk_sel,
+ ARRAY_SIZE(ad7173_clk_sel));
+ if (ret < 0) {
+ st->adc_mode |= FIELD_PREP(AD7173_ADC_MODE_CLOCKSEL_MASK,
+ AD7173_ADC_MODE_CLOCKSEL_INT);
+ ad7173_register_clk_provider(indio_dev);
+ } else {
+ st->adc_mode |= FIELD_PREP(AD7173_ADC_MODE_CLOCKSEL_MASK,
+ AD7173_ADC_MODE_CLOCKSEL_EXT + ret);
+ st->ext_clk = devm_clk_get(dev, ad7173_clk_sel[ret]);
+ if (IS_ERR(st->ext_clk))
+ return dev_err_probe(dev, PTR_ERR(st->ext_clk),
+ "Failed to get external clock\n");
+
+ ret = clk_prepare_enable(st->ext_clk);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to enable external clock\n");
+
+ ret = devm_add_action_or_reset(dev, ad7173_clk_disable_unprepare,
+ st->ext_clk);
+ if (ret)
+ return ret;
+ }
+
+ ret = fwnode_irq_get_byname(dev_fwnode(dev), "rdy");
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Interrupt 'rdy' is required\n");
+
+ ad7173_sigma_delta_info.irq_line = ret;
+
+ num_channels = device_get_child_node_count(dev);
+
+ if (st->info->has_temp)
+ num_channels++;
+
+ if (num_channels == 0)
+ return dev_err_probe(dev, -ENODATA, "No channels specified\n");
+ indio_dev->num_channels = num_channels;
+ st->num_channels = num_channels;
+
+ return ad7173_fw_parse_channel_config(indio_dev);
+}
+
+static int ad7173_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct ad7173_state *st;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+ st->info = spi_get_device_match_data(spi);
+ if (!st->info)
+ return -ENODEV;
+
+ ida_init(&st->cfg_slots_status);
+ ret = devm_add_action_or_reset(dev, ad7173_ida_destroy, st);
+ if (ret)
+ return ret;
+
+ indio_dev->name = st->info->name;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &ad7173_info;
+
+ spi->mode = SPI_MODE_3;
+ spi_setup(spi);
+
+ ad7173_sigma_delta_info.num_slots = st->info->num_configs;
+ ret = ad_sd_init(&st->sd, indio_dev, spi, &ad7173_sigma_delta_info);
+ if (ret)
+ return ret;
+
+ ret = ad7173_fw_parse_device_config(indio_dev);
+ if (ret)
+ return ret;
+
+ ret = devm_ad_sd_setup_buffer_and_trigger(dev, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = ad7173_setup(indio_dev);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_device_register(dev, indio_dev);
+ if (ret)
+ return ret;
+
+ if (IS_ENABLED(CONFIG_GPIOLIB))
+ return ad7173_gpio_init(st);
+
+ return 0;
+}
+
+static const struct of_device_id ad7173_of_match[] = {
+ { .compatible = "adi,ad7172-2",
+ .data = &ad7173_device_info[ID_AD7172_2]},
+ { .compatible = "adi,ad7172-4",
+ .data = &ad7173_device_info[ID_AD7172_4]},
+ { .compatible = "adi,ad7173-8",
+ .data = &ad7173_device_info[ID_AD7173_8]},
+ { .compatible = "adi,ad7175-2",
+ .data = &ad7173_device_info[ID_AD7175_2]},
+ { .compatible = "adi,ad7175-8",
+ .data = &ad7173_device_info[ID_AD7175_8]},
+ { .compatible = "adi,ad7176-2",
+ .data = &ad7173_device_info[ID_AD7176_2]},
+ { .compatible = "adi,ad7177-2",
+ .data = &ad7173_device_info[ID_AD7177_2]},
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad7173_of_match);
+
+static const struct spi_device_id ad7173_id_table[] = {
+ { "ad7172-2", (kernel_ulong_t)&ad7173_device_info[ID_AD7172_2]},
+ { "ad7172-4", (kernel_ulong_t)&ad7173_device_info[ID_AD7172_4]},
+ { "ad7173-8", (kernel_ulong_t)&ad7173_device_info[ID_AD7173_8]},
+ { "ad7175-2", (kernel_ulong_t)&ad7173_device_info[ID_AD7175_2]},
+ { "ad7175-8", (kernel_ulong_t)&ad7173_device_info[ID_AD7175_8]},
+ { "ad7176-2", (kernel_ulong_t)&ad7173_device_info[ID_AD7176_2]},
+ { "ad7177-2", (kernel_ulong_t)&ad7173_device_info[ID_AD7177_2]},
+ { }
+};
+MODULE_DEVICE_TABLE(spi, ad7173_id_table);
+
+static struct spi_driver ad7173_driver = {
+ .driver = {
+ .name = "ad7173",
+ .of_match_table = ad7173_of_match,
+ },
+ .probe = ad7173_probe,
+ .id_table = ad7173_id_table,
+};
+module_spi_driver(ad7173_driver);
+
+MODULE_IMPORT_NS(IIO_AD_SIGMA_DELTA);
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafo.de>");
+MODULE_AUTHOR("Dumitru Ceclan <dumitru.ceclan@analog.com>");
+MODULE_DESCRIPTION("Analog Devices AD7172/AD7173/AD7175/AD7176 ADC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c
index adc3cbe92d6e..7bcc7e2aa2a2 100644
--- a/drivers/iio/adc/ad7192.c
+++ b/drivers/iio/adc/ad7192.c
@@ -17,7 +17,9 @@
#include <linux/err.h>
#include <linux/sched.h>
#include <linux/delay.h>
-#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/property.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -364,19 +366,19 @@ static inline bool ad7192_valid_external_frequency(u32 freq)
freq <= AD7192_EXT_FREQ_MHZ_MAX);
}
-static int ad7192_of_clock_select(struct ad7192_state *st)
+static int ad7192_clock_select(struct ad7192_state *st)
{
- struct device_node *np = st->sd.spi->dev.of_node;
+ struct device *dev = &st->sd.spi->dev;
unsigned int clock_sel;
clock_sel = AD7192_CLK_INT;
/* use internal clock */
if (!st->mclk) {
- if (of_property_read_bool(np, "adi,int-clock-output-enable"))
+ if (device_property_read_bool(dev, "adi,int-clock-output-enable"))
clock_sel = AD7192_CLK_INT_CO;
} else {
- if (of_property_read_bool(np, "adi,clock-xtal"))
+ if (device_property_read_bool(dev, "adi,clock-xtal"))
clock_sel = AD7192_CLK_EXT_MCLK1_2;
else
clock_sel = AD7192_CLK_EXT_MCLK2;
@@ -385,7 +387,7 @@ static int ad7192_of_clock_select(struct ad7192_state *st)
return clock_sel;
}
-static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np)
+static int ad7192_setup(struct iio_dev *indio_dev, struct device *dev)
{
struct ad7192_state *st = iio_priv(indio_dev);
bool rej60_en, refin2_en;
@@ -407,7 +409,7 @@ static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np)
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",
+ dev_warn(dev, "device ID query failed (0x%X != 0x%X)\n",
id, st->chip_info->chip_id);
st->mode = FIELD_PREP(AD7192_MODE_SEL_MASK, AD7192_MODE_IDLE) |
@@ -416,30 +418,30 @@ static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np)
st->conf = FIELD_PREP(AD7192_CONF_GAIN_MASK, 0);
- rej60_en = of_property_read_bool(np, "adi,rejection-60-Hz-enable");
+ rej60_en = device_property_read_bool(dev, "adi,rejection-60-Hz-enable");
if (rej60_en)
st->mode |= AD7192_MODE_REJ60;
- refin2_en = of_property_read_bool(np, "adi,refin2-pins-enable");
+ refin2_en = device_property_read_bool(dev, "adi,refin2-pins-enable");
if (refin2_en && st->chip_info->chip_id != CHIPID_AD7195)
st->conf |= AD7192_CONF_REFSEL;
st->conf &= ~AD7192_CONF_CHOP;
- buf_en = of_property_read_bool(np, "adi,buffer-enable");
+ buf_en = device_property_read_bool(dev, "adi,buffer-enable");
if (buf_en)
st->conf |= AD7192_CONF_BUF;
- bipolar = of_property_read_bool(np, "bipolar");
+ bipolar = device_property_read_bool(dev, "bipolar");
if (!bipolar)
st->conf |= AD7192_CONF_UNIPOLAR;
- burnout_curr_en = of_property_read_bool(np,
- "adi,burnout-currents-enable");
+ burnout_curr_en = device_property_read_bool(dev,
+ "adi,burnout-currents-enable");
if (burnout_curr_en && buf_en) {
st->conf |= AD7192_CONF_BURN;
} else if (burnout_curr_en) {
- dev_warn(&st->sd.spi->dev,
+ dev_warn(dev,
"Can't enable burnout currents: see CHOP or buffer\n");
}
@@ -1117,9 +1119,7 @@ static int ad7192_probe(struct spi_device *spi)
}
st->int_vref_mv = ret / 1000;
- st->chip_info = of_device_get_match_data(&spi->dev);
- if (!st->chip_info)
- st->chip_info = (void *)spi_get_device_id(spi)->driver_data;
+ st->chip_info = spi_get_device_match_data(spi);
indio_dev->name = st->chip_info->name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = st->chip_info->channels;
@@ -1140,7 +1140,7 @@ static int ad7192_probe(struct spi_device *spi)
if (IS_ERR(st->mclk))
return PTR_ERR(st->mclk);
- st->clock_sel = ad7192_of_clock_select(st);
+ st->clock_sel = ad7192_clock_select(st);
if (st->clock_sel == AD7192_CLK_EXT_MCLK1_2 ||
st->clock_sel == AD7192_CLK_EXT_MCLK2) {
@@ -1152,7 +1152,7 @@ static int ad7192_probe(struct spi_device *spi)
}
}
- ret = ad7192_setup(indio_dev, spi->dev.of_node);
+ ret = ad7192_setup(indio_dev, &spi->dev);
if (ret)
return ret;
diff --git a/drivers/iio/adc/ad7292.c b/drivers/iio/adc/ad7292.c
index cccacec5db6d..6aadd14f459d 100644
--- a/drivers/iio/adc/ad7292.c
+++ b/drivers/iio/adc/ad7292.c
@@ -8,7 +8,8 @@
#include <linux/bitfield.h>
#include <linux/device.h>
#include <linux/module.h>
-#include <linux/of.h>
+#include <linux/mod_devicetable.h>
+#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
@@ -260,7 +261,6 @@ static int ad7292_probe(struct spi_device *spi)
{
struct ad7292_state *st;
struct iio_dev *indio_dev;
- struct device_node *child;
bool diff_channels = false;
int ret;
@@ -305,12 +305,11 @@ static int ad7292_probe(struct spi_device *spi)
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &ad7292_info;
- for_each_available_child_of_node(spi->dev.of_node, child) {
- diff_channels = of_property_read_bool(child, "diff-channels");
- if (diff_channels) {
- of_node_put(child);
+ device_for_each_child_node_scoped(&spi->dev, child) {
+ diff_channels = fwnode_property_read_bool(child,
+ "diff-channels");
+ if (diff_channels)
break;
- }
}
if (diff_channels) {
diff --git a/drivers/iio/adc/ad7944.c b/drivers/iio/adc/ad7944.c
new file mode 100644
index 000000000000..4af574ffa864
--- /dev/null
+++ b/drivers/iio/adc/ad7944.c
@@ -0,0 +1,524 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Analog Devices AD7944/85/86 PulSAR ADC family driver.
+ *
+ * Copyright 2024 Analog Devices, Inc.
+ * Copyright 2024 BayLibre, SAS
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+#include <linux/string_helpers.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define AD7944_INTERNAL_REF_MV 4096
+
+struct ad7944_timing_spec {
+ /* Normal mode max conversion time (t_{CONV}). */
+ unsigned int conv_ns;
+ /* TURBO mode max conversion time (t_{CONV}). */
+ unsigned int turbo_conv_ns;
+};
+
+enum ad7944_spi_mode {
+ /* datasheet calls this "4-wire mode" */
+ AD7944_SPI_MODE_DEFAULT,
+ /* datasheet calls this "3-wire mode" (not related to SPI_3WIRE!) */
+ AD7944_SPI_MODE_SINGLE,
+ /* datasheet calls this "chain mode" */
+ AD7944_SPI_MODE_CHAIN,
+};
+
+/* maps adi,spi-mode property value to enum */
+static const char * const ad7944_spi_modes[] = {
+ [AD7944_SPI_MODE_DEFAULT] = "",
+ [AD7944_SPI_MODE_SINGLE] = "single",
+ [AD7944_SPI_MODE_CHAIN] = "chain",
+};
+
+struct ad7944_adc {
+ struct spi_device *spi;
+ enum ad7944_spi_mode spi_mode;
+ struct spi_transfer xfers[3];
+ struct spi_message msg;
+ /* Chip-specific timing specifications. */
+ const struct ad7944_timing_spec *timing_spec;
+ /* GPIO connected to CNV pin. */
+ struct gpio_desc *cnv;
+ /* Optional GPIO to enable turbo mode. */
+ struct gpio_desc *turbo;
+ /* Indicates TURBO is hard-wired to be always enabled. */
+ bool always_turbo;
+ /* Reference voltage (millivolts). */
+ unsigned int ref_mv;
+
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ struct {
+ union {
+ u16 u16;
+ u32 u32;
+ } raw;
+ u64 timestamp __aligned(8);
+ } sample __aligned(IIO_DMA_MINALIGN);
+};
+
+/* quite time before CNV rising edge */
+#define T_QUIET_NS 20
+
+static const struct ad7944_timing_spec ad7944_timing_spec = {
+ .conv_ns = 420,
+ .turbo_conv_ns = 320,
+};
+
+static const struct ad7944_timing_spec ad7986_timing_spec = {
+ .conv_ns = 500,
+ .turbo_conv_ns = 400,
+};
+
+struct ad7944_chip_info {
+ const char *name;
+ const struct ad7944_timing_spec *timing_spec;
+ const struct iio_chan_spec channels[2];
+};
+
+/*
+ * AD7944_DEFINE_CHIP_INFO - Define a chip info structure for a specific chip
+ * @_name: The name of the chip
+ * @_ts: The timing specification for the chip
+ * @_bits: The number of bits in the conversion result
+ * @_diff: Whether the chip is true differential or not
+ */
+#define AD7944_DEFINE_CHIP_INFO(_name, _ts, _bits, _diff) \
+static const struct ad7944_chip_info _name##_chip_info = { \
+ .name = #_name, \
+ .timing_spec = &_ts##_timing_spec, \
+ .channels = { \
+ { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .differential = _diff, \
+ .channel = 0, \
+ .channel2 = _diff ? 1 : 0, \
+ .scan_index = 0, \
+ .scan_type.sign = _diff ? 's' : 'u', \
+ .scan_type.realbits = _bits, \
+ .scan_type.storagebits = _bits > 16 ? 32 : 16, \
+ .scan_type.endianness = IIO_CPU, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \
+ | BIT(IIO_CHAN_INFO_SCALE), \
+ }, \
+ IIO_CHAN_SOFT_TIMESTAMP(1), \
+ }, \
+}
+
+/* pseudo-differential with ground sense */
+AD7944_DEFINE_CHIP_INFO(ad7944, ad7944, 14, 0);
+AD7944_DEFINE_CHIP_INFO(ad7985, ad7944, 16, 0);
+/* fully differential */
+AD7944_DEFINE_CHIP_INFO(ad7986, ad7986, 18, 1);
+
+static void ad7944_unoptimize_msg(void *msg)
+{
+ spi_unoptimize_message(msg);
+}
+
+static int ad7944_3wire_cs_mode_init_msg(struct device *dev, struct ad7944_adc *adc,
+ const struct iio_chan_spec *chan)
+{
+ unsigned int t_conv_ns = adc->always_turbo ? adc->timing_spec->turbo_conv_ns
+ : adc->timing_spec->conv_ns;
+ struct spi_transfer *xfers = adc->xfers;
+ int ret;
+
+ /*
+ * NB: can get better performance from some SPI controllers if we use
+ * the same bits_per_word in every transfer.
+ */
+ xfers[0].bits_per_word = chan->scan_type.realbits;
+ /*
+ * CS is tied to CNV and we need a low to high transition to start the
+ * conversion, so place CNV low for t_QUIET to prepare for this.
+ */
+ xfers[0].delay.value = T_QUIET_NS;
+ xfers[0].delay.unit = SPI_DELAY_UNIT_NSECS;
+
+ /*
+ * CS has to be high for full conversion time to avoid triggering the
+ * busy indication.
+ */
+ xfers[1].cs_off = 1;
+ xfers[1].delay.value = t_conv_ns;
+ xfers[1].delay.unit = SPI_DELAY_UNIT_NSECS;
+ xfers[1].bits_per_word = chan->scan_type.realbits;
+
+ /* Then we can read the data during the acquisition phase */
+ xfers[2].rx_buf = &adc->sample.raw;
+ xfers[2].len = BITS_TO_BYTES(chan->scan_type.storagebits);
+ xfers[2].bits_per_word = chan->scan_type.realbits;
+
+ spi_message_init_with_transfers(&adc->msg, xfers, 3);
+
+ ret = spi_optimize_message(adc->spi, &adc->msg);
+ if (ret)
+ return ret;
+
+ return devm_add_action_or_reset(dev, ad7944_unoptimize_msg, &adc->msg);
+}
+
+static int ad7944_4wire_mode_init_msg(struct device *dev, struct ad7944_adc *adc,
+ const struct iio_chan_spec *chan)
+{
+ unsigned int t_conv_ns = adc->always_turbo ? adc->timing_spec->turbo_conv_ns
+ : adc->timing_spec->conv_ns;
+ struct spi_transfer *xfers = adc->xfers;
+ int ret;
+
+ /*
+ * NB: can get better performance from some SPI controllers if we use
+ * the same bits_per_word in every transfer.
+ */
+ xfers[0].bits_per_word = chan->scan_type.realbits;
+ /*
+ * CS has to be high for full conversion time to avoid triggering the
+ * busy indication.
+ */
+ xfers[0].cs_off = 1;
+ xfers[0].delay.value = t_conv_ns;
+ xfers[0].delay.unit = SPI_DELAY_UNIT_NSECS;
+
+ xfers[1].rx_buf = &adc->sample.raw;
+ xfers[1].len = BITS_TO_BYTES(chan->scan_type.storagebits);
+ xfers[1].bits_per_word = chan->scan_type.realbits;
+
+ spi_message_init_with_transfers(&adc->msg, xfers, 2);
+
+ ret = spi_optimize_message(adc->spi, &adc->msg);
+ if (ret)
+ return ret;
+
+ return devm_add_action_or_reset(dev, ad7944_unoptimize_msg, &adc->msg);
+}
+
+/**
+ * ad7944_convert_and_acquire - Perform a single conversion and acquisition
+ * @adc: The ADC device structure
+ * @chan: The channel specification
+ * Return: 0 on success, a negative error code on failure
+ *
+ * Perform a conversion and acquisition of a single sample using the
+ * pre-optimized adc->msg.
+ *
+ * Upon successful return adc->sample.raw will contain the conversion result.
+ */
+static int ad7944_convert_and_acquire(struct ad7944_adc *adc,
+ const struct iio_chan_spec *chan)
+{
+ int ret;
+
+ /*
+ * In 4-wire mode, the CNV line is held high for the entire conversion
+ * and acquisition process. In other modes adc->cnv is NULL and is
+ * ignored (CS is wired to CNV in those cases).
+ */
+ gpiod_set_value_cansleep(adc->cnv, 1);
+ ret = spi_sync(adc->spi, &adc->msg);
+ gpiod_set_value_cansleep(adc->cnv, 0);
+
+ return ret;
+}
+
+static int ad7944_single_conversion(struct ad7944_adc *adc,
+ const struct iio_chan_spec *chan,
+ int *val)
+{
+ int ret;
+
+ ret = ad7944_convert_and_acquire(adc, chan);
+ if (ret)
+ return ret;
+
+ if (chan->scan_type.storagebits > 16)
+ *val = adc->sample.raw.u32;
+ else
+ *val = adc->sample.raw.u16;
+
+ if (chan->scan_type.sign == 's')
+ *val = sign_extend32(*val, chan->scan_type.realbits - 1);
+
+ return IIO_VAL_INT;
+}
+
+static int ad7944_read_raw(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ int *val, int *val2, long info)
+{
+ struct ad7944_adc *adc = iio_priv(indio_dev);
+ int ret;
+
+ switch (info) {
+ case IIO_CHAN_INFO_RAW:
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
+ ret = ad7944_single_conversion(adc, chan, val);
+ iio_device_release_direct_mode(indio_dev);
+ return ret;
+
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_VOLTAGE:
+ *val = adc->ref_mv;
+
+ if (chan->scan_type.sign == 's')
+ *val2 = chan->scan_type.realbits - 1;
+ else
+ *val2 = chan->scan_type.realbits;
+
+ return IIO_VAL_FRACTIONAL_LOG2;
+ default:
+ return -EINVAL;
+ }
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info ad7944_iio_info = {
+ .read_raw = &ad7944_read_raw,
+};
+
+static irqreturn_t ad7944_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct ad7944_adc *adc = iio_priv(indio_dev);
+ int ret;
+
+ ret = ad7944_convert_and_acquire(adc, &indio_dev->channels[0]);
+ if (ret)
+ goto out;
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &adc->sample.raw,
+ pf->timestamp);
+
+out:
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static const char * const ad7944_power_supplies[] = {
+ "avdd", "dvdd", "bvdd", "vio"
+};
+
+static void ad7944_ref_disable(void *ref)
+{
+ regulator_disable(ref);
+}
+
+static int ad7944_probe(struct spi_device *spi)
+{
+ const struct ad7944_chip_info *chip_info;
+ struct device *dev = &spi->dev;
+ struct iio_dev *indio_dev;
+ struct ad7944_adc *adc;
+ bool have_refin = false;
+ struct regulator *ref;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*adc));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ adc = iio_priv(indio_dev);
+ adc->spi = spi;
+
+ chip_info = spi_get_device_match_data(spi);
+ if (!chip_info)
+ return dev_err_probe(dev, -EINVAL, "no chip info\n");
+
+ adc->timing_spec = chip_info->timing_spec;
+
+ ret = device_property_match_property_string(dev, "adi,spi-mode",
+ ad7944_spi_modes,
+ ARRAY_SIZE(ad7944_spi_modes));
+ /* absence of adi,spi-mode property means default mode */
+ if (ret == -EINVAL)
+ adc->spi_mode = AD7944_SPI_MODE_DEFAULT;
+ else if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "getting adi,spi-mode property failed\n");
+ else
+ adc->spi_mode = ret;
+
+ /*
+ * Some chips use unusual word sizes, so check now instead of waiting
+ * for the first xfer.
+ */
+ if (!spi_is_bpw_supported(spi, chip_info->channels[0].scan_type.realbits))
+ return dev_err_probe(dev, -EINVAL,
+ "SPI host does not support %d bits per word\n",
+ chip_info->channels[0].scan_type.realbits);
+
+ ret = devm_regulator_bulk_get_enable(dev,
+ ARRAY_SIZE(ad7944_power_supplies),
+ ad7944_power_supplies);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to get and enable supplies\n");
+
+ /*
+ * Sort out what is being used for the reference voltage. Options are:
+ * - internal reference: neither REF or REFIN is connected
+ * - internal reference with external buffer: REF not connected, REFIN
+ * is connected
+ * - external reference: REF is connected, REFIN is not connected
+ */
+
+ ref = devm_regulator_get_optional(dev, "ref");
+ if (IS_ERR(ref)) {
+ if (PTR_ERR(ref) != -ENODEV)
+ return dev_err_probe(dev, PTR_ERR(ref),
+ "failed to get REF supply\n");
+
+ ref = NULL;
+ }
+
+ ret = devm_regulator_get_enable_optional(dev, "refin");
+ if (ret == 0)
+ have_refin = true;
+ else if (ret != -ENODEV)
+ return dev_err_probe(dev, ret,
+ "failed to get and enable REFIN supply\n");
+
+ if (have_refin && ref)
+ return dev_err_probe(dev, -EINVAL,
+ "cannot have both refin and ref supplies\n");
+
+ if (ref) {
+ ret = regulator_enable(ref);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to enable REF supply\n");
+
+ ret = devm_add_action_or_reset(dev, ad7944_ref_disable, ref);
+ if (ret)
+ return ret;
+
+ ret = regulator_get_voltage(ref);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "failed to get REF voltage\n");
+
+ /* external reference */
+ adc->ref_mv = ret / 1000;
+ } else {
+ /* internal reference */
+ adc->ref_mv = AD7944_INTERNAL_REF_MV;
+ }
+
+ adc->cnv = devm_gpiod_get_optional(dev, "cnv", GPIOD_OUT_LOW);
+ if (IS_ERR(adc->cnv))
+ return dev_err_probe(dev, PTR_ERR(adc->cnv),
+ "failed to get CNV GPIO\n");
+
+ if (!adc->cnv && adc->spi_mode == AD7944_SPI_MODE_DEFAULT)
+ return dev_err_probe(&spi->dev, -EINVAL, "CNV GPIO is required\n");
+ if (adc->cnv && adc->spi_mode != AD7944_SPI_MODE_DEFAULT)
+ return dev_err_probe(&spi->dev, -EINVAL,
+ "CNV GPIO in single and chain mode is not currently supported\n");
+
+ adc->turbo = devm_gpiod_get_optional(dev, "turbo", GPIOD_OUT_LOW);
+ if (IS_ERR(adc->turbo))
+ return dev_err_probe(dev, PTR_ERR(adc->turbo),
+ "failed to get TURBO GPIO\n");
+
+ adc->always_turbo = device_property_present(dev, "adi,always-turbo");
+
+ if (adc->turbo && adc->always_turbo)
+ return dev_err_probe(dev, -EINVAL,
+ "cannot have both turbo-gpios and adi,always-turbo\n");
+
+ if (adc->spi_mode == AD7944_SPI_MODE_CHAIN && adc->always_turbo)
+ return dev_err_probe(dev, -EINVAL,
+ "cannot have both chain mode and always turbo\n");
+
+ switch (adc->spi_mode) {
+ case AD7944_SPI_MODE_DEFAULT:
+ ret = ad7944_4wire_mode_init_msg(dev, adc, &chip_info->channels[0]);
+ if (ret)
+ return ret;
+
+ break;
+ case AD7944_SPI_MODE_SINGLE:
+ ret = ad7944_3wire_cs_mode_init_msg(dev, adc, &chip_info->channels[0]);
+ if (ret)
+ return ret;
+
+ break;
+ case AD7944_SPI_MODE_CHAIN:
+ return dev_err_probe(dev, -EINVAL, "chain mode is not implemented\n");
+ }
+
+ indio_dev->name = chip_info->name;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &ad7944_iio_info;
+ indio_dev->channels = chip_info->channels;
+ indio_dev->num_channels = ARRAY_SIZE(chip_info->channels);
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ iio_pollfunc_store_time,
+ ad7944_trigger_handler, NULL);
+ if (ret)
+ return ret;
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static const struct of_device_id ad7944_of_match[] = {
+ { .compatible = "adi,ad7944", .data = &ad7944_chip_info },
+ { .compatible = "adi,ad7985", .data = &ad7985_chip_info },
+ { .compatible = "adi,ad7986", .data = &ad7986_chip_info },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad7944_of_match);
+
+static const struct spi_device_id ad7944_spi_id[] = {
+ { "ad7944", (kernel_ulong_t)&ad7944_chip_info },
+ { "ad7985", (kernel_ulong_t)&ad7985_chip_info },
+ { "ad7986", (kernel_ulong_t)&ad7986_chip_info },
+ { }
+
+};
+MODULE_DEVICE_TABLE(spi, ad7944_spi_id);
+
+static struct spi_driver ad7944_driver = {
+ .driver = {
+ .name = "ad7944",
+ .of_match_table = ad7944_of_match,
+ },
+ .probe = ad7944_probe,
+ .id_table = ad7944_spi_id,
+};
+module_spi_driver(ad7944_driver);
+
+MODULE_AUTHOR("David Lechner <dlechner@baylibre.com>");
+MODULE_DESCRIPTION("Analog Devices AD7944 PulSAR ADC family driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
index a602429cdde4..97a05f325df7 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -222,11 +222,11 @@ int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,
goto out;
sigma_delta->irq_dis = false;
- enable_irq(sigma_delta->spi->irq);
+ enable_irq(sigma_delta->irq_line);
timeout = wait_for_completion_timeout(&sigma_delta->completion, 2 * HZ);
if (timeout == 0) {
sigma_delta->irq_dis = true;
- disable_irq_nosync(sigma_delta->spi->irq);
+ disable_irq_nosync(sigma_delta->irq_line);
ret = -EIO;
} else {
ret = 0;
@@ -295,7 +295,7 @@ int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_SINGLE);
sigma_delta->irq_dis = false;
- enable_irq(sigma_delta->spi->irq);
+ enable_irq(sigma_delta->irq_line);
ret = wait_for_completion_interruptible_timeout(
&sigma_delta->completion, HZ);
@@ -315,7 +315,7 @@ int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
out:
if (!sigma_delta->irq_dis) {
- disable_irq_nosync(sigma_delta->spi->irq);
+ disable_irq_nosync(sigma_delta->irq_line);
sigma_delta->irq_dis = true;
}
@@ -396,7 +396,7 @@ static int ad_sd_buffer_postenable(struct iio_dev *indio_dev)
goto err_unlock;
sigma_delta->irq_dis = false;
- enable_irq(sigma_delta->spi->irq);
+ enable_irq(sigma_delta->irq_line);
return 0;
@@ -414,7 +414,7 @@ static int ad_sd_buffer_postdisable(struct iio_dev *indio_dev)
wait_for_completion_timeout(&sigma_delta->completion, HZ);
if (!sigma_delta->irq_dis) {
- disable_irq_nosync(sigma_delta->spi->irq);
+ disable_irq_nosync(sigma_delta->irq_line);
sigma_delta->irq_dis = true;
}
@@ -516,7 +516,7 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
irq_handled:
iio_trigger_notify_done(indio_dev->trig);
sigma_delta->irq_dis = false;
- enable_irq(sigma_delta->spi->irq);
+ enable_irq(sigma_delta->irq_line);
return IRQ_HANDLED;
}
@@ -587,13 +587,13 @@ static int devm_ad_sd_probe_trigger(struct device *dev, struct iio_dev *indio_de
sigma_delta->irq_dis = true;
/* the IRQ core clears IRQ_DISABLE_UNLAZY flag when freeing an IRQ */
- irq_set_status_flags(sigma_delta->spi->irq, IRQ_DISABLE_UNLAZY);
+ irq_set_status_flags(sigma_delta->irq_line, IRQ_DISABLE_UNLAZY);
/* Allow overwriting the flags from firmware */
if (!irq_flags)
irq_flags = sigma_delta->info->irq_flags;
- ret = devm_request_irq(dev, sigma_delta->spi->irq,
+ ret = devm_request_irq(dev, sigma_delta->irq_line,
ad_sd_data_rdy_trig_poll,
irq_flags | IRQF_NO_AUTOEN,
indio_dev->name,
@@ -673,6 +673,11 @@ int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev,
}
}
+ if (info->irq_line)
+ sigma_delta->irq_line = info->irq_line;
+ else
+ sigma_delta->irq_line = spi->irq;
+
iio_device_set_drvdata(indio_dev, sigma_delta);
return 0;
diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
index 4156639b3c8b..9444b0c5a93c 100644
--- a/drivers/iio/adc/adi-axi-adc.c
+++ b/drivers/iio/adc/adi-axi-adc.c
@@ -124,26 +124,12 @@ static struct iio_buffer *axi_adc_request_buffer(struct iio_backend *back,
struct iio_dev *indio_dev)
{
struct adi_axi_adc_state *st = iio_backend_get_priv(back);
- struct iio_buffer *buffer;
const char *dma_name;
- int ret;
if (device_property_read_string(st->dev, "dma-names", &dma_name))
dma_name = "rx";
- buffer = iio_dmaengine_buffer_alloc(st->dev, dma_name);
- if (IS_ERR(buffer)) {
- dev_err(st->dev, "Could not get DMA buffer, %ld\n",
- PTR_ERR(buffer));
- return ERR_CAST(buffer);
- }
-
- indio_dev->modes |= INDIO_BUFFER_HARDWARE;
- ret = iio_device_attach_buffer(indio_dev, buffer);
- if (ret)
- return ERR_PTR(ret);
-
- return buffer;
+ return iio_dmaengine_buffer_setup(st->dev, indio_dev, dma_name);
}
static void axi_adc_free_buffer(struct iio_backend *back,
@@ -207,9 +193,9 @@ static int adi_axi_adc_probe(struct platform_device *pdev)
if (ret)
return ret;
- if (*expected_ver > ver) {
+ if (ADI_AXI_PCORE_VER_MAJOR(ver) != ADI_AXI_PCORE_VER_MAJOR(*expected_ver)) {
dev_err(&pdev->dev,
- "IP core version is too old. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",
+ "Major version mismatch. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",
ADI_AXI_PCORE_VER_MAJOR(*expected_ver),
ADI_AXI_PCORE_VER_MINOR(*expected_ver),
ADI_AXI_PCORE_VER_PATCH(*expected_ver),
diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c
index 68c813de0605..394396b91630 100644
--- a/drivers/iio/adc/fsl-imx25-gcq.c
+++ b/drivers/iio/adc/fsl-imx25-gcq.c
@@ -12,8 +12,9 @@
#include <linux/interrupt.h>
#include <linux/mfd/imx25-tsadc.h>
#include <linux/module.h>
-#include <linux/of.h>
+#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@@ -198,8 +199,6 @@ static int mx25_gcq_ext_regulator_setup(struct device *dev,
static int mx25_gcq_setup_cfgs(struct platform_device *pdev,
struct mx25_gcq_priv *priv)
{
- struct device_node *np = pdev->dev.of_node;
- struct device_node *child;
struct device *dev = &pdev->dev;
int ret, i;
@@ -216,37 +215,30 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev,
MX25_ADCQ_CFG_IN(i) |
MX25_ADCQ_CFG_REFN_NGND2);
- for_each_child_of_node(np, child) {
+ device_for_each_child_node_scoped(dev, child) {
u32 reg;
u32 refp = MX25_ADCQ_CFG_REFP_INT;
u32 refn = MX25_ADCQ_CFG_REFN_NGND2;
- ret = of_property_read_u32(child, "reg", &reg);
- if (ret) {
- dev_err(dev, "Failed to get reg property\n");
- of_node_put(child);
- return ret;
- }
+ ret = fwnode_property_read_u32(child, "reg", &reg);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to get reg property\n");
- if (reg >= MX25_NUM_CFGS) {
- dev_err(dev,
+ if (reg >= MX25_NUM_CFGS)
+ return dev_err_probe(dev, -EINVAL,
"reg value is greater than the number of available configuration registers\n");
- of_node_put(child);
- return -EINVAL;
- }
- of_property_read_u32(child, "fsl,adc-refp", &refp);
- of_property_read_u32(child, "fsl,adc-refn", &refn);
+ fwnode_property_read_u32(child, "fsl,adc-refp", &refp);
+ fwnode_property_read_u32(child, "fsl,adc-refn", &refn);
switch (refp) {
case MX25_ADC_REFP_EXT:
case MX25_ADC_REFP_XP:
case MX25_ADC_REFP_YP:
ret = mx25_gcq_ext_regulator_setup(&pdev->dev, priv, refp);
- if (ret) {
- of_node_put(child);
+ if (ret)
return ret;
- }
priv->channel_vref_mv[reg] =
regulator_get_voltage(priv->vref[refp]);
/* Conversion from uV to mV */
@@ -256,9 +248,8 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev,
priv->channel_vref_mv[reg] = 2500;
break;
default:
- dev_err(dev, "Invalid positive reference %d\n", refp);
- of_node_put(child);
- return -EINVAL;
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid positive reference %d\n", refp);
}
/*
@@ -268,16 +259,13 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev,
refp = MX25_ADCQ_CFG_REFP(refp);
refn = MX25_ADCQ_CFG_REFN(refn);
- if ((refp & MX25_ADCQ_CFG_REFP_MASK) != refp) {
- dev_err(dev, "Invalid fsl,adc-refp property value\n");
- of_node_put(child);
- return -EINVAL;
- }
- if ((refn & MX25_ADCQ_CFG_REFN_MASK) != refn) {
- dev_err(dev, "Invalid fsl,adc-refn property value\n");
- of_node_put(child);
- return -EINVAL;
- }
+ if ((refp & MX25_ADCQ_CFG_REFP_MASK) != refp)
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid fsl,adc-refp property value\n");
+
+ if ((refn & MX25_ADCQ_CFG_REFN_MASK) != refn)
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid fsl,adc-refn property value\n");
regmap_update_bits(priv->regs, MX25_ADCQ_CFG(reg),
MX25_ADCQ_CFG_REFP_MASK |
@@ -294,6 +282,17 @@ static int mx25_gcq_setup_cfgs(struct platform_device *pdev,
return 0;
}
+static void mx25_gcq_reg_disable(void *reg)
+{
+ regulator_disable(reg);
+}
+
+/* Custom handling needed as this driver doesn't own the clock */
+static void mx25_gcq_clk_disable(void *clk)
+{
+ clk_disable_unprepare(clk);
+}
+
static int mx25_gcq_probe(struct platform_device *pdev)
{
struct iio_dev *indio_dev;
@@ -315,10 +314,9 @@ static int mx25_gcq_probe(struct platform_device *pdev)
return PTR_ERR(mem);
priv->regs = devm_regmap_init_mmio(dev, mem, &mx25_gcq_regconfig);
- if (IS_ERR(priv->regs)) {
- dev_err(dev, "Failed to initialize regmap\n");
- return PTR_ERR(priv->regs);
- }
+ if (IS_ERR(priv->regs))
+ return dev_err_probe(dev, PTR_ERR(priv->regs),
+ "Failed to initialize regmap\n");
mutex_init(&priv->lock);
@@ -334,69 +332,44 @@ static int mx25_gcq_probe(struct platform_device *pdev)
ret = regulator_enable(priv->vref[i]);
if (ret)
- goto err_regulator_disable;
+ return ret;
+
+ ret = devm_add_action_or_reset(dev, mx25_gcq_reg_disable,
+ priv->vref[i]);
+ if (ret)
+ return ret;
}
priv->clk = tsadc->clk;
ret = clk_prepare_enable(priv->clk);
- if (ret) {
- dev_err(dev, "Failed to enable clock\n");
- goto err_vref_disable;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable clock\n");
+
+ ret = devm_add_action_or_reset(dev, mx25_gcq_clk_disable,
+ priv->clk);
+ if (ret)
+ return ret;
ret = platform_get_irq(pdev, 0);
if (ret < 0)
- goto err_clk_unprepare;
+ return ret;
priv->irq = ret;
- ret = request_irq(priv->irq, mx25_gcq_irq, 0, pdev->name, priv);
- if (ret) {
- dev_err(dev, "Failed requesting IRQ\n");
- goto err_clk_unprepare;
- }
+ ret = devm_request_irq(dev, priv->irq, mx25_gcq_irq, 0, pdev->name,
+ priv);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed requesting IRQ\n");
indio_dev->channels = mx25_gcq_channels;
indio_dev->num_channels = ARRAY_SIZE(mx25_gcq_channels);
indio_dev->info = &mx25_gcq_iio_info;
indio_dev->name = driver_name;
- ret = iio_device_register(indio_dev);
- if (ret) {
- dev_err(dev, "Failed to register iio device\n");
- goto err_irq_free;
- }
-
- platform_set_drvdata(pdev, indio_dev);
+ ret = devm_iio_device_register(dev, indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to register iio device\n");
return 0;
-
-err_irq_free:
- free_irq(priv->irq, priv);
-err_clk_unprepare:
- clk_disable_unprepare(priv->clk);
-err_vref_disable:
- i = 4;
-err_regulator_disable:
- for (; i-- > 0;) {
- if (priv->vref[i])
- regulator_disable(priv->vref[i]);
- }
- return ret;
-}
-
-static void mx25_gcq_remove(struct platform_device *pdev)
-{
- struct iio_dev *indio_dev = platform_get_drvdata(pdev);
- struct mx25_gcq_priv *priv = iio_priv(indio_dev);
- int i;
-
- iio_device_unregister(indio_dev);
- free_irq(priv->irq, priv);
- clk_disable_unprepare(priv->clk);
- for (i = 4; i-- > 0;) {
- if (priv->vref[i])
- regulator_disable(priv->vref[i]);
- }
}
static const struct of_device_id mx25_gcq_ids[] = {
@@ -411,7 +384,6 @@ static struct platform_driver mx25_gcq_driver = {
.of_match_table = mx25_gcq_ids,
},
.probe = mx25_gcq_probe,
- .remove_new = mx25_gcq_remove,
};
module_platform_driver(mx25_gcq_driver);
diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
index c80c55fb8c6c..fef97c1d226a 100644
--- a/drivers/iio/adc/hx711.c
+++ b/drivers/iio/adc/hx711.c
@@ -7,7 +7,7 @@
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/of.h>
+#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/slab.h>
@@ -459,7 +459,6 @@ static const struct iio_chan_spec hx711_chan_spec[] = {
static int hx711_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct device_node *np = dev->of_node;
struct hx711_data *hx711_data;
struct iio_dev *indio_dev;
int ret;
@@ -533,7 +532,7 @@ static int hx711_probe(struct platform_device *pdev)
hx711_data->gain_chan_a = 128;
hx711_data->clock_frequency = 400000;
- ret = of_property_read_u32(np, "clock-frequency",
+ ret = device_property_read_u32(&pdev->dev, "clock-frequency",
&hx711_data->clock_frequency);
/*
diff --git a/drivers/iio/adc/max11410.c b/drivers/iio/adc/max11410.c
index 6af829349b4e..45368850b220 100644
--- a/drivers/iio/adc/max11410.c
+++ b/drivers/iio/adc/max11410.c
@@ -696,7 +696,6 @@ static int max11410_parse_channels(struct max11410_state *st,
struct device *dev = &st->spi_dev->dev;
struct max11410_channel_config *cfg;
struct iio_chan_spec *channels;
- struct fwnode_handle *child;
u32 reference, sig_path;
const char *node_name;
u32 inputs[2], scale;
@@ -720,7 +719,7 @@ static int max11410_parse_channels(struct max11410_state *st,
if (!st->channels)
return -ENOMEM;
- device_for_each_child_node(dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
node_name = fwnode_get_name(child);
if (fwnode_property_present(child, "diff-channels")) {
ret = fwnode_property_read_u32_array(child,
@@ -735,47 +734,37 @@ static int max11410_parse_channels(struct max11410_state *st,
inputs[1] = 0;
chanspec.differential = 0;
}
- if (ret) {
- fwnode_handle_put(child);
+ if (ret)
return ret;
- }
if (inputs[0] > MAX11410_CHANNEL_INDEX_MAX ||
- inputs[1] > MAX11410_CHANNEL_INDEX_MAX) {
- fwnode_handle_put(child);
+ inputs[1] > MAX11410_CHANNEL_INDEX_MAX)
return dev_err_probe(&indio_dev->dev, -EINVAL,
"Invalid channel index for %s, should be less than %d\n",
node_name,
MAX11410_CHANNEL_INDEX_MAX + 1);
- }
cfg = &st->channels[chan_idx];
reference = MAX11410_REFSEL_AVDD_AGND;
fwnode_property_read_u32(child, "adi,reference", &reference);
- if (reference > MAX11410_REFSEL_MAX) {
- fwnode_handle_put(child);
+ if (reference > MAX11410_REFSEL_MAX)
return dev_err_probe(&indio_dev->dev, -EINVAL,
"Invalid adi,reference value for %s, should be less than %d.\n",
node_name, MAX11410_REFSEL_MAX + 1);
- }
if (!max11410_get_vrefp(st, reference) ||
- (!max11410_get_vrefn(st, reference) && reference <= 2)) {
- fwnode_handle_put(child);
+ (!max11410_get_vrefn(st, reference) && reference <= 2))
return dev_err_probe(&indio_dev->dev, -EINVAL,
"Invalid VREF configuration for %s, either specify corresponding VREF regulators or change adi,reference property.\n",
node_name);
- }
sig_path = MAX11410_PGA_SIG_PATH_BUFFERED;
fwnode_property_read_u32(child, "adi,input-mode", &sig_path);
- if (sig_path > MAX11410_SIG_PATH_MAX) {
- fwnode_handle_put(child);
+ if (sig_path > MAX11410_SIG_PATH_MAX)
return dev_err_probe(&indio_dev->dev, -EINVAL,
"Invalid adi,input-mode value for %s, should be less than %d.\n",
node_name, MAX11410_SIG_PATH_MAX + 1);
- }
fwnode_property_read_u32(child, "settling-time-us",
&cfg->settling_time_us);
@@ -793,10 +782,8 @@ static int max11410_parse_channels(struct max11410_state *st,
cfg->scale_avail = devm_kcalloc(dev, MAX11410_SCALE_AVAIL_SIZE * 2,
sizeof(*cfg->scale_avail),
GFP_KERNEL);
- if (!cfg->scale_avail) {
- fwnode_handle_put(child);
+ if (!cfg->scale_avail)
return -ENOMEM;
- }
scale = max11410_get_scale(st, *cfg);
for (i = 0; i < MAX11410_SCALE_AVAIL_SIZE; i++) {
diff --git a/drivers/iio/adc/pac1934.c b/drivers/iio/adc/pac1934.c
index e0c2742da523..f751260605e4 100644
--- a/drivers/iio/adc/pac1934.c
+++ b/drivers/iio/adc/pac1934.c
@@ -1079,8 +1079,8 @@ static int pac1934_chip_identify(struct pac1934_chip_info *info)
* documentation related to the ACPI device definition
* https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ApplicationNotes/ApplicationNotes/PAC1934-Integration-Notes-for-Microsoft-Windows-10-and-Windows-11-Driver-Support-DS00002534.pdf
*/
-static bool pac1934_acpi_parse_channel_config(struct i2c_client *client,
- struct pac1934_chip_info *info)
+static int pac1934_acpi_parse_channel_config(struct i2c_client *client,
+ struct pac1934_chip_info *info)
{
acpi_handle handle;
union acpi_object *rez;
@@ -1095,7 +1095,7 @@ static bool pac1934_acpi_parse_channel_config(struct i2c_client *client,
rez = acpi_evaluate_dsm(handle, &guid, 0, PAC1934_ACPI_GET_NAMES_AND_MOHMS_VALS, NULL);
if (!rez)
- return false;
+ return -EINVAL;
for (i = 0; i < rez->package.count; i += 2) {
idx = i / 2;
@@ -1118,7 +1118,7 @@ static bool pac1934_acpi_parse_channel_config(struct i2c_client *client,
* and assign the default sampling rate
*/
info->sample_rate_value = PAC1934_DEFAULT_CHIP_SAMP_SPEED_HZ;
- return true;
+ return 0;
}
for (i = 0; i < rez->package.count; i++) {
@@ -1131,7 +1131,7 @@ static bool pac1934_acpi_parse_channel_config(struct i2c_client *client,
rez = acpi_evaluate_dsm(handle, &guid, 1, PAC1934_ACPI_GET_BIPOLAR_SETTINGS, NULL);
if (!rez)
- return false;
+ return -EINVAL;
bi_dir_mask = rez->package.elements[0].integer.value;
info->bi_dir[0] = ((bi_dir_mask & (1 << 3)) | (bi_dir_mask & (1 << 7))) != 0;
@@ -1143,19 +1143,18 @@ static bool pac1934_acpi_parse_channel_config(struct i2c_client *client,
rez = acpi_evaluate_dsm(handle, &guid, 1, PAC1934_ACPI_GET_SAMP, NULL);
if (!rez)
- return false;
+ return -EINVAL;
info->sample_rate_value = rez->package.elements[0].integer.value;
ACPI_FREE(rez);
- return true;
+ return 0;
}
-static bool pac1934_of_parse_channel_config(struct i2c_client *client,
- struct pac1934_chip_info *info)
+static int pac1934_fw_parse_channel_config(struct i2c_client *client,
+ struct pac1934_chip_info *info)
{
- struct fwnode_handle *node, *fwnode;
struct device *dev = &client->dev;
unsigned int current_channel;
int idx, ret;
@@ -1163,46 +1162,38 @@ static bool pac1934_of_parse_channel_config(struct i2c_client *client,
info->sample_rate_value = 1024;
current_channel = 1;
- fwnode = dev_fwnode(dev);
- fwnode_for_each_available_child_node(fwnode, node) {
+ device_for_each_child_node_scoped(dev, node) {
ret = fwnode_property_read_u32(node, "reg", &idx);
- if (ret) {
- dev_err_probe(dev, ret,
- "reading invalid channel index\n");
- goto err_fwnode;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "reading invalid channel index\n");
+
/* adjust idx to match channel index (1 to 4) from the datasheet */
idx--;
if (current_channel >= (info->phys_channels + 1) ||
- idx >= info->phys_channels || idx < 0) {
- dev_err_probe(dev, -EINVAL,
- "%s: invalid channel_index %d value\n",
- fwnode_get_name(node), idx);
- goto err_fwnode;
- }
+ idx >= info->phys_channels || idx < 0)
+ return dev_err_probe(dev, -EINVAL,
+ "%s: invalid channel_index %d value\n",
+ fwnode_get_name(node), idx);
/* enable channel */
info->active_channels[idx] = true;
ret = fwnode_property_read_u32(node, "shunt-resistor-micro-ohms",
&info->shunts[idx]);
- if (ret) {
- dev_err_probe(dev, ret,
- "%s: invalid shunt-resistor value: %d\n",
- fwnode_get_name(node), info->shunts[idx]);
- goto err_fwnode;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "%s: invalid shunt-resistor value: %d\n",
+ fwnode_get_name(node), info->shunts[idx]);
if (fwnode_property_present(node, "label")) {
ret = fwnode_property_read_string(node, "label",
(const char **)&info->labels[idx]);
- if (ret) {
- dev_err_probe(dev, ret,
- "%s: invalid rail-name value\n",
- fwnode_get_name(node));
- goto err_fwnode;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "%s: invalid rail-name value\n",
+ fwnode_get_name(node));
}
info->bi_dir[idx] = fwnode_property_read_bool(node, "bipolar");
@@ -1210,12 +1201,7 @@ static bool pac1934_of_parse_channel_config(struct i2c_client *client,
current_channel++;
}
- return true;
-
-err_fwnode:
- fwnode_handle_put(node);
-
- return false;
+ return 0;
}
static void pac1934_cancel_delayed_work(void *dwork)
@@ -1485,7 +1471,6 @@ static int pac1934_probe(struct i2c_client *client)
const struct pac1934_features *chip;
struct iio_dev *indio_dev;
int cnt, ret;
- bool match = false;
struct device *dev = &client->dev;
indio_dev = devm_iio_device_alloc(dev, sizeof(*info));
@@ -1519,16 +1504,16 @@ static int pac1934_probe(struct i2c_client *client)
}
if (acpi_match_device(dev->driver->acpi_match_table, dev))
- match = pac1934_acpi_parse_channel_config(client, info);
+ ret = pac1934_acpi_parse_channel_config(client, info);
else
/*
* This makes it possible to use also ACPI PRP0001 for
* registering the device using device tree properties.
*/
- match = pac1934_of_parse_channel_config(client, info);
+ ret = pac1934_fw_parse_channel_config(client, info);
- if (!match)
- return dev_err_probe(dev, -EINVAL,
+ if (ret)
+ return dev_err_probe(dev, ret,
"parameter parsing returned an error\n");
mutex_init(&info->lock);
diff --git a/drivers/iio/adc/qcom-spmi-adc5.c b/drivers/iio/adc/qcom-spmi-adc5.c
index b6b612d733ff..9b69f40beed8 100644
--- a/drivers/iio/adc/qcom-spmi-adc5.c
+++ b/drivers/iio/adc/qcom-spmi-adc5.c
@@ -825,7 +825,6 @@ static int adc5_get_fw_data(struct adc5_chip *adc)
const struct adc5_channels *adc_chan;
struct iio_chan_spec *iio_chan;
struct adc5_channel_prop prop, *chan_props;
- struct fwnode_handle *child;
unsigned int index = 0;
int ret;
@@ -849,12 +848,10 @@ static int adc5_get_fw_data(struct adc5_chip *adc)
if (!adc->data)
adc->data = &adc5_data_pmic;
- device_for_each_child_node(adc->dev, child) {
+ device_for_each_child_node_scoped(adc->dev, child) {
ret = adc5_get_fw_channel_data(adc, &prop, child, adc->data);
- if (ret) {
- fwnode_handle_put(child);
+ if (ret)
return ret;
- }
prop.scale_fn_type =
adc->data->adc_chans[prop.channel].scale_fn_type;
diff --git a/drivers/iio/adc/rcar-gyroadc.c b/drivers/iio/adc/rcar-gyroadc.c
index d524f2e8e927..15a21d2860e7 100644
--- a/drivers/iio/adc/rcar-gyroadc.c
+++ b/drivers/iio/adc/rcar-gyroadc.c
@@ -318,7 +318,6 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev)
struct rcar_gyroadc *priv = iio_priv(indio_dev);
struct device *dev = priv->dev;
struct device_node *np = dev->of_node;
- struct device_node *child;
struct regulator *vref;
unsigned int reg;
unsigned int adcmode = -1, childmode;
@@ -326,7 +325,7 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev)
unsigned int num_channels;
int ret, first = 1;
- for_each_child_of_node(np, child) {
+ for_each_available_child_of_node_scoped(np, child) {
of_id = of_match_node(rcar_gyroadc_child_match, child);
if (!of_id) {
dev_err(dev, "Ignoring unsupported ADC \"%pOFn\".",
@@ -352,7 +351,7 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev)
num_channels = ARRAY_SIZE(rcar_gyroadc_iio_channels_3);
break;
default:
- goto err_e_inval;
+ return -EINVAL;
}
/*
@@ -369,7 +368,7 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev)
dev_err(dev,
"Failed to get child reg property of ADC \"%pOFn\".\n",
child);
- goto err_of_node_put;
+ return ret;
}
/* Channel number is too high. */
@@ -377,7 +376,7 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev)
dev_err(dev,
"Only %i channels supported with %pOFn, but reg = <%i>.\n",
num_channels, child, reg);
- goto err_e_inval;
+ return -EINVAL;
}
}
@@ -386,7 +385,7 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev)
dev_err(dev,
"Channel %i uses different ADC mode than the rest.\n",
reg);
- goto err_e_inval;
+ return -EINVAL;
}
/* Channel is valid, grab the regulator. */
@@ -396,8 +395,7 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev)
if (IS_ERR(vref)) {
dev_dbg(dev, "Channel %i 'vref' supply not connected.\n",
reg);
- ret = PTR_ERR(vref);
- goto err_of_node_put;
+ return PTR_ERR(vref);
}
priv->vref[reg] = vref;
@@ -422,7 +420,6 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev)
* we can stop parsing here.
*/
if (childmode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) {
- of_node_put(child);
break;
}
}
@@ -433,12 +430,6 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev)
}
return 0;
-
-err_e_inval:
- ret = -EINVAL;
-err_of_node_put:
- of_node_put(child);
- return ret;
}
static void rcar_gyroadc_deinit_supplies(struct iio_dev *indio_dev)
diff --git a/drivers/iio/adc/rzg2l_adc.c b/drivers/iio/adc/rzg2l_adc.c
index 0921ff2d9b3a..cd3a7e46ea53 100644
--- a/drivers/iio/adc/rzg2l_adc.c
+++ b/drivers/iio/adc/rzg2l_adc.c
@@ -302,7 +302,6 @@ static irqreturn_t rzg2l_adc_isr(int irq, void *dev_id)
static int rzg2l_adc_parse_properties(struct platform_device *pdev, struct rzg2l_adc *adc)
{
struct iio_chan_spec *chan_array;
- struct fwnode_handle *fwnode;
struct rzg2l_adc_data *data;
unsigned int channel;
int num_channels;
@@ -330,17 +329,13 @@ static int rzg2l_adc_parse_properties(struct platform_device *pdev, struct rzg2l
return -ENOMEM;
i = 0;
- device_for_each_child_node(&pdev->dev, fwnode) {
+ device_for_each_child_node_scoped(&pdev->dev, fwnode) {
ret = fwnode_property_read_u32(fwnode, "reg", &channel);
- if (ret) {
- fwnode_handle_put(fwnode);
+ if (ret)
return ret;
- }
- if (channel >= RZG2L_ADC_MAX_CHANNELS) {
- fwnode_handle_put(fwnode);
+ if (channel >= RZG2L_ADC_MAX_CHANNELS)
return -EINVAL;
- }
chan_array[i].type = IIO_VOLTAGE;
chan_array[i].indexed = 1;
diff --git a/drivers/iio/adc/spear_adc.c b/drivers/iio/adc/spear_adc.c
index 71362c2ddf89..b6dd096391c1 100644
--- a/drivers/iio/adc/spear_adc.c
+++ b/drivers/iio/adc/spear_adc.c
@@ -5,8 +5,10 @@
* Copyright 2012 Stefan Roese <sr@denx.de>
*/
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/kernel.h>
@@ -15,8 +17,6 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/completion.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -70,7 +70,7 @@ struct adc_regs_spear6xx {
};
struct spear_adc_state {
- struct device_node *np;
+ struct device *dev;
struct adc_regs_spear3xx __iomem *adc_base_spear3xx;
struct adc_regs_spear6xx __iomem *adc_base_spear6xx;
struct clk *clk;
@@ -123,7 +123,7 @@ static void spear_adc_set_ctrl(struct spear_adc_state *st, int n,
static u32 spear_adc_get_average(struct spear_adc_state *st)
{
- if (of_device_is_compatible(st->np, "st,spear600-adc")) {
+ if (device_is_compatible(st->dev, "st,spear600-adc")) {
return __raw_readl(&st->adc_base_spear6xx->average.msb) &
SPEAR_ADC_DATA_MASK;
} else {
@@ -134,7 +134,7 @@ static u32 spear_adc_get_average(struct spear_adc_state *st)
static void spear_adc_set_scanrate(struct spear_adc_state *st, u32 rate)
{
- if (of_device_is_compatible(st->np, "st,spear600-adc")) {
+ if (device_is_compatible(st->dev, "st,spear600-adc")) {
__raw_writel(SPEAR600_ADC_SCAN_RATE_LO(rate),
&st->adc_base_spear6xx->scan_rate_lo);
__raw_writel(SPEAR600_ADC_SCAN_RATE_HI(rate),
@@ -266,7 +266,6 @@ static const struct iio_info spear_adc_info = {
static int spear_adc_probe(struct platform_device *pdev)
{
- struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
struct spear_adc_state *st;
struct iio_dev *indio_dev = NULL;
@@ -279,11 +278,10 @@ static int spear_adc_probe(struct platform_device *pdev)
"failed allocating iio device\n");
st = iio_priv(indio_dev);
+ st->dev = dev;
mutex_init(&st->lock);
- st->np = np;
-
/*
* SPEAr600 has a different register layout than other SPEAr SoC's
* (e.g. SPEAr3xx). Let's provide two register base addresses
@@ -310,8 +308,7 @@ static int spear_adc_probe(struct platform_device *pdev)
if (ret < 0)
return dev_err_probe(dev, ret, "failed requesting interrupt\n");
- if (of_property_read_u32(np, "sampling-frequency",
- &st->sampling_freq))
+ if (device_property_read_u32(dev, "sampling-frequency", &st->sampling_freq))
return dev_err_probe(dev, -EINVAL,
"sampling-frequency missing in DT\n");
@@ -319,13 +316,13 @@ static int spear_adc_probe(struct platform_device *pdev)
* Optional avg_samples defaults to 0, resulting in single data
* conversion
*/
- of_property_read_u32(np, "average-samples", &st->avg_samples);
+ device_property_read_u32(dev, "average-samples", &st->avg_samples);
/*
* Optional vref_external defaults to 0, resulting in internal vref
* selection
*/
- of_property_read_u32(np, "vref-external", &st->vref_external);
+ device_property_read_u32(dev, "vref-external", &st->vref_external);
spear_adc_configure(st);
@@ -346,19 +343,17 @@ static int spear_adc_probe(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_OF
static const struct of_device_id spear_adc_dt_ids[] = {
{ .compatible = "st,spear600-adc", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, spear_adc_dt_ids);
-#endif
static struct platform_driver spear_adc_driver = {
.probe = spear_adc_probe,
.driver = {
.name = SPEAR_ADC_MOD_NAME,
- .of_match_table = of_match_ptr(spear_adc_dt_ids),
+ .of_match_table = spear_adc_dt_ids,
},
};
diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
index b5d3c9cea5c4..36add95212c3 100644
--- a/drivers/iio/adc/stm32-adc.c
+++ b/drivers/iio/adc/stm32-adc.c
@@ -2187,58 +2187,52 @@ static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev,
struct iio_chan_spec *channels)
{
const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
- struct fwnode_handle *child;
+ struct device *dev = &indio_dev->dev;
const char *name;
int val, scan_index = 0, ret;
bool differential;
u32 vin[2];
- device_for_each_child_node(&indio_dev->dev, child) {
+ device_for_each_child_node_scoped(dev, child) {
ret = fwnode_property_read_u32(child, "reg", &val);
- if (ret) {
- dev_err(&indio_dev->dev, "Missing channel index %d\n", ret);
- goto err;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Missing channel index\n");
ret = fwnode_property_read_string(child, "label", &name);
/* label is optional */
if (!ret) {
- if (strlen(name) >= STM32_ADC_CH_SZ) {
- dev_err(&indio_dev->dev, "Label %s exceeds %d characters\n",
- name, STM32_ADC_CH_SZ);
- ret = -EINVAL;
- goto err;
- }
+ if (strlen(name) >= STM32_ADC_CH_SZ)
+ return dev_err_probe(dev, -EINVAL,
+ "Label %s exceeds %d characters\n",
+ name, STM32_ADC_CH_SZ);
+
strscpy(adc->chan_name[val], name, STM32_ADC_CH_SZ);
ret = stm32_adc_populate_int_ch(indio_dev, name, val);
if (ret == -ENOENT)
continue;
else if (ret)
- goto err;
+ return ret;
} else if (ret != -EINVAL) {
- dev_err(&indio_dev->dev, "Invalid label %d\n", ret);
- goto err;
+ return dev_err_probe(dev, ret, "Invalid label\n");
}
- if (val >= adc_info->max_channels) {
- dev_err(&indio_dev->dev, "Invalid channel %d\n", val);
- ret = -EINVAL;
- goto err;
- }
+ if (val >= adc_info->max_channels)
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid channel %d\n", val);
differential = false;
ret = fwnode_property_read_u32_array(child, "diff-channels", vin, 2);
/* diff-channels is optional */
if (!ret) {
differential = true;
- if (vin[0] != val || vin[1] >= adc_info->max_channels) {
- dev_err(&indio_dev->dev, "Invalid channel in%d-in%d\n",
- vin[0], vin[1]);
- goto err;
- }
+ if (vin[0] != val || vin[1] >= adc_info->max_channels)
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid channel in%d-in%d\n",
+ vin[0], vin[1]);
} else if (ret != -EINVAL) {
- dev_err(&indio_dev->dev, "Invalid diff-channels property %d\n", ret);
- goto err;
+ return dev_err_probe(dev, ret,
+ "Invalid diff-channels property\n");
}
stm32_adc_chan_init_one(indio_dev, &channels[scan_index], val,
@@ -2247,11 +2241,9 @@ static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev,
val = 0;
ret = fwnode_property_read_u32(child, "st,min-sample-time-ns", &val);
/* st,min-sample-time-ns is optional */
- if (ret && ret != -EINVAL) {
- dev_err(&indio_dev->dev, "Invalid st,min-sample-time-ns property %d\n",
- ret);
- goto err;
- }
+ if (ret && ret != -EINVAL)
+ return dev_err_probe(dev, ret,
+ "Invalid st,min-sample-time-ns property\n");
stm32_adc_smpr_init(adc, channels[scan_index].channel, val);
if (differential)
@@ -2261,11 +2253,6 @@ static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev,
}
return scan_index;
-
-err:
- fwnode_handle_put(child);
-
- return ret;
}
static int stm32_adc_chan_fw_init(struct iio_dev *indio_dev, bool timestamping)
diff --git a/drivers/iio/adc/ti-ads131e08.c b/drivers/iio/adc/ti-ads131e08.c
index fcfc46254313..cb04a29b3dba 100644
--- a/drivers/iio/adc/ti-ads131e08.c
+++ b/drivers/iio/adc/ti-ads131e08.c
@@ -694,7 +694,6 @@ static int ads131e08_alloc_channels(struct iio_dev *indio_dev)
struct ads131e08_channel_config *channel_config;
struct device *dev = &st->spi->dev;
struct iio_chan_spec *channels;
- struct fwnode_handle *node;
unsigned int channel, tmp;
int num_channels, i, ret;
@@ -736,10 +735,10 @@ static int ads131e08_alloc_channels(struct iio_dev *indio_dev)
return -ENOMEM;
i = 0;
- device_for_each_child_node(dev, node) {
+ device_for_each_child_node_scoped(dev, node) {
ret = fwnode_property_read_u32(node, "reg", &channel);
if (ret)
- goto err_child_out;
+ return ret;
ret = fwnode_property_read_u32(node, "ti,gain", &tmp);
if (ret) {
@@ -747,7 +746,7 @@ static int ads131e08_alloc_channels(struct iio_dev *indio_dev)
} else {
ret = ads131e08_pga_gain_to_field_value(st, tmp);
if (ret < 0)
- goto err_child_out;
+ return ret;
channel_config[i].pga_gain = tmp;
}
@@ -758,7 +757,7 @@ static int ads131e08_alloc_channels(struct iio_dev *indio_dev)
} else {
ret = ads131e08_validate_channel_mux(st, tmp);
if (ret)
- goto err_child_out;
+ return ret;
channel_config[i].mux = tmp;
}
@@ -785,9 +784,6 @@ static int ads131e08_alloc_channels(struct iio_dev *indio_dev)
return 0;
-err_child_out:
- fwnode_handle_put(node);
- return ret;
}
static void ads131e08_regulator_disable(void *data)
diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c
index 4a247ca25a44..0253064fadec 100644
--- a/drivers/iio/adc/twl4030-madc.c
+++ b/drivers/iio/adc/twl4030-madc.c
@@ -19,10 +19,12 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/delay.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/slab.h>
#include <linux/mfd/twl.h>
-#include <linux/module.h>
#include <linux/stddef.h>
#include <linux/mutex.h>
#include <linux/bitops.h>
@@ -30,7 +32,6 @@
#include <linux/types.h>
#include <linux/gfp.h>
#include <linux/err.h>
-#include <linux/of.h>
#include <linux/regulator/consumer.h>
#include <linux/iio/iio.h>
@@ -744,14 +745,14 @@ static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
*/
static int twl4030_madc_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
+ struct twl4030_madc_platform_data *pdata = dev_get_platdata(dev);
struct twl4030_madc_data *madc;
- struct twl4030_madc_platform_data *pdata = dev_get_platdata(&pdev->dev);
- struct device_node *np = pdev->dev.of_node;
int irq, ret;
u8 regval;
struct iio_dev *iio_dev = NULL;
- if (!pdata && !np) {
+ if (!pdata && !dev_fwnode(dev)) {
dev_err(&pdev->dev, "neither platform data nor Device Tree node available\n");
return -EINVAL;
}
@@ -779,7 +780,7 @@ static int twl4030_madc_probe(struct platform_device *pdev)
if (pdata)
madc->use_second_irq = (pdata->irq_line != 1);
else
- madc->use_second_irq = of_property_read_bool(np,
+ madc->use_second_irq = device_property_read_bool(dev,
"ti,system-uses-second-madc-irq");
madc->imr = madc->use_second_irq ? TWL4030_MADC_IMR2 :
@@ -905,20 +906,18 @@ static void twl4030_madc_remove(struct platform_device *pdev)
regulator_disable(madc->usb3v1);
}
-#ifdef CONFIG_OF
static const struct of_device_id twl_madc_of_match[] = {
{ .compatible = "ti,twl4030-madc", },
- { },
+ { }
};
MODULE_DEVICE_TABLE(of, twl_madc_of_match);
-#endif
static struct platform_driver twl4030_madc_driver = {
.probe = twl4030_madc_probe,
.remove_new = twl4030_madc_remove,
.driver = {
.name = "twl4030_madc",
- .of_match_table = of_match_ptr(twl_madc_of_match),
+ .of_match_table = twl_madc_of_match,
},
};