Skip to content

Commit

Permalink
Merge tag 'iio-fixes-for-6.11a' of ssh://gitolite.kernel.org/pub/scm/…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
gregkh committed Sep 3, 2024
2 parents 47ac09b + 0a3b517 commit 8cbec53
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 60 deletions.
30 changes: 17 additions & 13 deletions drivers/iio/adc/ad7124.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down
13 changes: 5 additions & 8 deletions drivers/iio/adc/ad7173.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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 },
Expand Down
28 changes: 2 additions & 26 deletions drivers/iio/adc/ad7606.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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,
Expand Down Expand Up @@ -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);
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/iio/adc/ad7606.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
48 changes: 45 additions & 3 deletions drivers/iio/adc/ad7606_par.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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;
}

Expand All @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/iio/adc/ad_sigma_delta.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/iio/adc/ti-ads1119.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 3 additions & 1 deletion drivers/iio/buffer/industrialio-buffer-dmaengine.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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);
Expand Down
13 changes: 11 additions & 2 deletions drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
8 changes: 4 additions & 4 deletions drivers/iio/inkern.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion drivers/staging/iio/frequency/ad9834.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 8cbec53

Please sign in to comment.