mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-09 05:31:17 -04:00
Merge tag 'iio-fixes-for-6.17a' 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.17 Usual mixed bunch of ancient issues and relatively new ones. adi,ad7124 - Fix channel lookup to use chan->address for indexing array. adi,ad7173 - Stop accidentally enabling more configs than supported at one time. adi,ad7380 - Fill in missing max_conversion_rate_hz for adaq4381-4 ams,as73211 - Fix uninitialized holes in scan data exposed to userspace. bosch,bmp280 - Check for error when requesting optional GPIO rather than simply assuming success or a NULL return when no GPIO provided. invensense,icm42600 - Change error code returned to -EBUSY on a temperature read with neither accelerometer nor gyroscope in use. Reduces chance of misinterpretation by userspace. kionix,sca3300 - Fix uninitialized holes in scan data exposed to userspace. maxim,thermocouple - Use a DMA-safe buffer for spi_read(). renesas,isl29501 - Fix ordering issue for big endian systems renesas,rsg2l - Fix an underflow issue around suspend/resume. - Make sure driver data is in place before enabling runtime PM that uses it. rohm,bd79124 - Add missing GPIOLIB dependency. May rework in future to allow this to be optional in future but for now this is the least invasive build fix. * tag 'iio-fixes-for-6.17a' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/jic23/iio: iio: pressure: bmp280: Use IS_ERR() in bmp280_common_probe() iio: light: as73211: Ensure buffer holes are zeroed iio: adc: rzg2l_adc: Set driver data before enabling runtime PM iio: adc: rzg2l: Cleanup suspend/resume path iio: adc: ad7380: fix missing max_conversion_rate_hz on adaq4381-4 iio: adc: bd79124: Add GPIOLIB dependency iio: imu: inv_icm42600: change invalid data error to -EBUSY iio: adc: ad7124: fix channel lookup in syscalib functions iio: temperature: maxim_thermocouple: use DMA-safe buffer for spi_read() iio: adc: ad7173: prevent scan if too many setups requested iio: proximity: isl29501: fix buffered read on big-endian systems iio: accel: sca3300: fix uninitialized iio scan data
This commit is contained in:
@@ -477,7 +477,7 @@ static irqreturn_t sca3300_trigger_handler(int irq, void *p)
|
||||
struct iio_dev *indio_dev = pf->indio_dev;
|
||||
struct sca3300_data *data = iio_priv(indio_dev);
|
||||
int bit, ret, val, i = 0;
|
||||
IIO_DECLARE_BUFFER_WITH_TS(s16, channels, SCA3300_SCAN_MAX);
|
||||
IIO_DECLARE_BUFFER_WITH_TS(s16, channels, SCA3300_SCAN_MAX) = { };
|
||||
|
||||
iio_for_each_active_channel(indio_dev, bit) {
|
||||
ret = sca3300_read_reg(data, indio_dev->channels[bit].address, &val);
|
||||
|
||||
@@ -1300,7 +1300,7 @@ config RN5T618_ADC
|
||||
|
||||
config ROHM_BD79124
|
||||
tristate "Rohm BD79124 ADC driver"
|
||||
depends on I2C
|
||||
depends on I2C && GPIOLIB
|
||||
select REGMAP_I2C
|
||||
select IIO_ADC_HELPER
|
||||
help
|
||||
|
||||
@@ -849,7 +849,7 @@ enum {
|
||||
static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan_spec *chan)
|
||||
{
|
||||
struct device *dev = &st->sd.spi->dev;
|
||||
struct ad7124_channel *ch = &st->channels[chan->channel];
|
||||
struct ad7124_channel *ch = &st->channels[chan->address];
|
||||
int ret;
|
||||
|
||||
if (ch->syscalib_mode == AD7124_SYSCALIB_ZERO_SCALE) {
|
||||
@@ -865,8 +865,8 @@ static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dev_dbg(dev, "offset for channel %d after zero-scale calibration: 0x%x\n",
|
||||
chan->channel, ch->cfg.calibration_offset);
|
||||
dev_dbg(dev, "offset for channel %lu after zero-scale calibration: 0x%x\n",
|
||||
chan->address, ch->cfg.calibration_offset);
|
||||
} else {
|
||||
ch->cfg.calibration_gain = st->gain_default;
|
||||
|
||||
@@ -880,8 +880,8 @@ static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dev_dbg(dev, "gain for channel %d after full-scale calibration: 0x%x\n",
|
||||
chan->channel, ch->cfg.calibration_gain);
|
||||
dev_dbg(dev, "gain for channel %lu after full-scale calibration: 0x%x\n",
|
||||
chan->address, ch->cfg.calibration_gain);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -924,7 +924,7 @@ static int ad7124_set_syscalib_mode(struct iio_dev *indio_dev,
|
||||
{
|
||||
struct ad7124_state *st = iio_priv(indio_dev);
|
||||
|
||||
st->channels[chan->channel].syscalib_mode = mode;
|
||||
st->channels[chan->address].syscalib_mode = mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -934,7 +934,7 @@ static int ad7124_get_syscalib_mode(struct iio_dev *indio_dev,
|
||||
{
|
||||
struct ad7124_state *st = iio_priv(indio_dev);
|
||||
|
||||
return st->channels[chan->channel].syscalib_mode;
|
||||
return st->channels[chan->address].syscalib_mode;
|
||||
}
|
||||
|
||||
static const struct iio_enum ad7124_syscalib_mode_enum = {
|
||||
|
||||
@@ -200,7 +200,7 @@ struct ad7173_channel_config {
|
||||
/*
|
||||
* Following fields are used to compare equality. If you
|
||||
* make adaptations in it, you most likely also have to adapt
|
||||
* ad7173_find_live_config(), too.
|
||||
* ad7173_is_setup_equal(), too.
|
||||
*/
|
||||
struct_group(config_props,
|
||||
bool bipolar;
|
||||
@@ -561,12 +561,19 @@ static void ad7173_reset_usage_cnts(struct ad7173_state *st)
|
||||
st->config_usage_counter = 0;
|
||||
}
|
||||
|
||||
static struct ad7173_channel_config *
|
||||
ad7173_find_live_config(struct ad7173_state *st, struct ad7173_channel_config *cfg)
|
||||
/**
|
||||
* ad7173_is_setup_equal - Compare two channel setups
|
||||
* @cfg1: First channel configuration
|
||||
* @cfg2: Second channel configuration
|
||||
*
|
||||
* Compares all configuration options that affect the registers connected to
|
||||
* SETUP_SEL, namely CONFIGx, FILTERx, GAINx and OFFSETx.
|
||||
*
|
||||
* Returns: true if the setups are identical, false otherwise
|
||||
*/
|
||||
static bool ad7173_is_setup_equal(const struct ad7173_channel_config *cfg1,
|
||||
const struct ad7173_channel_config *cfg2)
|
||||
{
|
||||
struct ad7173_channel_config *cfg_aux;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* This is just to make sure that the comparison is adapted after
|
||||
* struct ad7173_channel_config was changed.
|
||||
@@ -579,14 +586,22 @@ ad7173_find_live_config(struct ad7173_state *st, struct ad7173_channel_config *c
|
||||
u8 ref_sel;
|
||||
}));
|
||||
|
||||
return cfg1->bipolar == cfg2->bipolar &&
|
||||
cfg1->input_buf == cfg2->input_buf &&
|
||||
cfg1->odr == cfg2->odr &&
|
||||
cfg1->ref_sel == cfg2->ref_sel;
|
||||
}
|
||||
|
||||
static struct ad7173_channel_config *
|
||||
ad7173_find_live_config(struct ad7173_state *st, struct ad7173_channel_config *cfg)
|
||||
{
|
||||
struct ad7173_channel_config *cfg_aux;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < st->num_channels; i++) {
|
||||
cfg_aux = &st->channels[i].cfg;
|
||||
|
||||
if (cfg_aux->live &&
|
||||
cfg->bipolar == cfg_aux->bipolar &&
|
||||
cfg->input_buf == cfg_aux->input_buf &&
|
||||
cfg->odr == cfg_aux->odr &&
|
||||
cfg->ref_sel == cfg_aux->ref_sel)
|
||||
if (cfg_aux->live && ad7173_is_setup_equal(cfg, cfg_aux))
|
||||
return cfg_aux;
|
||||
}
|
||||
return NULL;
|
||||
@@ -1228,7 +1243,7 @@ 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;
|
||||
int i, j, k, ret;
|
||||
|
||||
for (i = 0; i < indio_dev->num_channels; i++) {
|
||||
if (test_bit(i, scan_mask))
|
||||
@@ -1239,6 +1254,54 @@ static int ad7173_update_scan_mode(struct iio_dev *indio_dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* On some chips, there are more channels that setups, so if there were
|
||||
* more unique setups requested than the number of available slots,
|
||||
* ad7173_set_channel() will have written over some of the slots. We
|
||||
* can detect this by making sure each assigned cfg_slot matches the
|
||||
* requested configuration. If it doesn't, we know that the slot was
|
||||
* overwritten by a different channel.
|
||||
*/
|
||||
for_each_set_bit(i, scan_mask, indio_dev->num_channels) {
|
||||
const struct ad7173_channel_config *cfg1, *cfg2;
|
||||
|
||||
cfg1 = &st->channels[i].cfg;
|
||||
|
||||
for_each_set_bit(j, scan_mask, indio_dev->num_channels) {
|
||||
cfg2 = &st->channels[j].cfg;
|
||||
|
||||
/*
|
||||
* Only compare configs that are assigned to the same
|
||||
* SETUP_SEL slot and don't compare channel to itself.
|
||||
*/
|
||||
if (i == j || cfg1->cfg_slot != cfg2->cfg_slot)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If we find two different configs trying to use the
|
||||
* same SETUP_SEL slot, then we know that the that we
|
||||
* have too many unique configurations requested for
|
||||
* the available slots and at least one was overwritten.
|
||||
*/
|
||||
if (!ad7173_is_setup_equal(cfg1, cfg2)) {
|
||||
/*
|
||||
* At this point, there isn't a way to tell
|
||||
* which setups are actually programmed in the
|
||||
* ADC anymore, so we could read them back to
|
||||
* see, but it is simpler to just turn off all
|
||||
* of the live flags so that everything gets
|
||||
* reprogramed on the next attempt read a sample.
|
||||
*/
|
||||
for (k = 0; k < st->num_channels; k++)
|
||||
st->channels[k].cfg.live = false;
|
||||
|
||||
dev_err(&st->sd.spi->dev,
|
||||
"Too many unique channel configurations requested for scan\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -873,6 +873,7 @@ static const struct ad7380_chip_info adaq4381_4_chip_info = {
|
||||
.has_hardware_gain = true,
|
||||
.available_scan_masks = ad7380_4_channel_scan_masks,
|
||||
.timing_specs = &ad7380_4_timing,
|
||||
.max_conversion_rate_hz = 4 * MEGA,
|
||||
};
|
||||
|
||||
static const struct spi_offload_config ad7380_offload_config = {
|
||||
|
||||
@@ -89,7 +89,6 @@ struct rzg2l_adc {
|
||||
struct completion completion;
|
||||
struct mutex lock;
|
||||
u16 last_val[RZG2L_ADC_MAX_CHANNELS];
|
||||
bool was_rpm_active;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -428,6 +427,8 @@ static int rzg2l_adc_probe(struct platform_device *pdev)
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, indio_dev);
|
||||
|
||||
adc = iio_priv(indio_dev);
|
||||
|
||||
adc->hw_params = device_get_match_data(dev);
|
||||
@@ -460,8 +461,6 @@ static int rzg2l_adc_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, indio_dev);
|
||||
|
||||
ret = rzg2l_adc_hw_init(dev, adc);
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret,
|
||||
@@ -541,14 +540,9 @@ static int rzg2l_adc_suspend(struct device *dev)
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (pm_runtime_suspended(dev)) {
|
||||
adc->was_rpm_active = false;
|
||||
} else {
|
||||
ret = pm_runtime_force_suspend(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
adc->was_rpm_active = true;
|
||||
}
|
||||
ret = pm_runtime_force_suspend(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
|
||||
if (ret)
|
||||
@@ -557,9 +551,7 @@ static int rzg2l_adc_suspend(struct device *dev)
|
||||
return 0;
|
||||
|
||||
rpm_restore:
|
||||
if (adc->was_rpm_active)
|
||||
pm_runtime_force_resume(dev);
|
||||
|
||||
pm_runtime_force_resume(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -577,11 +569,9 @@ static int rzg2l_adc_resume(struct device *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (adc->was_rpm_active) {
|
||||
ret = pm_runtime_force_resume(dev);
|
||||
if (ret)
|
||||
goto resets_restore;
|
||||
}
|
||||
ret = pm_runtime_force_resume(dev);
|
||||
if (ret)
|
||||
goto resets_restore;
|
||||
|
||||
ret = rzg2l_adc_hw_init(dev, adc);
|
||||
if (ret)
|
||||
@@ -590,10 +580,7 @@ static int rzg2l_adc_resume(struct device *dev)
|
||||
return 0;
|
||||
|
||||
rpm_restore:
|
||||
if (adc->was_rpm_active) {
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
}
|
||||
pm_runtime_force_suspend(dev);
|
||||
resets_restore:
|
||||
reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
|
||||
return ret;
|
||||
|
||||
@@ -32,8 +32,12 @@ static int inv_icm42600_temp_read(struct inv_icm42600_state *st, s16 *temp)
|
||||
goto exit;
|
||||
|
||||
*temp = (s16)be16_to_cpup(raw);
|
||||
/*
|
||||
* Temperature data is invalid if both accel and gyro are off.
|
||||
* Return -EBUSY in this case.
|
||||
*/
|
||||
if (*temp == INV_ICM42600_DATA_INVALID)
|
||||
ret = -EINVAL;
|
||||
ret = -EBUSY;
|
||||
|
||||
exit:
|
||||
mutex_unlock(&st->lock);
|
||||
|
||||
@@ -639,7 +639,7 @@ static irqreturn_t as73211_trigger_handler(int irq __always_unused, void *p)
|
||||
struct {
|
||||
__le16 chan[4];
|
||||
aligned_s64 ts;
|
||||
} scan;
|
||||
} scan = { };
|
||||
int data_result, ret;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
|
||||
@@ -3213,11 +3213,12 @@ int bmp280_common_probe(struct device *dev,
|
||||
|
||||
/* Bring chip out of reset if there is an assigned GPIO line */
|
||||
gpiod = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(gpiod))
|
||||
return dev_err_probe(dev, PTR_ERR(gpiod), "failed to get reset GPIO\n");
|
||||
|
||||
/* Deassert the signal */
|
||||
if (gpiod) {
|
||||
dev_info(dev, "release reset\n");
|
||||
gpiod_set_value(gpiod, 0);
|
||||
}
|
||||
dev_info(dev, "release reset\n");
|
||||
gpiod_set_value(gpiod, 0);
|
||||
|
||||
data->regmap = regmap;
|
||||
|
||||
|
||||
@@ -938,12 +938,18 @@ static irqreturn_t isl29501_trigger_handler(int irq, void *p)
|
||||
struct iio_dev *indio_dev = pf->indio_dev;
|
||||
struct isl29501_private *isl29501 = iio_priv(indio_dev);
|
||||
const unsigned long *active_mask = indio_dev->active_scan_mask;
|
||||
u32 buffer[4] __aligned(8) = {}; /* 1x16-bit + naturally aligned ts */
|
||||
u32 value;
|
||||
struct {
|
||||
u16 data;
|
||||
aligned_s64 ts;
|
||||
} scan = { };
|
||||
|
||||
if (test_bit(ISL29501_DISTANCE_SCAN_INDEX, active_mask))
|
||||
isl29501_register_read(isl29501, REG_DISTANCE, buffer);
|
||||
if (test_bit(ISL29501_DISTANCE_SCAN_INDEX, active_mask)) {
|
||||
isl29501_register_read(isl29501, REG_DISTANCE, &value);
|
||||
scan.data = value;
|
||||
}
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp);
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &scan, pf->timestamp);
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/trigger.h>
|
||||
@@ -121,8 +122,15 @@ struct maxim_thermocouple_data {
|
||||
struct spi_device *spi;
|
||||
const struct maxim_thermocouple_chip *chip;
|
||||
char tc_type;
|
||||
|
||||
u8 buffer[16] __aligned(IIO_DMA_MINALIGN);
|
||||
/* Buffer for reading up to 2 hardware channels. */
|
||||
struct {
|
||||
union {
|
||||
__be16 raw16;
|
||||
__be32 raw32;
|
||||
__be16 raw[2];
|
||||
};
|
||||
aligned_s64 timestamp;
|
||||
} buffer __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
static int maxim_thermocouple_read(struct maxim_thermocouple_data *data,
|
||||
@@ -130,18 +138,16 @@ static int maxim_thermocouple_read(struct maxim_thermocouple_data *data,
|
||||
{
|
||||
unsigned int storage_bytes = data->chip->read_size;
|
||||
unsigned int shift = chan->scan_type.shift + (chan->address * 8);
|
||||
__be16 buf16;
|
||||
__be32 buf32;
|
||||
int ret;
|
||||
|
||||
switch (storage_bytes) {
|
||||
case 2:
|
||||
ret = spi_read(data->spi, (void *)&buf16, storage_bytes);
|
||||
*val = be16_to_cpu(buf16);
|
||||
ret = spi_read(data->spi, &data->buffer.raw16, storage_bytes);
|
||||
*val = be16_to_cpu(data->buffer.raw16);
|
||||
break;
|
||||
case 4:
|
||||
ret = spi_read(data->spi, (void *)&buf32, storage_bytes);
|
||||
*val = be32_to_cpu(buf32);
|
||||
ret = spi_read(data->spi, &data->buffer.raw32, storage_bytes);
|
||||
*val = be32_to_cpu(data->buffer.raw32);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
@@ -166,9 +172,9 @@ static irqreturn_t maxim_thermocouple_trigger_handler(int irq, void *private)
|
||||
struct maxim_thermocouple_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
ret = spi_read(data->spi, data->buffer, data->chip->read_size);
|
||||
ret = spi_read(data->spi, data->buffer.raw, data->chip->read_size);
|
||||
if (!ret) {
|
||||
iio_push_to_buffers_with_ts(indio_dev, data->buffer,
|
||||
iio_push_to_buffers_with_ts(indio_dev, &data->buffer,
|
||||
sizeof(data->buffer),
|
||||
iio_get_time_ns(indio_dev));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user