diff options
Diffstat (limited to 'drivers/iio/adc')
-rw-r--r-- | drivers/iio/adc/Kconfig | 1 | ||||
-rw-r--r-- | drivers/iio/adc/ad7124.c | 33 | ||||
-rw-r--r-- | drivers/iio/adc/ad7606.c | 97 | ||||
-rw-r--r-- | drivers/iio/adc/ad7606.h | 17 | ||||
-rw-r--r-- | drivers/iio/adc/ad_sigma_delta.c | 3 | ||||
-rw-r--r-- | drivers/iio/adc/at91-sama5d2_adc.c | 12 | ||||
-rw-r--r-- | drivers/iio/adc/at91_adc.c | 4 | ||||
-rw-r--r-- | drivers/iio/adc/imx7d_adc.c | 24 | ||||
-rw-r--r-- | drivers/iio/adc/meson_saradc.c | 2 | ||||
-rw-r--r-- | drivers/iio/adc/mt6577_auxadc.c | 54 | ||||
-rw-r--r-- | drivers/iio/adc/rcar-gyroadc.c | 4 | ||||
-rw-r--r-- | drivers/iio/adc/stm32-adc-core.c | 21 | ||||
-rw-r--r-- | drivers/iio/adc/stm32-dfsdm-adc.c | 239 | ||||
-rw-r--r-- | drivers/iio/adc/stm32-dfsdm-core.c | 8 | ||||
-rw-r--r-- | drivers/iio/adc/stm32-dfsdm.h | 24 | ||||
-rw-r--r-- | drivers/iio/adc/stmpe-adc.c | 40 | ||||
-rw-r--r-- | drivers/iio/adc/sun4i-gpadc-iio.c | 2 |
17 files changed, 438 insertions, 147 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index f96a7702b020..7e3286265a38 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -1085,7 +1085,6 @@ config VIPERBOARD_ADC config XILINX_XADC tristate "Xilinx XADC driver" - depends on ARCH_ZYNQ || MICROBLAZE || COMPILE_TEST depends on HAS_IOMEM select IIO_BUFFER select IIO_TRIGGERED_BUFFER diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index 659ef37d5fe8..edc6f1cc90b2 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -61,6 +61,8 @@ #define AD7124_CONFIG_REF_SEL(x) FIELD_PREP(AD7124_CONFIG_REF_SEL_MSK, x) #define AD7124_CONFIG_PGA_MSK GENMASK(2, 0) #define AD7124_CONFIG_PGA(x) FIELD_PREP(AD7124_CONFIG_PGA_MSK, x) +#define AD7124_CONFIG_IN_BUFF_MSK GENMASK(7, 6) +#define AD7124_CONFIG_IN_BUFF(x) FIELD_PREP(AD7124_CONFIG_IN_BUFF_MSK, x) /* AD7124_FILTER_X */ #define AD7124_FILTER_FS_MSK GENMASK(10, 0) @@ -108,6 +110,8 @@ struct ad7124_chip_info { struct ad7124_channel_config { enum ad7124_ref_sel refsel; bool bipolar; + bool buf_positive; + bool buf_negative; unsigned int ain; unsigned int vref_mv; unsigned int pga_bits; @@ -117,7 +121,7 @@ struct ad7124_channel_config { struct ad7124_state { const struct ad7124_chip_info *chip_info; struct ad_sigma_delta sd; - struct ad7124_channel_config channel_config[4]; + struct ad7124_channel_config *channel_config; struct regulator *vref[4]; struct clk *mclk; unsigned int adc_control; @@ -435,6 +439,7 @@ static int ad7124_of_parse_channel_config(struct iio_dev *indio_dev, struct ad7124_state *st = iio_priv(indio_dev); struct device_node *child; struct iio_chan_spec *chan; + struct ad7124_channel_config *chan_config; unsigned int ain[2], channel = 0, tmp; int ret; @@ -449,8 +454,14 @@ static int ad7124_of_parse_channel_config(struct iio_dev *indio_dev, if (!chan) return -ENOMEM; + chan_config = devm_kcalloc(indio_dev->dev.parent, st->num_channels, + sizeof(*chan_config), GFP_KERNEL); + if (!chan_config) + return -ENOMEM; + indio_dev->channels = chan; indio_dev->num_channels = st->num_channels; + st->channel_config = chan_config; for_each_available_child_of_node(np, child) { ret = of_property_read_u32(child, "reg", &channel); @@ -462,13 +473,6 @@ static int ad7124_of_parse_channel_config(struct iio_dev *indio_dev, if (ret) goto err; - if (ain[0] >= st->chip_info->num_inputs || - ain[1] >= st->chip_info->num_inputs) { - dev_err(indio_dev->dev.parent, - "Input pin number out of range.\n"); - ret = -EINVAL; - goto err; - } st->channel_config[channel].ain = AD7124_CHANNEL_AINP(ain[0]) | AD7124_CHANNEL_AINM(ain[1]); st->channel_config[channel].bipolar = @@ -480,6 +484,11 @@ static int ad7124_of_parse_channel_config(struct iio_dev *indio_dev, else st->channel_config[channel].refsel = tmp; + st->channel_config[channel].buf_positive = + of_property_read_bool(child, "adi,buffered-positive"); + st->channel_config[channel].buf_negative = + of_property_read_bool(child, "adi,buffered-negative"); + *chan = ad7124_channel_template; chan->address = channel; chan->scan_index = channel; @@ -499,7 +508,7 @@ err: static int ad7124_setup(struct ad7124_state *st) { unsigned int val, fclk, power_mode; - int i, ret; + int i, ret, tmp; fclk = clk_get_rate(st->mclk); if (!fclk) @@ -532,8 +541,12 @@ static int ad7124_setup(struct ad7124_state *st) if (ret < 0) return ret; + tmp = (st->channel_config[i].buf_positive << 1) + + st->channel_config[i].buf_negative; + val = AD7124_CONFIG_BIPOLAR(st->channel_config[i].bipolar) | - AD7124_CONFIG_REF_SEL(st->channel_config[i].refsel); + AD7124_CONFIG_REF_SEL(st->channel_config[i].refsel) | + AD7124_CONFIG_IN_BUFF(tmp); ret = ad_sd_write_reg(&st->sd, AD7124_CONFIG(i), 2, val); if (ret < 0) return ret; diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c index 24c70c3cefb4..aba0fd123a51 100644 --- a/drivers/iio/adc/ad7606.c +++ b/drivers/iio/adc/ad7606.c @@ -140,7 +140,7 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, int *val2, long m) { - int ret; + int ret, ch = 0; struct ad7606_state *st = iio_priv(indio_dev); switch (m) { @@ -157,8 +157,10 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, *val = (short)ret; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: + if (st->sw_mode_en) + ch = chan->address; *val = 0; - *val2 = st->scale_avail[st->range]; + *val2 = st->scale_avail[st->range[ch]]; return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_OVERSAMPLING_RATIO: *val = st->oversampling; @@ -194,6 +196,32 @@ static ssize_t in_voltage_scale_available_show(struct device *dev, static IIO_DEVICE_ATTR_RO(in_voltage_scale_available, 0); +static int ad7606_write_scale_hw(struct iio_dev *indio_dev, int ch, int val) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + gpiod_set_value(st->gpio_range, val); + + return 0; +} + +static int ad7606_write_os_hw(struct iio_dev *indio_dev, int val) +{ + struct ad7606_state *st = iio_priv(indio_dev); + DECLARE_BITMAP(values, 3); + + values[0] = val; + + gpiod_set_array_value(ARRAY_SIZE(values), st->gpio_os->desc, + st->gpio_os->info, values); + + /* AD7616 requires a reset to update value */ + if (st->chip_info->os_req_reset) + ad7606_reset(st); + + return 0; +} + static int ad7606_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, @@ -201,15 +229,20 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, long mask) { struct ad7606_state *st = iio_priv(indio_dev); - DECLARE_BITMAP(values, 3); - int i; + int i, ret, ch = 0; switch (mask) { case IIO_CHAN_INFO_SCALE: mutex_lock(&st->lock); i = find_closest(val2, st->scale_avail, st->num_scales); - gpiod_set_value(st->gpio_range, i); - st->range = i; + if (st->sw_mode_en) + ch = chan->address; + ret = st->write_scale(indio_dev, ch, i); + if (ret < 0) { + mutex_unlock(&st->lock); + return ret; + } + st->range[ch] = i; mutex_unlock(&st->lock); return 0; @@ -218,17 +251,12 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, return -EINVAL; i = find_closest(val, st->oversampling_avail, st->num_os_ratios); - - values[0] = i; - mutex_lock(&st->lock); - gpiod_set_array_value(ARRAY_SIZE(values), st->gpio_os->desc, - st->gpio_os->info, values); - - /* AD7616 requires a reset to update value */ - if (st->chip_info->os_req_reset) - ad7606_reset(st); - + ret = st->write_os(indio_dev, i); + if (ret < 0) { + mutex_unlock(&st->lock); + return ret; + } st->oversampling = st->oversampling_avail[i]; mutex_unlock(&st->lock); @@ -536,7 +564,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, st->bops = bops; st->base_address = base_address; /* tied to logic low, analog input range is +/- 5V */ - st->range = 0; + st->range[0] = 0; st->oversampling = 1; st->scale_avail = ad7606_scale_avail; st->num_scales = ARRAY_SIZE(ad7606_scale_avail); @@ -589,6 +617,39 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, if (ret) dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); + st->write_scale = ad7606_write_scale_hw; + st->write_os = ad7606_write_os_hw; + + if (st->chip_info->sw_mode_config) + st->sw_mode_en = device_property_present(st->dev, + "adi,sw-mode"); + + if (st->sw_mode_en) { + /* After reset, in software mode, ±10 V is set by default */ + memset32(st->range, 2, ARRAY_SIZE(st->range)); + indio_dev->info = &ad7606_info_os_and_range; + + /* + * In software mode, the range gpio has no longer its function. + * Instead, the scale can be configured individually for each + * channel from the range registers. + */ + if (st->chip_info->write_scale_sw) + st->write_scale = st->chip_info->write_scale_sw; + + /* + * In software mode, the oversampling is no longer configured + * with GPIO pins. Instead, the oversampling can be configured + * in configuratiion register. + */ + if (st->chip_info->write_os_sw) + st->write_os = st->chip_info->write_os_sw; + + ret = st->chip_info->sw_mode_config(indio_dev); + if (ret < 0) + return ret; + } + st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, indio_dev->id); if (!st->trig) @@ -643,7 +704,7 @@ static int ad7606_resume(struct device *dev) struct ad7606_state *st = iio_priv(indio_dev); if (st->gpio_standby) { - gpiod_set_value(st->gpio_range, st->range); + gpiod_set_value(st->gpio_range, st->range[0]); gpiod_set_value(st->gpio_standby, 1); ad7606_reset(st); } diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h index f9ef52131e74..d8a509c2c428 100644 --- a/drivers/iio/adc/ad7606.h +++ b/drivers/iio/adc/ad7606.h @@ -16,6 +16,12 @@ * oversampling ratios. * @oversampling_num number of elements stored in oversampling_avail array * @os_req_reset some devices require a reset to update oversampling + * @write_scale_sw pointer to the function which writes the scale via spi + in software mode + * @write_os_sw pointer to the function which writes the os via spi + in software mode + * @sw_mode_config: pointer to a function which configured the device + * for software mode */ struct ad7606_chip_info { const struct iio_chan_spec *channels; @@ -23,6 +29,9 @@ struct ad7606_chip_info { const unsigned int *oversampling_avail; unsigned int oversampling_num; bool os_req_reset; + int (*write_scale_sw)(struct iio_dev *indio_dev, int ch, int val); + int (*write_os_sw)(struct iio_dev *indio_dev, int val); + int (*sw_mode_config)(struct iio_dev *indio_dev); }; /** @@ -34,11 +43,14 @@ struct ad7606_chip_info { * @range voltage range selection, selects which scale to apply * @oversampling oversampling selection * @base_address address from where to read data in parallel operation + * @sw_mode_en software mode enabled * @scale_avail pointer to the array which stores the available scales * @num_scales number of elements stored in the scale_avail array * @oversampling_avail pointer to the array which stores the available * oversampling ratios. * @num_os_ratios number of elements stored in oversampling_avail array + * @write_scale pointer to the function which writes the scale + * @write_os pointer to the function which writes the os * @lock protect sensor state from concurrent accesses to GPIOs * @gpio_convst GPIO descriptor for conversion start signal (CONVST) * @gpio_reset GPIO descriptor for device hard-reset @@ -57,13 +69,16 @@ struct ad7606_state { const struct ad7606_chip_info *chip_info; struct regulator *reg; const struct ad7606_bus_ops *bops; - unsigned int range; + unsigned int range[16]; unsigned int oversampling; void __iomem *base_address; + bool sw_mode_en; const unsigned int *scale_avail; unsigned int num_scales; const unsigned int *oversampling_avail; unsigned int num_os_ratios; + int (*write_scale)(struct iio_dev *indio_dev, int ch, int val); + int (*write_os)(struct iio_dev *indio_dev, int val); struct mutex lock; /* protect sensor state */ struct gpio_desc *gpio_convst; diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index 1423221c6e06..2640b75fb774 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -357,7 +357,7 @@ static int ad_sd_buffer_postenable(struct iio_dev *indio_dev) ret = ad_sigma_delta_set_channel(sigma_delta, indio_dev->channels[channel].address); if (ret) - goto err_predisable; + return ret; spi_bus_lock(sigma_delta->spi->master); sigma_delta->bus_locked = true; @@ -374,7 +374,6 @@ static int ad_sd_buffer_postenable(struct iio_dev *indio_dev) err_unlock: spi_bus_unlock(sigma_delta->spi->master); -err_predisable: return ret; } diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index d384cf0250ff..a2837a0e7cba 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -1578,8 +1578,7 @@ static void at91_adc_hw_init(struct at91_adc_state *st) static ssize_t at91_adc_get_fifo_state(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = - platform_get_drvdata(to_platform_device(dev)); + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct at91_adc_state *st = iio_priv(indio_dev); return scnprintf(buf, PAGE_SIZE, "%d\n", !!st->dma_st.dma_chan); @@ -1588,8 +1587,7 @@ static ssize_t at91_adc_get_fifo_state(struct device *dev, static ssize_t at91_adc_get_watermark(struct device *dev, struct device_attribute *attr, char *buf) { - struct iio_dev *indio_dev = - platform_get_drvdata(to_platform_device(dev)); + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct at91_adc_state *st = iio_priv(indio_dev); return scnprintf(buf, PAGE_SIZE, "%d\n", st->dma_st.watermark); @@ -1841,8 +1839,7 @@ static int at91_adc_remove(struct platform_device *pdev) static __maybe_unused int at91_adc_suspend(struct device *dev) { - struct iio_dev *indio_dev = - platform_get_drvdata(to_platform_device(dev)); + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct at91_adc_state *st = iio_priv(indio_dev); /* @@ -1862,8 +1859,7 @@ static __maybe_unused int at91_adc_suspend(struct device *dev) static __maybe_unused int at91_adc_resume(struct device *dev) { - struct iio_dev *indio_dev = - platform_get_drvdata(to_platform_device(dev)); + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct at91_adc_state *st = iio_priv(indio_dev); int ret; diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index d23709ed9049..32f1c4a33b20 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -1359,7 +1359,7 @@ static int at91_adc_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int at91_adc_suspend(struct device *dev) { - struct iio_dev *idev = platform_get_drvdata(to_platform_device(dev)); + struct iio_dev *idev = dev_get_drvdata(dev); struct at91_adc_state *st = iio_priv(idev); pinctrl_pm_select_sleep_state(dev); @@ -1370,7 +1370,7 @@ static int at91_adc_suspend(struct device *dev) static int at91_adc_resume(struct device *dev) { - struct iio_dev *idev = platform_get_drvdata(to_platform_device(dev)); + struct iio_dev *idev = dev_get_drvdata(dev); struct at91_adc_state *st = iio_priv(idev); clk_prepare_enable(st->clk); diff --git a/drivers/iio/adc/imx7d_adc.c b/drivers/iio/adc/imx7d_adc.c index 4fe97c2a0f43..26a7bbe4d534 100644 --- a/drivers/iio/adc/imx7d_adc.c +++ b/drivers/iio/adc/imx7d_adc.c @@ -78,6 +78,7 @@ #define IMX7D_REG_ADC_INT_STATUS_CHANNEL_CONV_TIME_OUT 0xf0000 #define IMX7D_ADC_TIMEOUT msecs_to_jiffies(100) +#define IMX7D_ADC_INPUT_CLK 24000000 enum imx7d_adc_clk_pre_div { IMX7D_ADC_ANALOG_CLK_PRE_DIV_4, @@ -100,8 +101,6 @@ struct imx7d_adc_feature { enum imx7d_adc_average_num avg_num; u32 core_time_unit; /* impact the sample rate */ - - bool average_en; }; struct imx7d_adc { @@ -179,7 +178,6 @@ static void imx7d_adc_feature_config(struct imx7d_adc *info) info->adc_feature.clk_pre_div = IMX7D_ADC_ANALOG_CLK_PRE_DIV_4; info->adc_feature.avg_num = IMX7D_ADC_AVERAGE_NUM_32; info->adc_feature.core_time_unit = 1; - info->adc_feature.average_en = true; } static void imx7d_adc_sample_rate_set(struct imx7d_adc *info) @@ -240,9 +238,8 @@ static void imx7d_adc_channel_set(struct imx7d_adc *info) /* the channel choose single conversion, and enable average mode */ cfg1 |= (IMX7D_REG_ADC_CH_CFG1_CHANNEL_EN | - IMX7D_REG_ADC_CH_CFG1_CHANNEL_SINGLE); - if (info->adc_feature.average_en) - cfg1 |= IMX7D_REG_ADC_CH_CFG1_CHANNEL_AVG_EN; + IMX7D_REG_ADC_CH_CFG1_CHANNEL_SINGLE | + IMX7D_REG_ADC_CH_CFG1_CHANNEL_AVG_EN); /* * physical channel 0 chose logical channel A @@ -272,13 +269,11 @@ static void imx7d_adc_channel_set(struct imx7d_adc *info) static u32 imx7d_adc_get_sample_rate(struct imx7d_adc *info) { - /* input clock is always 24MHz */ - u32 input_clk = 24000000; u32 analogue_core_clk; u32 core_time_unit = info->adc_feature.core_time_unit; u32 tmp; - analogue_core_clk = input_clk / info->pre_div_num; + analogue_core_clk = IMX7D_ADC_INPUT_CLK / info->pre_div_num; tmp = (core_time_unit + 1) * 6; return analogue_core_clk / tmp; @@ -493,11 +488,8 @@ static int imx7d_adc_probe(struct platform_device *pdev) info->dev = dev; info->regs = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(info->regs)) { - ret = PTR_ERR(info->regs); - dev_err(dev, "Failed to remap adc memory, err = %d\n", ret); - return ret; - } + if (IS_ERR(info->regs)) + return PTR_ERR(info->regs); irq = platform_get_irq(pdev, 0); if (irq < 0) { @@ -531,9 +523,7 @@ static int imx7d_adc_probe(struct platform_device *pdev) indio_dev->channels = imx7d_adc_iio_channels; indio_dev->num_channels = ARRAY_SIZE(imx7d_adc_iio_channels); - ret = devm_request_irq(dev, irq, - imx7d_adc_isr, 0, - dev_name(dev), info); + ret = devm_request_irq(dev, irq, imx7d_adc_isr, 0, dev_name(dev), info); if (ret < 0) { dev_err(dev, "Failed requesting irq, irq = %d\n", irq); return ret; diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index 70bbcf253cb6..7b28d045d271 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0-only +// SPDX-License-Identifier: GPL-2.0 /* * Amlogic Meson Successive Approximation Register (SAR) A/D Converter * diff --git a/drivers/iio/adc/mt6577_auxadc.c b/drivers/iio/adc/mt6577_auxadc.c index d1759c804b26..7bbb64ca3b32 100644 --- a/drivers/iio/adc/mt6577_auxadc.c +++ b/drivers/iio/adc/mt6577_auxadc.c @@ -34,10 +34,26 @@ #define MT6577_AUXADC_POWER_READY_MS 1 #define MT6577_AUXADC_SAMPLE_READY_US 25 +struct mtk_auxadc_compatible { + bool sample_data_cali; + bool check_global_idle; +}; + struct mt6577_auxadc_device { void __iomem *reg_base; struct clk *adc_clk; struct mutex lock; + const struct mtk_auxadc_compatible *dev_comp; +}; + +static const struct mtk_auxadc_compatible mt8173_compat = { + .sample_data_cali = false, + .check_global_idle = true, +}; + +static const struct mtk_auxadc_compatible mt6765_compat = { + .sample_data_cali = true, + .check_global_idle = false, }; #define MT6577_AUXADC_CHANNEL(idx) { \ @@ -66,6 +82,11 @@ static const struct iio_chan_spec mt6577_auxadc_iio_channels[] = { MT6577_AUXADC_CHANNEL(15), }; +static int mt_auxadc_get_cali_data(int rawdata, bool enable_cali) +{ + return rawdata; +} + static inline void mt6577_auxadc_mod_reg(void __iomem *reg, u32 or_mask, u32 and_mask) { @@ -112,15 +133,17 @@ static int mt6577_auxadc_read(struct iio_dev *indio_dev, /* we must delay here for hardware sample channel data */ udelay(MT6577_AUXADC_SAMPLE_READY_US); - /* check MTK_AUXADC_CON2 if auxadc is idle */ - ret = readl_poll_timeout(adc_dev->reg_base + MT6577_AUXADC_CON2, val, - ((val & MT6577_AUXADC_STA) == 0), - MT6577_AUXADC_SLEEP_US, - MT6577_AUXADC_TIMEOUT_US); - if (ret < 0) { - dev_err(indio_dev->dev.parent, - "wait for auxadc idle time out\n"); - goto err_timeout; + if (adc_dev->dev_comp->check_global_idle) { + /* check MTK_AUXADC_CON2 if auxadc is idle */ + ret = readl_poll_timeout(adc_dev->reg_base + MT6577_AUXADC_CON2, + val, ((val & MT6577_AUXADC_STA) == 0), + MT6577_AUXADC_SLEEP_US, + MT6577_AUXADC_TIMEOUT_US); + if (ret < 0) { + dev_err(indio_dev->dev.parent, + "wait for auxadc idle time out\n"); + goto err_timeout; + } } /* read channel and make sure ready bit == 1 */ @@ -155,6 +178,8 @@ static int mt6577_auxadc_read_raw(struct iio_dev *indio_dev, int *val2, long info) { + struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev); + switch (info) { case IIO_CHAN_INFO_PROCESSED: *val = mt6577_auxadc_read(indio_dev, chan); @@ -164,6 +189,8 @@ static int mt6577_auxadc_read_raw(struct iio_dev *indio_dev, chan->channel); return *val; } + if (adc_dev->dev_comp->sample_data_cali) + *val = mt_auxadc_get_cali_data(*val, true); return IIO_VAL_INT; default: @@ -296,10 +323,11 @@ static SIMPLE_DEV_PM_OPS(mt6577_auxadc_pm_ops, mt6577_auxadc_resume); static const struct of_device_id mt6577_auxadc_of_match[] = { - { .compatible = "mediatek,mt2701-auxadc", }, - { .compatible = "mediatek,mt2712-auxadc", }, - { .compatible = "mediatek,mt7622-auxadc", }, - { .compatible = "mediatek,mt8173-auxadc", }, + { .compatible = "mediatek,mt2701-auxadc", .data = &mt8173_compat}, + { .compatible = "mediatek,mt2712-auxadc", .data = &mt8173_compat}, + { .compatible = "mediatek,mt7622-auxadc", .data = &mt8173_compat}, + { .compatible = "mediatek,mt8173-auxadc", .data = &mt8173_compat}, + { .compatible = "mediatek,mt6765-auxadc", .data = &mt6765_compat}, { } }; MODULE_DEVICE_TABLE(of, mt6577_auxadc_of_match); diff --git a/drivers/iio/adc/rcar-gyroadc.c b/drivers/iio/adc/rcar-gyroadc.c index 2c0d0316d149..2d685730f867 100644 --- a/drivers/iio/adc/rcar-gyroadc.c +++ b/drivers/iio/adc/rcar-gyroadc.c @@ -485,10 +485,8 @@ static int rcar_gyroadc_probe(struct platform_device *pdev) int ret; indio_dev = devm_iio_device_alloc(dev, sizeof(*priv)); - if (!indio_dev) { - dev_err(dev, "Failed to allocate IIO device.\n"); + if (!indio_dev) return -ENOMEM; - } priv = iio_priv(indio_dev); priv->dev = dev; diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c index 2327ec18b40c..1f7ce5186dfc 100644 --- a/drivers/iio/adc/stm32-adc-core.c +++ b/drivers/iio/adc/stm32-adc-core.c @@ -87,6 +87,7 @@ struct stm32_adc_priv_cfg { * @domain: irq domain reference * @aclk: clock reference for the analog circuitry * @bclk: bus clock common for all ADCs, depends on part used + * @vdda: vdda analog supply reference * @vref: regulator reference * @cfg: compatible configuration data * @common: common data for all ADC instances @@ -97,6 +98,7 @@ struct stm32_adc_priv { struct irq_domain *domain; struct clk *aclk; struct clk *bclk; + struct regulator *vdda; struct regulator *vref; const struct stm32_adc_priv_cfg *cfg; struct stm32_adc_common common; @@ -394,10 +396,16 @@ static int stm32_adc_core_hw_start(struct device *dev) struct stm32_adc_priv *priv = to_stm32_adc_priv(common); int ret; + ret = regulator_enable(priv->vdda); + if (ret < 0) { + dev_err(dev, "vdda enable failed %d\n", ret); + return ret; + } + ret = regulator_enable(priv->vref); if (ret < 0) { dev_err(dev, "vref enable failed\n"); - return ret; + goto err_vdda_disable; } if (priv->bclk) { @@ -425,6 +433,8 @@ err_bclk_disable: clk_disable_unprepare(priv->bclk); err_regulator_disable: regulator_disable(priv->vref); +err_vdda_disable: + regulator_disable(priv->vdda); return ret; } @@ -441,6 +451,7 @@ static void stm32_adc_core_hw_stop(struct device *dev) if (priv->bclk) clk_disable_unprepare(priv->bclk); regulator_disable(priv->vref); + regulator_disable(priv->vdda); } static int stm32_adc_probe(struct platform_device *pdev) @@ -468,6 +479,14 @@ static int stm32_adc_probe(struct platform_device *pdev) return PTR_ERR(priv->common.base); priv->common.phys_base = res->start; + priv->vdda = devm_regulator_get(&pdev->dev, "vdda"); + if (IS_ERR(priv->vdda)) { + ret = PTR_ERR(priv->vdda); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "vdda get failed, %d\n", ret); + return ret; + } + priv->vref = devm_regulator_get(&pdev->dev, "vref"); if (IS_ERR(priv->vref)) { ret = PTR_ERR(priv->vref); diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index 19adc2b23472..ee1e0569d0e1 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -39,9 +39,16 @@ #define DFSDM_MAX_INT_OVERSAMPLING 256 #define DFSDM_MAX_FL_OVERSAMPLING 1024 -/* Max sample resolutions */ -#define DFSDM_MAX_RES BIT(31) -#define DFSDM_DATA_RES BIT(23) +/* Limit filter output resolution to 31 bits. (i.e. sample range is +/-2^30) */ +#define DFSDM_DATA_MAX BIT(30) +/* + * Data are output as two's complement data in a 24 bit field. + * Data from filters are in the range +/-2^(n-1) + * 2^(n-1) maximum positive value cannot be coded in 2's complement n bits + * An extra bit is required to avoid wrap-around of the binary code for 2^(n-1) + * So, the resolution of samples from filter is actually limited to 23 bits + */ +#define DFSDM_DATA_RES 24 /* Filter configuration */ #define DFSDM_CR1_CFG_MASK (DFSDM_CR1_RCH_MASK | DFSDM_CR1_RCONT_MASK | \ @@ -181,14 +188,15 @@ static int stm32_dfsdm_get_jextsel(struct iio_dev *indio_dev, return -EINVAL; } -static int stm32_dfsdm_set_osrs(struct stm32_dfsdm_filter *fl, - unsigned int fast, unsigned int oversamp) +static int stm32_dfsdm_compute_osrs(struct stm32_dfsdm_filter *fl, + unsigned int fast, unsigned int oversamp) { unsigned int i, d, fosr, iosr; - u64 res; - s64 delta; + u64 res, max; + int bits, shift; unsigned int m = 1; /* multiplication factor */ unsigned int p = fl->ford; /* filter order (ford) */ + struct stm32_dfsdm_filter_osr *flo = &fl->flo[fast]; pr_debug("%s: Requested oversampling: %d\n", __func__, oversamp); /* @@ -207,11 +215,8 @@ static int stm32_dfsdm_set_osrs(struct stm32_dfsdm_filter *fl, /* * Look for filter and integrator oversampling ratios which allows - * to reach 24 bits data output resolution. - * Leave as soon as if exact resolution if reached. - * Otherwise the higher resolution below 32 bits is kept. + * to maximize data output resolution. */ - fl->res = 0; for (fosr = 1; fosr <= DFSDM_MAX_FL_OVERSAMPLING; fosr++) { for (iosr = 1; iosr <= DFSDM_MAX_INT_OVERSAMPLING; iosr++) { if (fast) @@ -236,33 +241,91 @@ static int stm32_dfsdm_set_osrs(struct stm32_dfsdm_filter *fl, res = fosr; for (i = p - 1; i > 0; i--) { res = res * (u64)fosr; - if (res > DFSDM_MAX_RES) + if (res > DFSDM_DATA_MAX) break; } - if (res > DFSDM_MAX_RES) + if (res > DFSDM_DATA_MAX) continue; + res = res * (u64)m * (u64)iosr; - if (res > DFSDM_MAX_RES) + if (res > DFSDM_DATA_MAX) continue; - delta = res - DFSDM_DATA_RES; - - if (res >= fl->res) { - fl->res = res; - fl->fosr = fosr; - fl->iosr = iosr; - fl->fast = fast; - pr_debug("%s: fosr = %d, iosr = %d\n", - __func__, fl->fosr, fl->iosr); + if (res >= flo->res) { + flo->res = res; + flo->fosr = fosr; + flo->iosr = iosr; + + bits = fls(flo->res); + /* 8 LBSs in data register contain chan info */ + max = flo->res << 8; + + /* if resolution is not a power of two */ + if (flo->res > BIT(bits - 1)) + bits++; + else + max--; + + shift = DFSDM_DATA_RES - bits; + /* + * Compute right/left shift + * Right shift is performed by hardware + * when transferring samples to data register. + * Left shift is done by software on buffer + */ + if (shift > 0) { + /* Resolution is lower than 24 bits */ + flo->rshift = 0; + flo->lshift = shift; + } else { + /* + * If resolution is 24 bits or more, + * max positive value may be ambiguous + * (equal to max negative value as sign + * bit is dropped). + * Reduce resolution to 23 bits (rshift) + * to keep the sign on bit 23 and treat + * saturation before rescaling on 24 + * bits (lshift). + */ + flo->rshift = 1 - shift; + flo->lshift = 1; + max >>= flo->rshift; + } + flo->max = (s32)max; + + pr_debug("%s: fast %d, fosr %d, iosr %d, res 0x%llx/%d bits, rshift %d, lshift %d\n", + __func__, fast, flo->fosr, flo->iosr, + flo->res, bits, flo->rshift, + flo->lshift); } - - if (!delta) - return 0; } } - if (!fl->res) + if (!flo->res) + return -EINVAL; + + return 0; +} + +static int stm32_dfsdm_compute_all_osrs(struct iio_dev *indio_dev, + unsigned int oversamp) +{ + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); + struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id]; + int ret0, ret1; + + memset(&fl->flo[0], 0, sizeof(fl->flo[0])); + memset(&fl->flo[1], 0, sizeof(fl->flo[1])); + + ret0 = stm32_dfsdm_compute_osrs(fl, 0, oversamp); + ret1 = stm32_dfsdm_compute_osrs(fl, 1, oversamp); + if (ret0 < 0 && ret1 < 0) { + dev_err(&indio_dev->dev, + "Filter parameters not found: errors %d/%d\n", + ret0, ret1); return -EINVAL; + } return 0; } @@ -384,6 +447,50 @@ static int stm32_dfsdm_filter_set_trig(struct stm32_dfsdm_adc *adc, return 0; } +static int stm32_dfsdm_channels_configure(struct stm32_dfsdm_adc *adc, + unsigned int fl_id, + struct iio_trigger *trig) +{ + struct iio_dev *indio_dev = iio_priv_to_dev(adc); + struct regmap *regmap = adc->dfsdm->regmap; + struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[fl_id]; + struct stm32_dfsdm_filter_osr *flo = &fl->flo[0]; + const struct iio_chan_spec *chan; + unsigned int bit; + int ret; + + fl->fast = 0; + + /* + * In continuous mode, use fast mode configuration, + * if it provides a better resolution. + */ + if (adc->nconv == 1 && !trig && + (indio_dev->currentmode & INDIO_BUFFER_SOFTWARE)) { + if (fl->flo[1].res >= fl->flo[0].res) { + fl->fast = 1; + flo = &fl->flo[1]; + } + } + + if (!flo->res) + return -EINVAL; + + for_each_set_bit(bit, &adc->smask, + sizeof(adc->smask) * BITS_PER_BYTE) { + chan = indio_dev->channels + bit; + + ret = regmap_update_bits(regmap, + DFSDM_CHCFGR2(chan->channel), + DFSDM_CHCFGR2_DTRBS_MASK, + DFSDM_CHCFGR2_DTRBS(flo->rshift)); + if (ret) + return ret; + } + + return 0; +} + static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc, unsigned int fl_id, struct iio_trigger *trig) @@ -391,6 +498,7 @@ static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc, struct iio_dev *indio_dev = iio_priv_to_dev(adc); struct regmap *regmap = adc->dfsdm->regmap; struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[fl_id]; + struct stm32_dfsdm_filter_osr *flo = &fl->flo[fl->fast]; u32 cr1; const struct iio_chan_spec *chan; unsigned int bit, jchg = 0; @@ -398,13 +506,13 @@ static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc, /* Average integrator oversampling */ ret = regmap_update_bits(regmap, DFSDM_FCR(fl_id), DFSDM_FCR_IOSR_MASK, - DFSDM_FCR_IOSR(fl->iosr - 1)); + DFSDM_FCR_IOSR(flo->iosr - 1)); if (ret) return ret; /* Filter order and Oversampling */ ret = regmap_update_bits(regmap, DFSDM_FCR(fl_id), DFSDM_FCR_FOSR_MASK, - DFSDM_FCR_FOSR(fl->fosr - 1)); + DFSDM_FCR_FOSR(flo->fosr - 1)); if (ret) return ret; @@ -417,6 +525,12 @@ static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc, if (ret) return ret; + ret = regmap_update_bits(regmap, DFSDM_CR1(fl_id), + DFSDM_CR1_FAST_MASK, + DFSDM_CR1_FAST(fl->fast)); + if (ret) + return ret; + /* * DFSDM modes configuration W.R.T audio/iio type modes * ---------------------------------------------------------------- @@ -563,7 +677,6 @@ static int dfsdm_adc_set_samp_freq(struct iio_dev *indio_dev, unsigned int spi_freq) { struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); - struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id]; unsigned int oversamp; int ret; @@ -573,11 +686,10 @@ static int dfsdm_adc_set_samp_freq(struct iio_dev *indio_dev, "Rate not accurate. requested (%u), actual (%u)\n", sample_freq, spi_freq / oversamp); - ret = stm32_dfsdm_set_osrs(fl, 0, oversamp); - if (ret < 0) { - dev_err(&indio_dev->dev, "No filter parameters that match!\n"); + ret = stm32_dfsdm_compute_all_osrs(indio_dev, oversamp); + if (ret < 0) return ret; - } + adc->sample_freq = spi_freq / oversamp; adc->oversamp = oversamp; @@ -623,6 +735,10 @@ static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc, struct regmap *regmap = adc->dfsdm->regmap; int ret; + ret = stm32_dfsdm_channels_configure(adc, adc->fl_id, trig); + if (ret < 0) + return ret; + ret = stm32_dfsdm_start_channel(adc); if (ret < 0) return ret; @@ -702,6 +818,30 @@ static unsigned int stm32_dfsdm_adc_dma_residue(struct stm32_dfsdm_adc *adc) return 0; } +static inline void stm32_dfsdm_process_data(struct stm32_dfsdm_adc *adc, + s32 *buffer) +{ + struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id]; + struct stm32_dfsdm_filter_osr *flo = &fl->flo[fl->fast]; + unsigned int i = adc->nconv; + s32 *ptr = buffer; + + while (i--) { + /* Mask 8 LSB that contains the channel ID */ + *ptr &= 0xFFFFFF00; + /* Convert 2^(n-1) sample to 2^(n-1)-1 to avoid wrap-around */ + if (*ptr > flo->max) + *ptr -= 1; + /* + * Samples from filter are retrieved with 23 bits resolution + * or less. Shift left to align MSB on 24 bits. + */ + *ptr <<= flo->lshift; + + ptr++; + } +} + static irqreturn_t stm32_dfsdm_adc_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; @@ -710,7 +850,9 @@ static irqreturn_t stm32_dfsdm_adc_trigger_handler(int irq, void *p) int available = stm32_dfsdm_adc_dma_residue(adc); while (available >= indio_dev->scan_bytes) { - u32 *buffer = (u32 *)&adc->rx_buf[adc->bufi]; + s32 *buffer = (s32 *)&adc->rx_buf[adc->bufi]; + + stm32_dfsdm_process_data(adc, buffer); iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp); @@ -751,10 +893,10 @@ static void stm32_dfsdm_dma_buffer_done(void *data) old_pos = adc->bufi; while (available >= indio_dev->scan_bytes) { - u32 *buffer = (u32 *)&adc->rx_buf[adc->bufi]; + s32 *buffer = (s32 *)&adc->rx_buf[adc->bufi]; + + stm32_dfsdm_process_data(adc, buffer); - /* Mask 8 LSB that contains the channel ID */ - *buffer = (*buffer & 0xFFFFFF00) << 8; available -= indio_dev->scan_bytes; adc->bufi += indio_dev->scan_bytes; if (adc->bufi >= adc->buf_sz) { @@ -776,6 +918,11 @@ static void stm32_dfsdm_dma_buffer_done(void *data) static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev) { struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); + /* + * The DFSDM supports half-word transfers. However, for 16 bits record, + * 4 bytes buswidth is kept, to avoid losing samples LSBs when left + * shift is required. + */ struct dma_slave_config config = { .src_addr = (dma_addr_t)adc->dfsdm->phys_base, .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, @@ -1068,7 +1215,6 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev, int val, int val2, long mask) { struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); - struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id]; struct stm32_dfsdm_channel *ch = &adc->dfsdm->ch_list[chan->channel]; unsigned int spi_freq; int ret = -EINVAL; @@ -1078,7 +1224,7 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev, ret = iio_device_claim_direct_mode(indio_dev); if (ret) return ret; - ret = stm32_dfsdm_set_osrs(fl, 0, val); + ret = stm32_dfsdm_compute_all_osrs(indio_dev, val); if (!ret) adc->oversamp = val; iio_device_release_direct_mode(indio_dev); @@ -1277,11 +1423,11 @@ static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev, BIT(IIO_CHAN_INFO_SAMP_FREQ); if (adc->dev_data->type == DFSDM_AUDIO) { - ch->scan_type.sign = 's'; ch->ext_info = dfsdm_adc_audio_ext_info; } else { - ch->scan_type.sign = 'u'; + ch->scan_type.shift = 8; } + ch->scan_type.sign = 's'; ch->scan_type.realbits = 24; ch->scan_type.storagebits = 32; @@ -1327,8 +1473,7 @@ static int stm32_dfsdm_adc_init(struct iio_dev *indio_dev) int ret, chan_idx; adc->oversamp = DFSDM_DEFAULT_OVERSAMPLING; - ret = stm32_dfsdm_set_osrs(&adc->dfsdm->fl_list[adc->fl_id], 0, - adc->oversamp); + ret = stm32_dfsdm_compute_all_osrs(indio_dev, adc->oversamp); if (ret < 0) return ret; @@ -1456,6 +1601,12 @@ static int stm32_dfsdm_adc_probe(struct platform_device *pdev) * So IRQ associated to filter instance 0 is dedicated to the Filter 0. */ irq = platform_get_irq(pdev, 0); + if (irq < 0) { + if (irq != -EPROBE_DEFER) + dev_err(dev, "Failed to get IRQ: %d\n", irq); + return irq; + } + ret = devm_request_irq(dev, irq, stm32_dfsdm_irq, 0, pdev->name, adc); if (ret < 0) { diff --git a/drivers/iio/adc/stm32-dfsdm-core.c b/drivers/iio/adc/stm32-dfsdm-core.c index 0a4d3746d21c..26e2011c5868 100644 --- a/drivers/iio/adc/stm32-dfsdm-core.c +++ b/drivers/iio/adc/stm32-dfsdm-core.c @@ -233,6 +233,8 @@ static int stm32_dfsdm_parse_of(struct platform_device *pdev, } priv->dfsdm.phys_base = res->start; priv->dfsdm.base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(priv->dfsdm.base)) + return PTR_ERR(priv->dfsdm.base); /* * "dfsdm" clock is mandatory for DFSDM peripheral clocking. @@ -242,8 +244,10 @@ static int stm32_dfsdm_parse_of(struct platform_device *pdev, */ priv->clk = devm_clk_get(&pdev->dev, "dfsdm"); if (IS_ERR(priv->clk)) { - dev_err(&pdev->dev, "No stm32_dfsdm_clk clock found\n"); - return -EINVAL; + ret = PTR_ERR(priv->clk); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "Failed to get clock (%d)\n", ret); + return ret; } priv->aclk = devm_clk_get(&pdev->dev, "audio"); diff --git a/drivers/iio/adc/stm32-dfsdm.h b/drivers/iio/adc/stm32-dfsdm.h index 8708394b0725..5dbdae4ed881 100644 --- a/drivers/iio/adc/stm32-dfsdm.h +++ b/drivers/iio/adc/stm32-dfsdm.h @@ -243,19 +243,33 @@ enum stm32_dfsdm_sinc_order { }; /** - * struct stm32_dfsdm_filter - structure relative to stm32 FDSDM filter + * struct stm32_dfsdm_filter_osr - DFSDM filter settings linked to oversampling * @iosr: integrator oversampling * @fosr: filter oversampling - * @ford: filter order + * @rshift: output sample right shift (hardware shift) + * @lshift: output sample left shift (software shift) * @res: output sample resolution + * @max: output sample maximum positive value + */ +struct stm32_dfsdm_filter_osr { + unsigned int iosr; + unsigned int fosr; + unsigned int rshift; + unsigned int lshift; + u64 res; + s32 max; +}; + +/** + * struct stm32_dfsdm_filter - structure relative to stm32 FDSDM filter + * @ford: filter order + * @flo: filter oversampling data table indexed by fast mode flag * @sync_mode: filter synchronized with filter 0 * @fast: filter fast mode */ struct stm32_dfsdm_filter { - unsigned int iosr; - unsigned int fosr; enum stm32_dfsdm_sinc_order ford; - u64 res; + struct stm32_dfsdm_filter_osr flo[2]; unsigned int sync_mode; unsigned int fast; }; diff --git a/drivers/iio/adc/stmpe-adc.c b/drivers/iio/adc/stmpe-adc.c index 7921f827c6ec..bd72727fc417 100644 --- a/drivers/iio/adc/stmpe-adc.c +++ b/drivers/iio/adc/stmpe-adc.c @@ -65,6 +65,8 @@ static int stmpe_read_voltage(struct stmpe_adc *info, mutex_lock(&info->lock); + reinit_completion(&info->completion); + info->channel = (u8)chan->channel; if (info->channel > STMPE_ADC_LAST_NR) { @@ -72,23 +74,16 @@ static int stmpe_read_voltage(struct stmpe_adc *info, return -EINVAL; } - stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_EN, - STMPE_ADC_CH(info->channel)); - stmpe_reg_write(info->stmpe, STMPE_REG_ADC_CAPT, STMPE_ADC_CH(info->channel)); - *val = info->value; - - ret = wait_for_completion_interruptible_timeout - (&info->completion, STMPE_ADC_TIMEOUT); + ret = wait_for_completion_timeout(&info->completion, STMPE_ADC_TIMEOUT); if (ret <= 0) { + stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_STA, + STMPE_ADC_CH(info->channel)); mutex_unlock(&info->lock); - if (ret == 0) - return -ETIMEDOUT; - else - return ret; + return -ETIMEDOUT; } *val = info->value; @@ -105,6 +100,8 @@ static int stmpe_read_temp(struct stmpe_adc *info, mutex_lock(&info->lock); + reinit_completion(&info->completion); + info->channel = (u8)chan->channel; if (info->channel != STMPE_TEMP_CHANNEL) { @@ -115,15 +112,11 @@ static int stmpe_read_temp(struct stmpe_adc *info, stmpe_reg_write(info->stmpe, STMPE_REG_TEMP_CTRL, STMPE_START_ONE_TEMP_CONV); - ret = wait_for_completion_interruptible_timeout - (&info->completion, STMPE_ADC_TIMEOUT); + ret = wait_for_completion_timeout(&info->completion, STMPE_ADC_TIMEOUT); if (ret <= 0) { mutex_unlock(&info->lock); - if (ret == 0) - return -ETIMEDOUT; - else - return ret; + return -ETIMEDOUT; } /* @@ -331,6 +324,12 @@ static int stmpe_adc_probe(struct platform_device *pdev) if (ret) return ret; + stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_EN, + ~(norequest_mask & 0xFF)); + + stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_STA, + ~(norequest_mask & 0xFF)); + return devm_iio_device_register(&pdev->dev, indio_dev); } @@ -353,9 +352,14 @@ static struct platform_driver stmpe_adc_driver = { .pm = &stmpe_adc_pm_ops, }, }; - module_platform_driver(stmpe_adc_driver); +static const struct of_device_id stmpe_adc_ids[] = { + { .compatible = "st,stmpe-adc", }, + { }, +}; +MODULE_DEVICE_TABLE(of, stmpe_adc_ids); + MODULE_AUTHOR("Stefan Agner <stefan.agner@toradex.com>"); MODULE_DESCRIPTION("STMPEXXX ADC driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index a09e7f5dd8f7..f13c6248a662 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0-only +// SPDX-License-Identifier: GPL-2.0 /* ADC driver for sunxi platforms' (A10, A13 and A31) GPADC * * Copyright (c) 2016 Quentin Schulz <quentin.schulz@free-electrons.com> |