Commit 8cbec539 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'iio-fixes-for-6.11a' of...

Merge tag 'iio-fixes-for-6.11a' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/jic23/iio into char-misc-linus

Jonathan writes:

IIO: 1st set of fixes for 6.11

The usual mixed bag of new issues and ancient ones.
The fact so many are ADI is probably due to an uptick in upstreaming
effort from Analog + Baylibre  meaning existing code is getting more eyes
on it. Hence it's a good sign not a reflection of inherent high bug
incidence!

Core and helper related
-----------------------

in kernel interfaces
- Fix missing application of scale to the integer part of
  IIO_INT_PLUS_XXX value pairs when using the
  iio_convert_raw_to_processed*() helper.
buffer-dmaengine
- Make sure to release DMA channel in error path.

Driver related
--------------

adi,ad-sigma-delta library
- Check irq-flags for the correct irq if multiple are provided.
adi,ad7124
- Wait after reset before reading the chip ID register.
- Compare only the relevant field when looking for an existing
  config to reuse for a new channel.
- Fix an off by one in which channel config is being filled from
  firmware.
adi,ad7173
- Fix missing vendor prefix in compatible strings.
- Fix wrong info for GPIO related bit positions for ad4114,ad4115 and ad4116.
adi,ad7606
- Drop incorrect check on frstdata when in serial mode, it only applies to
  parallel mode.
adi,ad9834
- Check userspace input for frequency parameter to avoid div by zero.
invensense,mpu6050
- Avoid reading interrupt status on some older chips as it seems there
  is a hardware problem that surfaces as a result of adding wake on
  motion support to the driver (which these chips don't support).
ti,ads1119
- Fix incorrect IRQ flag (new driver so no firmware compatibility regression
  issues with fixing this now).

* tag 'iio-fixes-for-6.11a' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/jic23/iio:
  iio: imu: inv_mpu6050: fix interrupt status read for old buggy chips
  iio: adc: ad7173: fix GPIO device info
  iio: adc: ad7124: fix DT configuration parsing
  iio: adc: ad_sigma_delta: fix irq_flags on irq request
  iio: adc: ads1119: Fix IRQ flags
  iio: fix scale application in iio_convert_raw_to_processed_unlocked
  iio: adc: ad7124: fix config comparison
  iio: adc: ad7124: fix chip ID mismatch
  iio: adc: ad7173: Fix incorrect compatible string
  iio: buffer-dmaengine: fix releasing dma channel on error
  iio: adc: ad7606: remove frstdata check for serial mode
  staging: iio: frequency: ad9834: Validate frequency parameter value
parents 47ac09b9 0a3b517c
......@@ -147,15 +147,18 @@ struct ad7124_chip_info {
struct ad7124_channel_config {
bool live;
unsigned int cfg_slot;
enum ad7124_ref_sel refsel;
bool bipolar;
bool buf_positive;
bool buf_negative;
unsigned int vref_mv;
unsigned int pga_bits;
unsigned int odr;
unsigned int odr_sel_bits;
unsigned int filter_type;
/* Following fields are used to compare equality. */
struct_group(config_props,
enum ad7124_ref_sel refsel;
bool bipolar;
bool buf_positive;
bool buf_negative;
unsigned int vref_mv;
unsigned int pga_bits;
unsigned int odr;
unsigned int odr_sel_bits;
unsigned int filter_type;
);
};
struct ad7124_channel {
......@@ -334,11 +337,12 @@ static struct ad7124_channel_config *ad7124_find_similar_live_cfg(struct ad7124_
ptrdiff_t cmp_size;
int i;
cmp_size = (u8 *)&cfg->live - (u8 *)cfg;
cmp_size = sizeof_field(struct ad7124_channel_config, config_props);
for (i = 0; i < st->num_channels; i++) {
cfg_aux = &st->channels[i].cfg;
if (cfg_aux->live && !memcmp(cfg, cfg_aux, cmp_size))
if (cfg_aux->live &&
!memcmp(&cfg->config_props, &cfg_aux->config_props, cmp_size))
return cfg_aux;
}
......@@ -764,6 +768,7 @@ static int ad7124_soft_reset(struct ad7124_state *st)
if (ret < 0)
return ret;
fsleep(200);
timeout = 100;
do {
ret = ad_sd_read_reg(&st->sd, AD7124_STATUS, 1, &readval);
......@@ -839,8 +844,6 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev,
st->channels = channels;
device_for_each_child_node_scoped(dev, child) {
cfg = &st->channels[channel].cfg;
ret = fwnode_property_read_u32(child, "reg", &channel);
if (ret)
return ret;
......@@ -858,6 +861,7 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev,
st->channels[channel].ain = AD7124_CHANNEL_AINP(ain[0]) |
AD7124_CHANNEL_AINM(ain[1]);
cfg = &st->channels[channel].cfg;
cfg->bipolar = fwnode_property_read_bool(child, "bipolar");
ret = fwnode_property_read_u32(child, "adi,reference-select", &tmp);
......
......@@ -302,7 +302,6 @@ static const struct ad7173_device_info ad4114_device_info = {
.num_configs = 8,
.num_voltage_in = 16,
.num_gpios = 4,
.higher_gpio_bits = true,
.has_vincom_input = true,
.has_temp = true,
.has_input_buf = true,
......@@ -320,7 +319,6 @@ static const struct ad7173_device_info ad4115_device_info = {
.num_configs = 8,
.num_voltage_in = 16,
.num_gpios = 4,
.higher_gpio_bits = true,
.has_vincom_input = true,
.has_temp = true,
.has_input_buf = true,
......@@ -338,7 +336,6 @@ static const struct ad7173_device_info ad4116_device_info = {
.num_configs = 8,
.num_voltage_in = 16,
.num_gpios = 4,
.higher_gpio_bits = true,
.has_vincom_input = true,
.has_temp = true,
.has_input_buf = true,
......@@ -1435,11 +1432,11 @@ static int ad7173_probe(struct spi_device *spi)
}
static const struct of_device_id ad7173_of_match[] = {
{ .compatible = "ad4111", .data = &ad4111_device_info },
{ .compatible = "ad4112", .data = &ad4112_device_info },
{ .compatible = "ad4114", .data = &ad4114_device_info },
{ .compatible = "ad4115", .data = &ad4115_device_info },
{ .compatible = "ad4116", .data = &ad4116_device_info },
{ .compatible = "adi,ad4111", .data = &ad4111_device_info },
{ .compatible = "adi,ad4112", .data = &ad4112_device_info },
{ .compatible = "adi,ad4114", .data = &ad4114_device_info },
{ .compatible = "adi,ad4115", .data = &ad4115_device_info },
{ .compatible = "adi,ad4116", .data = &ad4116_device_info },
{ .compatible = "adi,ad7172-2", .data = &ad7172_2_device_info },
{ .compatible = "adi,ad7172-4", .data = &ad7172_4_device_info },
{ .compatible = "adi,ad7173-8", .data = &ad7173_8_device_info },
......
......@@ -49,7 +49,7 @@ static const unsigned int ad7616_oversampling_avail[8] = {
1, 2, 4, 8, 16, 32, 64, 128,
};
static int ad7606_reset(struct ad7606_state *st)
int ad7606_reset(struct ad7606_state *st)
{
if (st->gpio_reset) {
gpiod_set_value(st->gpio_reset, 1);
......@@ -60,6 +60,7 @@ static int ad7606_reset(struct ad7606_state *st)
return -ENODEV;
}
EXPORT_SYMBOL_NS_GPL(ad7606_reset, IIO_AD7606);
static int ad7606_reg_access(struct iio_dev *indio_dev,
unsigned int reg,
......@@ -88,31 +89,6 @@ static int ad7606_read_samples(struct ad7606_state *st)
{
unsigned int num = st->chip_info->num_channels - 1;
u16 *data = st->data;
int ret;
/*
* The frstdata signal is set to high while and after reading the sample
* of the first channel and low for all other channels. This can be used
* to check that the incoming data is correctly aligned. During normal
* operation the data should never become unaligned, but some glitch or
* electrostatic discharge might cause an extra read or clock cycle.
* Monitoring the frstdata signal allows to recover from such failure
* situations.
*/
if (st->gpio_frstdata) {
ret = st->bops->read_block(st->dev, 1, data);
if (ret)
return ret;
if (!gpiod_get_value(st->gpio_frstdata)) {
ad7606_reset(st);
return -EIO;
}
data++;
num--;
}
return st->bops->read_block(st->dev, num, data);
}
......
......@@ -151,6 +151,8 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
const char *name, unsigned int id,
const struct ad7606_bus_ops *bops);
int ad7606_reset(struct ad7606_state *st);
enum ad7606_supported_device_ids {
ID_AD7605_4,
ID_AD7606_8,
......
......@@ -7,6 +7,7 @@
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include <linux/err.h>
......@@ -21,8 +22,29 @@ static int ad7606_par16_read_block(struct device *dev,
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ad7606_state *st = iio_priv(indio_dev);
insw((unsigned long)st->base_address, buf, count);
/*
* On the parallel interface, the frstdata signal is set to high while
* and after reading the sample of the first channel and low for all
* other channels. This can be used to check that the incoming data is
* correctly aligned. During normal operation the data should never
* become unaligned, but some glitch or electrostatic discharge might
* cause an extra read or clock cycle. Monitoring the frstdata signal
* allows to recover from such failure situations.
*/
int num = count;
u16 *_buf = buf;
if (st->gpio_frstdata) {
insw((unsigned long)st->base_address, _buf, 1);
if (!gpiod_get_value(st->gpio_frstdata)) {
ad7606_reset(st);
return -EIO;
}
_buf++;
num--;
}
insw((unsigned long)st->base_address, _buf, num);
return 0;
}
......@@ -35,8 +57,28 @@ static int ad7606_par8_read_block(struct device *dev,
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct ad7606_state *st = iio_priv(indio_dev);
insb((unsigned long)st->base_address, buf, count * 2);
/*
* On the parallel interface, the frstdata signal is set to high while
* and after reading the sample of the first channel and low for all
* other channels. This can be used to check that the incoming data is
* correctly aligned. During normal operation the data should never
* become unaligned, but some glitch or electrostatic discharge might
* cause an extra read or clock cycle. Monitoring the frstdata signal
* allows to recover from such failure situations.
*/
int num = count;
u16 *_buf = buf;
if (st->gpio_frstdata) {
insb((unsigned long)st->base_address, _buf, 2);
if (!gpiod_get_value(st->gpio_frstdata)) {
ad7606_reset(st);
return -EIO;
}
_buf++;
num--;
}
insb((unsigned long)st->base_address, _buf, num * 2);
return 0;
}
......
......@@ -569,7 +569,7 @@ EXPORT_SYMBOL_NS_GPL(ad_sd_validate_trigger, IIO_AD_SIGMA_DELTA);
static int devm_ad_sd_probe_trigger(struct device *dev, struct iio_dev *indio_dev)
{
struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
unsigned long irq_flags = irq_get_trigger_type(sigma_delta->spi->irq);
unsigned long irq_flags = irq_get_trigger_type(sigma_delta->irq_line);
int ret;
if (dev != &sigma_delta->spi->dev) {
......
......@@ -735,7 +735,7 @@ static int ads1119_probe(struct i2c_client *client)
if (client->irq > 0) {
ret = devm_request_threaded_irq(dev, client->irq,
ads1119_irq_handler,
NULL, IRQF_TRIGGER_FALLING,
NULL, IRQF_ONESHOT,
"ads1119", indio_dev);
if (ret)
return dev_err_probe(dev, ret,
......
......@@ -237,7 +237,7 @@ static struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev,
ret = dma_get_slave_caps(chan, &caps);
if (ret < 0)
goto err_free;
goto err_release;
/* Needs to be aligned to the maximum of the minimums */
if (caps.src_addr_widths)
......@@ -263,6 +263,8 @@ static struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev,
return &dmaengine_buffer->queue.buffer;
err_release:
dma_release_channel(chan);
err_free:
kfree(dmaengine_buffer);
return ERR_PTR(ret);
......
......@@ -248,12 +248,20 @@ static irqreturn_t inv_mpu6050_interrupt_handle(int irq, void *p)
int result;
switch (st->chip_type) {
case INV_MPU6000:
case INV_MPU6050:
case INV_MPU9150:
/*
* WoM is not supported and interrupt status read seems to be broken for
* some chips. Since data ready is the only interrupt, bypass interrupt
* status read and always assert data ready bit.
*/
wom_bits = 0;
int_status = INV_MPU6050_BIT_RAW_DATA_RDY_INT;
goto data_ready_interrupt;
case INV_MPU6500:
case INV_MPU6515:
case INV_MPU6880:
case INV_MPU6000:
case INV_MPU9150:
case INV_MPU9250:
case INV_MPU9255:
wom_bits = INV_MPU6500_BIT_WOM_INT;
......@@ -279,6 +287,7 @@ static irqreturn_t inv_mpu6050_interrupt_handle(int irq, void *p)
}
}
data_ready_interrupt:
/* handle raw data interrupt */
if (int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT) {
indio_dev->pollfunc->timestamp = st->it_timestamp;
......
......@@ -647,17 +647,17 @@ static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan,
break;
case IIO_VAL_INT_PLUS_MICRO:
if (scale_val2 < 0)
*processed = -raw64 * scale_val;
*processed = -raw64 * scale_val * scale;
else
*processed = raw64 * scale_val;
*processed = raw64 * scale_val * scale;
*processed += div_s64(raw64 * (s64)scale_val2 * scale,
1000000LL);
break;
case IIO_VAL_INT_PLUS_NANO:
if (scale_val2 < 0)
*processed = -raw64 * scale_val;
*processed = -raw64 * scale_val * scale;
else
*processed = raw64 * scale_val;
*processed = raw64 * scale_val * scale;
*processed += div_s64(raw64 * (s64)scale_val2 * scale,
1000000000LL);
break;
......
......@@ -114,7 +114,7 @@ static int ad9834_write_frequency(struct ad9834_state *st,
clk_freq = clk_get_rate(st->mclk);
if (fout > (clk_freq / 2))
if (!clk_freq || fout > (clk_freq / 2))
return -EINVAL;
regval = ad9834_calc_freqreg(clk_freq, fout);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment