diff options
Diffstat (limited to 'drivers/iio')
415 files changed, 7427 insertions, 3042 deletions
diff --git a/drivers/iio/accel/adxl345.h b/drivers/iio/accel/adxl345.h index bc6d634bd85c..7d482dd595fa 100644 --- a/drivers/iio/accel/adxl345.h +++ b/drivers/iio/accel/adxl345.h @@ -111,6 +111,10 @@ */ #define ADXL375_USCALE 480000 +struct regmap; + +bool adxl345_is_volatile_reg(struct device *dev, unsigned int reg); + struct adxl345_chip_info { const char *name; int uscale; diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index 375c27d16827..2e5fdd479e8d 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -8,6 +8,7 @@ */ #include <linux/bitfield.h> +#include <linux/bitops.h> #include <linux/interrupt.h> #include <linux/module.h> #include <linux/property.h> @@ -17,6 +18,7 @@ #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> #include <linux/iio/buffer.h> +#include <linux/iio/events.h> #include <linux/iio/kfifo_buf.h> #include "adxl345.h" @@ -31,18 +33,71 @@ #define ADXL345_INT1 0 #define ADXL345_INT2 1 +#define ADXL345_REG_TAP_AXIS_MSK GENMASK(2, 0) +#define ADXL345_REG_TAP_SUPPRESS_MSK BIT(3) +#define ADXL345_REG_TAP_SUPPRESS BIT(3) + +#define ADXL345_TAP_Z_EN BIT(0) +#define ADXL345_TAP_Y_EN BIT(1) +#define ADXL345_TAP_X_EN BIT(2) + +/* single/double tap */ +enum adxl345_tap_type { + ADXL345_SINGLE_TAP, + ADXL345_DOUBLE_TAP, +}; + +static const unsigned int adxl345_tap_int_reg[] = { + [ADXL345_SINGLE_TAP] = ADXL345_INT_SINGLE_TAP, + [ADXL345_DOUBLE_TAP] = ADXL345_INT_DOUBLE_TAP, +}; + +enum adxl345_tap_time_type { + ADXL345_TAP_TIME_LATENT, + ADXL345_TAP_TIME_WINDOW, + ADXL345_TAP_TIME_DUR, +}; + +static const unsigned int adxl345_tap_time_reg[] = { + [ADXL345_TAP_TIME_LATENT] = ADXL345_REG_LATENT, + [ADXL345_TAP_TIME_WINDOW] = ADXL345_REG_WINDOW, + [ADXL345_TAP_TIME_DUR] = ADXL345_REG_DUR, +}; + struct adxl345_state { const struct adxl345_chip_info *info; struct regmap *regmap; bool fifo_delay; /* delay: delay is needed for SPI */ int irq; - u8 intio; - u8 int_map; u8 watermark; u8 fifo_mode; + + u32 tap_duration_us; + u32 tap_latent_us; + u32 tap_window_us; + __le16 fifo_buf[ADXL345_DIRS * ADXL345_FIFO_SIZE + 1] __aligned(IIO_DMA_MINALIGN); }; +static struct iio_event_spec adxl345_events[] = { + { + /* single tap */ + .type = IIO_EV_TYPE_GESTURE, + .dir = IIO_EV_DIR_SINGLETAP, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_TIMEOUT), + }, + { + /* double tap */ + .type = IIO_EV_TYPE_GESTURE, + .dir = IIO_EV_DIR_DOUBLETAP, + .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_RESET_TIMEOUT) | + BIT(IIO_EV_INFO_TAP2_MIN_DELAY), + }, +}; + #define ADXL345_CHANNEL(index, reg, axis) { \ .type = IIO_ACCEL, \ .modified = 1, \ @@ -59,6 +114,8 @@ struct adxl345_state { .storagebits = 16, \ .endianness = IIO_LE, \ }, \ + .event_spec = adxl345_events, \ + .num_event_specs = ARRAY_SIZE(adxl345_events), \ } enum adxl345_chans { @@ -76,6 +133,25 @@ static const unsigned long adxl345_scan_masks[] = { 0 }; +bool adxl345_is_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ADXL345_REG_DATA_AXIS(0): + case ADXL345_REG_DATA_AXIS(1): + case ADXL345_REG_DATA_AXIS(2): + case ADXL345_REG_DATA_AXIS(3): + case ADXL345_REG_DATA_AXIS(4): + case ADXL345_REG_DATA_AXIS(5): + case ADXL345_REG_ACT_TAP_STATUS: + case ADXL345_REG_FIFO_STATUS: + case ADXL345_REG_INT_SOURCE: + return true; + default: + return false; + } +} +EXPORT_SYMBOL_NS_GPL(adxl345_is_volatile_reg, "IIO_ADXL345"); + /** * adxl345_set_measure_en() - Enable and disable measuring. * @@ -96,24 +172,215 @@ static int adxl345_set_measure_en(struct adxl345_state *st, bool en) return regmap_write(st->regmap, ADXL345_REG_POWER_CTL, val); } -static int adxl345_set_interrupts(struct adxl345_state *st) +/* tap */ + +static int _adxl345_set_tap_int(struct adxl345_state *st, + enum adxl345_tap_type type, bool state) { + unsigned int int_map = 0x00; + unsigned int tap_threshold; + bool axis_valid; + bool singletap_args_valid = false; + bool doubletap_args_valid = false; + bool en = false; + u32 axis_ctrl; int ret; - unsigned int int_enable = st->int_map; - unsigned int int_map; + + ret = regmap_read(st->regmap, ADXL345_REG_TAP_AXIS, &axis_ctrl); + if (ret) + return ret; + + axis_valid = FIELD_GET(ADXL345_REG_TAP_AXIS_MSK, axis_ctrl) > 0; + + ret = regmap_read(st->regmap, ADXL345_REG_THRESH_TAP, &tap_threshold); + if (ret) + return ret; /* - * Any bits set to 0 in the INT map register send their respective - * interrupts to the INT1 pin, whereas bits set to 1 send their respective - * interrupts to the INT2 pin. The intio shall convert this accordingly. + * Note: A value of 0 for threshold and/or dur may result in undesirable + * behavior if single tap/double tap interrupts are enabled. */ - int_map = st->intio ? st->int_map : ~st->int_map; + singletap_args_valid = tap_threshold > 0 && st->tap_duration_us > 0; - ret = regmap_write(st->regmap, ADXL345_REG_INT_MAP, int_map); + if (type == ADXL345_SINGLE_TAP) { + en = axis_valid && singletap_args_valid; + } else { + /* doubletap: Window must be equal or greater than latent! */ + doubletap_args_valid = st->tap_latent_us > 0 && + st->tap_window_us > 0 && + st->tap_window_us >= st->tap_latent_us; + + en = axis_valid && singletap_args_valid && doubletap_args_valid; + } + + if (state && en) + int_map |= adxl345_tap_int_reg[type]; + + return regmap_update_bits(st->regmap, ADXL345_REG_INT_ENABLE, + adxl345_tap_int_reg[type], int_map); +} + +static int adxl345_is_tap_en(struct adxl345_state *st, + enum iio_modifier axis, + enum adxl345_tap_type type, bool *en) +{ + unsigned int regval; + u32 axis_ctrl; + int ret; + + ret = regmap_read(st->regmap, ADXL345_REG_TAP_AXIS, &axis_ctrl); if (ret) return ret; - return regmap_write(st->regmap, ADXL345_REG_INT_ENABLE, int_enable); + /* Verify if axis is enabled for the tap detection. */ + switch (axis) { + case IIO_MOD_X: + *en = FIELD_GET(ADXL345_TAP_X_EN, axis_ctrl); + break; + case IIO_MOD_Y: + *en = FIELD_GET(ADXL345_TAP_Y_EN, axis_ctrl); + break; + case IIO_MOD_Z: + *en = FIELD_GET(ADXL345_TAP_Z_EN, axis_ctrl); + break; + default: + *en = false; + return -EINVAL; + } + + if (*en) { + /* + * If axis allow for tap detection, verify if the interrupt is + * enabled for tap detection. + */ + ret = regmap_read(st->regmap, ADXL345_REG_INT_ENABLE, ®val); + if (ret) + return ret; + + *en = adxl345_tap_int_reg[type] & regval; + } + + return 0; +} + +static int adxl345_set_singletap_en(struct adxl345_state *st, + enum iio_modifier axis, bool en) +{ + int ret; + u32 axis_ctrl; + + switch (axis) { + case IIO_MOD_X: + axis_ctrl = ADXL345_TAP_X_EN; + break; + case IIO_MOD_Y: + axis_ctrl = ADXL345_TAP_Y_EN; + break; + case IIO_MOD_Z: + axis_ctrl = ADXL345_TAP_Z_EN; + break; + default: + return -EINVAL; + } + + if (en) + ret = regmap_set_bits(st->regmap, ADXL345_REG_TAP_AXIS, + axis_ctrl); + else + ret = regmap_clear_bits(st->regmap, ADXL345_REG_TAP_AXIS, + axis_ctrl); + if (ret) + return ret; + + return _adxl345_set_tap_int(st, ADXL345_SINGLE_TAP, en); +} + +static int adxl345_set_doubletap_en(struct adxl345_state *st, bool en) +{ + int ret; + + /* + * Generally suppress detection of spikes during the latency period as + * double taps here, this is fully optional for double tap detection + */ + ret = regmap_update_bits(st->regmap, ADXL345_REG_TAP_AXIS, + ADXL345_REG_TAP_SUPPRESS_MSK, + en ? ADXL345_REG_TAP_SUPPRESS : 0x00); + if (ret) + return ret; + + return _adxl345_set_tap_int(st, ADXL345_DOUBLE_TAP, en); +} + +static int _adxl345_set_tap_time(struct adxl345_state *st, + enum adxl345_tap_time_type type, u32 val_us) +{ + unsigned int regval; + + switch (type) { + case ADXL345_TAP_TIME_WINDOW: + st->tap_window_us = val_us; + break; + case ADXL345_TAP_TIME_LATENT: + st->tap_latent_us = val_us; + break; + case ADXL345_TAP_TIME_DUR: + st->tap_duration_us = val_us; + break; + } + + /* + * The scale factor is 1250us / LSB for tap_window_us and tap_latent_us. + * For tap_duration_us the scale factor is 625us / LSB. + */ + if (type == ADXL345_TAP_TIME_DUR) + regval = DIV_ROUND_CLOSEST(val_us, 625); + else + regval = DIV_ROUND_CLOSEST(val_us, 1250); + + return regmap_write(st->regmap, adxl345_tap_time_reg[type], regval); +} + +static int adxl345_set_tap_duration(struct adxl345_state *st, u32 val_int, + u32 val_fract_us) +{ + /* + * Max value is 255 * 625 us = 0.159375 seconds + * + * Note: the scaling is similar to the scaling in the ADXL380 + */ + if (val_int || val_fract_us > 159375) + return -EINVAL; + + return _adxl345_set_tap_time(st, ADXL345_TAP_TIME_DUR, val_fract_us); +} + +static int adxl345_set_tap_window(struct adxl345_state *st, u32 val_int, + u32 val_fract_us) +{ + /* + * Max value is 255 * 1250 us = 0.318750 seconds + * + * Note: the scaling is similar to the scaling in the ADXL380 + */ + if (val_int || val_fract_us > 318750) + return -EINVAL; + + return _adxl345_set_tap_time(st, ADXL345_TAP_TIME_WINDOW, val_fract_us); +} + +static int adxl345_set_tap_latent(struct adxl345_state *st, u32 val_int, + u32 val_fract_us) +{ + /* + * Max value is 255 * 1250 us = 0.318750 seconds + * + * Note: the scaling is similar to the scaling in the ADXL380 + */ + if (val_int || val_fract_us > 318750) + return -EINVAL; + + return _adxl345_set_tap_time(st, ADXL345_TAP_TIME_LATENT, val_fract_us); } static int adxl345_read_raw(struct iio_dev *indio_dev, @@ -136,7 +403,7 @@ static int adxl345_read_raw(struct iio_dev *indio_dev, ret = regmap_bulk_read(st->regmap, ADXL345_REG_DATA_AXIS(chan->address), &accel, sizeof(accel)); - if (ret < 0) + if (ret) return ret; *val = sign_extend32(le16_to_cpu(accel), 12); @@ -148,7 +415,7 @@ static int adxl345_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_CALIBBIAS: ret = regmap_read(st->regmap, ADXL345_REG_OFS_AXIS(chan->address), ®val); - if (ret < 0) + if (ret) return ret; /* * 8-bit resolution at +/- 2g, that is 4x accel data scale @@ -159,7 +426,7 @@ static int adxl345_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case IIO_CHAN_INFO_SAMP_FREQ: ret = regmap_read(st->regmap, ADXL345_REG_BW_RATE, ®val); - if (ret < 0) + if (ret) return ret; samp_freq_nhz = ADXL345_BASE_RATE_NANO_HZ << @@ -201,6 +468,157 @@ static int adxl345_write_raw(struct iio_dev *indio_dev, return -EINVAL; } +static int adxl345_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct adxl345_state *st = iio_priv(indio_dev); + bool int_en; + int ret; + + switch (type) { + case IIO_EV_TYPE_GESTURE: + switch (dir) { + case IIO_EV_DIR_SINGLETAP: + ret = adxl345_is_tap_en(st, chan->channel2, + ADXL345_SINGLE_TAP, &int_en); + if (ret) + return ret; + return int_en; + case IIO_EV_DIR_DOUBLETAP: + ret = adxl345_is_tap_en(st, chan->channel2, + ADXL345_DOUBLE_TAP, &int_en); + if (ret) + return ret; + return int_en; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int adxl345_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + bool state) +{ + struct adxl345_state *st = iio_priv(indio_dev); + + switch (type) { + case IIO_EV_TYPE_GESTURE: + switch (dir) { + case IIO_EV_DIR_SINGLETAP: + return adxl345_set_singletap_en(st, chan->channel2, state); + case IIO_EV_DIR_DOUBLETAP: + return adxl345_set_doubletap_en(st, state); + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int adxl345_read_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) +{ + struct adxl345_state *st = iio_priv(indio_dev); + unsigned int tap_threshold; + int ret; + + switch (type) { + case IIO_EV_TYPE_GESTURE: + switch (info) { + case IIO_EV_INFO_VALUE: + /* + * The scale factor would be 62.5mg/LSB (i.e. 0xFF = 16g) but + * not applied here. In context of this general purpose sensor, + * what imports is rather signal intensity than the absolute + * measured g value. + */ + ret = regmap_read(st->regmap, ADXL345_REG_THRESH_TAP, + &tap_threshold); + if (ret) + return ret; + *val = sign_extend32(tap_threshold, 7); + return IIO_VAL_INT; + case IIO_EV_INFO_TIMEOUT: + *val = st->tap_duration_us; + *val2 = 1000000; + return IIO_VAL_FRACTIONAL; + case IIO_EV_INFO_RESET_TIMEOUT: + *val = st->tap_window_us; + *val2 = 1000000; + return IIO_VAL_FRACTIONAL; + case IIO_EV_INFO_TAP2_MIN_DELAY: + *val = st->tap_latent_us; + *val2 = 1000000; + return IIO_VAL_FRACTIONAL; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int adxl345_write_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) +{ + struct adxl345_state *st = iio_priv(indio_dev); + int ret; + + ret = adxl345_set_measure_en(st, false); + if (ret) + return ret; + + switch (type) { + case IIO_EV_TYPE_GESTURE: + switch (info) { + case IIO_EV_INFO_VALUE: + ret = regmap_write(st->regmap, ADXL345_REG_THRESH_TAP, + min(val, 0xFF)); + if (ret) + return ret; + break; + case IIO_EV_INFO_TIMEOUT: + ret = adxl345_set_tap_duration(st, val, val2); + if (ret) + return ret; + break; + case IIO_EV_INFO_RESET_TIMEOUT: + ret = adxl345_set_tap_window(st, val, val2); + if (ret) + return ret; + break; + case IIO_EV_INFO_TAP2_MIN_DELAY: + ret = adxl345_set_tap_latent(st, val, val2); + if (ret) + return ret; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + return adxl345_set_measure_en(st, true); +} + static int adxl345_reg_access(struct iio_dev *indio_dev, unsigned int reg, unsigned int writeval, unsigned int *readval) { @@ -214,7 +632,7 @@ static int adxl345_reg_access(struct iio_dev *indio_dev, unsigned int reg, static int adxl345_set_watermark(struct iio_dev *indio_dev, unsigned int value) { struct adxl345_state *st = iio_priv(indio_dev); - unsigned int fifo_mask = 0x1F; + const unsigned int fifo_mask = 0x1F, watermark_mask = 0x02; int ret; value = min(value, ADXL345_FIFO_SIZE - 1); @@ -224,9 +642,8 @@ static int adxl345_set_watermark(struct iio_dev *indio_dev, unsigned int value) return ret; st->watermark = value; - st->int_map |= ADXL345_INT_WATERMARK; - - return 0; + return regmap_update_bits(st->regmap, ADXL345_REG_INT_ENABLE, + watermark_mask, ADXL345_INT_WATERMARK); } static int adxl345_write_raw_get_fmt(struct iio_dev *indio_dev, @@ -265,21 +682,25 @@ static const struct attribute_group adxl345_attrs_group = { static int adxl345_set_fifo(struct adxl345_state *st) { + unsigned int intio; int ret; /* FIFO should only be configured while in standby mode */ ret = adxl345_set_measure_en(st, false); - if (ret < 0) + if (ret) + return ret; + + ret = regmap_read(st->regmap, ADXL345_REG_INT_MAP, &intio); + if (ret) return ret; ret = regmap_write(st->regmap, ADXL345_REG_FIFO_CTL, FIELD_PREP(ADXL345_FIFO_CTL_SAMPLES_MSK, st->watermark) | - FIELD_PREP(ADXL345_FIFO_CTL_TRIGGER_MSK, - st->intio) | + FIELD_PREP(ADXL345_FIFO_CTL_TRIGGER_MSK, intio) | FIELD_PREP(ADXL345_FIFO_CTL_MODE_MSK, st->fifo_mode)); - if (ret < 0) + if (ret) return ret; return adxl345_set_measure_en(st, true); @@ -300,7 +721,7 @@ static int adxl345_get_samples(struct adxl345_state *st) int ret; ret = regmap_read(st->regmap, ADXL345_REG_FIFO_STATUS, ®val); - if (ret < 0) + if (ret) return ret; return FIELD_GET(ADXL345_REG_FIFO_STATUS_MSK, regval); @@ -328,7 +749,7 @@ static int adxl345_fifo_transfer(struct adxl345_state *st, int samples) /* read 3x 2 byte elements from base address into next fifo_buf position */ ret = regmap_bulk_read(st->regmap, ADXL345_REG_XYZ_BASE, st->fifo_buf + (i * count / 2), count); - if (ret < 0) + if (ret) return ret; /* @@ -374,11 +795,6 @@ static void adxl345_fifo_reset(struct adxl345_state *st) static int adxl345_buffer_postenable(struct iio_dev *indio_dev) { struct adxl345_state *st = iio_priv(indio_dev); - int ret; - - ret = adxl345_set_interrupts(st); - if (ret < 0) - return ret; st->fifo_mode = ADXL345_FIFO_STREAM; return adxl345_set_fifo(st); @@ -391,11 +807,10 @@ static int adxl345_buffer_predisable(struct iio_dev *indio_dev) st->fifo_mode = ADXL345_FIFO_BYPASS; ret = adxl345_set_fifo(st); - if (ret < 0) + if (ret) return ret; - st->int_map = 0x00; - return adxl345_set_interrupts(st); + return regmap_write(st->regmap, ADXL345_REG_INT_ENABLE, 0x00); } static const struct iio_buffer_setup_ops adxl345_buffer_ops = { @@ -422,6 +837,48 @@ static int adxl345_fifo_push(struct iio_dev *indio_dev, return 0; } +static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat, + enum iio_modifier tap_dir) +{ + s64 ts = iio_get_time_ns(indio_dev); + struct adxl345_state *st = iio_priv(indio_dev); + int samples; + int ret = -ENOENT; + + if (FIELD_GET(ADXL345_INT_SINGLE_TAP, int_stat)) { + ret = iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, tap_dir, + IIO_EV_TYPE_GESTURE, + IIO_EV_DIR_SINGLETAP), + ts); + if (ret) + return ret; + } + + if (FIELD_GET(ADXL345_INT_DOUBLE_TAP, int_stat)) { + ret = iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, tap_dir, + IIO_EV_TYPE_GESTURE, + IIO_EV_DIR_DOUBLETAP), + ts); + if (ret) + return ret; + } + + if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) { + samples = adxl345_get_samples(st); + if (samples < 0) + return -EINVAL; + + if (adxl345_fifo_push(indio_dev, samples) < 0) + return -EINVAL; + + ret = 0; + } + + return ret; +} + /** * adxl345_irq_handler() - Handle irqs of the ADXL345. * @irq: The irq being handled. @@ -433,21 +890,35 @@ static irqreturn_t adxl345_irq_handler(int irq, void *p) { struct iio_dev *indio_dev = p; struct adxl345_state *st = iio_priv(indio_dev); + unsigned int regval; + enum iio_modifier tap_dir = IIO_NO_MOD; + u32 axis_ctrl; int int_stat; - int samples; + int ret; - if (regmap_read(st->regmap, ADXL345_REG_INT_SOURCE, &int_stat)) + ret = regmap_read(st->regmap, ADXL345_REG_TAP_AXIS, &axis_ctrl); + if (ret) return IRQ_NONE; - if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) { - samples = adxl345_get_samples(st); - if (samples < 0) - goto err; - - if (adxl345_fifo_push(indio_dev, samples) < 0) - goto err; + if (FIELD_GET(ADXL345_REG_TAP_AXIS_MSK, axis_ctrl)) { + ret = regmap_read(st->regmap, ADXL345_REG_ACT_TAP_STATUS, ®val); + if (ret) + return IRQ_NONE; + + if (FIELD_GET(ADXL345_TAP_Z_EN, regval)) + tap_dir = IIO_MOD_Z; + else if (FIELD_GET(ADXL345_TAP_Y_EN, regval)) + tap_dir = IIO_MOD_Y; + else if (FIELD_GET(ADXL345_TAP_X_EN, regval)) + tap_dir = IIO_MOD_X; } + if (regmap_read(st->regmap, ADXL345_REG_INT_SOURCE, &int_stat)) + return IRQ_NONE; + + if (adxl345_push_event(indio_dev, int_stat, tap_dir)) + goto err; + if (FIELD_GET(ADXL345_INT_OVERRUN, int_stat)) goto err; @@ -464,6 +935,10 @@ static const struct iio_info adxl345_info = { .read_raw = adxl345_read_raw, .write_raw = adxl345_write_raw, .write_raw_get_fmt = adxl345_write_raw_get_fmt, + .read_event_config = adxl345_read_event_config, + .write_event_config = adxl345_write_event_config, + .read_event_value = adxl345_read_event_value, + .write_event_value = adxl345_write_event_value, .debugfs_reg_access = &adxl345_reg_access, .hwfifo_set_watermark = adxl345_set_watermark, }; @@ -492,10 +967,12 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, struct adxl345_state *st; struct iio_dev *indio_dev; u32 regval; + u8 intio = ADXL345_INT1; unsigned int data_format_mask = (ADXL345_DATA_FORMAT_RANGE | ADXL345_DATA_FORMAT_JUSTIFY | ADXL345_DATA_FORMAT_FULL_RES | ADXL345_DATA_FORMAT_SELF_TEST); + unsigned int tap_threshold; int ret; indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); @@ -509,6 +986,12 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, return -ENODEV; st->fifo_delay = fifo_delay_default; + /* Init with reasonable values */ + tap_threshold = 48; /* 48 [0x30] -> ~3g */ + st->tap_duration_us = 16; /* 16 [0x10] -> .010 */ + st->tap_window_us = 64; /* 64 [0x40] -> .080 */ + st->tap_latent_us = 16; /* 16 [0x10] -> .020 */ + indio_dev->name = st->info->name; indio_dev->info = &adxl345_info; indio_dev->modes = INDIO_DIRECT_MODE; @@ -516,6 +999,11 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, indio_dev->num_channels = ARRAY_SIZE(adxl345_channels); indio_dev->available_scan_masks = adxl345_scan_masks; + /* Reset interrupts at start up */ + ret = regmap_write(st->regmap, ADXL345_REG_INT_ENABLE, 0x00); + if (ret) + return ret; + if (setup) { /* Perform optional initial bus specific configuration */ ret = setup(dev, st->regmap); @@ -540,7 +1028,7 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, } ret = regmap_read(st->regmap, ADXL345_REG_DEVID, ®val); - if (ret < 0) + if (ret) return dev_err_probe(dev, ret, "Error reading device ID\n"); if (regval != ADXL345_DEVID) @@ -549,23 +1037,37 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, /* Enable measurement mode */ ret = adxl345_set_measure_en(st, true); - if (ret < 0) + if (ret) return dev_err_probe(dev, ret, "Failed to enable measurement mode\n"); ret = devm_add_action_or_reset(dev, adxl345_powerdown, st); - if (ret < 0) + if (ret) return ret; - st->intio = ADXL345_INT1; st->irq = fwnode_irq_get_byname(dev_fwnode(dev), "INT1"); if (st->irq < 0) { - st->intio = ADXL345_INT2; + intio = ADXL345_INT2; st->irq = fwnode_irq_get_byname(dev_fwnode(dev), "INT2"); if (st->irq < 0) - st->intio = ADXL345_INT_NONE; + intio = ADXL345_INT_NONE; } - if (st->intio != ADXL345_INT_NONE) { + if (intio != ADXL345_INT_NONE) { + /* + * Any bits set to 0 in the INT map register send their respective + * interrupts to the INT1 pin, whereas bits set to 1 send their respective + * interrupts to the INT2 pin. The intio shall convert this accordingly. + */ + regval = intio ? 0xff : 0; + + ret = regmap_write(st->regmap, ADXL345_REG_INT_MAP, regval); + if (ret) + return ret; + + ret = regmap_write(st->regmap, ADXL345_REG_THRESH_TAP, tap_threshold); + if (ret) + return ret; + /* FIFO_STREAM mode is going to be activated later */ ret = devm_iio_kfifo_buffer_setup(dev, indio_dev, &adxl345_buffer_ops); if (ret) @@ -581,7 +1083,7 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, ret = regmap_write(st->regmap, ADXL345_REG_FIFO_CTL, FIELD_PREP(ADXL345_FIFO_CTL_MODE_MSK, ADXL345_FIFO_BYPASS)); - if (ret < 0) + if (ret) return ret; } diff --git a/drivers/iio/accel/adxl345_i2c.c b/drivers/iio/accel/adxl345_i2c.c index 8c385dd6c01d..af84c0043c6c 100644 --- a/drivers/iio/accel/adxl345_i2c.c +++ b/drivers/iio/accel/adxl345_i2c.c @@ -17,6 +17,8 @@ static const struct regmap_config adxl345_i2c_regmap_config = { .reg_bits = 8, .val_bits = 8, + .volatile_reg = adxl345_is_volatile_reg, + .cache_type = REGCACHE_MAPLE, }; static int adxl345_i2c_probe(struct i2c_client *client) diff --git a/drivers/iio/accel/adxl345_spi.c b/drivers/iio/accel/adxl345_spi.c index 7e518aea17bf..0315f4bfd69a 100644 --- a/drivers/iio/accel/adxl345_spi.c +++ b/drivers/iio/accel/adxl345_spi.c @@ -19,6 +19,8 @@ static const struct regmap_config adxl345_spi_regmap_config = { .val_bits = 8, /* Setting bits 7 and 6 enables multiple-byte read */ .read_flag_mask = BIT(7) | BIT(6), + .volatile_reg = adxl345_is_volatile_reg, + .cache_type = REGCACHE_MAPLE, }; static int adxl345_spi_setup(struct device *dev, struct regmap *regmap) diff --git a/drivers/iio/accel/adxl355_core.c b/drivers/iio/accel/adxl355_core.c index cbac622ef821..2e00fd51b4d5 100644 --- a/drivers/iio/accel/adxl355_core.c +++ b/drivers/iio/accel/adxl355_core.c @@ -666,8 +666,8 @@ static irqreturn_t adxl355_trigger_handler(int irq, void *p) if (ret) goto out_unlock_notify; - iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer, - pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &data->buffer, + sizeof(data->buffer), pf->timestamp); out_unlock_notify: mutex_unlock(&data->lock); diff --git a/drivers/iio/accel/adxl367_i2c.c b/drivers/iio/accel/adxl367_i2c.c index 80f0b642b9b0..1c7d2eb054a2 100644 --- a/drivers/iio/accel/adxl367_i2c.c +++ b/drivers/iio/accel/adxl367_i2c.c @@ -68,7 +68,7 @@ MODULE_DEVICE_TABLE(i2c, adxl367_i2c_id); static const struct of_device_id adxl367_of_match[] = { { .compatible = "adi,adxl367" }, - { }, + { } }; MODULE_DEVICE_TABLE(of, adxl367_of_match); diff --git a/drivers/iio/accel/adxl367_spi.c b/drivers/iio/accel/adxl367_spi.c index 49d7c8fbe8ed..3fed56bb9054 100644 --- a/drivers/iio/accel/adxl367_spi.c +++ b/drivers/iio/accel/adxl367_spi.c @@ -139,13 +139,13 @@ static int adxl367_spi_probe(struct spi_device *spi) static const struct spi_device_id adxl367_spi_id[] = { { "adxl367", 0 }, - { }, + { } }; MODULE_DEVICE_TABLE(spi, adxl367_spi_id); static const struct of_device_id adxl367_of_match[] = { { .compatible = "adi,adxl367" }, - { }, + { } }; MODULE_DEVICE_TABLE(of, adxl367_of_match); diff --git a/drivers/iio/accel/adxl372_i2c.c b/drivers/iio/accel/adxl372_i2c.c index 43d5fd921be7..186d4fe9a556 100644 --- a/drivers/iio/accel/adxl372_i2c.c +++ b/drivers/iio/accel/adxl372_i2c.c @@ -43,7 +43,7 @@ static int adxl372_i2c_probe(struct i2c_client *client) static const struct i2c_device_id adxl372_i2c_id[] = { { "adxl372" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, adxl372_i2c_id); diff --git a/drivers/iio/accel/adxl372_spi.c b/drivers/iio/accel/adxl372_spi.c index 1ab1997a55b1..39941b519c3b 100644 --- a/drivers/iio/accel/adxl372_spi.c +++ b/drivers/iio/accel/adxl372_spi.c @@ -34,7 +34,7 @@ static int adxl372_spi_probe(struct spi_device *spi) static const struct spi_device_id adxl372_spi_id[] = { { "adxl372", 0 }, - {} + { } }; MODULE_DEVICE_TABLE(spi, adxl372_spi_id); diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index aa664a923f91..93a868678722 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -887,7 +887,7 @@ static irqreturn_t bma180_trigger_handler(int irq, void *p) mutex_unlock(&data->mutex); - iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, time_ns); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), time_ns); err: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c index 96ba028157ee..38f7498431ee 100644 --- a/drivers/iio/accel/bma220_spi.c +++ b/drivers/iio/accel/bma220_spi.c @@ -103,8 +103,8 @@ static irqreturn_t bma220_trigger_handler(int irq, void *p) if (ret < 0) goto err; - iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, - pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), + pf->timestamp); err: mutex_unlock(&data->lock); iio_trigger_notify_done(indio_dev->trig); @@ -307,12 +307,12 @@ static DEFINE_SIMPLE_DEV_PM_OPS(bma220_pm_ops, bma220_suspend, bma220_resume); static const struct spi_device_id bma220_spi_id[] = { {"bma220", 0}, - {} + { } }; static const struct acpi_device_id bma220_acpi_id[] = { {"BMA0220", 0}, - {} + { } }; MODULE_DEVICE_TABLE(spi, bma220_spi_id); diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c index 23f5e1ce9cc4..85e23badf733 100644 --- a/drivers/iio/accel/bma400_core.c +++ b/drivers/iio/accel/bma400_core.c @@ -1591,8 +1591,9 @@ static irqreturn_t bma400_trigger_handler(int irq, void *p) data->buffer.temperature = temp; } - iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &data->buffer, + sizeof(data->buffer), + iio_get_time_ns(indio_dev)); mutex_unlock(&data->mutex); iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/accel/bmc150-accel-i2c.c b/drivers/iio/accel/bmc150-accel-i2c.c index 0d4ce6c38931..b4604f441553 100644 --- a/drivers/iio/accel/bmc150-accel-i2c.c +++ b/drivers/iio/accel/bmc150-accel-i2c.c @@ -240,7 +240,7 @@ static const struct acpi_device_id bmc150_accel_acpi_match[] = { {"BOSC0200"}, {"BSBA0150"}, {"DUAL250E"}, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match); @@ -255,7 +255,7 @@ static const struct i2c_device_id bmc150_accel_id[] = { {"bmc150_accel"}, {"bmc156_accel", BOSCH_BMC156}, {"bmi055_accel"}, - {} + { } }; MODULE_DEVICE_TABLE(i2c, bmc150_accel_id); @@ -271,7 +271,7 @@ static const struct of_device_id bmc150_accel_of_match[] = { { .compatible = "bosch,bmc150_accel" }, { .compatible = "bosch,bmc156_accel" }, { .compatible = "bosch,bmi055_accel" }, - { }, + { } }; MODULE_DEVICE_TABLE(of, bmc150_accel_of_match); diff --git a/drivers/iio/accel/bmc150-accel-spi.c b/drivers/iio/accel/bmc150-accel-spi.c index 70b3642656ab..26ce50b37716 100644 --- a/drivers/iio/accel/bmc150-accel-spi.c +++ b/drivers/iio/accel/bmc150-accel-spi.c @@ -48,7 +48,7 @@ static const struct acpi_device_id bmc150_accel_acpi_match[] = { {"BMC150A"}, {"BMI055A"}, {"BSBA0150"}, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match); @@ -62,7 +62,7 @@ static const struct spi_device_id bmc150_accel_id[] = { {"bmc150_accel"}, {"bmc156_accel", BOSCH_BMC156}, {"bmi055_accel"}, - {} + { } }; MODULE_DEVICE_TABLE(spi, bmc150_accel_id); diff --git a/drivers/iio/accel/bmi088-accel-i2c.c b/drivers/iio/accel/bmi088-accel-i2c.c index bd22bd0d3c25..310f863029bb 100644 --- a/drivers/iio/accel/bmi088-accel-i2c.c +++ b/drivers/iio/accel/bmi088-accel-i2c.c @@ -40,7 +40,7 @@ static const struct of_device_id bmi088_of_match[] = { { .compatible = "bosch,bmi085-accel" }, { .compatible = "bosch,bmi088-accel" }, { .compatible = "bosch,bmi090l-accel" }, - {} + { } }; MODULE_DEVICE_TABLE(of, bmi088_of_match); @@ -48,7 +48,7 @@ static const struct i2c_device_id bmi088_accel_id[] = { { "bmi085-accel", BOSCH_BMI085 }, { "bmi088-accel", BOSCH_BMI088 }, { "bmi090l-accel", BOSCH_BMI090L }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, bmi088_accel_id); diff --git a/drivers/iio/accel/bmi088-accel-spi.c b/drivers/iio/accel/bmi088-accel-spi.c index c9d51a74c07f..44cb50c76cb1 100644 --- a/drivers/iio/accel/bmi088-accel-spi.c +++ b/drivers/iio/accel/bmi088-accel-spi.c @@ -67,7 +67,7 @@ static const struct of_device_id bmi088_of_match[] = { { .compatible = "bosch,bmi085-accel" }, { .compatible = "bosch,bmi088-accel" }, { .compatible = "bosch,bmi090l-accel" }, - {} + { } }; MODULE_DEVICE_TABLE(of, bmi088_of_match); @@ -75,7 +75,7 @@ static const struct spi_device_id bmi088_accel_id[] = { {"bmi085-accel", BOSCH_BMI085}, {"bmi088-accel", BOSCH_BMI088}, {"bmi090l-accel", BOSCH_BMI090L}, - {} + { } }; MODULE_DEVICE_TABLE(spi, bmi088_accel_id); diff --git a/drivers/iio/accel/da280.c b/drivers/iio/accel/da280.c index 992286828844..c2dd123b9021 100644 --- a/drivers/iio/accel/da280.c +++ b/drivers/iio/accel/da280.c @@ -157,7 +157,7 @@ static const struct da280_match_data da280_match_data = { "da280", 3 }; static const struct acpi_device_id da280_acpi_match[] = { { "NSA2513", (kernel_ulong_t)&da217_match_data }, { "MIRAACC", (kernel_ulong_t)&da280_match_data }, - {} + { } }; MODULE_DEVICE_TABLE(acpi, da280_acpi_match); @@ -165,7 +165,7 @@ static const struct i2c_device_id da280_i2c_id[] = { { "da217", (kernel_ulong_t)&da217_match_data }, { "da226", (kernel_ulong_t)&da226_match_data }, { "da280", (kernel_ulong_t)&da280_match_data }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, da280_i2c_id); diff --git a/drivers/iio/accel/da311.c b/drivers/iio/accel/da311.c index 94f827acdd1c..e1df7b009d89 100644 --- a/drivers/iio/accel/da311.c +++ b/drivers/iio/accel/da311.c @@ -269,7 +269,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(da311_pm_ops, da311_suspend, da311_resume); static const struct i2c_device_id da311_i2c_id[] = { { "da311" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, da311_i2c_id); diff --git a/drivers/iio/accel/dmard10.c b/drivers/iio/accel/dmard10.c index 35c0eefb741e..71cd1928baa6 100644 --- a/drivers/iio/accel/dmard10.c +++ b/drivers/iio/accel/dmard10.c @@ -232,7 +232,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(dmard10_pm_ops, dmard10_suspend, static const struct i2c_device_id dmard10_i2c_id[] = { { "dmard10" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, dmard10_i2c_id); diff --git a/drivers/iio/accel/fxls8962af-core.c b/drivers/iio/accel/fxls8962af-core.c index bf1d3923a181..12598feaa693 100644 --- a/drivers/iio/accel/fxls8962af-core.c +++ b/drivers/iio/accel/fxls8962af-core.c @@ -23,6 +23,7 @@ #include <linux/regulator/consumer.h> #include <linux/regmap.h> #include <linux/types.h> +#include <linux/units.h> #include <linux/iio/buffer.h> #include <linux/iio/events.h> @@ -439,8 +440,16 @@ static int fxls8962af_read_raw(struct iio_dev *indio_dev, *val = FXLS8962AF_TEMP_CENTER_VAL; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - *val = 0; - return fxls8962af_read_full_scale(data, val2); + switch (chan->type) { + case IIO_TEMP: + *val = MILLIDEGREE_PER_DEGREE; + return IIO_VAL_INT; + case IIO_ACCEL: + *val = 0; + return fxls8962af_read_full_scale(data, val2); + default: + return -EINVAL; + } case IIO_CHAN_INFO_SAMP_FREQ: return fxls8962af_read_samp_freq(data, val, val2); default: @@ -736,9 +745,11 @@ static const struct iio_event_spec fxls8962af_event[] = { .type = IIO_TEMP, \ .address = FXLS8962AF_TEMP_OUT, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_OFFSET),\ .scan_index = -1, \ .scan_type = { \ + .sign = 's', \ .realbits = 8, \ .storagebits = 8, \ }, \ @@ -983,8 +994,8 @@ static int fxls8962af_fifo_flush(struct iio_dev *indio_dev) sizeof(data->scan.channels[0])); } - iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, - tstamp); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, + sizeof(data->scan), tstamp); tstamp += sample_period; } diff --git a/drivers/iio/accel/fxls8962af-i2c.c b/drivers/iio/accel/fxls8962af-i2c.c index 1b9156b6b2e3..106198a12474 100644 --- a/drivers/iio/accel/fxls8962af-i2c.c +++ b/drivers/iio/accel/fxls8962af-i2c.c @@ -32,14 +32,14 @@ static const struct i2c_device_id fxls8962af_id[] = { { "fxls8964af", fxls8964af }, { "fxls8967af", fxls8967af }, { "fxls8974cf", fxls8974cf }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, fxls8962af_id); static const struct of_device_id fxls8962af_of_match[] = { { .compatible = "nxp,fxls8962af" }, { .compatible = "nxp,fxls8964af" }, - {} + { } }; MODULE_DEVICE_TABLE(of, fxls8962af_of_match); diff --git a/drivers/iio/accel/fxls8962af-spi.c b/drivers/iio/accel/fxls8962af-spi.c index 46fc6e002714..bdafd1f615d9 100644 --- a/drivers/iio/accel/fxls8962af-spi.c +++ b/drivers/iio/accel/fxls8962af-spi.c @@ -30,14 +30,14 @@ static int fxls8962af_probe(struct spi_device *spi) static const struct of_device_id fxls8962af_spi_of_match[] = { { .compatible = "nxp,fxls8962af" }, { .compatible = "nxp,fxls8964af" }, - {} + { } }; MODULE_DEVICE_TABLE(of, fxls8962af_spi_of_match); static const struct spi_device_id fxls8962af_spi_id_table[] = { { "fxls8962af", fxls8962af }, { "fxls8964af", fxls8964af }, - {} + { } }; MODULE_DEVICE_TABLE(spi, fxls8962af_spi_id_table); diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c index 078fab2abb68..2ff591b3458f 100644 --- a/drivers/iio/accel/hid-sensor-accel-3d.c +++ b/drivers/iio/accel/hid-sensor-accel-3d.c @@ -228,7 +228,7 @@ static void hid_sensor_push_data(struct iio_dev *indio_dev, void *data, int len, int64_t timestamp) { dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); - iio_push_to_buffers_with_timestamp(indio_dev, data, timestamp); + iio_push_to_buffers_with_ts(indio_dev, data, len, timestamp); } /* Callback handler to send event after all samples are received and captured */ @@ -440,7 +440,7 @@ static const struct platform_device_id hid_accel_3d_ids[] = { { /* gravity sensor */ .name = "HID-SENSOR-20007b", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(platform, hid_accel_3d_ids); diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index f2496cad8ec2..910d7b5716e1 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -674,8 +674,8 @@ static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data) return 0; } -static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data, - bool status) +static int kxcjk1013_setup_interrupt(struct kxcjk1013_data *data, + bool status, bool is_new_data) { const struct kx_chipset_regs *regs = data->info->regs; int ret; @@ -690,69 +690,12 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data, if (ret < 0) return ret; - ret = kxcjk1013_chip_update_thresholds(data); - if (ret < 0) - return ret; - - ret = i2c_smbus_read_byte_data(data->client, regs->int_ctrl1); - if (ret < 0) { - dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); - return ret; - } - - if (status) - ret |= KXCJK1013_REG_INT_CTRL1_BIT_IEN; - else - ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN; - - ret = i2c_smbus_write_byte_data(data->client, regs->int_ctrl1, ret); - if (ret < 0) { - dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); - return ret; - } - - ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1); - if (ret < 0) { - dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); - return ret; - } - - if (status) - ret |= KXCJK1013_REG_CTRL1_BIT_WUFE; - else - ret &= ~KXCJK1013_REG_CTRL1_BIT_WUFE; - - ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret); - if (ret < 0) { - dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); - return ret; - } - - if (store_mode == OPERATION) { - ret = kxcjk1013_set_mode(data, OPERATION); + if (is_new_data == true) { + ret = kxcjk1013_chip_update_thresholds(data); if (ret < 0) return ret; } - return 0; -} - -static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data, - bool status) -{ - const struct kx_chipset_regs *regs = data->info->regs; - int ret; - enum kxcjk1013_mode store_mode; - - ret = kxcjk1013_get_mode(data, &store_mode); - if (ret < 0) - return ret; - - /* This is requirement by spec to change state to STANDBY */ - ret = kxcjk1013_set_mode(data, STANDBY); - if (ret < 0) - return ret; - ret = i2c_smbus_read_byte_data(data->client, regs->int_ctrl1); if (ret < 0) { dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n"); @@ -776,10 +719,17 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data, return ret; } - if (status) - ret |= KXCJK1013_REG_CTRL1_BIT_DRDY; - else - ret &= ~KXCJK1013_REG_CTRL1_BIT_DRDY; + if (is_new_data) { + if (status) + ret |= KXCJK1013_REG_CTRL1_BIT_DRDY; + else + ret &= ~KXCJK1013_REG_CTRL1_BIT_DRDY; + } else { + if (status) + ret |= KXCJK1013_REG_CTRL1_BIT_WUFE; + else + ret &= ~KXCJK1013_REG_CTRL1_BIT_WUFE; + } ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret); if (ret < 0) { @@ -1112,7 +1062,7 @@ static int kxcjk1013_write_event_config(struct iio_dev *indio_dev, return ret; } - ret = kxcjk1013_setup_any_motion_interrupt(data, state); + ret = kxcjk1013_setup_interrupt(data, state, false); if (ret < 0) { kxcjk1013_set_power_state(data, false); data->ev_enable_state = 0; @@ -1253,8 +1203,8 @@ static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p) if (ret < 0) goto err; - iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, - data->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), + data->timestamp); err: iio_trigger_notify_done(indio_dev->trig); @@ -1293,10 +1243,7 @@ static int kxcjk1013_data_rdy_trigger_set_state(struct iio_trigger *trig, mutex_unlock(&data->mutex); return ret; } - if (data->motion_trig == trig) - ret = kxcjk1013_setup_any_motion_interrupt(data, state); - else - ret = kxcjk1013_setup_new_data_interrupt(data, state); + ret = kxcjk1013_setup_interrupt(data, state, data->motion_trig != trig); if (ret < 0) { kxcjk1013_set_power_state(data, false); mutex_unlock(&data->mutex); diff --git a/drivers/iio/accel/kxsd9-i2c.c b/drivers/iio/accel/kxsd9-i2c.c index 3857d2edf250..1fa88b99149e 100644 --- a/drivers/iio/accel/kxsd9-i2c.c +++ b/drivers/iio/accel/kxsd9-i2c.c @@ -38,7 +38,7 @@ static void kxsd9_i2c_remove(struct i2c_client *client) static const struct of_device_id kxsd9_of_match[] = { { .compatible = "kionix,kxsd9", }, - { }, + { } }; MODULE_DEVICE_TABLE(of, kxsd9_of_match); diff --git a/drivers/iio/accel/kxsd9-spi.c b/drivers/iio/accel/kxsd9-spi.c index a05f4467d94a..cbb6c6412665 100644 --- a/drivers/iio/accel/kxsd9-spi.c +++ b/drivers/iio/accel/kxsd9-spi.c @@ -38,7 +38,7 @@ static void kxsd9_spi_remove(struct spi_device *spi) static const struct spi_device_id kxsd9_spi_id[] = { {"kxsd9", 0}, - { }, + { } }; MODULE_DEVICE_TABLE(spi, kxsd9_spi_id); diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c index 0ededf8cfdca..cfc31265cdd0 100644 --- a/drivers/iio/accel/kxsd9.c +++ b/drivers/iio/accel/kxsd9.c @@ -229,9 +229,8 @@ static irqreturn_t kxsd9_trigger_handler(int irq, void *p) goto out; } - iio_push_to_buffers_with_timestamp(indio_dev, - &hw_values, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &hw_values, sizeof(hw_values), + iio_get_time_ns(indio_dev)); out: iio_trigger_notify_done(indio_dev->trig); @@ -273,7 +272,7 @@ kxsd9_get_mount_matrix(const struct iio_dev *indio_dev, static const struct iio_chan_spec_ext_info kxsd9_ext_info[] = { IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE, kxsd9_get_mount_matrix), - { }, + { } }; #define KXSD9_ACCEL_CHAN(axis, index) \ diff --git a/drivers/iio/accel/mma7455_core.c b/drivers/iio/accel/mma7455_core.c index 30746621052c..a2b5bdf14dde 100644 --- a/drivers/iio/accel/mma7455_core.c +++ b/drivers/iio/accel/mma7455_core.c @@ -103,8 +103,9 @@ static irqreturn_t mma7455_trigger_handler(int irq, void *p) if (ret) goto done; - iio_push_to_buffers_with_timestamp(indio_dev, &mma7455->scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &mma7455->scan, + sizeof(mma7455->scan), + iio_get_time_ns(indio_dev)); done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/accel/mma7660.c b/drivers/iio/accel/mma7660.c index 2894aff80161..d0a16f227903 100644 --- a/drivers/iio/accel/mma7660.c +++ b/drivers/iio/accel/mma7660.c @@ -262,7 +262,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(mma7660_pm_ops, mma7660_suspend, static const struct i2c_device_id mma7660_i2c_id[] = { { "mma7660" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, mma7660_i2c_id); @@ -274,7 +274,7 @@ MODULE_DEVICE_TABLE(of, mma7660_of_match); static const struct acpi_device_id mma7660_acpi_id[] = { {"MMA7660", 0}, - {} + { } }; MODULE_DEVICE_TABLE(acpi, mma7660_acpi_id); diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 05f5482f366e..aba444a980d9 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -1103,8 +1103,9 @@ static irqreturn_t mma8452_trigger_handler(int irq, void *p) if (ret < 0) goto done; - iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &data->buffer, + sizeof(data->buffer), + iio_get_time_ns(indio_dev)); done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c index 1b96687da01a..b89bad9e6fe6 100644 --- a/drivers/iio/accel/mma9551.c +++ b/drivers/iio/accel/mma9551.c @@ -578,14 +578,14 @@ static const struct dev_pm_ops mma9551_pm_ops = { static const struct acpi_device_id mma9551_acpi_match[] = { {"MMA9551", 0}, - {}, + { } }; MODULE_DEVICE_TABLE(acpi, mma9551_acpi_match); static const struct i2c_device_id mma9551_id[] = { { "mma9551" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, mma9551_id); diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c index 00e224efc8ed..1bbe660b254f 100644 --- a/drivers/iio/accel/mma9553.c +++ b/drivers/iio/accel/mma9553.c @@ -919,7 +919,7 @@ static const struct iio_enum mma9553_calibgender_enum = { static const struct iio_chan_spec_ext_info mma9553_ext_info[] = { IIO_ENUM("calibgender", IIO_SHARED_BY_TYPE, &mma9553_calibgender_enum), IIO_ENUM_AVAILABLE("calibgender", IIO_SHARED_BY_TYPE, &mma9553_calibgender_enum), - {}, + { } }; #define MMA9553_PEDOMETER_CHANNEL(_type, _mask) { \ @@ -1216,14 +1216,14 @@ static const struct dev_pm_ops mma9553_pm_ops = { static const struct acpi_device_id mma9553_acpi_match[] = { {"MMA9553", 0}, - {}, + { } }; MODULE_DEVICE_TABLE(acpi, mma9553_acpi_match); static const struct i2c_device_id mma9553_id[] = { { "mma9553" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, mma9553_id); diff --git a/drivers/iio/accel/msa311.c b/drivers/iio/accel/msa311.c index d31c11fbbe68..c31c53abc3d0 100644 --- a/drivers/iio/accel/msa311.c +++ b/drivers/iio/accel/msa311.c @@ -919,8 +919,8 @@ static irqreturn_t msa311_buffer_thread(int irq, void *p) mutex_unlock(&msa311->lock); - iio_push_to_buffers_with_timestamp(indio_dev, &buf, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &buf, sizeof(buf), + iio_get_time_ns(indio_dev)); notify_done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c index cb5c4e354fc0..1075c8ce0e37 100644 --- a/drivers/iio/accel/mxc4005.c +++ b/drivers/iio/accel/mxc4005.c @@ -335,8 +335,8 @@ static irqreturn_t mxc4005_trigger_handler(int irq, void *private) if (ret < 0) goto err; - iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, - pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), + pf->timestamp); err: iio_trigger_notify_done(indio_dev->trig); @@ -573,14 +573,14 @@ static const struct acpi_device_id mxc4005_acpi_match[] = { {"MXC4005", 0}, {"MXC6655", 0}, {"MDA6655", 0}, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, mxc4005_acpi_match); static const struct of_device_id mxc4005_of_match[] = { { .compatible = "memsic,mxc4005", }, { .compatible = "memsic,mxc6655", }, - { }, + { } }; MODULE_DEVICE_TABLE(of, mxc4005_of_match); diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c index 3fb0f386c3db..aabe4491efd7 100644 --- a/drivers/iio/accel/sca3000.c +++ b/drivers/iio/accel/sca3000.c @@ -1541,7 +1541,7 @@ static const struct spi_device_id sca3000_id[] = { {"sca3000_e02", e02}, {"sca3000_e04", e04}, {"sca3000_e05", e05}, - {} + { } }; MODULE_DEVICE_TABLE(spi, sca3000_id); diff --git a/drivers/iio/accel/sca3300.c b/drivers/iio/accel/sca3300.c index ca0ce83e42b2..67416a406e2f 100644 --- a/drivers/iio/accel/sca3300.c +++ b/drivers/iio/accel/sca3300.c @@ -58,15 +58,6 @@ enum sca3300_scan_indexes { SCA3300_SCAN_MAX }; -/* - * Buffer size max case: - * Three accel channels, two bytes per channel. - * Temperature channel, two bytes. - * Three incli channels, two bytes per channel. - * Timestamp channel, eight bytes. - */ -#define SCA3300_MAX_BUFFER_SIZE (ALIGN(sizeof(s16) * SCA3300_SCAN_MAX, sizeof(s64)) + sizeof(s64)) - #define SCA3300_ACCEL_CHANNEL(index, reg, axis) { \ .type = IIO_ACCEL, \ .address = reg, \ @@ -193,9 +184,6 @@ struct sca3300_chip_info { * @spi: SPI device structure * @lock: Data buffer lock * @chip: Sensor chip specific information - * @buffer: Triggered buffer: - * -SCA3300: 4 channel 16-bit data + 64-bit timestamp - * -SCL3300: 7 channel 16-bit data + 64-bit timestamp * @txbuf: Transmit buffer * @rxbuf: Receive buffer */ @@ -203,7 +191,6 @@ struct sca3300_data { struct spi_device *spi; struct mutex lock; const struct sca3300_chip_info *chip; - u8 buffer[SCA3300_MAX_BUFFER_SIZE] __aligned(sizeof(s64)); u8 txbuf[4] __aligned(IIO_DMA_MINALIGN); u8 rxbuf[4]; }; @@ -492,7 +479,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; - s16 *channels = (s16 *)data->buffer; + 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); @@ -505,8 +492,8 @@ static irqreturn_t sca3300_trigger_handler(int irq, void *p) channels[i++] = val; } - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, channels, sizeof(channels), + iio_get_time_ns(indio_dev)); out: iio_trigger_notify_done(indio_dev->trig); @@ -674,14 +661,14 @@ static int sca3300_probe(struct spi_device *spi) static const struct of_device_id sca3300_dt_ids[] = { { .compatible = "murata,sca3300"}, { .compatible = "murata,scl3300"}, - {} + { } }; MODULE_DEVICE_TABLE(of, sca3300_dt_ids); static const struct spi_device_id sca3300_ids[] = { { "sca3300" }, { "scl3300" }, - {} + { } }; MODULE_DEVICE_TABLE(spi, sca3300_ids); diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index ab4fdba75a0a..f24449500533 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -126,14 +126,14 @@ static const struct of_device_id st_accel_of_match[] = { .compatible = "st,iis328dq", .data = IIS328DQ_ACCEL_DEV_NAME, }, - {}, + { } }; MODULE_DEVICE_TABLE(of, st_accel_of_match); static const struct acpi_device_id st_accel_acpi_match[] = { {"SMO8840", (kernel_ulong_t)LIS2DH12_ACCEL_DEV_NAME}, {"SMO8A90", (kernel_ulong_t)LNG2DM_ACCEL_DEV_NAME}, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, st_accel_acpi_match); @@ -164,7 +164,7 @@ static const struct i2c_device_id st_accel_id_table[] = { { LSM303C_ACCEL_DEV_NAME }, { SC7A20_ACCEL_DEV_NAME }, { IIS328DQ_ACCEL_DEV_NAME }, - {}, + { } }; MODULE_DEVICE_TABLE(i2c, st_accel_id_table); diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c index 6146754fe47f..d8ec0555f42a 100644 --- a/drivers/iio/accel/st_accel_spi.c +++ b/drivers/iio/accel/st_accel_spi.c @@ -108,7 +108,7 @@ static const struct of_device_id st_accel_of_match[] = { .compatible = "st,iis328dq", .data = IIS328DQ_ACCEL_DEV_NAME, }, - {} + { } }; MODULE_DEVICE_TABLE(of, st_accel_of_match); @@ -167,7 +167,7 @@ static const struct spi_device_id st_accel_id_table[] = { { LIS302DL_ACCEL_DEV_NAME }, { LSM303C_ACCEL_DEV_NAME }, { IIS328DQ_ACCEL_DEV_NAME }, - {}, + { } }; MODULE_DEVICE_TABLE(spi, st_accel_id_table); diff --git a/drivers/iio/accel/stk8312.c b/drivers/iio/accel/stk8312.c index 471c154c3631..dfac2e44191f 100644 --- a/drivers/iio/accel/stk8312.c +++ b/drivers/iio/accel/stk8312.c @@ -460,8 +460,8 @@ static irqreturn_t stk8312_trigger_handler(int irq, void *p) } mutex_unlock(&data->lock); - iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, - pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), + pf->timestamp); err: iio_trigger_notify_done(indio_dev->trig); @@ -635,7 +635,7 @@ static const struct i2c_device_id stk8312_i2c_id[] = { /* Deprecated in favour of lowercase form */ { "STK8312" }, { "stk8312" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, stk8312_i2c_id); diff --git a/drivers/iio/accel/stk8ba50.c b/drivers/iio/accel/stk8ba50.c index cab592a68622..05d4fd540eb2 100644 --- a/drivers/iio/accel/stk8ba50.c +++ b/drivers/iio/accel/stk8ba50.c @@ -340,8 +340,8 @@ static irqreturn_t stk8ba50_trigger_handler(int irq, void *p) data->scan.chans[i++] = ret; } } - iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, - pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), + pf->timestamp); err: mutex_unlock(&data->lock); iio_trigger_notify_done(indio_dev->trig); @@ -526,13 +526,13 @@ static DEFINE_SIMPLE_DEV_PM_OPS(stk8ba50_pm_ops, stk8ba50_suspend, static const struct i2c_device_id stk8ba50_i2c_id[] = { { "stk8ba50" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, stk8ba50_i2c_id); static const struct acpi_device_id stk8ba50_acpi_id[] = { {"STK8BA50", 0}, - {} + { } }; MODULE_DEVICE_TABLE(acpi, stk8ba50_acpi_id); diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 6529df1a498c..ea3ba1397392 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -6,6 +6,9 @@ menu "Analog to digital converters" +config IIO_ADC_HELPER + tristate + config AB8500_GPADC bool "ST-Ericsson AB8500 GPADC driver" depends on AB8500_CORE && REGULATOR_AB8500 @@ -25,10 +28,15 @@ config AD4000 tristate "Analog Devices AD4000 ADC Driver" depends on SPI select IIO_BUFFER + select IIO_BUFFER_DMAENGINE select IIO_TRIGGERED_BUFFER + select SPI_OFFLOAD help Say yes here to build support for Analog Devices AD4000 high speed - SPI analog to digital converters (ADC). + SPI analog to digital converters (ADC). If intended to use with + SPI offloading support, it is recommended to enable + CONFIG_SPI_AXI_SPI_ENGINE, CONFIG_PWM_AXI_PWMGEN, and + CONFIG_SPI_OFFLOAD_TRIGGER_PWM. To compile this driver as a module, choose M here: the module will be called ad4000. @@ -129,8 +137,9 @@ 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 + select GPIOLIB + select GPIO_REGMAP + select REGMAP_SPI help Say yes here to build support for Analog Devices AD7173 and similar ADC Currently supported models: @@ -281,6 +290,8 @@ config AD7606_IFACE_SPI tristate "Analog Devices AD7606 ADC driver with spi interface support" depends on SPI select AD7606 + select IIO_BUFFER_DMAENGINE + select SPI_OFFLOAD help Say yes here to build spi interface support for Analog Devices: ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC). @@ -319,6 +330,7 @@ config AD7766 config AD7768_1 tristate "Analog Devices AD7768-1 ADC driver" depends on SPI + select REGMAP_SPI select IIO_BUFFER select IIO_TRIGGER select IIO_TRIGGERED_BUFFER @@ -1092,6 +1104,17 @@ config NAU7802 To compile this driver as a module, choose M here: the module will be called nau7802. +config NCT7201 + tristate "Nuvoton Instruments NCT7201 and NCT7202 Power Monitor" + depends on I2C + select REGMAP_I2C + help + If you say yes here you get support for the Nuvoton NCT7201 and + NCT7202 Voltage Monitor. + + This driver can also be built as a module. If so, the module + will be called nct7201. + config NPCM_ADC tristate "Nuvoton NPCM ADC driver" depends on ARCH_NPCM || COMPILE_TEST @@ -1232,6 +1255,18 @@ config RN5T618_ADC This driver can also be built as a module. If so, the module will be called rn5t618-adc. +config ROHM_BD79124 + tristate "Rohm BD79124 ADC driver" + depends on I2C + select REGMAP_I2C + select IIO_ADC_HELPER + help + Say yes here to build support for the ROHM BD79124 ADC. The + ROHM BD79124 is a 12-bit, 8-channel, SAR ADC. The ADC supports + also an automatic measurement mode, with an alarm interrupt for + out-of-window measurements. The window is configurable for each + channel. + config ROCKCHIP_SARADC tristate "Rockchip SARADC driver" depends on ARCH_ROCKCHIP || COMPILE_TEST @@ -1263,6 +1298,7 @@ config RICHTEK_RTQ6056 config RZG2L_ADC tristate "Renesas RZ/G2L ADC driver" depends on ARCH_RZG2L || COMPILE_TEST + select IIO_ADC_HELPER help Say yes here to build support for the ADC found in Renesas RZ/G2L family. @@ -1397,6 +1433,7 @@ config SUN4I_GPADC config SUN20I_GPADC tristate "Allwinner D1/T113s/T507/R329 and similar GPADCs driver" depends on ARCH_SUNXI || COMPILE_TEST + select IIO_ADC_HELPER help Say yes here to build support for Allwinner (D1, T113, T507 and R329) SoCs GPADC. This ADC provides up to 16 channels. @@ -1440,18 +1477,6 @@ config TI_ADC084S021 This driver can also be built as a module. If so, the module will be called ti-adc084s021. -config TI_ADC12138 - tristate "Texas Instruments ADC12130/ADC12132/ADC12138" - depends on SPI - select IIO_BUFFER - select IIO_TRIGGERED_BUFFER - help - If you say yes here you get support for Texas Instruments ADC12130, - ADC12132 and ADC12138 chips. - - This driver can also be built as a module. If so, the module will be - called ti-adc12138. - config TI_ADC108S102 tristate "Texas Instruments ADC108S102 and ADC128S102 driver" depends on SPI @@ -1464,12 +1489,24 @@ config TI_ADC108S102 To compile this driver as a module, choose M here: the module will be called ti-adc108s102. +config TI_ADC12138 + tristate "Texas Instruments ADC12130/ADC12132/ADC12138" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + If you say yes here you get support for Texas Instruments ADC12130, + ADC12132 and ADC12138 chips. + + This driver can also be built as a module. If so, the module will be + called ti-adc12138. + config TI_ADC128S052 tristate "Texas Instruments ADC128S052/ADC122S021/ADC124S021" depends on SPI help If you say yes here you get support for Texas Instruments ADC128S052, - ADC122S021 and ADC124S021 chips. + ADC122S021, ADC124S021 and ROHM Semiconductor BD79104 chips. This driver can also be built as a module. If so, the module will be called ti-adc128s052. @@ -1499,6 +1536,16 @@ config TI_ADS1015 This driver can also be built as a module. If so, the module will be called ti-ads1015. +config TI_ADS1100 + tristate "Texas Instruments ADS1100 and ADS1000 ADC" + depends on I2C + help + If you say yes here you get support for Texas Instruments ADS1100 and + ADS1000 ADC chips. + + This driver can also be built as a module. If so, the module will be + called ti-ads1100. + config TI_ADS1119 tristate "Texas Instruments ADS1119 ADC" depends on I2C @@ -1511,6 +1558,42 @@ config TI_ADS1119 This driver can also be built as a module. If so, the module will be called ti-ads1119. +config TI_ADS124S08 + tristate "Texas Instruments ADS124S08" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + If you say yes here you get support for Texas Instruments ADS124S08 + and ADS124S06 ADC chips + + This driver can also be built as a module. If so, the module will be + called ti-ads124s08. + +config TI_ADS1298 + tristate "Texas Instruments ADS1298" + depends on SPI + select IIO_BUFFER + select IIO_KFIFO_BUF + help + If you say yes here you get support for Texas Instruments ADS1298 + medical ADC chips + + This driver can also be built as a module. If so, the module will be + called ti-ads1298. + +config TI_ADS131E08 + tristate "Texas Instruments ADS131E08" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes here to get support for Texas Instruments ADS131E04, ADS131E06 + and ADS131E08 chips. + + This driver can also be built as a module. If so, the module will be + called ti-ads131e08. + config TI_ADS7138 tristate "Texas Instruments ADS7128 and ADS7138 ADC driver" depends on I2C @@ -1532,27 +1615,6 @@ config TI_ADS7924 This driver can also be built as a module. If so, the module will be called ti-ads7924. -config TI_ADS1100 - tristate "Texas Instruments ADS1100 and ADS1000 ADC" - depends on I2C - help - If you say yes here you get support for Texas Instruments ADS1100 and - ADS1000 ADC chips. - - This driver can also be built as a module. If so, the module will be - called ti-ads1100. - -config TI_ADS1298 - tristate "Texas Instruments ADS1298" - depends on SPI - select IIO_BUFFER - help - If you say yes here you get support for Texas Instruments ADS1298 - medical ADC chips - - This driver can also be built as a module. If so, the module will be - called ti-ads1298. - config TI_ADS7950 tristate "Texas Instruments ADS7950 ADC driver" depends on SPI && GPIOLIB @@ -1588,30 +1650,6 @@ config TI_ADS8688 This driver can also be built as a module. If so, the module will be called ti-ads8688. -config TI_ADS124S08 - tristate "Texas Instruments ADS124S08" - depends on SPI - select IIO_BUFFER - select IIO_TRIGGERED_BUFFER - help - If you say yes here you get support for Texas Instruments ADS124S08 - and ADS124S06 ADC chips - - This driver can also be built as a module. If so, the module will be - called ti-ads124s08. - -config TI_ADS131E08 - tristate "Texas Instruments ADS131E08" - depends on SPI - select IIO_BUFFER - select IIO_TRIGGERED_BUFFER - help - Say yes here to get support for Texas Instruments ADS131E04, ADS131E06 - and ADS131E08 chips. - - This driver can also be built as a module. If so, the module will be - called ti-ads131e08. - config TI_AM335X_ADC tristate "TI's AM335X ADC driver" depends on MFD_TI_AM335X_TSCADC && HAS_DMA diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 3e918c3eec69..09ae6edb2650 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -3,6 +3,8 @@ # Makefile for IIO ADC drivers # +obj-$(CONFIG_IIO_ADC_HELPER) += industrialio-adc.o + # When adding new entries keep the list in alphabetical order obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o @@ -97,6 +99,7 @@ obj-$(CONFIG_MESON_SARADC) += meson_saradc.o obj-$(CONFIG_MP2629_ADC) += mp2629_adc.o obj-$(CONFIG_MXS_LRADC_ADC) += mxs-lradc-adc.o obj-$(CONFIG_NAU7802) += nau7802.o +obj-$(CONFIG_NCT7201) += nct7201.o obj-$(CONFIG_NPCM_ADC) += npcm_adc.o obj-$(CONFIG_PAC1921) += pac1921.o obj-$(CONFIG_PAC1934) += pac1934.o @@ -110,6 +113,7 @@ obj-$(CONFIG_QCOM_VADC_COMMON) += qcom-vadc-common.o obj-$(CONFIG_RCAR_GYRO_ADC) += rcar-gyroadc.o obj-$(CONFIG_RICHTEK_RTQ6056) += rtq6056.o obj-$(CONFIG_RN5T618_ADC) += rn5t618-adc.o +obj-$(CONFIG_ROHM_BD79124) += rohm-bd79124.o obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o obj-$(CONFIG_RZG2L_ADC) += rzg2l_adc.o obj-$(CONFIG_SC27XX_ADC) += sc27xx_adc.o diff --git a/drivers/iio/adc/ad4000.c b/drivers/iio/adc/ad4000.c index 4fe8dee48da9..5609a7845b6f 100644 --- a/drivers/iio/adc/ad4000.c +++ b/drivers/iio/adc/ad4000.c @@ -15,12 +15,14 @@ #include <linux/mod_devicetable.h> #include <linux/gpio/consumer.h> #include <linux/regulator/consumer.h> +#include <linux/spi/offload/consumer.h> #include <linux/spi/spi.h> #include <linux/units.h> #include <linux/util_macros.h> -#include <linux/iio/iio.h> +#include <linux/iio/iio.h> #include <linux/iio/buffer.h> +#include <linux/iio/buffer-dmaengine.h> #include <linux/iio/triggered_buffer.h> #include <linux/iio/trigger_consumer.h> @@ -32,10 +34,11 @@ /* AD4000 Configuration Register programmable bits */ #define AD4000_CFG_SPAN_COMP BIT(3) /* Input span compression */ #define AD4000_CFG_HIGHZ BIT(2) /* High impedance mode */ +#define AD4000_CFG_TURBO BIT(1) /* Turbo mode */ #define AD4000_SCALE_OPTIONS 2 -#define __AD4000_DIFF_CHANNEL(_sign, _real_bits, _storage_bits, _reg_access) \ +#define __AD4000_DIFF_CHANNEL(_sign, _real_bits, _storage_bits, _reg_access, _offl)\ { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ @@ -43,54 +46,65 @@ .channel = 0, \ .channel2 = 1, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ - BIT(IIO_CHAN_INFO_SCALE), \ + BIT(IIO_CHAN_INFO_SCALE) | \ + (_offl ? BIT(IIO_CHAN_INFO_SAMP_FREQ) : 0), \ .info_mask_separate_available = _reg_access ? BIT(IIO_CHAN_INFO_SCALE) : 0,\ .scan_index = 0, \ .scan_type = { \ .sign = _sign, \ .realbits = _real_bits, \ .storagebits = _storage_bits, \ - .shift = _storage_bits - _real_bits, \ - .endianness = IIO_BE, \ + .shift = (_offl ? 0 : _storage_bits - _real_bits), \ + .endianness = _offl ? IIO_CPU : IIO_BE \ }, \ } -#define AD4000_DIFF_CHANNEL(_sign, _real_bits, _reg_access) \ +#define AD4000_DIFF_CHANNEL(_sign, _real_bits, _reg_access, _offl) \ __AD4000_DIFF_CHANNEL((_sign), (_real_bits), \ - ((_real_bits) > 16 ? 32 : 16), (_reg_access)) + (((_offl) || ((_real_bits) > 16)) ? 32 : 16), \ + (_reg_access), (_offl)) +/* + * When SPI offload is configured, transfers are executed without CPU + * intervention so no soft timestamp can be recorded when transfers run. + * Because of that, the macros that set timestamp channel are only used when + * transfers are not offloaded. + */ #define AD4000_DIFF_CHANNELS(_sign, _real_bits, _reg_access) \ { \ - AD4000_DIFF_CHANNEL(_sign, _real_bits, _reg_access), \ + AD4000_DIFF_CHANNEL(_sign, _real_bits, _reg_access, 0), \ IIO_CHAN_SOFT_TIMESTAMP(1), \ } -#define __AD4000_PSEUDO_DIFF_CHANNEL(_sign, _real_bits, _storage_bits, _reg_access)\ +#define __AD4000_PSEUDO_DIFF_CHANNEL(_sign, _real_bits, _storage_bits, \ + _reg_access, _offl) \ { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ .channel = 0, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_SCALE) | \ - BIT(IIO_CHAN_INFO_OFFSET), \ + BIT(IIO_CHAN_INFO_OFFSET) | \ + (_offl ? BIT(IIO_CHAN_INFO_SAMP_FREQ) : 0), \ .info_mask_separate_available = _reg_access ? BIT(IIO_CHAN_INFO_SCALE) : 0,\ .scan_index = 0, \ .scan_type = { \ .sign = _sign, \ .realbits = _real_bits, \ .storagebits = _storage_bits, \ - .shift = _storage_bits - _real_bits, \ - .endianness = IIO_BE, \ + .shift = (_offl ? 0 : _storage_bits - _real_bits), \ + .endianness = _offl ? IIO_CPU : IIO_BE \ }, \ } -#define AD4000_PSEUDO_DIFF_CHANNEL(_sign, _real_bits, _reg_access) \ +#define AD4000_PSEUDO_DIFF_CHANNEL(_sign, _real_bits, _reg_access, _offl) \ __AD4000_PSEUDO_DIFF_CHANNEL((_sign), (_real_bits), \ - ((_real_bits) > 16 ? 32 : 16), (_reg_access)) + (((_offl) || ((_real_bits) > 16)) ? 32 : 16),\ + (_reg_access), (_offl)) #define AD4000_PSEUDO_DIFF_CHANNELS(_sign, _real_bits, _reg_access) \ { \ - AD4000_PSEUDO_DIFF_CHANNEL(_sign, _real_bits, _reg_access), \ + AD4000_PSEUDO_DIFF_CHANNEL(_sign, _real_bits, _reg_access, 0), \ IIO_CHAN_SOFT_TIMESTAMP(1), \ } @@ -184,212 +198,298 @@ struct ad4000_chip_info { const char *dev_name; struct iio_chan_spec chan_spec[2]; struct iio_chan_spec reg_access_chan_spec[2]; + struct iio_chan_spec offload_chan_spec; + struct iio_chan_spec reg_access_offload_chan_spec; const struct ad4000_time_spec *time_spec; bool has_hardware_gain; + int max_rate_hz; }; static const struct ad4000_chip_info ad4000_chip_info = { .dev_name = "ad4000", .chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0), .reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 1), + .offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0, 1), + .reg_access_offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 1, 1), .time_spec = &ad4000_t_spec, + .max_rate_hz = 2 * MEGA, }; static const struct ad4000_chip_info ad4001_chip_info = { .dev_name = "ad4001", .chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0), .reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 16, 1), + .offload_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 0, 1), + .reg_access_offload_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 1, 1), .time_spec = &ad4000_t_spec, + .max_rate_hz = 2 * MEGA, }; static const struct ad4000_chip_info ad4002_chip_info = { .dev_name = "ad4002", .chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 0), .reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 1), + .offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18, 0, 1), + .reg_access_offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18, 1, 1), .time_spec = &ad4000_t_spec, + .max_rate_hz = 2 * MEGA, }; static const struct ad4000_chip_info ad4003_chip_info = { .dev_name = "ad4003", .chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0), .reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 18, 1), + .offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 0, 1), + .reg_access_offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 1, 1), .time_spec = &ad4000_t_spec, + .max_rate_hz = 2 * MEGA, }; static const struct ad4000_chip_info ad4004_chip_info = { .dev_name = "ad4004", .chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0), .reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 1), + .offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0, 1), + .reg_access_offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 1, 1), .time_spec = &ad4000_t_spec, + .max_rate_hz = 1 * MEGA, }; static const struct ad4000_chip_info ad4005_chip_info = { .dev_name = "ad4005", .chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0), .reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 16, 1), + .offload_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 0, 1), + .reg_access_offload_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 1, 1), .time_spec = &ad4000_t_spec, + .max_rate_hz = 1 * MEGA, }; static const struct ad4000_chip_info ad4006_chip_info = { .dev_name = "ad4006", .chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 0), .reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 1), + .offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18, 0, 1), + .reg_access_offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18, 1, 1), .time_spec = &ad4000_t_spec, + .max_rate_hz = 1 * MEGA, }; static const struct ad4000_chip_info ad4007_chip_info = { .dev_name = "ad4007", .chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0), .reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 18, 1), + .offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 0, 1), + .reg_access_offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 1, 1), .time_spec = &ad4000_t_spec, + .max_rate_hz = 1 * MEGA, }; static const struct ad4000_chip_info ad4008_chip_info = { .dev_name = "ad4008", .chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0), .reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 1), + .offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0, 1), + .reg_access_offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 1, 1), .time_spec = &ad4000_t_spec, + .max_rate_hz = 500 * KILO, }; static const struct ad4000_chip_info ad4010_chip_info = { .dev_name = "ad4010", .chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 0), .reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 1), + .offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18, 0, 1), + .reg_access_offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18, 1, 1), .time_spec = &ad4000_t_spec, + .max_rate_hz = 500 * KILO, }; static const struct ad4000_chip_info ad4011_chip_info = { .dev_name = "ad4011", .chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0), .reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 18, 1), + .offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 0, 1), + .reg_access_offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 1, 1), .time_spec = &ad4000_t_spec, + .max_rate_hz = 500 * KILO, }; static const struct ad4000_chip_info ad4020_chip_info = { .dev_name = "ad4020", .chan_spec = AD4000_DIFF_CHANNELS('s', 20, 0), .reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 20, 1), + .offload_chan_spec = AD4000_DIFF_CHANNEL('s', 20, 0, 1), + .reg_access_offload_chan_spec = AD4000_DIFF_CHANNEL('s', 20, 1, 1), .time_spec = &ad4020_t_spec, + .max_rate_hz = 1800 * KILO, }; static const struct ad4000_chip_info ad4021_chip_info = { .dev_name = "ad4021", .chan_spec = AD4000_DIFF_CHANNELS('s', 20, 0), .reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 20, 1), + .offload_chan_spec = AD4000_DIFF_CHANNEL('s', 20, 0, 1), + .reg_access_offload_chan_spec = AD4000_DIFF_CHANNEL('s', 20, 1, 1), .time_spec = &ad4020_t_spec, + .max_rate_hz = 1 * MEGA, }; static const struct ad4000_chip_info ad4022_chip_info = { .dev_name = "ad4022", .chan_spec = AD4000_DIFF_CHANNELS('s', 20, 0), .reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 20, 1), + .offload_chan_spec = AD4000_DIFF_CHANNEL('s', 20, 0, 1), + .reg_access_offload_chan_spec = AD4000_DIFF_CHANNEL('s', 20, 1, 1), .time_spec = &ad4020_t_spec, + .max_rate_hz = 500 * KILO, }; static const struct ad4000_chip_info adaq4001_chip_info = { .dev_name = "adaq4001", .chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0), .reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 16, 1), + .offload_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 0, 1), + .reg_access_offload_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 1, 1), .time_spec = &ad4000_t_spec, .has_hardware_gain = true, + .max_rate_hz = 2 * MEGA, }; static const struct ad4000_chip_info adaq4003_chip_info = { .dev_name = "adaq4003", .chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0), .reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 18, 1), + .offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 0, 1), + .reg_access_offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 1, 1), .time_spec = &ad4000_t_spec, .has_hardware_gain = true, + .max_rate_hz = 2 * MEGA, }; static const struct ad4000_chip_info ad7685_chip_info = { .dev_name = "ad7685", .chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0), + .offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0, 1), .time_spec = &ad7687_t_spec, + .max_rate_hz = 250 * KILO, }; static const struct ad4000_chip_info ad7686_chip_info = { .dev_name = "ad7686", .chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0), + .offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0, 1), .time_spec = &ad7686_t_spec, + .max_rate_hz = 500 * KILO, }; static const struct ad4000_chip_info ad7687_chip_info = { .dev_name = "ad7687", .chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0), + .offload_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 0, 1), .time_spec = &ad7687_t_spec, + .max_rate_hz = 250 * KILO, }; static const struct ad4000_chip_info ad7688_chip_info = { .dev_name = "ad7688", .chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0), + .offload_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 0, 1), .time_spec = &ad7686_t_spec, + .max_rate_hz = 500 * KILO, }; static const struct ad4000_chip_info ad7690_chip_info = { .dev_name = "ad7690", .chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0), + .offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 0, 1), .time_spec = &ad7690_t_spec, + .max_rate_hz = 400 * KILO, }; static const struct ad4000_chip_info ad7691_chip_info = { .dev_name = "ad7691", .chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0), + .offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 0, 1), .time_spec = &ad7691_t_spec, + .max_rate_hz = 250 * KILO, }; static const struct ad4000_chip_info ad7693_chip_info = { .dev_name = "ad7693", .chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0), + .offload_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 0, 1), .time_spec = &ad7686_t_spec, + .max_rate_hz = 500 * KILO, }; static const struct ad4000_chip_info ad7942_chip_info = { .dev_name = "ad7942", .chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 14, 0), + .offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 14, 0, 1), .time_spec = &ad7687_t_spec, + .max_rate_hz = 250 * KILO, }; static const struct ad4000_chip_info ad7946_chip_info = { .dev_name = "ad7946", .chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 14, 0), + .offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 14, 0, 1), .time_spec = &ad7686_t_spec, + .max_rate_hz = 500 * KILO, }; static const struct ad4000_chip_info ad7980_chip_info = { .dev_name = "ad7980", .chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0), + .offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0, 1), .time_spec = &ad7980_t_spec, + .max_rate_hz = 1 * MEGA, }; static const struct ad4000_chip_info ad7982_chip_info = { .dev_name = "ad7982", .chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0), + .offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 0, 1), .time_spec = &ad7980_t_spec, + .max_rate_hz = 1 * MEGA, }; static const struct ad4000_chip_info ad7983_chip_info = { .dev_name = "ad7983", .chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0), + .offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0, 1), .time_spec = &ad7983_t_spec, + .max_rate_hz = 1 * MEGA + 333 * KILO + 333, }; static const struct ad4000_chip_info ad7984_chip_info = { .dev_name = "ad7984", .chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0), + .offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 0, 1), .time_spec = &ad7983_t_spec, + .max_rate_hz = 1 * MEGA + 333 * KILO + 333, }; static const struct ad4000_chip_info ad7988_1_chip_info = { .dev_name = "ad7988-1", .chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0), + .offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0, 1), .time_spec = &ad7988_1_t_spec, + .max_rate_hz = 100 * KILO, }; static const struct ad4000_chip_info ad7988_5_chip_info = { .dev_name = "ad7988-5", .chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0), + .offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0, 1), .time_spec = &ad7686_t_spec, + .max_rate_hz = 500 * KILO, +}; + +static const struct spi_offload_config ad4000_offload_config = { + .capability_flags = SPI_OFFLOAD_CAP_TRIGGER | + SPI_OFFLOAD_CAP_RX_STREAM_DMA, }; struct ad4000_state { @@ -397,6 +497,13 @@ struct ad4000_state { struct gpio_desc *cnv_gpio; struct spi_transfer xfers[2]; struct spi_message msg; + struct spi_transfer offload_xfer; + struct spi_message offload_msg; + struct spi_offload *offload; + struct spi_offload_trigger *offload_trigger; + bool using_offload; + unsigned long offload_trigger_hz; + int max_rate_hz; struct mutex lock; /* Protect read modify write cycle */ int vref_mv; enum ad4000_sdi sdi_pin; @@ -411,8 +518,10 @@ struct ad4000_state { */ struct { union { - __be16 sample_buf16; - __be32 sample_buf32; + __be16 sample_buf16_be; + __be32 sample_buf32_be; + u16 sample_buf16; + u32 sample_buf32; } data; aligned_s64 timestamp; } scan __aligned(IIO_DMA_MINALIGN); @@ -487,6 +596,25 @@ static int ad4000_read_reg(struct ad4000_state *st, unsigned int *val) return ret; } +static int ad4000_set_sampling_freq(struct ad4000_state *st, int freq) +{ + struct spi_offload_trigger_config config = { + .type = SPI_OFFLOAD_TRIGGER_PERIODIC, + .periodic = { + .frequency_hz = freq, + }, + }; + int ret; + + ret = spi_offload_trigger_validate(st->offload_trigger, &config); + if (ret) + return ret; + + st->offload_trigger_hz = config.periodic.frequency_hz; + + return 0; +} + static int ad4000_convert_and_acquire(struct ad4000_state *st) { int ret; @@ -515,10 +643,17 @@ static int ad4000_single_conversion(struct iio_dev *indio_dev, if (ret < 0) return ret; - if (chan->scan_type.storagebits > 16) - sample = be32_to_cpu(st->scan.data.sample_buf32); - else - sample = be16_to_cpu(st->scan.data.sample_buf16); + if (chan->scan_type.endianness == IIO_BE) { + if (chan->scan_type.realbits > 16) + sample = be32_to_cpu(st->scan.data.sample_buf32_be); + else + sample = be16_to_cpu(st->scan.data.sample_buf16_be); + } else { + if (chan->scan_type.realbits > 16) + sample = st->scan.data.sample_buf32; + else + sample = st->scan.data.sample_buf16; + } sample >>= chan->scan_type.shift; @@ -555,6 +690,9 @@ static int ad4000_read_raw(struct iio_dev *indio_dev, *val = mult_frac(st->vref_mv, 1, 10); return IIO_VAL_INT; + case IIO_CHAN_INFO_SAMP_FREQ: + *val = st->offload_trigger_hz; + return IIO_VAL_INT; default: return -EINVAL; } @@ -620,6 +758,7 @@ static int ad4000_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { + struct ad4000_state *st = iio_priv(indio_dev); int ret; switch (mask) { @@ -629,6 +768,15 @@ static int ad4000_write_raw(struct iio_dev *indio_dev, ret = __ad4000_write_raw(indio_dev, chan, val2); iio_device_release_direct(indio_dev); return ret; + case IIO_CHAN_INFO_SAMP_FREQ: + if (val < 1 || val > st->max_rate_hz) + return -EINVAL; + + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + ret = ad4000_set_sampling_freq(st, val); + iio_device_release_direct(indio_dev); + return ret; default: return -EINVAL; } @@ -645,7 +793,8 @@ static irqreturn_t ad4000_trigger_handler(int irq, void *p) if (ret < 0) goto err_out; - iio_push_to_buffers_with_timestamp(indio_dev, &st->scan, pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &st->scan, sizeof(st->scan), + pf->timestamp); err_out: iio_trigger_notify_done(indio_dev->trig); @@ -659,10 +808,114 @@ static const struct iio_info ad4000_reg_access_info = { .write_raw_get_fmt = &ad4000_write_raw_get_fmt, }; +static const struct iio_info ad4000_offload_info = { + .read_raw = &ad4000_read_raw, + .write_raw = &ad4000_write_raw, + .write_raw_get_fmt = &ad4000_write_raw_get_fmt, +}; + static const struct iio_info ad4000_info = { .read_raw = &ad4000_read_raw, }; +static int ad4000_offload_buffer_postenable(struct iio_dev *indio_dev) +{ + struct ad4000_state *st = iio_priv(indio_dev); + struct spi_offload_trigger_config config = { + .type = SPI_OFFLOAD_TRIGGER_PERIODIC, + .periodic = { + .frequency_hz = st->offload_trigger_hz, + }, + }; + + return spi_offload_trigger_enable(st->offload, st->offload_trigger, + &config); +} + +static int ad4000_offload_buffer_predisable(struct iio_dev *indio_dev) +{ + struct ad4000_state *st = iio_priv(indio_dev); + + spi_offload_trigger_disable(st->offload, st->offload_trigger); + + return 0; +} + +static const struct iio_buffer_setup_ops ad4000_offload_buffer_setup_ops = { + .postenable = &ad4000_offload_buffer_postenable, + .predisable = &ad4000_offload_buffer_predisable, +}; + +static int ad4000_spi_offload_setup(struct iio_dev *indio_dev, + struct ad4000_state *st) +{ + struct spi_device *spi = st->spi; + struct device *dev = &spi->dev; + struct dma_chan *rx_dma; + int ret; + + st->offload_trigger = devm_spi_offload_trigger_get(dev, st->offload, + SPI_OFFLOAD_TRIGGER_PERIODIC); + if (IS_ERR(st->offload_trigger)) + return dev_err_probe(dev, PTR_ERR(st->offload_trigger), + "Failed to get offload trigger\n"); + + ret = ad4000_set_sampling_freq(st, st->max_rate_hz); + if (ret) + return dev_err_probe(dev, ret, + "Failed to set sampling frequency\n"); + + rx_dma = devm_spi_offload_rx_stream_request_dma_chan(dev, st->offload); + if (IS_ERR(rx_dma)) + return dev_err_probe(dev, PTR_ERR(rx_dma), + "Failed to get offload RX DMA\n"); + + ret = devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, rx_dma, + IIO_BUFFER_DIRECTION_IN); + if (ret) + return dev_err_probe(dev, ret, "Failed to setup DMA buffer\n"); + + return 0; +} + +/* + * This executes a data sample transfer when using SPI offloading. The device + * connections should be in "3-wire" mode, selected either when the adi,sdi-pin + * device tree property is absent or set to "high". Also, the ADC CNV pin must + * be connected to a SPI controller CS (it can't be connected to a GPIO). + * + * In order to achieve the maximum sample rate, we only do one transfer per + * SPI offload trigger. Because the ADC output has a one sample latency (delay) + * when the device is wired in "3-wire" mode and only one transfer per sample is + * being made in turbo mode, the first data sample is not valid because it + * contains the output of an earlier conversion result. We also set transfer + * `bits_per_word` to achieve higher throughput by using the minimum number of + * SCLK cycles. Also, a delay is added to make sure we meet the minimum quiet + * time before releasing the CS line. + * + * Note that, with `bits_per_word` set to the number of ADC precision bits, + * transfers use larger word sizes that get stored in 'in-memory wordsizes' that + * are always in native CPU byte order. Because of that, IIO buffer elements + * ought to be read in CPU endianness which requires setting IIO scan_type + * endianness accordingly (i.e. IIO_CPU). + */ +static int ad4000_prepare_offload_message(struct ad4000_state *st, + const struct iio_chan_spec *chan) +{ + struct spi_transfer *xfer = &st->offload_xfer; + + xfer->bits_per_word = chan->scan_type.realbits; + xfer->len = chan->scan_type.realbits > 16 ? 4 : 2; + xfer->delay.value = st->time_spec->t_quiet2_ns; + xfer->delay.unit = SPI_DELAY_UNIT_NSECS; + xfer->offload_flags = SPI_OFFLOAD_XFER_RX_STREAM; + + spi_message_init_with_transfers(&st->offload_msg, xfer, 1); + st->offload_msg.offload = st->offload; + + return devm_spi_optimize_message(&st->spi->dev, st->spi, &st->offload_msg); +} + /* * This executes a data sample transfer for when the device connections are * in "3-wire" mode, selected when the adi,sdi-pin device tree property is @@ -689,7 +942,16 @@ static int ad4000_prepare_3wire_mode_message(struct ad4000_state *st, xfers[0].cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; xfers[1].rx_buf = &st->scan.data; - xfers[1].len = BITS_TO_BYTES(chan->scan_type.storagebits); + xfers[1].len = chan->scan_type.realbits > 16 ? 4 : 2; + + /* + * If the device is set up for SPI offloading, IIO channel scan_type is + * set to IIO_CPU. When that is the case, use larger SPI word sizes for + * single-shot reads too. Thus, sample data can be correctly handled in + * ad4000_single_conversion() according to scan_type endianness. + */ + if (chan->scan_type.endianness != IIO_BE) + xfers[1].bits_per_word = chan->scan_type.realbits; xfers[1].delay.value = st->time_spec->t_quiet2_ns; xfers[1].delay.unit = SPI_DELAY_UNIT_NSECS; @@ -733,6 +995,9 @@ static int ad4000_config(struct ad4000_state *st) if (device_property_present(&st->spi->dev, "adi,high-z-input")) reg_val |= FIELD_PREP(AD4000_CFG_HIGHZ, 1); + if (st->using_offload) + reg_val |= FIELD_PREP(AD4000_CFG_TURBO, 1); + return ad4000_write_reg(st, reg_val); } @@ -755,6 +1020,7 @@ static int ad4000_probe(struct spi_device *spi) st = iio_priv(indio_dev); st->spi = spi; st->time_spec = chip->time_spec; + st->max_rate_hz = chip->max_rate_hz; ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(ad4000_power_supplies), ad4000_power_supplies); @@ -772,6 +1038,26 @@ static int ad4000_probe(struct spi_device *spi) return dev_err_probe(dev, PTR_ERR(st->cnv_gpio), "Failed to get CNV GPIO"); + st->offload = devm_spi_offload_get(dev, spi, &ad4000_offload_config); + ret = PTR_ERR_OR_ZERO(st->offload); + if (ret && ret != -ENODEV) + return dev_err_probe(dev, ret, "Failed to get offload\n"); + + st->using_offload = !IS_ERR(st->offload); + if (st->using_offload) { + indio_dev->setup_ops = &ad4000_offload_buffer_setup_ops; + ret = ad4000_spi_offload_setup(indio_dev, st); + if (ret) + return ret; + } else { + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, + &iio_pollfunc_store_time, + &ad4000_trigger_handler, + NULL); + if (ret) + return ret; + } + ret = device_property_match_property_string(dev, "adi,sdi-pin", ad4000_sdi_pin, ARRAY_SIZE(ad4000_sdi_pin)); @@ -784,7 +1070,6 @@ static int ad4000_probe(struct spi_device *spi) switch (st->sdi_pin) { case AD4000_SDI_MOSI: indio_dev->info = &ad4000_reg_access_info; - indio_dev->channels = chip->reg_access_chan_spec; /* * In "3-wire mode", the ADC SDI line must be kept high when @@ -796,9 +1081,26 @@ static int ad4000_probe(struct spi_device *spi) if (ret < 0) return ret; + if (st->using_offload) { + indio_dev->channels = &chip->reg_access_offload_chan_spec; + indio_dev->num_channels = 1; + ret = ad4000_prepare_offload_message(st, indio_dev->channels); + if (ret) + return dev_err_probe(dev, ret, + "Failed to optimize SPI msg\n"); + } else { + indio_dev->channels = chip->reg_access_chan_spec; + indio_dev->num_channels = ARRAY_SIZE(chip->reg_access_chan_spec); + } + + /* + * Call ad4000_prepare_3wire_mode_message() so single-shot read + * SPI messages are always initialized. + */ ret = ad4000_prepare_3wire_mode_message(st, &indio_dev->channels[0]); if (ret) - return ret; + return dev_err_probe(dev, ret, + "Failed to optimize SPI msg\n"); ret = ad4000_config(st); if (ret < 0) @@ -806,19 +1108,38 @@ static int ad4000_probe(struct spi_device *spi) break; case AD4000_SDI_VIO: - indio_dev->info = &ad4000_info; - indio_dev->channels = chip->chan_spec; + if (st->using_offload) { + indio_dev->info = &ad4000_offload_info; + indio_dev->channels = &chip->offload_chan_spec; + indio_dev->num_channels = 1; + + ret = ad4000_prepare_offload_message(st, indio_dev->channels); + if (ret) + return dev_err_probe(dev, ret, + "Failed to optimize SPI msg\n"); + } else { + indio_dev->info = &ad4000_info; + indio_dev->channels = chip->chan_spec; + indio_dev->num_channels = ARRAY_SIZE(chip->chan_spec); + } + ret = ad4000_prepare_3wire_mode_message(st, &indio_dev->channels[0]); if (ret) - return ret; + return dev_err_probe(dev, ret, + "Failed to optimize SPI msg\n"); break; case AD4000_SDI_CS: + if (st->using_offload) + return dev_err_probe(dev, -EPROTONOSUPPORT, + "Unsupported sdi-pin + offload config\n"); indio_dev->info = &ad4000_info; indio_dev->channels = chip->chan_spec; + indio_dev->num_channels = ARRAY_SIZE(chip->chan_spec); ret = ad4000_prepare_4wire_mode_message(st, &indio_dev->channels[0]); if (ret) - return ret; + return dev_err_probe(dev, ret, + "Failed to optimize SPI msg\n"); break; case AD4000_SDI_GND: @@ -830,7 +1151,6 @@ static int ad4000_probe(struct spi_device *spi) } indio_dev->name = chip->dev_name; - indio_dev->num_channels = 2; ret = devm_mutex_init(dev, &st->lock); if (ret) @@ -853,12 +1173,6 @@ static int ad4000_probe(struct spi_device *spi) ad4000_fill_scale_tbl(st, &indio_dev->channels[0]); - ret = devm_iio_triggered_buffer_setup(dev, indio_dev, - &iio_pollfunc_store_time, - &ad4000_trigger_handler, NULL); - if (ret) - return ret; - return devm_iio_device_register(dev, indio_dev); } @@ -947,3 +1261,4 @@ module_spi_driver(ad4000_driver); MODULE_AUTHOR("Marcelo Schmitt <marcelo.schmitt@analog.com>"); MODULE_DESCRIPTION("Analog Devices AD4000 ADC driver"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("IIO_DMAENGINE_BUFFER"); diff --git a/drivers/iio/adc/ad4030.c b/drivers/iio/adc/ad4030.c index 9a020680885d..1bc2f9a22470 100644 --- a/drivers/iio/adc/ad4030.c +++ b/drivers/iio/adc/ad4030.c @@ -147,7 +147,6 @@ struct ad4030_state { struct spi_device *spi; struct regmap *regmap; const struct ad4030_chip_info *chip; - const struct iio_scan_type *current_scan_type; struct gpio_desc *cnv_gpio; int vref_uv; int vio_uv; @@ -245,7 +244,6 @@ static int ad4030_enter_config_mode(struct ad4030_state *st) struct spi_transfer xfer = { .tx_buf = st->tx_data, - .bits_per_word = 8, .len = 1, .speed_hz = AD4030_SPI_MAX_REG_XFER_SPEED, }; @@ -261,7 +259,6 @@ static int ad4030_exit_config_mode(struct ad4030_state *st) struct spi_transfer xfer = { .tx_buf = st->tx_data, - .bits_per_word = 8, .len = 3, .speed_hz = AD4030_SPI_MAX_REG_XFER_SPEED, }; @@ -277,7 +274,6 @@ static int ad4030_spi_read(void *context, const void *reg, size_t reg_size, struct spi_transfer xfer = { .tx_buf = st->tx_data, .rx_buf = st->rx_data.raw, - .bits_per_word = 8, .len = reg_size + val_size, .speed_hz = AD4030_SPI_MAX_REG_XFER_SPEED, }; @@ -312,7 +308,6 @@ static int ad4030_spi_write(void *context, const void *data, size_t count) ((u8 *)data)[2] == 0x81; struct spi_transfer xfer = { .tx_buf = st->tx_data, - .bits_per_word = 8, .len = count, .speed_hz = AD4030_SPI_MAX_REG_XFER_SPEED, }; @@ -390,16 +385,17 @@ static int ad4030_get_chan_scale(struct iio_dev *indio_dev, struct ad4030_state *st = iio_priv(indio_dev); const struct iio_scan_type *scan_type; - if (chan->differential) { - scan_type = iio_get_current_scan_type(indio_dev, - st->chip->channels); + scan_type = iio_get_current_scan_type(indio_dev, st->chip->channels); + if (IS_ERR(scan_type)) + return PTR_ERR(scan_type); + + if (chan->differential) *val = (st->vref_uv * 2) / MILLI; - *val2 = scan_type->realbits; - return IIO_VAL_FRACTIONAL_LOG2; - } + else + *val = st->vref_uv / MILLI; + + *val2 = scan_type->realbits; - *val = st->vref_uv / MILLI; - *val2 = chan->scan_type.realbits; return IIO_VAL_FRACTIONAL_LOG2; } @@ -561,11 +557,6 @@ static int ad4030_set_mode(struct iio_dev *indio_dev, unsigned long mask) st->mode = AD4030_OUT_DATA_MD_DIFF; } - st->current_scan_type = iio_get_current_scan_type(indio_dev, - st->chip->channels); - if (IS_ERR(st->current_scan_type)) - return PTR_ERR(st->current_scan_type); - return regmap_update_bits(st->regmap, AD4030_REG_MODES, AD4030_REG_MODES_MASK_OUT_DATA_MODE, st->mode); @@ -613,15 +604,20 @@ static void ad4030_extract_interleaved(u8 *src, u32 *ch0, u32 *ch1) static int ad4030_conversion(struct iio_dev *indio_dev) { struct ad4030_state *st = iio_priv(indio_dev); - unsigned char diff_realbytes = - BITS_TO_BYTES(st->current_scan_type->realbits); - unsigned char diff_storagebytes = - BITS_TO_BYTES(st->current_scan_type->storagebits); + const struct iio_scan_type *scan_type; + unsigned char diff_realbytes, diff_storagebytes; unsigned int bytes_to_read; unsigned long cnv_nb = BIT(st->avg_log2); unsigned int i; int ret; + scan_type = iio_get_current_scan_type(indio_dev, st->chip->channels); + if (IS_ERR(scan_type)) + return PTR_ERR(scan_type); + + diff_realbytes = BITS_TO_BYTES(scan_type->realbits); + diff_storagebytes = BITS_TO_BYTES(scan_type->storagebits); + /* Number of bytes for one differential channel */ bytes_to_read = diff_realbytes; /* Add one byte if we are using a differential + common byte mode */ @@ -646,6 +642,12 @@ static int ad4030_conversion(struct iio_dev *indio_dev) &st->rx_data.dual.diff[0], &st->rx_data.dual.diff[1]); + /* + * If no common mode voltage channel is enabled, we can use the raw + * data as is. Otherwise, we need to rearrange the data a bit to match + * the natural alignment of the IIO buffer. + */ + if (st->mode != AD4030_OUT_DATA_MD_16_DIFF_8_COM && st->mode != AD4030_OUT_DATA_MD_24_DIFF_8_COM) return 0; @@ -672,11 +674,6 @@ static int ad4030_single_conversion(struct iio_dev *indio_dev, if (ret) return ret; - st->current_scan_type = iio_get_current_scan_type(indio_dev, - st->chip->channels); - if (IS_ERR(st->current_scan_type)) - return PTR_ERR(st->current_scan_type); - ret = ad4030_conversion(indio_dev); if (ret) return ret; @@ -706,8 +703,8 @@ static irqreturn_t ad4030_trigger_handler(int irq, void *p) if (ret) goto out; - iio_push_to_buffers_with_timestamp(indio_dev, st->rx_data.raw, - pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &st->rx_data, sizeof(st->rx_data), + pf->timestamp); out: iio_trigger_notify_done(indio_dev->trig); @@ -867,6 +864,12 @@ static int ad4030_get_current_scan_type(const struct iio_dev *indio_dev, return st->avg_log2 ? AD4030_SCAN_TYPE_AVG : AD4030_SCAN_TYPE_NORMAL; } +static int ad4030_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + return ad4030_set_mode(indio_dev, *scan_mask); +} + static const struct iio_info ad4030_iio_info = { .read_avail = ad4030_read_avail, .read_raw = ad4030_read_raw, @@ -874,13 +877,9 @@ static const struct iio_info ad4030_iio_info = { .debugfs_reg_access = ad4030_reg_access, .read_label = ad4030_read_label, .get_current_scan_type = ad4030_get_current_scan_type, + .update_scan_mode = ad4030_update_scan_mode, }; -static int ad4030_buffer_preenable(struct iio_dev *indio_dev) -{ - return ad4030_set_mode(indio_dev, *indio_dev->active_scan_mask); -} - static bool ad4030_validate_scan_mask(struct iio_dev *indio_dev, const unsigned long *scan_mask) { @@ -894,7 +893,6 @@ static bool ad4030_validate_scan_mask(struct iio_dev *indio_dev, } static const struct iio_buffer_setup_ops ad4030_buffer_setup_ops = { - .preenable = ad4030_buffer_preenable, .validate_scan_mask = ad4030_validate_scan_mask, }; diff --git a/drivers/iio/adc/ad4130.c b/drivers/iio/adc/ad4130.c index 0f4c9cd6c102..6cf790ff3eb5 100644 --- a/drivers/iio/adc/ad4130.c +++ b/drivers/iio/adc/ad4130.c @@ -522,15 +522,15 @@ static int ad4130_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) return GPIO_LINE_DIRECTION_OUT; } -static void ad4130_gpio_set(struct gpio_chip *gc, unsigned int offset, - int value) +static int ad4130_gpio_set(struct gpio_chip *gc, unsigned int offset, + int value) { struct ad4130_state *st = gpiochip_get_data(gc); unsigned int mask = FIELD_PREP(AD4130_IO_CONTROL_GPIO_DATA_MASK, BIT(offset)); - regmap_update_bits(st->regmap, AD4130_IO_CONTROL_REG, mask, - value ? mask : 0); + return regmap_update_bits(st->regmap, AD4130_IO_CONTROL_REG, mask, + value ? mask : 0); } static int ad4130_set_mode(struct ad4130_state *st, enum ad4130_mode mode) @@ -2064,7 +2064,7 @@ static int ad4130_probe(struct spi_device *spi) st->gc.can_sleep = true; st->gc.init_valid_mask = ad4130_gpio_init_valid_mask; st->gc.get_direction = ad4130_gpio_get_direction; - st->gc.set = ad4130_gpio_set; + st->gc.set_rv = ad4130_gpio_set; ret = devm_gpiochip_add_data(dev, &st->gc, st); if (ret) diff --git a/drivers/iio/adc/ad4695.c b/drivers/iio/adc/ad4695.c index 8222c8ab2940..cda419638d9a 100644 --- a/drivers/iio/adc/ad4695.c +++ b/drivers/iio/adc/ad4695.c @@ -105,9 +105,7 @@ #define AD4695_REG_ACCESS_SCLK_HZ (10 * MEGA) /* Max number of voltage input channels. */ -#define AD4695_MAX_CHANNELS 16 -/* Max size of 1 raw sample in bytes. */ -#define AD4695_MAX_CHANNEL_SIZE 2 +#define AD4695_MAX_VIN_CHANNELS 16 enum ad4695_in_pair { AD4695_IN_PAIR_REFGND, @@ -145,8 +143,8 @@ struct ad4695_state { /* offload also requires separate gpio to manually control CNV */ struct gpio_desc *cnv_gpio; /* voltages channels plus temperature and timestamp */ - struct iio_chan_spec iio_chan[AD4695_MAX_CHANNELS + 2]; - struct ad4695_channel_config channels_cfg[AD4695_MAX_CHANNELS]; + struct iio_chan_spec iio_chan[AD4695_MAX_VIN_CHANNELS + 2]; + struct ad4695_channel_config channels_cfg[AD4695_MAX_VIN_CHANNELS]; const struct ad4695_chip_info *chip_info; int sample_freq_range[3]; /* Reference voltage. */ @@ -159,11 +157,10 @@ struct ad4695_state { * to control CS and add a delay between the last SCLK and next * CNV rising edges. */ - struct spi_transfer buf_read_xfer[AD4695_MAX_CHANNELS * 2 + 3]; + struct spi_transfer buf_read_xfer[AD4695_MAX_VIN_CHANNELS * 2 + 3]; struct spi_message buf_read_msg; /* Raw conversion data received. */ - u8 buf[ALIGN((AD4695_MAX_CHANNELS + 2) * AD4695_MAX_CHANNEL_SIZE, - sizeof(s64)) + sizeof(s64)] __aligned(IIO_DMA_MINALIGN); + IIO_DECLARE_DMA_BUFFER_WITH_TS(u16, buf, AD4695_MAX_VIN_CHANNELS + 1); u16 raw_data; /* Commands to send for single conversion. */ u16 cnv_cmd; @@ -660,9 +657,8 @@ static int ad4695_buffer_preenable(struct iio_dev *indio_dev) iio_for_each_active_channel(indio_dev, bit) { xfer = &st->buf_read_xfer[num_xfer]; xfer->bits_per_word = 16; - xfer->rx_buf = &st->buf[rx_buf_offset]; + xfer->rx_buf = &st->buf[rx_buf_offset++]; xfer->len = 2; - rx_buf_offset += xfer->len; if (bit == temp_chan_bit) { temp_en = 1; @@ -801,7 +797,8 @@ static irqreturn_t ad4695_trigger_handler(int irq, void *p) if (ret) goto out; - iio_push_to_buffers_with_timestamp(indio_dev, st->buf, pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, st->buf, sizeof(st->buf), + pf->timestamp); out: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/adc/ad4851.c b/drivers/iio/adc/ad4851.c index 98ebc853db79..f1d2e2896f2a 100644 --- a/drivers/iio/adc/ad4851.c +++ b/drivers/iio/adc/ad4851.c @@ -1034,7 +1034,7 @@ static int ad4858_parse_channels(struct iio_dev *indio_dev) struct device *dev = &st->spi->dev; struct iio_chan_spec *ad4851_channels; const struct iio_chan_spec ad4851_chan = AD4858_IIO_CHANNEL; - int ret; + int ret, i = 0; ret = ad4851_parse_channels_common(indio_dev, &ad4851_channels, ad4851_chan); @@ -1042,15 +1042,15 @@ static int ad4858_parse_channels(struct iio_dev *indio_dev) return ret; device_for_each_child_node_scoped(dev, child) { - ad4851_channels->has_ext_scan_type = 1; + ad4851_channels[i].has_ext_scan_type = 1; if (fwnode_property_read_bool(child, "bipolar")) { - ad4851_channels->ext_scan_type = ad4851_scan_type_20_b; - ad4851_channels->num_ext_scan_type = ARRAY_SIZE(ad4851_scan_type_20_b); + ad4851_channels[i].ext_scan_type = ad4851_scan_type_20_b; + ad4851_channels[i].num_ext_scan_type = ARRAY_SIZE(ad4851_scan_type_20_b); } else { - ad4851_channels->ext_scan_type = ad4851_scan_type_20_u; - ad4851_channels->num_ext_scan_type = ARRAY_SIZE(ad4851_scan_type_20_u); + ad4851_channels[i].ext_scan_type = ad4851_scan_type_20_u; + ad4851_channels[i].num_ext_scan_type = ARRAY_SIZE(ad4851_scan_type_20_u); } - ad4851_channels++; + i++; } indio_dev->channels = ad4851_channels; diff --git a/drivers/iio/adc/ad7091r-base.c b/drivers/iio/adc/ad7091r-base.c index 931ff71b2888..647a7852dd8d 100644 --- a/drivers/iio/adc/ad7091r-base.c +++ b/drivers/iio/adc/ad7091r-base.c @@ -387,13 +387,8 @@ EXPORT_SYMBOL_NS_GPL(ad7091r_writeable_reg, "IIO_AD7091R"); bool ad7091r_volatile_reg(struct device *dev, unsigned int reg) { - switch (reg) { - case AD7091R_REG_RESULT: - case AD7091R_REG_ALERT: - return true; - default: - return false; - } + /* The volatile ad7091r registers are also the only RO ones. */ + return !ad7091r_writeable_reg(dev, reg); } EXPORT_SYMBOL_NS_GPL(ad7091r_volatile_reg, "IIO_AD7091R"); diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index 3ea81a98e455..92596f15e797 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -32,7 +32,7 @@ #define AD7124_IO_CONTROL_2 0x04 #define AD7124_ID 0x05 #define AD7124_ERROR 0x06 -#define AD7124_ERROR_EN 0x07 +#define AD7124_ERROR_EN 0x07 #define AD7124_MCLK_COUNT 0x08 #define AD7124_CHANNEL(x) (0x09 + (x)) #define AD7124_CONFIG(x) (0x19 + (x)) @@ -41,68 +41,58 @@ #define AD7124_GAIN(x) (0x31 + (x)) /* AD7124_STATUS */ -#define AD7124_STATUS_POR_FLAG_MSK BIT(4) +#define AD7124_STATUS_POR_FLAG BIT(4) /* AD7124_ADC_CONTROL */ -#define AD7124_ADC_STATUS_EN_MSK BIT(10) -#define AD7124_ADC_STATUS_EN(x) FIELD_PREP(AD7124_ADC_STATUS_EN_MSK, x) -#define AD7124_ADC_CTRL_REF_EN_MSK BIT(8) -#define AD7124_ADC_CTRL_REF_EN(x) FIELD_PREP(AD7124_ADC_CTRL_REF_EN_MSK, x) -#define AD7124_ADC_CTRL_PWR_MSK GENMASK(7, 6) -#define AD7124_ADC_CTRL_PWR(x) FIELD_PREP(AD7124_ADC_CTRL_PWR_MSK, x) -#define AD7124_ADC_CTRL_MODE_MSK GENMASK(5, 2) -#define AD7124_ADC_CTRL_MODE(x) FIELD_PREP(AD7124_ADC_CTRL_MODE_MSK, x) - -#define AD7124_MODE_CAL_INT_ZERO 0x5 /* Internal Zero-Scale Calibration */ -#define AD7124_MODE_CAL_INT_FULL 0x6 /* Internal Full-Scale Calibration */ -#define AD7124_MODE_CAL_SYS_ZERO 0x7 /* System Zero-Scale Calibration */ -#define AD7124_MODE_CAL_SYS_FULL 0x8 /* System Full-Scale Calibration */ - -/* AD7124 ID */ -#define AD7124_DEVICE_ID_MSK GENMASK(7, 4) -#define AD7124_DEVICE_ID_GET(x) FIELD_GET(AD7124_DEVICE_ID_MSK, x) -#define AD7124_SILICON_REV_MSK GENMASK(3, 0) -#define AD7124_SILICON_REV_GET(x) FIELD_GET(AD7124_SILICON_REV_MSK, x) - -#define CHIPID_AD7124_4 0x0 -#define CHIPID_AD7124_8 0x1 +#define AD7124_ADC_CONTROL_MODE GENMASK(5, 2) +#define AD7124_ADC_CONTROL_MODE_CONTINUOUS 0 +#define AD7124_ADC_CONTROL_MODE_SINGLE 1 +#define AD7124_ADC_CONTROL_MODE_STANDBY 2 +#define AD7124_ADC_CONTROL_MODE_POWERDOWN 3 +#define AD7124_ADC_CONTROL_MODE_IDLE 4 +#define AD7124_ADC_CONTROL_MODE_INT_OFFSET_CALIB 5 /* Internal Zero-Scale Calibration */ +#define AD7124_ADC_CONTROL_MODE_INT_GAIN_CALIB 6 /* Internal Full-Scale Calibration */ +#define AD7124_ADC_CONTROL_MODE_SYS_OFFSET_CALIB 7 /* System Zero-Scale Calibration */ +#define AD7124_ADC_CONTROL_MODE_SYS_GAIN_CALIB 8 /* System Full-Scale Calibration */ +#define AD7124_ADC_CONTROL_POWER_MODE GENMASK(7, 6) +#define AD7124_ADC_CONTROL_POWER_MODE_LOW 0 +#define AD7124_ADC_CONTROL_POWER_MODE_MID 1 +#define AD7124_ADC_CONTROL_POWER_MODE_FULL 2 +#define AD7124_ADC_CONTROL_REF_EN BIT(8) +#define AD7124_ADC_CONTROL_DATA_STATUS BIT(10) + +/* AD7124_ID */ +#define AD7124_ID_SILICON_REVISION GENMASK(3, 0) +#define AD7124_ID_DEVICE_ID GENMASK(7, 4) +#define AD7124_ID_DEVICE_ID_AD7124_4 0x0 +#define AD7124_ID_DEVICE_ID_AD7124_8 0x1 /* AD7124_CHANNEL_X */ -#define AD7124_CHANNEL_EN_MSK BIT(15) -#define AD7124_CHANNEL_EN(x) FIELD_PREP(AD7124_CHANNEL_EN_MSK, x) -#define AD7124_CHANNEL_SETUP_MSK GENMASK(14, 12) -#define AD7124_CHANNEL_SETUP(x) FIELD_PREP(AD7124_CHANNEL_SETUP_MSK, x) -#define AD7124_CHANNEL_AINP_MSK GENMASK(9, 5) -#define AD7124_CHANNEL_AINP(x) FIELD_PREP(AD7124_CHANNEL_AINP_MSK, x) -#define AD7124_CHANNEL_AINM_MSK GENMASK(4, 0) -#define AD7124_CHANNEL_AINM(x) FIELD_PREP(AD7124_CHANNEL_AINM_MSK, x) +#define AD7124_CHANNEL_ENABLE BIT(15) +#define AD7124_CHANNEL_SETUP GENMASK(14, 12) +#define AD7124_CHANNEL_AINP GENMASK(9, 5) +#define AD7124_CHANNEL_AINM GENMASK(4, 0) +#define AD7124_CHANNEL_AINx_TEMPSENSOR 16 +#define AD7124_CHANNEL_AINx_AVSS 17 /* AD7124_CONFIG_X */ -#define AD7124_CONFIG_BIPOLAR_MSK BIT(11) -#define AD7124_CONFIG_BIPOLAR(x) FIELD_PREP(AD7124_CONFIG_BIPOLAR_MSK, x) -#define AD7124_CONFIG_REF_SEL_MSK GENMASK(4, 3) -#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(6, 5) -#define AD7124_CONFIG_IN_BUFF(x) FIELD_PREP(AD7124_CONFIG_IN_BUFF_MSK, x) +#define AD7124_CONFIG_BIPOLAR BIT(11) +#define AD7124_CONFIG_IN_BUFF GENMASK(6, 5) +#define AD7124_CONFIG_AIN_BUFP BIT(6) +#define AD7124_CONFIG_AIN_BUFM BIT(5) +#define AD7124_CONFIG_REF_SEL GENMASK(4, 3) +#define AD7124_CONFIG_PGA GENMASK(2, 0) /* AD7124_FILTER_X */ -#define AD7124_FILTER_FS_MSK GENMASK(10, 0) -#define AD7124_FILTER_FS(x) FIELD_PREP(AD7124_FILTER_FS_MSK, x) -#define AD7124_FILTER_TYPE_MSK GENMASK(23, 21) -#define AD7124_FILTER_TYPE_SEL(x) FIELD_PREP(AD7124_FILTER_TYPE_MSK, x) +#define AD7124_FILTER_FS GENMASK(10, 0) +#define AD7124_FILTER_FILTER GENMASK(23, 21) +#define AD7124_FILTER_FILTER_SINC4 0 +#define AD7124_FILTER_FILTER_SINC3 2 -#define AD7124_SINC3_FILTER 2 -#define AD7124_SINC4_FILTER 0 - -#define AD7124_CONF_ADDR_OFFSET 20 #define AD7124_MAX_CONFIGS 8 #define AD7124_MAX_CHANNELS 16 /* AD7124 input sources */ -#define AD7124_INPUT_TEMPSENSOR 16 -#define AD7124_INPUT_AVSS 17 enum ad7124_ids { ID_AD7124_4, @@ -206,12 +196,12 @@ struct ad7124_state { static struct ad7124_chip_info ad7124_chip_info_tbl[] = { [ID_AD7124_4] = { .name = "ad7124-4", - .chip_id = CHIPID_AD7124_4, + .chip_id = AD7124_ID_DEVICE_ID_AD7124_4, .num_inputs = 8, }, [ID_AD7124_8] = { .name = "ad7124-8", - .chip_id = CHIPID_AD7124_8, + .chip_id = AD7124_ID_DEVICE_ID_AD7124_8, .num_inputs = 16, }, }; @@ -260,8 +250,8 @@ static int ad7124_set_mode(struct ad_sigma_delta *sd, { struct ad7124_state *st = container_of(sd, struct ad7124_state, sd); - st->adc_control &= ~AD7124_ADC_CTRL_MODE_MSK; - st->adc_control |= AD7124_ADC_CTRL_MODE(mode); + st->adc_control &= ~AD7124_ADC_CONTROL_MODE; + st->adc_control |= FIELD_PREP(AD7124_ADC_CONTROL_MODE, mode); return ad_sd_write_reg(&st->sd, AD7124_ADC_CONTROL, 2, st->adc_control); } @@ -300,41 +290,15 @@ static int ad7124_get_3db_filter_freq(struct ad7124_state *st, fadc = st->channels[channel].cfg.odr; switch (st->channels[channel].cfg.filter_type) { - case AD7124_SINC3_FILTER: + case AD7124_FILTER_FILTER_SINC3: + return DIV_ROUND_CLOSEST(fadc * 272, 1000); + case AD7124_FILTER_FILTER_SINC4: return DIV_ROUND_CLOSEST(fadc * 230, 1000); - case AD7124_SINC4_FILTER: - return DIV_ROUND_CLOSEST(fadc * 262, 1000); default: return -EINVAL; } } -static void ad7124_set_3db_filter_freq(struct ad7124_state *st, unsigned int channel, - unsigned int freq) -{ - unsigned int sinc4_3db_odr; - unsigned int sinc3_3db_odr; - unsigned int new_filter; - unsigned int new_odr; - - sinc4_3db_odr = DIV_ROUND_CLOSEST(freq * 1000, 230); - sinc3_3db_odr = DIV_ROUND_CLOSEST(freq * 1000, 262); - - if (sinc4_3db_odr > sinc3_3db_odr) { - new_filter = AD7124_SINC3_FILTER; - new_odr = sinc4_3db_odr; - } else { - new_filter = AD7124_SINC4_FILTER; - new_odr = sinc3_3db_odr; - } - - if (new_odr != st->channels[channel].cfg.odr) - st->channels[channel].cfg.live = false; - - st->channels[channel].cfg.filter_type = new_filter; - st->channels[channel].cfg.odr = new_odr; -} - static struct ad7124_channel_config *ad7124_find_similar_live_cfg(struct ad7124_state *st, struct ad7124_channel_config *cfg) { @@ -413,8 +377,7 @@ static int ad7124_init_config_vref(struct ad7124_state *st, struct ad7124_channe return 0; case AD7124_INT_REF: cfg->vref_mv = 2500; - st->adc_control &= ~AD7124_ADC_CTRL_REF_EN_MSK; - st->adc_control |= AD7124_ADC_CTRL_REF_EN(1); + st->adc_control |= AD7124_ADC_CONTROL_REF_EN; return 0; default: return dev_err_probe(dev, -EINVAL, "Invalid reference %d\n", refsel); @@ -438,18 +401,20 @@ static int ad7124_write_config(struct ad7124_state *st, struct ad7124_channel_co if (ret) return ret; - tmp = (cfg->buf_positive << 1) + cfg->buf_negative; - val = AD7124_CONFIG_BIPOLAR(cfg->bipolar) | AD7124_CONFIG_REF_SEL(cfg->refsel) | - AD7124_CONFIG_IN_BUFF(tmp) | AD7124_CONFIG_PGA(cfg->pga_bits); + val = FIELD_PREP(AD7124_CONFIG_BIPOLAR, cfg->bipolar) | + FIELD_PREP(AD7124_CONFIG_REF_SEL, cfg->refsel) | + (cfg->buf_positive ? AD7124_CONFIG_AIN_BUFP : 0) | + (cfg->buf_negative ? AD7124_CONFIG_AIN_BUFM : 0) | + FIELD_PREP(AD7124_CONFIG_PGA, cfg->pga_bits); ret = ad_sd_write_reg(&st->sd, AD7124_CONFIG(cfg->cfg_slot), 2, val); if (ret < 0) return ret; - tmp = AD7124_FILTER_TYPE_SEL(cfg->filter_type) | - AD7124_FILTER_FS(cfg->odr_sel_bits); + tmp = FIELD_PREP(AD7124_FILTER_FILTER, cfg->filter_type) | + FIELD_PREP(AD7124_FILTER_FS, cfg->odr_sel_bits); return ad7124_spi_write_mask(st, AD7124_FILTER(cfg->cfg_slot), - AD7124_FILTER_TYPE_MSK | AD7124_FILTER_FS_MSK, + AD7124_FILTER_FILTER | AD7124_FILTER_FS, tmp, 3); } @@ -514,7 +479,8 @@ static int ad7124_enable_channel(struct ad7124_state *st, struct ad7124_channel { ch->cfg.live = true; return ad_sd_write_reg(&st->sd, AD7124_CHANNEL(ch->nr), 2, ch->ain | - AD7124_CHANNEL_SETUP(ch->cfg.cfg_slot) | AD7124_CHANNEL_EN(1)); + FIELD_PREP(AD7124_CHANNEL_SETUP, ch->cfg.cfg_slot) | + AD7124_CHANNEL_ENABLE); } static int ad7124_prepare_read(struct ad7124_state *st, int address) @@ -564,8 +530,10 @@ static int ad7124_append_status(struct ad_sigma_delta *sd, bool append) unsigned int adc_control = st->adc_control; int ret; - adc_control &= ~AD7124_ADC_STATUS_EN_MSK; - adc_control |= AD7124_ADC_STATUS_EN(append); + if (append) + adc_control |= AD7124_ADC_CONTROL_DATA_STATUS; + else + adc_control &= ~AD7124_ADC_CONTROL_DATA_STATUS; ret = ad_sd_write_reg(&st->sd, AD7124_ADC_CONTROL, 2, adc_control); if (ret < 0) @@ -580,7 +548,7 @@ static int ad7124_disable_one(struct ad_sigma_delta *sd, unsigned int chan) { struct ad7124_state *st = container_of(sd, struct ad7124_state, sd); - /* The relevant thing here is that AD7124_CHANNEL_EN_MSK is cleared. */ + /* The relevant thing here is that AD7124_CHANNEL_ENABLE is cleared. */ return ad_sd_write_reg(&st->sd, AD7124_CHANNEL(chan), 2, 0); } @@ -739,16 +707,8 @@ static int ad7124_write_raw(struct iio_dev *indio_dev, st->channels[chan->address].cfg.pga_bits = res; break; - case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: - if (val2 != 0) { - ret = -EINVAL; - break; - } - - ad7124_set_3db_filter_freq(st, chan->address, val); - break; default: - ret = -EINVAL; + ret = -EINVAL; } mutex_unlock(&st->cfgs_lock); @@ -802,7 +762,7 @@ static int ad7124_update_scan_mode(struct iio_dev *indio_dev, if (bit_set) ret = __ad7124_set_channel(&st->sd, i); else - ret = ad7124_spi_write_mask(st, AD7124_CHANNEL(i), AD7124_CHANNEL_EN_MSK, + ret = ad7124_spi_write_mask(st, AD7124_CHANNEL(i), AD7124_CHANNEL_ENABLE, 0, 2); if (ret < 0) { mutex_unlock(&st->cfgs_lock); @@ -843,14 +803,14 @@ static int ad7124_soft_reset(struct ad7124_state *st) if (ret < 0) return dev_err_probe(dev, ret, "Error reading status register\n"); - if (!(readval & AD7124_STATUS_POR_FLAG_MSK)) + if (!(readval & AD7124_STATUS_POR_FLAG)) break; /* The AD7124 requires typically 2ms to power up and settle */ usleep_range(100, 2000); } while (--timeout); - if (readval & AD7124_STATUS_POR_FLAG_MSK) + if (readval & AD7124_STATUS_POR_FLAG) return dev_err_probe(dev, -EIO, "Soft reset failed\n"); ret = ad_sd_read_reg(&st->sd, AD7124_GAIN(0), 3, &st->gain_default); @@ -872,8 +832,8 @@ static int ad7124_check_chip_id(struct ad7124_state *st) if (ret < 0) return dev_err_probe(dev, ret, "Failure to read ID register\n"); - chip_id = AD7124_DEVICE_ID_GET(readval); - silicon_rev = AD7124_SILICON_REV_GET(readval); + chip_id = FIELD_GET(AD7124_ID_DEVICE_ID, readval); + silicon_rev = FIELD_GET(AD7124_ID_SILICON_REVISION, readval); if (chip_id != st->chip_info->chip_id) return dev_err_probe(dev, -ENODEV, @@ -901,7 +861,7 @@ static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan if (ch->syscalib_mode == AD7124_SYSCALIB_ZERO_SCALE) { ch->cfg.calibration_offset = 0x800000; - ret = ad_sd_calibrate(&st->sd, AD7124_MODE_CAL_SYS_ZERO, + ret = ad_sd_calibrate(&st->sd, AD7124_ADC_CONTROL_MODE_SYS_OFFSET_CALIB, chan->address); if (ret < 0) return ret; @@ -916,7 +876,7 @@ static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan } else { ch->cfg.calibration_gain = st->gain_default; - ret = ad_sd_calibrate(&st->sd, AD7124_MODE_CAL_SYS_FULL, + ret = ad_sd_calibrate(&st->sd, AD7124_ADC_CONTROL_MODE_SYS_GAIN_CALIB, chan->address); if (ret < 0) return ret; @@ -1031,7 +991,7 @@ static bool ad7124_valid_input_select(unsigned int ain, const struct ad7124_chip if (ain >= info->num_inputs && ain < 16) return false; - return ain <= FIELD_MAX(AD7124_CHANNEL_AINM_MSK); + return ain <= FIELD_MAX(AD7124_CHANNEL_AINM); } static int ad7124_parse_channel_config(struct iio_dev *indio_dev, @@ -1096,8 +1056,8 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev, "diff-channels property of %pfwP contains invalid data\n", child); st->channels[channel].nr = channel; - st->channels[channel].ain = AD7124_CHANNEL_AINP(ain[0]) | - AD7124_CHANNEL_AINM(ain[1]); + st->channels[channel].ain = FIELD_PREP(AD7124_CHANNEL_AINP, ain[0]) | + FIELD_PREP(AD7124_CHANNEL_AINM, ain[1]); cfg = &st->channels[channel].cfg; cfg->bipolar = fwnode_property_read_bool(child, "bipolar"); @@ -1123,8 +1083,8 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev, if (num_channels < AD7124_MAX_CHANNELS) { st->channels[num_channels] = (struct ad7124_channel) { .nr = num_channels, - .ain = AD7124_CHANNEL_AINP(AD7124_INPUT_TEMPSENSOR) | - AD7124_CHANNEL_AINM(AD7124_INPUT_AVSS), + .ain = FIELD_PREP(AD7124_CHANNEL_AINP, AD7124_CHANNEL_AINx_TEMPSENSOR) | + FIELD_PREP(AD7124_CHANNEL_AINM, AD7124_CHANNEL_AINx_AVSS), .cfg = { .bipolar = true, }, @@ -1175,11 +1135,11 @@ static int ad7124_setup(struct ad7124_state *st) } /* Set the power mode */ - st->adc_control &= ~AD7124_ADC_CTRL_PWR_MSK; - st->adc_control |= AD7124_ADC_CTRL_PWR(power_mode); + st->adc_control &= ~AD7124_ADC_CONTROL_POWER_MODE; + st->adc_control |= FIELD_PREP(AD7124_ADC_CONTROL_POWER_MODE, power_mode); - st->adc_control &= ~AD7124_ADC_CTRL_MODE_MSK; - st->adc_control |= AD7124_ADC_CTRL_MODE(AD_SD_MODE_IDLE); + st->adc_control &= ~AD7124_ADC_CONTROL_MODE; + st->adc_control |= FIELD_PREP(AD7124_ADC_CONTROL_MODE, AD_SD_MODE_IDLE); mutex_init(&st->cfgs_lock); INIT_KFIFO(st->live_cfgs_fifo); @@ -1233,7 +1193,7 @@ static int __ad7124_calibrate_all(struct ad7124_state *st, struct iio_dev *indio * usual: first zero-scale then full-scale calibration. */ if (st->channels[i].cfg.pga_bits > 0) { - ret = ad_sd_calibrate(&st->sd, AD7124_MODE_CAL_INT_FULL, i); + ret = ad_sd_calibrate(&st->sd, AD7124_ADC_CONTROL_MODE_INT_GAIN_CALIB, i); if (ret < 0) return ret; @@ -1250,7 +1210,7 @@ static int __ad7124_calibrate_all(struct ad7124_state *st, struct iio_dev *indio return ret; } - ret = ad_sd_calibrate(&st->sd, AD7124_MODE_CAL_INT_ZERO, i); + ret = ad_sd_calibrate(&st->sd, AD7124_ADC_CONTROL_MODE_INT_OFFSET_CALIB, i); if (ret < 0) return ret; @@ -1279,9 +1239,9 @@ static int ad7124_calibrate_all(struct ad7124_state *st, struct iio_dev *indio_d * The resulting calibration is then also valid for high-speed, so just * restore adc_control afterwards. */ - if (FIELD_GET(AD7124_ADC_CTRL_PWR_MSK, adc_control) >= AD7124_FULL_POWER) { - st->adc_control &= ~AD7124_ADC_CTRL_PWR_MSK; - st->adc_control |= AD7124_ADC_CTRL_PWR(AD7124_MID_POWER); + if (FIELD_GET(AD7124_ADC_CONTROL_POWER_MODE, adc_control) >= AD7124_FULL_POWER) { + st->adc_control &= ~AD7124_ADC_CONTROL_POWER_MODE; + st->adc_control |= FIELD_PREP(AD7124_ADC_CONTROL_POWER_MODE, AD7124_MID_POWER); } ret = __ad7124_calibrate_all(st, indio_dev); diff --git a/drivers/iio/adc/ad7173.c b/drivers/iio/adc/ad7173.c index 69de5886474c..b3e6bd2a55d7 100644 --- a/drivers/iio/adc/ad7173.c +++ b/drivers/iio/adc/ad7173.c @@ -230,10 +230,8 @@ struct ad7173_state { 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 unsigned int ad4115_sinc5_data_rates[] = { @@ -288,8 +286,6 @@ 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), }; @@ -543,12 +539,6 @@ static int ad7173_gpio_init(struct ad7173_state *st) 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) { @@ -1797,10 +1787,7 @@ static int ad7173_probe(struct spi_device *spi) if (ret) return ret; - if (IS_ENABLED(CONFIG_GPIOLIB)) - return ad7173_gpio_init(st); - - return 0; + return ad7173_gpio_init(st); } static const struct of_device_id ad7173_of_match[] = { diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c index 7fef2727f89e..3364ac6c4631 100644 --- a/drivers/iio/adc/ad7266.c +++ b/drivers/iio/adc/ad7266.c @@ -86,10 +86,9 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p) int ret; ret = spi_read(st->spi, st->data.sample, 4); - if (ret == 0) { - iio_push_to_buffers_with_timestamp(indio_dev, &st->data, - pf->timestamp); - } + if (ret == 0) + iio_push_to_buffers_with_ts(indio_dev, &st->data, sizeof(st->data), + pf->timestamp); iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/adc/ad7280a.c b/drivers/iio/adc/ad7280a.c index f9f32737db80..dda2986ccda0 100644 --- a/drivers/iio/adc/ad7280a.c +++ b/drivers/iio/adc/ad7280a.c @@ -572,7 +572,7 @@ static const struct iio_chan_spec_ext_info ad7280_cell_ext_info[] = { .write = ad7280_store_balance_timer, .shared = IIO_SEPARATE, }, - {} + { } }; static const struct iio_event_spec ad7280_events[] = { diff --git a/drivers/iio/adc/ad7298.c b/drivers/iio/adc/ad7298.c index 28b88092b4aa..7c0538ea15c8 100644 --- a/drivers/iio/adc/ad7298.c +++ b/drivers/iio/adc/ad7298.c @@ -155,8 +155,8 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p) if (b_sent) goto done; - iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, st->rx_buf, sizeof(st->rx_buf), + iio_get_time_ns(indio_dev)); done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c index aef85093eb16..d96bd12dfea6 100644 --- a/drivers/iio/adc/ad7380.c +++ b/drivers/iio/adc/ad7380.c @@ -13,6 +13,7 @@ * ad7381-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7381-4.pdf * ad7383/4-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7383-4-ad7384-4.pdf * ad7386/7/8-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7386-4-7387-4-7388-4.pdf + * ad7389-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7389-4.pdf * adaq4370-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4370-4.pdf * adaq4380-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4380-4.pdf * adaq4381-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4381-4.pdf @@ -119,7 +120,8 @@ struct ad7380_chip_info { const char * const *supplies; unsigned int num_supplies; bool external_ref_only; - bool adaq_internal_ref_only; + bool internal_ref_only; + unsigned int internal_ref_mv; const char * const *vcm_supplies; unsigned int num_vcm_supplies; const unsigned long *available_scan_masks; @@ -609,6 +611,7 @@ static const struct ad7380_chip_info ad7380_chip_info = { .num_simult_channels = 2, .supplies = ad7380_supplies, .num_supplies = ARRAY_SIZE(ad7380_supplies), + .internal_ref_mv = AD7380_INTERNAL_REF_MV, .available_scan_masks = ad7380_2_channel_scan_masks, .timing_specs = &ad7380_timing, .max_conversion_rate_hz = 4 * MEGA, @@ -622,6 +625,7 @@ static const struct ad7380_chip_info ad7381_chip_info = { .num_simult_channels = 2, .supplies = ad7380_supplies, .num_supplies = ARRAY_SIZE(ad7380_supplies), + .internal_ref_mv = AD7380_INTERNAL_REF_MV, .available_scan_masks = ad7380_2_channel_scan_masks, .timing_specs = &ad7380_timing, .max_conversion_rate_hz = 4 * MEGA, @@ -637,6 +641,7 @@ static const struct ad7380_chip_info ad7383_chip_info = { .num_supplies = ARRAY_SIZE(ad7380_supplies), .vcm_supplies = ad7380_2_channel_vcm_supplies, .num_vcm_supplies = ARRAY_SIZE(ad7380_2_channel_vcm_supplies), + .internal_ref_mv = AD7380_INTERNAL_REF_MV, .available_scan_masks = ad7380_2_channel_scan_masks, .timing_specs = &ad7380_timing, .max_conversion_rate_hz = 4 * MEGA, @@ -652,6 +657,7 @@ static const struct ad7380_chip_info ad7384_chip_info = { .num_supplies = ARRAY_SIZE(ad7380_supplies), .vcm_supplies = ad7380_2_channel_vcm_supplies, .num_vcm_supplies = ARRAY_SIZE(ad7380_2_channel_vcm_supplies), + .internal_ref_mv = AD7380_INTERNAL_REF_MV, .available_scan_masks = ad7380_2_channel_scan_masks, .timing_specs = &ad7380_timing, .max_conversion_rate_hz = 4 * MEGA, @@ -665,6 +671,7 @@ static const struct ad7380_chip_info ad7386_chip_info = { .num_simult_channels = 2, .supplies = ad7380_supplies, .num_supplies = ARRAY_SIZE(ad7380_supplies), + .internal_ref_mv = AD7380_INTERNAL_REF_MV, .has_mux = true, .available_scan_masks = ad7380_2x2_channel_scan_masks, .timing_specs = &ad7380_timing, @@ -679,6 +686,7 @@ static const struct ad7380_chip_info ad7387_chip_info = { .num_simult_channels = 2, .supplies = ad7380_supplies, .num_supplies = ARRAY_SIZE(ad7380_supplies), + .internal_ref_mv = AD7380_INTERNAL_REF_MV, .has_mux = true, .available_scan_masks = ad7380_2x2_channel_scan_masks, .timing_specs = &ad7380_timing, @@ -693,6 +701,7 @@ static const struct ad7380_chip_info ad7388_chip_info = { .num_simult_channels = 2, .supplies = ad7380_supplies, .num_supplies = ARRAY_SIZE(ad7380_supplies), + .internal_ref_mv = AD7380_INTERNAL_REF_MV, .has_mux = true, .available_scan_masks = ad7380_2x2_channel_scan_masks, .timing_specs = &ad7380_timing, @@ -721,6 +730,7 @@ static const struct ad7380_chip_info ad7381_4_chip_info = { .num_simult_channels = 4, .supplies = ad7380_supplies, .num_supplies = ARRAY_SIZE(ad7380_supplies), + .internal_ref_mv = AD7380_INTERNAL_REF_MV, .available_scan_masks = ad7380_4_channel_scan_masks, .timing_specs = &ad7380_4_timing, .max_conversion_rate_hz = 4 * MEGA, @@ -734,6 +744,7 @@ static const struct ad7380_chip_info ad7383_4_chip_info = { .num_simult_channels = 4, .supplies = ad7380_supplies, .num_supplies = ARRAY_SIZE(ad7380_supplies), + .internal_ref_mv = AD7380_INTERNAL_REF_MV, .vcm_supplies = ad7380_4_channel_vcm_supplies, .num_vcm_supplies = ARRAY_SIZE(ad7380_4_channel_vcm_supplies), .available_scan_masks = ad7380_4_channel_scan_masks, @@ -749,6 +760,7 @@ static const struct ad7380_chip_info ad7384_4_chip_info = { .num_simult_channels = 4, .supplies = ad7380_supplies, .num_supplies = ARRAY_SIZE(ad7380_supplies), + .internal_ref_mv = AD7380_INTERNAL_REF_MV, .vcm_supplies = ad7380_4_channel_vcm_supplies, .num_vcm_supplies = ARRAY_SIZE(ad7380_4_channel_vcm_supplies), .available_scan_masks = ad7380_4_channel_scan_masks, @@ -764,6 +776,7 @@ static const struct ad7380_chip_info ad7386_4_chip_info = { .num_simult_channels = 4, .supplies = ad7380_supplies, .num_supplies = ARRAY_SIZE(ad7380_supplies), + .internal_ref_mv = AD7380_INTERNAL_REF_MV, .has_mux = true, .available_scan_masks = ad7380_2x4_channel_scan_masks, .timing_specs = &ad7380_4_timing, @@ -778,6 +791,7 @@ static const struct ad7380_chip_info ad7387_4_chip_info = { .num_simult_channels = 4, .supplies = ad7380_supplies, .num_supplies = ARRAY_SIZE(ad7380_supplies), + .internal_ref_mv = AD7380_INTERNAL_REF_MV, .has_mux = true, .available_scan_masks = ad7380_2x4_channel_scan_masks, .timing_specs = &ad7380_4_timing, @@ -792,12 +806,28 @@ static const struct ad7380_chip_info ad7388_4_chip_info = { .num_simult_channels = 4, .supplies = ad7380_supplies, .num_supplies = ARRAY_SIZE(ad7380_supplies), + .internal_ref_mv = AD7380_INTERNAL_REF_MV, .has_mux = true, .available_scan_masks = ad7380_2x4_channel_scan_masks, .timing_specs = &ad7380_4_timing, .max_conversion_rate_hz = 4 * MEGA, }; +static const struct ad7380_chip_info ad7389_4_chip_info = { + .name = "ad7389-4", + .channels = ad7380_4_channels, + .offload_channels = ad7380_4_offload_channels, + .num_channels = ARRAY_SIZE(ad7380_4_channels), + .num_simult_channels = 4, + .supplies = ad7380_supplies, + .num_supplies = ARRAY_SIZE(ad7380_supplies), + .internal_ref_only = true, + .internal_ref_mv = AD7380_INTERNAL_REF_MV, + .available_scan_masks = ad7380_4_channel_scan_masks, + .timing_specs = &ad7380_4_timing, + .max_conversion_rate_hz = 4 * MEGA, +}; + static const struct ad7380_chip_info adaq4370_4_chip_info = { .name = "adaq4370-4", .channels = adaq4380_4_channels, @@ -806,7 +836,8 @@ static const struct ad7380_chip_info adaq4370_4_chip_info = { .num_simult_channels = 4, .supplies = adaq4380_supplies, .num_supplies = ARRAY_SIZE(adaq4380_supplies), - .adaq_internal_ref_only = true, + .internal_ref_only = true, + .internal_ref_mv = ADAQ4380_INTERNAL_REF_MV, .has_hardware_gain = true, .available_scan_masks = ad7380_4_channel_scan_masks, .timing_specs = &ad7380_4_timing, @@ -821,7 +852,8 @@ static const struct ad7380_chip_info adaq4380_4_chip_info = { .num_simult_channels = 4, .supplies = adaq4380_supplies, .num_supplies = ARRAY_SIZE(adaq4380_supplies), - .adaq_internal_ref_only = true, + .internal_ref_only = true, + .internal_ref_mv = ADAQ4380_INTERNAL_REF_MV, .has_hardware_gain = true, .available_scan_masks = ad7380_4_channel_scan_masks, .timing_specs = &ad7380_4_timing, @@ -836,7 +868,8 @@ static const struct ad7380_chip_info adaq4381_4_chip_info = { .num_simult_channels = 4, .supplies = adaq4380_supplies, .num_supplies = ARRAY_SIZE(adaq4380_supplies), - .adaq_internal_ref_only = true, + .internal_ref_only = true, + .internal_ref_mv = ADAQ4380_INTERNAL_REF_MV, .has_hardware_gain = true, .available_scan_masks = ad7380_4_channel_scan_masks, .timing_specs = &ad7380_4_timing, @@ -876,8 +909,7 @@ struct ad7380_state { * Make the buffer large enough for MAX_NUM_CHANNELS 32-bit samples and * one 64-bit aligned 64-bit timestamp. */ - u8 scan_data[ALIGN(MAX_NUM_CHANNELS * sizeof(u32), sizeof(s64)) - + sizeof(s64)] __aligned(IIO_DMA_MINALIGN); + IIO_DECLARE_DMA_BUFFER_WITH_TS(u8, scan_data, MAX_NUM_CHANNELS * sizeof(u32)); /* buffers for reading/writing registers */ u16 tx; u16 rx; @@ -1327,8 +1359,8 @@ static irqreturn_t ad7380_trigger_handler(int irq, void *p) if (ret) goto out; - iio_push_to_buffers_with_timestamp(indio_dev, &st->scan_data, - pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &st->scan_data, sizeof(st->scan_data), + pf->timestamp); out: iio_trigger_notify_done(indio_dev->trig); @@ -1859,7 +1891,7 @@ static int ad7380_probe(struct spi_device *spi) "Failed to enable power supplies\n"); fsleep(T_POWERUP_US); - if (st->chip_info->adaq_internal_ref_only) { + if (st->chip_info->internal_ref_only) { /* * ADAQ chips use fixed internal reference but still * require a specific reference supply to power it. @@ -1867,7 +1899,7 @@ static int ad7380_probe(struct spi_device *spi) * in bulk_get_enable(). */ - st->vref_mv = ADAQ4380_INTERNAL_REF_MV; + st->vref_mv = st->chip_info->internal_ref_mv; /* these chips don't have a register bit for this */ external_ref_en = false; @@ -1892,7 +1924,8 @@ static int ad7380_probe(struct spi_device *spi) "Failed to get refio regulator\n"); external_ref_en = ret != -ENODEV; - st->vref_mv = external_ref_en ? ret / 1000 : AD7380_INTERNAL_REF_MV; + st->vref_mv = external_ref_en ? ret / 1000 + : st->chip_info->internal_ref_mv; } if (st->chip_info->num_vcm_supplies > ARRAY_SIZE(st->vcm_mv)) @@ -2045,6 +2078,7 @@ static const struct of_device_id ad7380_of_match_table[] = { { .compatible = "adi,ad7386-4", .data = &ad7386_4_chip_info }, { .compatible = "adi,ad7387-4", .data = &ad7387_4_chip_info }, { .compatible = "adi,ad7388-4", .data = &ad7388_4_chip_info }, + { .compatible = "adi,ad7389-4", .data = &ad7389_4_chip_info }, { .compatible = "adi,adaq4370-4", .data = &adaq4370_4_chip_info }, { .compatible = "adi,adaq4380-4", .data = &adaq4380_4_chip_info }, { .compatible = "adi,adaq4381-4", .data = &adaq4381_4_chip_info }, @@ -2066,6 +2100,7 @@ static const struct spi_device_id ad7380_id_table[] = { { "ad7386-4", (kernel_ulong_t)&ad7386_4_chip_info }, { "ad7387-4", (kernel_ulong_t)&ad7387_4_chip_info }, { "ad7388-4", (kernel_ulong_t)&ad7388_4_chip_info }, + { "ad7389-4", (kernel_ulong_t)&ad7389_4_chip_info }, { "adaq4370-4", (kernel_ulong_t)&adaq4370_4_chip_info }, { "adaq4380-4", (kernel_ulong_t)&adaq4380_4_chip_info }, { "adaq4381-4", (kernel_ulong_t)&adaq4381_4_chip_info }, diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c index 37b0515cf4fc..ddb607ac1860 100644 --- a/drivers/iio/adc/ad7476.c +++ b/drivers/iio/adc/ad7476.c @@ -99,8 +99,8 @@ static irqreturn_t ad7476_trigger_handler(int irq, void *p) if (b_sent < 0) goto done; - iio_push_to_buffers_with_timestamp(indio_dev, st->data, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, st->data, sizeof(st->data), + iio_get_time_ns(indio_dev)); done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c index 703556eb7257..185243dee86e 100644 --- a/drivers/iio/adc/ad7606.c +++ b/drivers/iio/adc/ad7606.c @@ -13,6 +13,7 @@ #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/property.h> #include <linux/pwm.h> #include <linux/regulator/consumer.h> @@ -94,121 +95,35 @@ static const unsigned int ad7616_oversampling_avail[8] = { 1, 2, 4, 8, 16, 32, 64, 128, }; -static const struct iio_chan_spec ad7605_channels[] = { - IIO_CHAN_SOFT_TIMESTAMP(4), - AD7605_CHANNEL(0), - AD7605_CHANNEL(1), - AD7605_CHANNEL(2), - AD7605_CHANNEL(3), -}; - -static const struct iio_chan_spec ad7606_channels_16bit[] = { - IIO_CHAN_SOFT_TIMESTAMP(8), - AD7606_CHANNEL(0, 16), - AD7606_CHANNEL(1, 16), - AD7606_CHANNEL(2, 16), - AD7606_CHANNEL(3, 16), - AD7606_CHANNEL(4, 16), - AD7606_CHANNEL(5, 16), - AD7606_CHANNEL(6, 16), - AD7606_CHANNEL(7, 16), -}; - -static const struct iio_chan_spec ad7606_channels_18bit[] = { - IIO_CHAN_SOFT_TIMESTAMP(8), - AD7606_CHANNEL(0, 18), - AD7606_CHANNEL(1, 18), - AD7606_CHANNEL(2, 18), - AD7606_CHANNEL(3, 18), - AD7606_CHANNEL(4, 18), - AD7606_CHANNEL(5, 18), - AD7606_CHANNEL(6, 18), - AD7606_CHANNEL(7, 18), -}; - -static const struct iio_chan_spec ad7607_channels[] = { - IIO_CHAN_SOFT_TIMESTAMP(8), - AD7606_CHANNEL(0, 14), - AD7606_CHANNEL(1, 14), - AD7606_CHANNEL(2, 14), - AD7606_CHANNEL(3, 14), - AD7606_CHANNEL(4, 14), - AD7606_CHANNEL(5, 14), - AD7606_CHANNEL(6, 14), - AD7606_CHANNEL(7, 14), -}; - -static const struct iio_chan_spec ad7608_channels[] = { - IIO_CHAN_SOFT_TIMESTAMP(8), - AD7606_CHANNEL(0, 18), - AD7606_CHANNEL(1, 18), - AD7606_CHANNEL(2, 18), - AD7606_CHANNEL(3, 18), - AD7606_CHANNEL(4, 18), - AD7606_CHANNEL(5, 18), - AD7606_CHANNEL(6, 18), - AD7606_CHANNEL(7, 18), -}; - -/* - * The current assumption that this driver makes for AD7616, is that it's - * working in Hardware Mode with Serial, Burst and Sequencer modes activated. - * To activate them, following pins must be pulled high: - * -SER/PAR - * -SEQEN - * And following pins must be pulled low: - * -WR/BURST - * -DB4/SER1W - */ -static const struct iio_chan_spec ad7616_channels[] = { - IIO_CHAN_SOFT_TIMESTAMP(16), - AD7606_CHANNEL(0, 16), - AD7606_CHANNEL(1, 16), - AD7606_CHANNEL(2, 16), - AD7606_CHANNEL(3, 16), - AD7606_CHANNEL(4, 16), - AD7606_CHANNEL(5, 16), - AD7606_CHANNEL(6, 16), - AD7606_CHANNEL(7, 16), - AD7606_CHANNEL(8, 16), - AD7606_CHANNEL(9, 16), - AD7606_CHANNEL(10, 16), - AD7606_CHANNEL(11, 16), - AD7606_CHANNEL(12, 16), - AD7606_CHANNEL(13, 16), - AD7606_CHANNEL(14, 16), - AD7606_CHANNEL(15, 16), -}; - static int ad7606c_18bit_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch); + struct iio_chan_spec *chan); static int ad7606c_16bit_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch); + struct iio_chan_spec *chan); static int ad7606_16bit_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch); + struct iio_chan_spec *chan); static int ad7607_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch); + struct iio_chan_spec *chan); static int ad7608_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch); + struct iio_chan_spec *chan); static int ad7609_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch); + struct iio_chan_spec *chan); static int ad7616_sw_mode_setup(struct iio_dev *indio_dev); static int ad7606b_sw_mode_setup(struct iio_dev *indio_dev); const struct ad7606_chip_info ad7605_4_info = { - .channels = ad7605_channels, + .max_samplerate = 300 * KILO, .name = "ad7605-4", + .bits = 16, .num_adc_channels = 4, - .num_channels = 5, .scale_setup_cb = ad7606_16bit_chan_scale_setup, }; EXPORT_SYMBOL_NS_GPL(ad7605_4_info, "IIO_AD7606"); const struct ad7606_chip_info ad7606_8_info = { - .channels = ad7606_channels_16bit, + .max_samplerate = 200 * KILO, .name = "ad7606-8", + .bits = 16, .num_adc_channels = 8, - .num_channels = 9, .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), .scale_setup_cb = ad7606_16bit_chan_scale_setup, @@ -216,108 +131,116 @@ const struct ad7606_chip_info ad7606_8_info = { EXPORT_SYMBOL_NS_GPL(ad7606_8_info, "IIO_AD7606"); const struct ad7606_chip_info ad7606_6_info = { - .channels = ad7606_channels_16bit, + .max_samplerate = 200 * KILO, .name = "ad7606-6", + .bits = 16, .num_adc_channels = 6, - .num_channels = 7, .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), .scale_setup_cb = ad7606_16bit_chan_scale_setup, + .offload_storagebits = 32, }; EXPORT_SYMBOL_NS_GPL(ad7606_6_info, "IIO_AD7606"); const struct ad7606_chip_info ad7606_4_info = { - .channels = ad7606_channels_16bit, + .max_samplerate = 200 * KILO, .name = "ad7606-4", + .bits = 16, .num_adc_channels = 4, - .num_channels = 5, .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), .scale_setup_cb = ad7606_16bit_chan_scale_setup, + .offload_storagebits = 32, }; EXPORT_SYMBOL_NS_GPL(ad7606_4_info, "IIO_AD7606"); const struct ad7606_chip_info ad7606b_info = { - .channels = ad7606_channels_16bit, .max_samplerate = 800 * KILO, .name = "ad7606b", + .bits = 16, .num_adc_channels = 8, - .num_channels = 9, .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), .scale_setup_cb = ad7606_16bit_chan_scale_setup, .sw_setup_cb = ad7606b_sw_mode_setup, + .offload_storagebits = 32, }; EXPORT_SYMBOL_NS_GPL(ad7606b_info, "IIO_AD7606"); const struct ad7606_chip_info ad7606c_16_info = { - .channels = ad7606_channels_16bit, + .max_samplerate = 1 * MEGA, .name = "ad7606c16", + .bits = 16, .num_adc_channels = 8, - .num_channels = 9, .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), .scale_setup_cb = ad7606c_16bit_chan_scale_setup, .sw_setup_cb = ad7606b_sw_mode_setup, + .offload_storagebits = 32, }; EXPORT_SYMBOL_NS_GPL(ad7606c_16_info, "IIO_AD7606"); const struct ad7606_chip_info ad7607_info = { - .channels = ad7607_channels, + .max_samplerate = 200 * KILO, .name = "ad7607", + .bits = 14, .num_adc_channels = 8, - .num_channels = 9, .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), .scale_setup_cb = ad7607_chan_scale_setup, + .offload_storagebits = 32, }; EXPORT_SYMBOL_NS_GPL(ad7607_info, "IIO_AD7606"); const struct ad7606_chip_info ad7608_info = { - .channels = ad7608_channels, + .max_samplerate = 200 * KILO, .name = "ad7608", + .bits = 18, .num_adc_channels = 8, - .num_channels = 9, .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), .scale_setup_cb = ad7608_chan_scale_setup, + .offload_storagebits = 32, }; EXPORT_SYMBOL_NS_GPL(ad7608_info, "IIO_AD7606"); const struct ad7606_chip_info ad7609_info = { - .channels = ad7608_channels, + .max_samplerate = 200 * KILO, .name = "ad7609", + .bits = 18, .num_adc_channels = 8, - .num_channels = 9, .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), .scale_setup_cb = ad7609_chan_scale_setup, + .offload_storagebits = 32, }; EXPORT_SYMBOL_NS_GPL(ad7609_info, "IIO_AD7606"); const struct ad7606_chip_info ad7606c_18_info = { - .channels = ad7606_channels_18bit, + .max_samplerate = 1 * MEGA, .name = "ad7606c18", + .bits = 18, .num_adc_channels = 8, - .num_channels = 9, .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), .scale_setup_cb = ad7606c_18bit_chan_scale_setup, .sw_setup_cb = ad7606b_sw_mode_setup, + .offload_storagebits = 32, }; EXPORT_SYMBOL_NS_GPL(ad7606c_18_info, "IIO_AD7606"); const struct ad7606_chip_info ad7616_info = { - .channels = ad7616_channels, + .max_samplerate = 1 * MEGA, .init_delay_ms = 15, .name = "ad7616", + .bits = 16, .num_adc_channels = 16, - .num_channels = 17, .oversampling_avail = ad7616_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7616_oversampling_avail), .os_req_reset = true, .scale_setup_cb = ad7606_16bit_chan_scale_setup, .sw_setup_cb = ad7616_sw_mode_setup, + .offload_storagebits = 16, }; EXPORT_SYMBOL_NS_GPL(ad7616_info, "IIO_AD7606"); @@ -335,10 +258,10 @@ int ad7606_reset(struct ad7606_state *st) EXPORT_SYMBOL_NS_GPL(ad7606_reset, "IIO_AD7606"); static int ad7606_16bit_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch) + struct iio_chan_spec *chan) { struct ad7606_state *st = iio_priv(indio_dev); - struct ad7606_chan_scale *cs = &st->chan_scales[ch]; + struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index]; if (!st->sw_mode_en) { /* tied to logic low, analog input range is +/- 5V */ @@ -362,7 +285,6 @@ static int ad7606_get_chan_config(struct iio_dev *indio_dev, int ch, { struct ad7606_state *st = iio_priv(indio_dev); unsigned int num_channels = st->chip_info->num_adc_channels; - unsigned int offset = indio_dev->num_channels - st->chip_info->num_adc_channels; struct device *dev = st->dev; int ret; @@ -378,7 +300,7 @@ static int ad7606_get_chan_config(struct iio_dev *indio_dev, int ch, continue; /* channel number (here) is from 1 to num_channels */ - if (reg < offset || reg > num_channels) { + if (reg < 1 || reg > num_channels) { dev_warn(dev, "Invalid channel number (ignoring): %d\n", reg); continue; @@ -414,10 +336,10 @@ static int ad7606_get_chan_config(struct iio_dev *indio_dev, int ch, } static int ad7606c_18bit_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch) + struct iio_chan_spec *chan) { struct ad7606_state *st = iio_priv(indio_dev); - struct ad7606_chan_scale *cs = &st->chan_scales[ch]; + struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index]; bool bipolar, differential; int ret; @@ -428,7 +350,8 @@ static int ad7606c_18bit_chan_scale_setup(struct iio_dev *indio_dev, return 0; } - ret = ad7606_get_chan_config(indio_dev, ch, &bipolar, &differential); + ret = ad7606_get_chan_config(indio_dev, chan->scan_index, &bipolar, + &differential); if (ret) return ret; @@ -471,10 +394,10 @@ static int ad7606c_18bit_chan_scale_setup(struct iio_dev *indio_dev, } static int ad7606c_16bit_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch) + struct iio_chan_spec *chan) { struct ad7606_state *st = iio_priv(indio_dev); - struct ad7606_chan_scale *cs = &st->chan_scales[ch]; + struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index]; bool bipolar, differential; int ret; @@ -485,7 +408,8 @@ static int ad7606c_16bit_chan_scale_setup(struct iio_dev *indio_dev, return 0; } - ret = ad7606_get_chan_config(indio_dev, ch, &bipolar, &differential); + ret = ad7606_get_chan_config(indio_dev, chan->scan_index, &bipolar, + &differential); if (ret) return ret; @@ -529,10 +453,10 @@ static int ad7606c_16bit_chan_scale_setup(struct iio_dev *indio_dev, } static int ad7607_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch) + struct iio_chan_spec *chan) { struct ad7606_state *st = iio_priv(indio_dev); - struct ad7606_chan_scale *cs = &st->chan_scales[ch]; + struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index]; cs->range = 0; cs->scale_avail = ad7607_hw_scale_avail; @@ -541,10 +465,10 @@ static int ad7607_chan_scale_setup(struct iio_dev *indio_dev, } static int ad7608_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch) + struct iio_chan_spec *chan) { struct ad7606_state *st = iio_priv(indio_dev); - struct ad7606_chan_scale *cs = &st->chan_scales[ch]; + struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index]; cs->range = 0; cs->scale_avail = ad7606_18bit_hw_scale_avail; @@ -553,10 +477,10 @@ static int ad7608_chan_scale_setup(struct iio_dev *indio_dev, } static int ad7609_chan_scale_setup(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch) + struct iio_chan_spec *chan) { struct ad7606_state *st = iio_priv(indio_dev); - struct ad7606_chan_scale *cs = &st->chan_scales[ch]; + struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index]; cs->range = 0; cs->scale_avail = ad7609_hw_scale_avail; @@ -599,7 +523,7 @@ static int ad7606_pwm_set_high(struct ad7606_state *st) return ret; } -static int ad7606_pwm_set_low(struct ad7606_state *st) +int ad7606_pwm_set_low(struct ad7606_state *st) { struct pwm_state cnvst_pwm_state; int ret; @@ -612,8 +536,9 @@ static int ad7606_pwm_set_low(struct ad7606_state *st) return ret; } +EXPORT_SYMBOL_NS_GPL(ad7606_pwm_set_low, "IIO_AD7606"); -static int ad7606_pwm_set_swing(struct ad7606_state *st) +int ad7606_pwm_set_swing(struct ad7606_state *st) { struct pwm_state cnvst_pwm_state; @@ -623,6 +548,7 @@ static int ad7606_pwm_set_swing(struct ad7606_state *st) return pwm_apply_might_sleep(st->cnvst_pwm, &cnvst_pwm_state); } +EXPORT_SYMBOL_NS_GPL(ad7606_pwm_set_swing, "IIO_AD7606"); static bool ad7606_pwm_is_swinging(struct ad7606_state *st) { @@ -679,8 +605,8 @@ static irqreturn_t ad7606_trigger_handler(int irq, void *p) if (ret) goto error_ret; - iio_push_to_buffers_with_timestamp(indio_dev, &st->data, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &st->data, sizeof(st->data), + iio_get_time_ns(indio_dev)); error_ret: iio_trigger_notify_done(indio_dev->trig); /* The rising edge of the CONVST signal starts a new conversion. */ @@ -693,8 +619,8 @@ static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch, int *val) { struct ad7606_state *st = iio_priv(indio_dev); - unsigned int realbits = st->chip_info->channels[1].scan_type.realbits; const struct iio_chan_spec *chan; + unsigned int realbits; int ret; if (st->gpio_convst) { @@ -711,7 +637,7 @@ static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch, * will not happen because IIO_CHAN_INFO_RAW is not supported for the backend. * TODO: Add support for reading a single value when the backend is used. */ - if (!st->back) { + if (st->trig) { ret = wait_for_completion_timeout(&st->completion, msecs_to_jiffies(1000)); if (!ret) { @@ -719,25 +645,30 @@ static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch, goto error_ret; } } else { - fsleep(1); + /* + * If the BUSY interrupt is not available, wait enough time for + * the longest possible conversion (max for the whole family is + * around 350us). + */ + fsleep(400); } ret = ad7606_read_samples(st); if (ret) goto error_ret; - chan = &indio_dev->channels[ch + 1]; - if (chan->scan_type.sign == 'u') { - if (realbits > 16) - *val = st->data.buf32[ch]; - else - *val = st->data.buf16[ch]; - } else { - if (realbits > 16) - *val = sign_extend32(st->data.buf32[ch], realbits - 1); - else - *val = sign_extend32(st->data.buf16[ch], realbits - 1); - } + chan = &indio_dev->channels[ch]; + realbits = chan->scan_type.realbits; + + if (realbits > 16) + *val = st->data.buf32[ch]; + else + *val = st->data.buf16[ch]; + + *val &= GENMASK(realbits - 1, 0); + + if (chan->scan_type.sign == 's') + *val = sign_extend32(*val, realbits - 1); error_ret: if (!st->gpio_convst) { @@ -765,14 +696,14 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_RAW: if (!iio_device_claim_direct(indio_dev)) return -EBUSY; - ret = ad7606_scan_direct(indio_dev, chan->address, val); + ret = ad7606_scan_direct(indio_dev, chan->scan_index, val); iio_device_release_direct(indio_dev); if (ret < 0) return ret; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: if (st->sw_mode_en) - ch = chan->address; + ch = chan->scan_index; cs = &st->chan_scales[ch]; *val = cs->scale_avail[cs->range][0]; *val2 = cs->scale_avail[cs->range][1]; @@ -781,10 +712,6 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, *val = st->oversampling; return IIO_VAL_INT; case IIO_CHAN_INFO_SAMP_FREQ: - /* - * TODO: return the real frequency intead of the requested one once - * pwm_get_state_hw comes upstream. - */ pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state); *val = DIV_ROUND_CLOSEST_ULL(NSEC_PER_SEC, cnvst_pwm_state.period); return IIO_VAL_INT; @@ -854,7 +781,7 @@ static int ad7606_write_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_SCALE: if (st->sw_mode_en) - ch = chan->address; + ch = chan->scan_index; cs = &st->chan_scales[ch]; for (i = 0; i < cs->num_scales; i++) { scale_avail_uv[i] = cs->scale_avail[i][0] * MICRO + @@ -1061,7 +988,7 @@ static int ad7606_read_avail(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: if (st->sw_mode_en) - ch = chan->address; + ch = chan->scan_index; cs = &st->chan_scales[ch]; *vals = (int *)cs->scale_avail; @@ -1276,29 +1203,91 @@ static int ad7606b_sw_mode_setup(struct iio_dev *indio_dev) return st->bops->sw_mode_config(indio_dev); } -static int ad7606_chan_scales_setup(struct iio_dev *indio_dev) +static int ad7606_probe_channels(struct iio_dev *indio_dev) { struct ad7606_state *st = iio_priv(indio_dev); - unsigned int offset = indio_dev->num_channels - st->chip_info->num_adc_channels; - struct iio_chan_spec *chans; - size_t size; - int ch, ret; - - /* Clone IIO channels, since some may be differential */ - size = indio_dev->num_channels * sizeof(*indio_dev->channels); - chans = devm_kzalloc(st->dev, size, GFP_KERNEL); - if (!chans) + struct device *dev = indio_dev->dev.parent; + struct iio_chan_spec *channels; + bool slow_bus; + int ret, i; + + slow_bus = !(st->bops->iio_backend_config || st->offload_en); + indio_dev->num_channels = st->chip_info->num_adc_channels; + + /* Slow buses also get 1 more channel for soft timestamp */ + if (slow_bus) + indio_dev->num_channels++; + + channels = devm_kcalloc(dev, indio_dev->num_channels, sizeof(*channels), + GFP_KERNEL); + if (!channels) return -ENOMEM; - memcpy(chans, indio_dev->channels, size); - indio_dev->channels = chans; + for (i = 0; i < st->chip_info->num_adc_channels; i++) { + struct iio_chan_spec *chan = &channels[i]; - for (ch = 0; ch < st->chip_info->num_adc_channels; ch++) { - ret = st->chip_info->scale_setup_cb(indio_dev, &chans[ch + offset], ch); + chan->type = IIO_VOLTAGE; + chan->indexed = 1; + chan->channel = i; + chan->scan_index = i; + chan->scan_type.sign = 's'; + chan->scan_type.realbits = st->chip_info->bits; + /* + * If in SPI offload mode, storagebits are set based + * on the spi-engine hw implementation. + */ + chan->scan_type.storagebits = st->offload_en ? + st->chip_info->offload_storagebits : + (st->chip_info->bits > 16 ? 32 : 16); + + chan->scan_type.endianness = IIO_CPU; + + if (indio_dev->modes & INDIO_DIRECT_MODE) + chan->info_mask_separate |= BIT(IIO_CHAN_INFO_RAW); + + if (st->sw_mode_en) { + chan->info_mask_separate |= BIT(IIO_CHAN_INFO_SCALE); + chan->info_mask_separate_available |= + BIT(IIO_CHAN_INFO_SCALE); + + /* + * All chips with software mode support oversampling, + * so we skip the oversampling_available check. And the + * shared_by_type instead of shared_by_all on slow + * buses is for backward compatibility. + */ + if (slow_bus) + chan->info_mask_shared_by_type |= + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); + else + chan->info_mask_shared_by_all |= + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); + + chan->info_mask_shared_by_all_available |= + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); + } else { + chan->info_mask_shared_by_type |= + BIT(IIO_CHAN_INFO_SCALE); + + if (st->chip_info->oversampling_avail) + chan->info_mask_shared_by_all |= + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); + } + + if (!slow_bus) + chan->info_mask_shared_by_all |= + BIT(IIO_CHAN_INFO_SAMP_FREQ); + + ret = st->chip_info->scale_setup_cb(indio_dev, chan); if (ret) return ret; } + if (slow_bus) + channels[i] = (struct iio_chan_spec)IIO_CHAN_SOFT_TIMESTAMP(i); + + indio_dev->channels = channels; + return 0; } @@ -1322,11 +1311,19 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, st = iio_priv(indio_dev); dev_set_drvdata(dev, indio_dev); + ret = devm_mutex_init(dev, &st->lock); + if (ret) + return ret; + st->dev = dev; - mutex_init(&st->lock); st->bops = bops; st->base_address = base_address; st->oversampling = 1; + st->sw_mode_en = device_property_read_bool(dev, "adi,sw-mode"); + + if (st->sw_mode_en && !chip_info->sw_setup_cb) + return dev_err_probe(dev, -EINVAL, + "Software mode is not supported for this chip\n"); ret = devm_regulator_get_enable(dev, "avcc"); if (ret) @@ -1355,10 +1352,21 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, else indio_dev->info = &ad7606_info_no_os_or_range; } - indio_dev->modes = INDIO_DIRECT_MODE; + + /* AXI ADC backend doesn't support single read. */ + indio_dev->modes = st->bops->iio_backend_config ? 0 : INDIO_DIRECT_MODE; indio_dev->name = chip_info->name; - indio_dev->channels = st->chip_info->channels; - indio_dev->num_channels = st->chip_info->num_channels; + + /* Using spi-engine with offload support ? */ + if (st->bops->offload_config) { + ret = st->bops->offload_config(dev, indio_dev); + if (ret) + return ret; + } + + ret = ad7606_probe_channels(indio_dev); + if (ret) + return ret; ret = ad7606_reset(st); if (ret) @@ -1371,7 +1379,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, } /* If convst pin is not defined, setup PWM. */ - if (!st->gpio_convst) { + if (!st->gpio_convst || st->offload_en) { st->cnvst_pwm = devm_pwm_get(dev, NULL); if (IS_ERR(st->cnvst_pwm)) return PTR_ERR(st->cnvst_pwm); @@ -1401,8 +1409,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, * If there is a backend, the PWM should not overpass the maximum sampling * frequency the chip supports. */ - ret = ad7606_set_sampling_freq(st, - chip_info->max_samplerate ? : 2 * KILO); + ret = ad7606_set_sampling_freq(st, chip_info->max_samplerate); if (ret) return ret; @@ -1411,8 +1418,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, return ret; indio_dev->setup_ops = &ad7606_backend_buffer_ops; - } else { - + } else if (!st->offload_en) { /* Reserve the PWM use only for backend (force gpio_convst definition) */ if (!st->gpio_convst) return dev_err_probe(dev, -EINVAL, @@ -1450,17 +1456,12 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, st->write_scale = ad7606_write_scale_hw; st->write_os = ad7606_write_os_hw; - st->sw_mode_en = st->chip_info->sw_setup_cb && - device_property_present(st->dev, "adi,sw-mode"); - if (st->sw_mode_en) { + /* Offload needs 1 DOUT line, applying this setting in sw_setup_cb. */ + if (st->sw_mode_en || st->offload_en) { indio_dev->info = &ad7606_info_sw_mode; st->chip_info->sw_setup_cb(indio_dev); } - ret = ad7606_chan_scales_setup(indio_dev); - if (ret) - return ret; - return devm_iio_device_register(dev, indio_dev); } EXPORT_SYMBOL_NS_GPL(ad7606_probe, "IIO_AD7606"); diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h index 71a30525eaab..441e62c521bc 100644 --- a/drivers/iio/adc/ad7606.h +++ b/drivers/iio/adc/ad7606.h @@ -40,119 +40,48 @@ #define AD7606_RANGE_CH_ADDR(ch) (0x03 + ((ch) >> 1)) #define AD7606_OS_MODE 0x08 -#define AD760X_CHANNEL(num, mask_sep, mask_type, mask_all, \ - mask_sep_avail, mask_all_avail, bits) { \ - .type = IIO_VOLTAGE, \ - .indexed = 1, \ - .channel = num, \ - .address = num, \ - .info_mask_separate = mask_sep, \ - .info_mask_separate_available = \ - mask_sep_avail, \ - .info_mask_shared_by_type = mask_type, \ - .info_mask_shared_by_all = mask_all, \ - .info_mask_shared_by_all_available = \ - mask_all_avail, \ - .scan_index = num, \ - .scan_type = { \ - .sign = 's', \ - .realbits = (bits), \ - .storagebits = (bits) > 16 ? 32 : 16, \ - .endianness = IIO_CPU, \ - }, \ -} - -#define AD7606_SW_CHANNEL(num, bits) \ - AD760X_CHANNEL(num, \ - /* mask separate */ \ - BIT(IIO_CHAN_INFO_RAW) | \ - BIT(IIO_CHAN_INFO_SCALE), \ - /* mask type */ \ - BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ - /* mask all */ \ - 0, \ - /* mask separate available */ \ - BIT(IIO_CHAN_INFO_SCALE), \ - /* mask all available */ \ - BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ - bits) - -#define AD7605_CHANNEL(num) \ - AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \ - BIT(IIO_CHAN_INFO_SCALE), 0, 0, 0, 16) - -#define AD7606_CHANNEL(num, bits) \ - AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \ - BIT(IIO_CHAN_INFO_SCALE), \ - BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ - 0, 0, bits) - -#define AD7616_CHANNEL(num) AD7606_SW_CHANNEL(num, 16) - -#define AD7606_BI_CHANNEL(num) \ - AD760X_CHANNEL(num, 0, \ - BIT(IIO_CHAN_INFO_SCALE), \ - BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ - BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ - 0, 0, 16) - -#define AD7606_BI_SW_CHANNEL(num) \ - AD760X_CHANNEL(num, \ - /* mask separate */ \ - BIT(IIO_CHAN_INFO_SCALE), \ - /* mask type */ \ - 0, \ - /* mask all */ \ - BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ - BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ - /* mask separate available */ \ - BIT(IIO_CHAN_INFO_SCALE), \ - /* mask all available */ \ - BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ - 16) - struct ad7606_state; typedef int (*ad7606_scale_setup_cb_t)(struct iio_dev *indio_dev, - struct iio_chan_spec *chan, int ch); + struct iio_chan_spec *chan); typedef int (*ad7606_sw_setup_cb_t)(struct iio_dev *indio_dev); /** * struct ad7606_chip_info - chip specific information - * @channels: channel specification - * @max_samplerate: maximum supported samplerate - * @name device name - * @num_channels: number of channels - * @num_adc_channels the number of channels the ADC actually inputs. + * @max_samplerate: maximum supported sample rate + * @name: device name + * @bits: data width in bits + * @num_adc_channels: the number of physical voltage inputs * @scale_setup_cb: callback to setup the scales for each channel * @sw_setup_cb: callback to setup the software mode if available. - * @oversampling_avail pointer to the array which stores the available + * @oversampling_avail: pointer to the array which stores the available * oversampling ratios. - * @oversampling_num number of elements stored in oversampling_avail array - * @os_req_reset some devices require a reset to update oversampling - * @init_delay_ms required delay in milliseconds for initialization + * @oversampling_num: number of elements stored in oversampling_avail array + * @os_req_reset: some devices require a reset to update oversampling + * @init_delay_ms: required delay in milliseconds for initialization * after a restart + * @offload_storagebits: storage bits used by the offload hw implementation */ struct ad7606_chip_info { - const struct iio_chan_spec *channels; unsigned int max_samplerate; const char *name; + unsigned int bits; unsigned int num_adc_channels; - unsigned int num_channels; ad7606_scale_setup_cb_t scale_setup_cb; ad7606_sw_setup_cb_t sw_setup_cb; const unsigned int *oversampling_avail; unsigned int oversampling_num; bool os_req_reset; unsigned long init_delay_ms; + u8 offload_storagebits; }; /** * struct ad7606_chan_scale - channel scale configuration - * @scale_avail pointer to the array which stores the available scales - * @num_scales number of elements stored in the scale_avail array - * @range voltage range selection, selects which scale to apply - * @reg_offset offset for the register value, to be applied when + * @scale_avail: pointer to the array which stores the available scales + * @num_scales: number of elements stored in the scale_avail array + * @range: voltage range selection, selects which scale to apply + * @reg_offset: offset for the register value, to be applied when * writing the value of 'range' to the register value */ struct ad7606_chan_scale { @@ -165,32 +94,35 @@ struct ad7606_chan_scale { /** * struct ad7606_state - driver instance specific data - * @dev pointer to kernel device - * @chip_info entry in the table of chips that describes this device - * @bops bus operations (SPI or parallel) - * @chan_scales scale configuration for channels - * @oversampling oversampling selection - * @cnvst_pwm pointer to the PWM device connected to the cnvst pin - * @base_address address from where to read data in parallel operation - * @sw_mode_en software mode enabled - * @oversampling_avail pointer to the array which stores the available + * @dev: pointer to kernel device + * @chip_info: entry in the table of chips that describes this device + * @bops: bus operations (SPI or parallel) + * @chan_scales: scale configuration for channels + * @oversampling: oversampling selection + * @cnvst_pwm: pointer to the PWM device connected to the cnvst pin + * @base_address: address from where to read data in parallel operation + * @sw_mode_en: software mode enabled + * @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 - * @gpio_range GPIO descriptor for range selection - * @gpio_standby GPIO descriptor for stand-by signal (STBY), + * @num_os_ratios: number of elements stored in oversampling_avail array + * @back: pointer to the iio_backend structure, if used + * @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 + * @gpio_range: GPIO descriptor for range selection + * @gpio_standby: GPIO descriptor for stand-by signal (STBY), * controls power-down mode of device - * @gpio_frstdata GPIO descriptor for reading from device when data + * @gpio_frstdata: GPIO descriptor for reading from device when data * is being read on the first channel - * @gpio_os GPIO descriptors to control oversampling on the device - * @complete completion to indicate end of conversion - * @trig The IIO trigger associated with the device. - * @data buffer for reading data from the device - * @d16 be16 buffer for reading data from the device + * @gpio_os: GPIO descriptors to control oversampling on the device + * @trig: The IIO trigger associated with the device. + * @completion: completion to indicate end of conversion + * @data: buffer for reading data from the device + * @offload_en: SPI offload enabled + * @bus_data: bus-specific variables + * @d16: be16 buffer for reading data from the device */ struct ad7606_state { struct device *dev; @@ -217,36 +149,44 @@ struct ad7606_state { struct iio_trigger *trig; struct completion completion; + bool offload_en; + void *bus_data; + /* * DMA (thus cache coherency maintenance) may require the * transfer buffers to live in their own cache lines. - * 16 * 16-bit samples + 64-bit timestamp - for AD7616 - * 8 * 32-bit samples + 64-bit timestamp - for AD7616C-18 (and similar) + * 16 * 16-bit samples for AD7616 + * 8 * 32-bit samples for AD7616C-18 (and similar) */ - union { - u16 buf16[20]; - u32 buf32[10]; + struct { + union { + u16 buf16[16]; + u32 buf32[8]; + }; + aligned_s64 timestamp; } data __aligned(IIO_DMA_MINALIGN); __be16 d16[2]; }; /** * struct ad7606_bus_ops - driver bus operations - * @iio_backend_config function pointer for configuring the iio_backend for + * @iio_backend_config: function pointer for configuring the iio_backend for * the compatibles that use it - * @read_block function pointer for reading blocks of data + * @read_block: function pointer for reading blocks of data * @sw_mode_config: pointer to a function which configured the device * for software mode - * @reg_read function pointer for reading spi register - * @reg_write function pointer for writing spi register - * @write_mask function pointer for write spi register with mask - * @update_scan_mode function pointer for handling the calls to iio_info's update_scan - * mode when enabling/disabling channels. - * @rd_wr_cmd pointer to the function which calculates the spi address + * @offload_config: function pointer for configuring offload support, + * where any + * @reg_read: function pointer for reading spi register + * @reg_write: function pointer for writing spi register + * @update_scan_mode: function pointer for handling the calls to iio_info's + * update_scan mode when enabling/disabling channels. + * @rd_wr_cmd: pointer to the function which calculates the spi address */ struct ad7606_bus_ops { /* more methods added in future? */ int (*iio_backend_config)(struct device *dev, struct iio_dev *indio_dev); + int (*offload_config)(struct device *dev, struct iio_dev *indio_dev); int (*read_block)(struct device *dev, int num, void *data); int (*sw_mode_config)(struct iio_dev *indio_dev); int (*reg_read)(struct ad7606_state *st, unsigned int addr); @@ -254,13 +194,13 @@ struct ad7606_bus_ops { unsigned int addr, unsigned int val); int (*update_scan_mode)(struct iio_dev *indio_dev, const unsigned long *scan_mask); - u16 (*rd_wr_cmd)(int addr, char isWriteOp); + u16 (*rd_wr_cmd)(int addr, char is_write_op); }; /** - * struct ad7606_bus_info - agregate ad7606_chip_info and ad7606_bus_ops - * @chip_info entry in the table of chips that describes this device - * @bops bus operations (SPI or parallel) + * struct ad7606_bus_info - aggregate ad7606_chip_info and ad7606_bus_ops + * @chip_info: entry in the table of chips that describes this device + * @bops: bus operations (SPI or parallel) */ struct ad7606_bus_info { const struct ad7606_chip_info *chip_info; @@ -272,6 +212,8 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, const struct ad7606_bus_ops *bops); int ad7606_reset(struct ad7606_state *st); +int ad7606_pwm_set_swing(struct ad7606_state *st); +int ad7606_pwm_set_low(struct ad7606_state *st); extern const struct ad7606_chip_info ad7605_4_info; extern const struct ad7606_chip_info ad7606_8_info; diff --git a/drivers/iio/adc/ad7606_par.c b/drivers/iio/adc/ad7606_par.c index 335fb481bfde..634852c4bbd2 100644 --- a/drivers/iio/adc/ad7606_par.c +++ b/drivers/iio/adc/ad7606_par.c @@ -21,28 +21,6 @@ #include "ad7606.h" #include "ad7606_bus_iface.h" -static const struct iio_chan_spec ad7606b_bi_channels[] = { - AD7606_BI_CHANNEL(0), - AD7606_BI_CHANNEL(1), - AD7606_BI_CHANNEL(2), - AD7606_BI_CHANNEL(3), - AD7606_BI_CHANNEL(4), - AD7606_BI_CHANNEL(5), - AD7606_BI_CHANNEL(6), - AD7606_BI_CHANNEL(7), -}; - -static const struct iio_chan_spec ad7606b_bi_sw_channels[] = { - AD7606_BI_SW_CHANNEL(0), - AD7606_BI_SW_CHANNEL(1), - AD7606_BI_SW_CHANNEL(2), - AD7606_BI_SW_CHANNEL(3), - AD7606_BI_SW_CHANNEL(4), - AD7606_BI_SW_CHANNEL(5), - AD7606_BI_SW_CHANNEL(6), - AD7606_BI_SW_CHANNEL(7), -}; - static int ad7606_par_bus_update_scan_mode(struct iio_dev *indio_dev, const unsigned long *scan_mask) { @@ -94,9 +72,6 @@ static int ad7606_par_bus_setup_iio_backend(struct device *dev, return ret; } - indio_dev->channels = ad7606b_bi_channels; - indio_dev->num_channels = 8; - return 0; } @@ -120,19 +95,11 @@ static int ad7606_par_bus_reg_write(struct ad7606_state *st, unsigned int addr, return pdata->bus_reg_write(st->back, addr, val); } -static int ad7606_par_bus_sw_mode_config(struct iio_dev *indio_dev) -{ - indio_dev->channels = ad7606b_bi_sw_channels; - - return 0; -} - static const struct ad7606_bus_ops ad7606_bi_bops = { .iio_backend_config = ad7606_par_bus_setup_iio_backend, .update_scan_mode = ad7606_par_bus_update_scan_mode, .reg_read = ad7606_par_bus_reg_read, .reg_write = ad7606_par_bus_reg_write, - .sw_mode_config = ad7606_par_bus_sw_mode_config, }; static int ad7606_par16_read_block(struct device *dev, @@ -255,6 +222,8 @@ static const struct platform_device_id ad7606_driver_ids[] = { { .name = "ad7606-6", .driver_data = (kernel_ulong_t)&ad7606_6_info, }, { .name = "ad7606-8", .driver_data = (kernel_ulong_t)&ad7606_8_info, }, { .name = "ad7606b", .driver_data = (kernel_ulong_t)&ad7606b_info, }, + { .name = "ad7606c-16", .driver_data = (kernel_ulong_t)&ad7606c_16_info }, + { .name = "ad7606c-18", .driver_data = (kernel_ulong_t)&ad7606c_18_info }, { .name = "ad7607", .driver_data = (kernel_ulong_t)&ad7607_info, }, { .name = "ad7608", .driver_data = (kernel_ulong_t)&ad7608_info, }, { .name = "ad7609", .driver_data = (kernel_ulong_t)&ad7609_info, }, @@ -268,6 +237,8 @@ static const struct of_device_id ad7606_of_match[] = { { .compatible = "adi,ad7606-6", .data = &ad7606_6_info }, { .compatible = "adi,ad7606-8", .data = &ad7606_8_info }, { .compatible = "adi,ad7606b", .data = &ad7606b_info }, + { .compatible = "adi,ad7606c-16", .data = &ad7606c_16_info }, + { .compatible = "adi,ad7606c-18", .data = &ad7606c_18_info }, { .compatible = "adi,ad7607", .data = &ad7607_info }, { .compatible = "adi,ad7608", .data = &ad7608_info }, { .compatible = "adi,ad7609", .data = &ad7609_info }, diff --git a/drivers/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c index 179115e90988..f28e4ca37707 100644 --- a/drivers/iio/adc/ad7606_spi.c +++ b/drivers/iio/adc/ad7606_spi.c @@ -5,70 +5,43 @@ * Copyright 2011 Analog Devices Inc. */ +#include <linux/bitmap.h> #include <linux/err.h> +#include <linux/math.h> #include <linux/module.h> +#include <linux/pwm.h> +#include <linux/spi/offload/consumer.h> +#include <linux/spi/offload/provider.h> #include <linux/spi/spi.h> #include <linux/types.h> +#include <linux/units.h> +#include <linux/iio/buffer-dmaengine.h> #include <linux/iio/iio.h> -#include "ad7606.h" -#define MAX_SPI_FREQ_HZ 23500000 /* VDRIVE above 4.75 V */ +#include <dt-bindings/iio/adc/adi,ad7606.h> -static const struct iio_chan_spec ad7616_sw_channels[] = { - IIO_CHAN_SOFT_TIMESTAMP(16), - AD7616_CHANNEL(0), - AD7616_CHANNEL(1), - AD7616_CHANNEL(2), - AD7616_CHANNEL(3), - AD7616_CHANNEL(4), - AD7616_CHANNEL(5), - AD7616_CHANNEL(6), - AD7616_CHANNEL(7), - AD7616_CHANNEL(8), - AD7616_CHANNEL(9), - AD7616_CHANNEL(10), - AD7616_CHANNEL(11), - AD7616_CHANNEL(12), - AD7616_CHANNEL(13), - AD7616_CHANNEL(14), - AD7616_CHANNEL(15), -}; +#include "ad7606.h" -static const struct iio_chan_spec ad7606b_sw_channels[] = { - IIO_CHAN_SOFT_TIMESTAMP(8), - AD7606_SW_CHANNEL(0, 16), - AD7606_SW_CHANNEL(1, 16), - AD7606_SW_CHANNEL(2, 16), - AD7606_SW_CHANNEL(3, 16), - AD7606_SW_CHANNEL(4, 16), - AD7606_SW_CHANNEL(5, 16), - AD7606_SW_CHANNEL(6, 16), - AD7606_SW_CHANNEL(7, 16), -}; +#define MAX_SPI_FREQ_HZ 23500000 /* VDRIVE above 4.75 V */ -static const struct iio_chan_spec ad7606c_18_sw_channels[] = { - IIO_CHAN_SOFT_TIMESTAMP(8), - AD7606_SW_CHANNEL(0, 18), - AD7606_SW_CHANNEL(1, 18), - AD7606_SW_CHANNEL(2, 18), - AD7606_SW_CHANNEL(3, 18), - AD7606_SW_CHANNEL(4, 18), - AD7606_SW_CHANNEL(5, 18), - AD7606_SW_CHANNEL(6, 18), - AD7606_SW_CHANNEL(7, 18), +struct spi_bus_data { + struct spi_offload *offload; + struct spi_offload_trigger *offload_trigger; + struct spi_transfer offload_xfer; + struct spi_message offload_msg; }; -static u16 ad7616_spi_rd_wr_cmd(int addr, char isWriteOp) +static u16 ad7616_spi_rd_wr_cmd(int addr, char is_write_op) { /* * The address of register consist of one w/r bit * 6 bits of address followed by one reserved bit. */ - return ((addr & 0x7F) << 1) | ((isWriteOp & 0x1) << 7); + return ((addr & 0x7F) << 1) | ((is_write_op & 0x1) << 7); } -static u16 ad7606B_spi_rd_wr_cmd(int addr, char is_write_op) +static u16 ad7606b_spi_rd_wr_cmd(int addr, char is_write_op) { /* * The address of register consists of one bit which @@ -155,87 +128,275 @@ static int ad7606_spi_reg_write(struct ad7606_state *st, struct spi_device *spi = to_spi_device(st->dev); st->d16[0] = cpu_to_be16((st->bops->rd_wr_cmd(addr, 1) << 8) | - (val & 0x1FF)); + (val & 0xFF)); return spi_write(spi, &st->d16[0], sizeof(st->d16[0])); } -static int ad7616_sw_mode_config(struct iio_dev *indio_dev) +static int ad7606b_sw_mode_config(struct iio_dev *indio_dev) { + struct ad7606_state *st = iio_priv(indio_dev); + + /* Configure device spi to output on a single channel */ + return st->bops->reg_write(st, AD7606_CONFIGURATION_REGISTER, + AD7606_SINGLE_DOUT); +} + +static const struct spi_offload_config ad7606_spi_offload_config = { + .capability_flags = SPI_OFFLOAD_CAP_TRIGGER | + SPI_OFFLOAD_CAP_RX_STREAM_DMA, +}; + +static int ad7606_spi_offload_buffer_postenable(struct iio_dev *indio_dev) +{ + const struct iio_scan_type *scan_type; + struct ad7606_state *st = iio_priv(indio_dev); + struct spi_bus_data *bus_data = st->bus_data; + struct spi_transfer *xfer = &bus_data->offload_xfer; + struct spi_device *spi = to_spi_device(st->dev); + struct spi_offload_trigger_config config = { + .type = SPI_OFFLOAD_TRIGGER_DATA_READY, + }; + int ret; + + scan_type = &indio_dev->channels[0].scan_type; + + xfer->bits_per_word = scan_type->realbits; + xfer->offload_flags = SPI_OFFLOAD_XFER_RX_STREAM; /* - * Scale can be configured individually for each channel - * in software mode. + * Using SPI offload, storagebits are related to the spi-engine + * hw implementation, can be 16 or 32, so can't be used to compute + * struct spi_transfer.len. Using realbits instead. */ - indio_dev->channels = ad7616_sw_channels; + xfer->len = (scan_type->realbits > 16 ? 4 : 2) * + st->chip_info->num_adc_channels; + + spi_message_init_with_transfers(&bus_data->offload_msg, xfer, 1); + bus_data->offload_msg.offload = bus_data->offload; + + ret = spi_optimize_message(spi, &bus_data->offload_msg); + if (ret) { + dev_err(st->dev, "failed to prepare offload, err: %d\n", ret); + return ret; + } + + ret = spi_offload_trigger_enable(bus_data->offload, + bus_data->offload_trigger, + &config); + if (ret) + goto err_unoptimize_message; + + ret = ad7606_pwm_set_swing(st); + if (ret) + goto err_offload_exit_conversion_mode; return 0; + +err_offload_exit_conversion_mode: + spi_offload_trigger_disable(bus_data->offload, + bus_data->offload_trigger); + +err_unoptimize_message: + spi_unoptimize_message(&bus_data->offload_msg); + + return ret; } -static int ad7606B_sw_mode_config(struct iio_dev *indio_dev) +static int ad7606_spi_offload_buffer_predisable(struct iio_dev *indio_dev) { struct ad7606_state *st = iio_priv(indio_dev); + struct spi_bus_data *bus_data = st->bus_data; + int ret; - /* Configure device spi to output on a single channel */ - st->bops->reg_write(st, - AD7606_CONFIGURATION_REGISTER, - AD7606_SINGLE_DOUT); + ret = ad7606_pwm_set_low(st); + if (ret) + return ret; + + spi_offload_trigger_disable(bus_data->offload, + bus_data->offload_trigger); + spi_unoptimize_message(&bus_data->offload_msg); + + return 0; +} + +static const struct iio_buffer_setup_ops ad7606_offload_buffer_setup_ops = { + .postenable = ad7606_spi_offload_buffer_postenable, + .predisable = ad7606_spi_offload_buffer_predisable, +}; + +static bool ad7606_spi_offload_trigger_match( + struct spi_offload_trigger *trigger, + enum spi_offload_trigger_type type, + u64 *args, u32 nargs) +{ + if (type != SPI_OFFLOAD_TRIGGER_DATA_READY) + return false; /* - * Scale can be configured individually for each channel - * in software mode. + * Requires 1 arg: + * args[0] is the trigger event. */ - indio_dev->channels = ad7606b_sw_channels; + if (nargs != 1 || args[0] != AD7606_TRIGGER_EVENT_BUSY) + return false; + + return true; +} + +static int ad7606_spi_offload_trigger_request( + struct spi_offload_trigger *trigger, + enum spi_offload_trigger_type type, + u64 *args, u32 nargs) +{ + /* Should already be validated by match, but just in case. */ + if (nargs != 1) + return -EINVAL; + + return 0; +} + +static int ad7606_spi_offload_trigger_validate( + struct spi_offload_trigger *trigger, + struct spi_offload_trigger_config *config) +{ + if (config->type != SPI_OFFLOAD_TRIGGER_DATA_READY) + return -EINVAL; return 0; } -static int ad7606c_18_sw_mode_config(struct iio_dev *indio_dev) +static const struct spi_offload_trigger_ops ad7606_offload_trigger_ops = { + .match = ad7606_spi_offload_trigger_match, + .request = ad7606_spi_offload_trigger_request, + .validate = ad7606_spi_offload_trigger_validate, +}; + +static int ad7606_spi_offload_probe(struct device *dev, + struct iio_dev *indio_dev) { + struct ad7606_state *st = iio_priv(indio_dev); + struct spi_device *spi = to_spi_device(dev); + struct spi_bus_data *bus_data; + struct dma_chan *rx_dma; + struct spi_offload_trigger_info trigger_info = { + .fwnode = dev_fwnode(dev), + .ops = &ad7606_offload_trigger_ops, + .priv = st, + }; int ret; - ret = ad7606B_sw_mode_config(indio_dev); + bus_data = devm_kzalloc(dev, sizeof(*bus_data), GFP_KERNEL); + if (!bus_data) + return -ENOMEM; + st->bus_data = bus_data; + + bus_data->offload = devm_spi_offload_get(dev, spi, + &ad7606_spi_offload_config); + ret = PTR_ERR_OR_ZERO(bus_data->offload); + if (ret && ret != -ENODEV) + return dev_err_probe(dev, ret, "failed to get SPI offload\n"); + /* Allow main ad7606_probe function to continue. */ + if (ret == -ENODEV) + return 0; + + ret = devm_spi_offload_trigger_register(dev, &trigger_info); if (ret) - return ret; + return dev_err_probe(dev, ret, + "failed to register offload trigger\n"); + + bus_data->offload_trigger = devm_spi_offload_trigger_get(dev, + bus_data->offload, SPI_OFFLOAD_TRIGGER_DATA_READY); + if (IS_ERR(bus_data->offload_trigger)) + return dev_err_probe(dev, PTR_ERR(bus_data->offload_trigger), + "failed to get offload trigger\n"); + + /* TODO: PWM setup should be ok, done for the backend. PWM mutex ? */ + rx_dma = devm_spi_offload_rx_stream_request_dma_chan(dev, + bus_data->offload); + if (IS_ERR(rx_dma)) + return dev_err_probe(dev, PTR_ERR(rx_dma), + "failed to get offload RX DMA\n"); + + ret = devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, + rx_dma, IIO_BUFFER_DIRECTION_IN); + if (ret) + return dev_err_probe(dev, ret, + "failed to setup offload RX DMA\n"); + + /* Use offload ops. */ + indio_dev->setup_ops = &ad7606_offload_buffer_setup_ops; - indio_dev->channels = ad7606c_18_sw_channels; + st->offload_en = true; + + return 0; +} + +static int ad7606_spi_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + if (st->offload_en) { + unsigned int num_adc_ch = st->chip_info->num_adc_channels; + + /* + * SPI offload requires that all channels are enabled since + * there isn't a way to selectively disable channels that get + * read (this is simultaneous sampling ADC) and the DMA buffer + * has no way of demuxing the data to filter out unwanted + * channels. + */ + if (bitmap_weight(scan_mask, num_adc_ch) != num_adc_ch) + return -EINVAL; + } return 0; } static const struct ad7606_bus_ops ad7606_spi_bops = { + .offload_config = ad7606_spi_offload_probe, .read_block = ad7606_spi_read_block, + .update_scan_mode = ad7606_spi_update_scan_mode, }; static const struct ad7606_bus_ops ad7607_spi_bops = { + .offload_config = ad7606_spi_offload_probe, .read_block = ad7606_spi_read_block14to16, + .update_scan_mode = ad7606_spi_update_scan_mode, }; static const struct ad7606_bus_ops ad7608_spi_bops = { + .offload_config = ad7606_spi_offload_probe, .read_block = ad7606_spi_read_block18to32, + .update_scan_mode = ad7606_spi_update_scan_mode, }; static const struct ad7606_bus_ops ad7616_spi_bops = { + .offload_config = ad7606_spi_offload_probe, .read_block = ad7606_spi_read_block, .reg_read = ad7606_spi_reg_read, .reg_write = ad7606_spi_reg_write, .rd_wr_cmd = ad7616_spi_rd_wr_cmd, - .sw_mode_config = ad7616_sw_mode_config, + .update_scan_mode = ad7606_spi_update_scan_mode, }; static const struct ad7606_bus_ops ad7606b_spi_bops = { + .offload_config = ad7606_spi_offload_probe, .read_block = ad7606_spi_read_block, .reg_read = ad7606_spi_reg_read, .reg_write = ad7606_spi_reg_write, - .rd_wr_cmd = ad7606B_spi_rd_wr_cmd, - .sw_mode_config = ad7606B_sw_mode_config, + .rd_wr_cmd = ad7606b_spi_rd_wr_cmd, + .sw_mode_config = ad7606b_sw_mode_config, + .update_scan_mode = ad7606_spi_update_scan_mode, }; static const struct ad7606_bus_ops ad7606c_18_spi_bops = { + .offload_config = ad7606_spi_offload_probe, .read_block = ad7606_spi_read_block18to32, .reg_read = ad7606_spi_reg_read, .reg_write = ad7606_spi_reg_write, - .rd_wr_cmd = ad7606B_spi_rd_wr_cmd, - .sw_mode_config = ad7606c_18_sw_mode_config, + .rd_wr_cmd = ad7606b_spi_rd_wr_cmd, + .sw_mode_config = ad7606b_sw_mode_config, + .update_scan_mode = ad7606_spi_update_scan_mode, }; static const struct ad7606_bus_info ad7605_4_bus_info = { @@ -348,3 +509,4 @@ MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); MODULE_DESCRIPTION("Analog Devices AD7606 ADC"); MODULE_LICENSE("GPL v2"); MODULE_IMPORT_NS("IIO_AD7606"); +MODULE_IMPORT_NS("IIO_DMAENGINE_BUFFER"); diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c index 5e0be36af0c5..51134023534a 100644 --- a/drivers/iio/adc/ad7768-1.c +++ b/drivers/iio/adc/ad7768-1.c @@ -4,14 +4,17 @@ * * Copyright 2017 Analog Devices Inc. */ +#include <linux/array_size.h> #include <linux/bitfield.h> #include <linux/clk.h> +#include <linux/completion.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/err.h> #include <linux/gpio/consumer.h> -#include <linux/kernel.h> +#include <linux/interrupt.h> #include <linux/module.h> +#include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/sysfs.h> #include <linux/spi/spi.h> @@ -53,12 +56,15 @@ #define AD7768_REG_SPI_DIAG_ENABLE 0x28 #define AD7768_REG_ADC_DIAG_ENABLE 0x29 #define AD7768_REG_DIG_DIAG_ENABLE 0x2A -#define AD7768_REG_ADC_DATA 0x2C +#define AD7768_REG24_ADC_DATA 0x2C #define AD7768_REG_MASTER_STATUS 0x2D #define AD7768_REG_SPI_DIAG_STATUS 0x2E #define AD7768_REG_ADC_DIAG_STATUS 0x2F #define AD7768_REG_DIG_DIAG_STATUS 0x30 #define AD7768_REG_MCLK_COUNTER 0x31 +#define AD7768_REG_COEFF_CONTROL 0x32 +#define AD7768_REG24_COEFF_DATA 0x33 +#define AD7768_REG_ACCESS_KEY 0x34 /* AD7768_REG_POWER_CLOCK */ #define AD7768_PWR_MCLK_DIV_MSK GENMASK(5, 4) @@ -76,9 +82,6 @@ #define AD7768_CONV_MODE_MSK GENMASK(2, 0) #define AD7768_CONV_MODE(x) FIELD_PREP(AD7768_CONV_MODE_MSK, x) -#define AD7768_RD_FLAG_MSK(x) (BIT(6) | ((x) & 0x3F)) -#define AD7768_WR_FLAG_MSK(x) ((x) & 0x3F) - enum ad7768_conv_mode { AD7768_CONTINUOUS, AD7768_ONE_SHOT, @@ -153,6 +156,8 @@ static const struct iio_chan_spec ad7768_channels[] = { struct ad7768_state { struct spi_device *spi; + struct regmap *regmap; + struct regmap *regmap24; struct regulator *vref; struct clk *mclk; unsigned int mclk_freq; @@ -160,6 +165,7 @@ struct ad7768_state { struct completion completion; struct iio_trigger *trig; struct gpio_desc *gpio_sync_in; + struct gpio_desc *gpio_reset; const char *labels[ARRAY_SIZE(ad7768_channels)]; /* * DMA (thus cache coherency maintenance) may require the @@ -175,46 +181,82 @@ struct ad7768_state { } data __aligned(IIO_DMA_MINALIGN); }; -static int ad7768_spi_reg_read(struct ad7768_state *st, unsigned int addr, - unsigned int len) -{ - unsigned int shift; - int ret; +static const struct regmap_range ad7768_regmap_rd_ranges[] = { + regmap_reg_range(AD7768_REG_CHIP_TYPE, AD7768_REG_CHIP_GRADE), + regmap_reg_range(AD7768_REG_SCRATCH_PAD, AD7768_REG_SCRATCH_PAD), + regmap_reg_range(AD7768_REG_VENDOR_L, AD7768_REG_VENDOR_H), + regmap_reg_range(AD7768_REG_INTERFACE_FORMAT, AD7768_REG_GAIN_LO), + regmap_reg_range(AD7768_REG_SPI_DIAG_ENABLE, AD7768_REG_DIG_DIAG_ENABLE), + regmap_reg_range(AD7768_REG_MASTER_STATUS, AD7768_REG_COEFF_CONTROL), + regmap_reg_range(AD7768_REG_ACCESS_KEY, AD7768_REG_ACCESS_KEY), +}; - shift = 32 - (8 * len); - st->data.d8[0] = AD7768_RD_FLAG_MSK(addr); +static const struct regmap_access_table ad7768_regmap_rd_table = { + .yes_ranges = ad7768_regmap_rd_ranges, + .n_yes_ranges = ARRAY_SIZE(ad7768_regmap_rd_ranges), +}; - ret = spi_write_then_read(st->spi, st->data.d8, 1, - &st->data.d32, len); - if (ret < 0) - return ret; +static const struct regmap_range ad7768_regmap_wr_ranges[] = { + regmap_reg_range(AD7768_REG_SCRATCH_PAD, AD7768_REG_SCRATCH_PAD), + regmap_reg_range(AD7768_REG_INTERFACE_FORMAT, AD7768_REG_GPIO_WRITE), + regmap_reg_range(AD7768_REG_OFFSET_HI, AD7768_REG_GAIN_LO), + regmap_reg_range(AD7768_REG_SPI_DIAG_ENABLE, AD7768_REG_DIG_DIAG_ENABLE), + regmap_reg_range(AD7768_REG_SPI_DIAG_STATUS, AD7768_REG_SPI_DIAG_STATUS), + regmap_reg_range(AD7768_REG_COEFF_CONTROL, AD7768_REG_COEFF_CONTROL), + regmap_reg_range(AD7768_REG_ACCESS_KEY, AD7768_REG_ACCESS_KEY), +}; - return (be32_to_cpu(st->data.d32) >> shift); -} +static const struct regmap_access_table ad7768_regmap_wr_table = { + .yes_ranges = ad7768_regmap_wr_ranges, + .n_yes_ranges = ARRAY_SIZE(ad7768_regmap_wr_ranges), +}; -static int ad7768_spi_reg_write(struct ad7768_state *st, - unsigned int addr, - unsigned int val) -{ - st->data.d8[0] = AD7768_WR_FLAG_MSK(addr); - st->data.d8[1] = val & 0xFF; +static const struct regmap_config ad7768_regmap_config = { + .name = "ad7768-1-8", + .reg_bits = 8, + .val_bits = 8, + .read_flag_mask = BIT(6), + .rd_table = &ad7768_regmap_rd_table, + .wr_table = &ad7768_regmap_wr_table, + .max_register = AD7768_REG_ACCESS_KEY, + .use_single_write = true, + .use_single_read = true, +}; - return spi_write(st->spi, st->data.d8, 2); -} +static const struct regmap_range ad7768_regmap24_rd_ranges[] = { + regmap_reg_range(AD7768_REG24_ADC_DATA, AD7768_REG24_ADC_DATA), + regmap_reg_range(AD7768_REG24_COEFF_DATA, AD7768_REG24_COEFF_DATA), +}; -static int ad7768_set_mode(struct ad7768_state *st, - enum ad7768_conv_mode mode) -{ - int regval; +static const struct regmap_access_table ad7768_regmap24_rd_table = { + .yes_ranges = ad7768_regmap24_rd_ranges, + .n_yes_ranges = ARRAY_SIZE(ad7768_regmap24_rd_ranges), +}; - regval = ad7768_spi_reg_read(st, AD7768_REG_CONVERSION, 1); - if (regval < 0) - return regval; +static const struct regmap_range ad7768_regmap24_wr_ranges[] = { + regmap_reg_range(AD7768_REG24_COEFF_DATA, AD7768_REG24_COEFF_DATA), +}; - regval &= ~AD7768_CONV_MODE_MSK; - regval |= AD7768_CONV_MODE(mode); +static const struct regmap_access_table ad7768_regmap24_wr_table = { + .yes_ranges = ad7768_regmap24_wr_ranges, + .n_yes_ranges = ARRAY_SIZE(ad7768_regmap24_wr_ranges), +}; - return ad7768_spi_reg_write(st, AD7768_REG_CONVERSION, regval); +static const struct regmap_config ad7768_regmap24_config = { + .name = "ad7768-1-24", + .reg_bits = 8, + .val_bits = 24, + .read_flag_mask = BIT(6), + .rd_table = &ad7768_regmap24_rd_table, + .wr_table = &ad7768_regmap24_wr_table, + .max_register = AD7768_REG24_COEFF_DATA, +}; + +static int ad7768_set_mode(struct ad7768_state *st, + enum ad7768_conv_mode mode) +{ + return regmap_update_bits(st->regmap, AD7768_REG_CONVERSION, + AD7768_CONV_MODE_MSK, AD7768_CONV_MODE(mode)); } static int ad7768_scan_direct(struct iio_dev *indio_dev) @@ -233,9 +275,10 @@ static int ad7768_scan_direct(struct iio_dev *indio_dev) if (!ret) return -ETIMEDOUT; - readval = ad7768_spi_reg_read(st, AD7768_REG_ADC_DATA, 3); - if (readval < 0) - return readval; + ret = regmap_read(st->regmap24, AD7768_REG24_ADC_DATA, &readval); + if (ret) + return ret; + /* * Any SPI configuration of the AD7768-1 can only be * performed in continuous conversion mode. @@ -258,16 +301,23 @@ static int ad7768_reg_access(struct iio_dev *indio_dev, if (!iio_device_claim_direct(indio_dev)) return -EBUSY; + ret = -EINVAL; if (readval) { - ret = ad7768_spi_reg_read(st, reg, 1); - if (ret < 0) - goto err_release; - *readval = ret; - ret = 0; + if (regmap_check_range_table(st->regmap, reg, &ad7768_regmap_rd_table)) + ret = regmap_read(st->regmap, reg, readval); + + if (regmap_check_range_table(st->regmap24, reg, &ad7768_regmap24_rd_table)) + ret = regmap_read(st->regmap24, reg, readval); + } else { - ret = ad7768_spi_reg_write(st, reg, writeval); + if (regmap_check_range_table(st->regmap, reg, &ad7768_regmap_wr_table)) + ret = regmap_write(st->regmap, reg, writeval); + + if (regmap_check_range_table(st->regmap24, reg, &ad7768_regmap24_wr_table)) + ret = regmap_write(st->regmap24, reg, writeval); + } -err_release: + iio_device_release_direct(indio_dev); return ret; @@ -284,7 +334,7 @@ static int ad7768_set_dig_fil(struct ad7768_state *st, else mode = AD7768_DIG_FIL_DEC_RATE(dec_rate); - ret = ad7768_spi_reg_write(st, AD7768_REG_DIGITAL_FILTER, mode); + ret = regmap_write(st->regmap, AD7768_REG_DIGITAL_FILTER, mode); if (ret < 0) return ret; @@ -321,7 +371,7 @@ static int ad7768_set_freq(struct ad7768_state *st, */ pwr_mode = AD7768_PWR_MCLK_DIV(ad7768_clk_config[idx].mclk_div) | AD7768_PWR_PWRMODE(ad7768_clk_config[idx].pwrmode); - ret = ad7768_spi_reg_write(st, AD7768_REG_POWER_CLOCK, pwr_mode); + ret = regmap_write(st->regmap, AD7768_REG_POWER_CLOCK, pwr_mode); if (ret < 0) return ret; @@ -440,19 +490,30 @@ static int ad7768_setup(struct ad7768_state *st) { int ret; - /* - * Two writes to the SPI_RESET[1:0] bits are required to initiate - * a software reset. The bits must first be set to 11, and then - * to 10. When the sequence is detected, the reset occurs. - * See the datasheet, page 70. - */ - ret = ad7768_spi_reg_write(st, AD7768_REG_SYNC_RESET, 0x3); - if (ret) - return ret; + st->gpio_reset = devm_gpiod_get_optional(&st->spi->dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(st->gpio_reset)) + return PTR_ERR(st->gpio_reset); - ret = ad7768_spi_reg_write(st, AD7768_REG_SYNC_RESET, 0x2); - if (ret) - return ret; + if (st->gpio_reset) { + fsleep(10); + gpiod_set_value_cansleep(st->gpio_reset, 0); + fsleep(200); + } else { + /* + * Two writes to the SPI_RESET[1:0] bits are required to initiate + * a software reset. The bits must first be set to 11, and then + * to 10. When the sequence is detected, the reset occurs. + * See the datasheet, page 70. + */ + ret = regmap_write(st->regmap, AD7768_REG_SYNC_RESET, 0x3); + if (ret) + return ret; + + ret = regmap_write(st->regmap, AD7768_REG_SYNC_RESET, 0x2); + if (ret) + return ret; + } st->gpio_sync_in = devm_gpiod_get(&st->spi->dev, "adi,sync-in", GPIOD_OUT_LOW); @@ -474,8 +535,9 @@ static irqreturn_t ad7768_trigger_handler(int irq, void *p) if (ret < 0) goto out; - iio_push_to_buffers_with_timestamp(indio_dev, &st->data.scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &st->data.scan, + sizeof(st->data.scan), + iio_get_time_ns(indio_dev)); out: iio_trigger_notify_done(indio_dev->trig); @@ -505,18 +567,19 @@ static int ad7768_buffer_postenable(struct iio_dev *indio_dev) * continuous read mode. Subsequent data reads do not require an * initial 8-bit write to query the ADC_DATA register. */ - return ad7768_spi_reg_write(st, AD7768_REG_INTERFACE_FORMAT, 0x01); + return regmap_write(st->regmap, AD7768_REG_INTERFACE_FORMAT, 0x01); } static int ad7768_buffer_predisable(struct iio_dev *indio_dev) { struct ad7768_state *st = iio_priv(indio_dev); + unsigned int unused; /* * To exit continuous read mode, perform a single read of the ADC_DATA * reg (0x2C), which allows further configuration of the device. */ - return ad7768_spi_reg_read(st, AD7768_REG_ADC_DATA, 3); + return regmap_read(st->regmap24, AD7768_REG24_ADC_DATA, &unused); } static const struct iio_buffer_setup_ops ad7768_buffer_ops = { @@ -559,6 +622,31 @@ static int ad7768_set_channel_label(struct iio_dev *indio_dev, return 0; } +static int ad7768_triggered_buffer_alloc(struct iio_dev *indio_dev) +{ + struct ad7768_state *st = iio_priv(indio_dev); + int ret; + + st->trig = devm_iio_trigger_alloc(indio_dev->dev.parent, "%s-dev%d", + indio_dev->name, + iio_device_id(indio_dev)); + if (!st->trig) + return -ENOMEM; + + st->trig->ops = &ad7768_trigger_ops; + iio_trigger_set_drvdata(st->trig, indio_dev); + ret = devm_iio_trigger_register(indio_dev->dev.parent, st->trig); + if (ret) + return ret; + + indio_dev->trig = iio_trigger_get(st->trig); + + return devm_iio_triggered_buffer_setup(indio_dev->dev.parent, indio_dev, + &iio_pollfunc_store_time, + &ad7768_trigger_handler, + &ad7768_buffer_ops); +} + static int ad7768_probe(struct spi_device *spi) { struct ad7768_state *st; @@ -587,6 +675,16 @@ static int ad7768_probe(struct spi_device *spi) st->spi = spi; + st->regmap = devm_regmap_init_spi(spi, &ad7768_regmap_config); + if (IS_ERR(st->regmap)) + return dev_err_probe(&spi->dev, PTR_ERR(st->regmap), + "Failed to initialize regmap"); + + st->regmap24 = devm_regmap_init_spi(spi, &ad7768_regmap24_config); + if (IS_ERR(st->regmap24)) + return dev_err_probe(&spi->dev, PTR_ERR(st->regmap24), + "Failed to initialize regmap24"); + st->vref = devm_regulator_get(&spi->dev, "vref"); if (IS_ERR(st->vref)) return PTR_ERR(st->vref); @@ -619,20 +717,6 @@ static int ad7768_probe(struct spi_device *spi) return ret; } - st->trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d", - indio_dev->name, - iio_device_id(indio_dev)); - if (!st->trig) - return -ENOMEM; - - st->trig->ops = &ad7768_trigger_ops; - iio_trigger_set_drvdata(st->trig, indio_dev); - ret = devm_iio_trigger_register(&spi->dev, st->trig); - if (ret) - return ret; - - indio_dev->trig = iio_trigger_get(st->trig); - init_completion(&st->completion); ret = ad7768_set_channel_label(indio_dev, ARRAY_SIZE(ad7768_channels)); @@ -646,10 +730,7 @@ static int ad7768_probe(struct spi_device *spi) if (ret) return ret; - ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, - &iio_pollfunc_store_time, - &ad7768_trigger_handler, - &ad7768_buffer_ops); + ret = ad7768_triggered_buffer_alloc(indio_dev); if (ret) return ret; @@ -658,7 +739,7 @@ static int ad7768_probe(struct spi_device *spi) static const struct spi_device_id ad7768_id_table[] = { { "ad7768-1", 0 }, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad7768_id_table); diff --git a/drivers/iio/adc/ad7779.c b/drivers/iio/adc/ad7779.c index a5d87faa5e12..845adc510239 100644 --- a/drivers/iio/adc/ad7779.c +++ b/drivers/iio/adc/ad7779.c @@ -595,7 +595,8 @@ static irqreturn_t ad7779_trigger_handler(int irq, void *p) goto exit_handler; } - iio_push_to_buffers_with_timestamp(indio_dev, &st->data, pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &st->data, sizeof(st->data), + pf->timestamp); exit_handler: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c index 597c2686ffa4..041fc25e3209 100644 --- a/drivers/iio/adc/ad7791.c +++ b/drivers/iio/adc/ad7791.c @@ -464,7 +464,7 @@ static const struct spi_device_id ad7791_spi_ids[] = { { "ad7789", AD7789 }, { "ad7790", AD7790 }, { "ad7791", AD7791 }, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad7791_spi_ids); diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c index 87945efb940b..0369151c7db1 100644 --- a/drivers/iio/adc/ad7923.c +++ b/drivers/iio/adc/ad7923.c @@ -207,8 +207,8 @@ static irqreturn_t ad7923_trigger_handler(int irq, void *p) if (b_sent) goto done; - iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, st->rx_buf, sizeof(st->rx_buf), + iio_get_time_ns(indio_dev)); done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/adc/ad7944.c b/drivers/iio/adc/ad7944.c index 2f949fe55873..7722cf9e8214 100644 --- a/drivers/iio/adc/ad7944.c +++ b/drivers/iio/adc/ad7944.c @@ -190,11 +190,6 @@ static int ad7944_3wire_cs_mode_init_msg(struct device *dev, struct ad7944_adc * struct spi_transfer *xfers = adc->xfers; /* - * 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. */ @@ -208,7 +203,6 @@ static int ad7944_3wire_cs_mode_init_msg(struct device *dev, struct ad7944_adc * 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; @@ -228,11 +222,6 @@ static int ad7944_4wire_mode_init_msg(struct device *dev, struct ad7944_adc *adc struct spi_transfer *xfers = adc->xfers; /* - * 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. */ @@ -377,6 +366,8 @@ static int ad7944_single_conversion(struct ad7944_adc *adc, if (chan->scan_type.sign == 's') *val = sign_extend32(*val, chan->scan_type.realbits - 1); + else + *val &= GENMASK(chan->scan_type.realbits - 1, 0); return IIO_VAL_INT; } diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c index 993f4651b73a..9c02f9199139 100644 --- a/drivers/iio/adc/ad799x.c +++ b/drivers/iio/adc/ad799x.c @@ -958,7 +958,7 @@ static const struct i2c_device_id ad799x_id[] = { { "ad7994", ad7994 }, { "ad7997", ad7997 }, { "ad7998", ad7998 }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, ad799x_id); diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index 6c37f8e21120..4c5f8d29a559 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -587,6 +587,10 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p) * byte set to zero. */ ad_sd_read_reg_raw(sigma_delta, data_reg, transfer_size, &data[1]); break; + + default: + dev_err_ratelimited(&indio_dev->dev, "Unsupported reg_size: %u\n", reg_size); + goto irq_handled; } /* diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c index cf942c043457..4116c44197b8 100644 --- a/drivers/iio/adc/adi-axi-adc.c +++ b/drivers/iio/adc/adi-axi-adc.c @@ -702,7 +702,7 @@ static const struct of_device_id adi_axi_adc_of_match[] = { { .compatible = "adi,axi-adc-10.0.a", .data = &adc_generic }, { .compatible = "adi,axi-ad485x", .data = &adi_axi_ad485x }, { .compatible = "adi,axi-ad7606x", .data = &adc_ad7606 }, - { /* end of list */ } + { } }; MODULE_DEVICE_TABLE(of, adi_axi_adc_of_match); diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index 414610afcb2c..c3450246730e 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -586,15 +586,6 @@ struct at91_adc_temp { u16 saved_oversampling; }; -/* - * Buffer size requirements: - * No channels * bytes_per_channel(2) + timestamp bytes (8) - * Divided by 2 because we need half words. - * We assume 32 channels for now, has to be increased if needed. - * Nobody minds a buffer being too big. - */ -#define AT91_BUFFER_MAX_HWORDS ((32 * 2 + 8) / 2) - struct at91_adc_state { void __iomem *base; int irq; @@ -616,8 +607,8 @@ struct at91_adc_state { struct at91_adc_temp temp_st; struct iio_dev *indio_dev; struct device *dev; - /* Ensure naturally aligned timestamp */ - u16 buffer[AT91_BUFFER_MAX_HWORDS] __aligned(8); + /* We assume 32 channels for now, has to be increased if needed. */ + IIO_DECLARE_BUFFER_WITH_TS(u16, buffer, 32); /* * lock to prevent concurrent 'single conversion' requests through * sysfs. diff --git a/drivers/iio/adc/axp20x_adc.c b/drivers/iio/adc/axp20x_adc.c index 9fd7027623d0..71584ffd3632 100644 --- a/drivers/iio/adc/axp20x_adc.c +++ b/drivers/iio/adc/axp20x_adc.c @@ -163,14 +163,14 @@ static const struct iio_map axp20x_maps[] = { IIO_MAP("batt_v", "axp20x-battery-power-supply", "batt_v"), IIO_MAP("batt_chrg_i", "axp20x-battery-power-supply", "batt_chrg_i"), IIO_MAP("batt_dischrg_i", "axp20x-battery-power-supply", "batt_dischrg_i"), - { /* sentinel */ } + { } }; static const struct iio_map axp22x_maps[] = { IIO_MAP("batt_v", "axp20x-battery-power-supply", "batt_v"), IIO_MAP("batt_chrg_i", "axp20x-battery-power-supply", "batt_chrg_i"), IIO_MAP("batt_dischrg_i", "axp20x-battery-power-supply", "batt_dischrg_i"), - { /* sentinel */ } + { } }; static struct iio_map axp717_maps[] = { @@ -1074,7 +1074,7 @@ static const struct of_device_id axp20x_adc_of_match[] = { { .compatible = "x-powers,axp221-adc", .data = (void *)&axp22x_data, }, { .compatible = "x-powers,axp717-adc", .data = (void *)&axp717_data, }, { .compatible = "x-powers,axp813-adc", .data = (void *)&axp813_data, }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, axp20x_adc_of_match); @@ -1084,7 +1084,7 @@ static const struct platform_device_id axp20x_adc_id_match[] = { { .name = "axp22x-adc", .driver_data = (kernel_ulong_t)&axp22x_data, }, { .name = "axp717-adc", .driver_data = (kernel_ulong_t)&axp717_data, }, { .name = "axp813-adc", .driver_data = (kernel_ulong_t)&axp813_data, }, - { /* sentinel */ }, + { } }; MODULE_DEVICE_TABLE(platform, axp20x_adc_id_match); diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c index 45542efc3ece..c8283279c477 100644 --- a/drivers/iio/adc/axp288_adc.c +++ b/drivers/iio/adc/axp288_adc.c @@ -110,7 +110,7 @@ static const struct iio_map axp288_adc_default_maps[] = { IIO_MAP("BATT_CHG_I", "axp288-chrg", "axp288-chrg-curr"), IIO_MAP("BATT_DISCHRG_I", "axp288-chrg", "axp288-chrg-d-curr"), IIO_MAP("BATT_V", "axp288-batt", "axp288-batt-volt"), - {}, + { } }; static int axp288_adc_read_channel(int *val, unsigned long address, @@ -207,7 +207,7 @@ static const struct dmi_system_id axp288_adc_ts_bias_override[] = { }, .driver_data = (void *)(uintptr_t)AXP288_ADC_TS_BIAS_80UA, }, - {} + { } }; static int axp288_adc_initialize(struct axp288_adc_info *info) diff --git a/drivers/iio/adc/cpcap-adc.c b/drivers/iio/adc/cpcap-adc.c index c218acf6c9c6..ba7cbd3b4822 100644 --- a/drivers/iio/adc/cpcap-adc.c +++ b/drivers/iio/adc/cpcap-adc.c @@ -942,7 +942,7 @@ static const struct of_device_id cpcap_adc_id_table[] = { .compatible = "motorola,mapphone-cpcap-adc", .data = &mapphone_adc, }, - { /* sentinel */ }, + { } }; MODULE_DEVICE_TABLE(of, cpcap_adc_id_table); diff --git a/drivers/iio/adc/da9150-gpadc.c b/drivers/iio/adc/da9150-gpadc.c index 0290345ade84..b99291ce2a45 100644 --- a/drivers/iio/adc/da9150-gpadc.c +++ b/drivers/iio/adc/da9150-gpadc.c @@ -296,7 +296,7 @@ static const struct iio_map da9150_gpadc_default_maps[] = { IIO_MAP("VBUS", "da9150-charger", "CHAN_VBUS"), IIO_MAP("TJUNC_CORE", "da9150-charger", "CHAN_TJUNC"), IIO_MAP("VBAT", "da9150-charger", "CHAN_VBAT"), - {}, + { } }; static int da9150_gpadc_probe(struct platform_device *pdev) diff --git a/drivers/iio/adc/dln2-adc.c b/drivers/iio/adc/dln2-adc.c index 359e26e3f5bc..9dbd2c87938c 100644 --- a/drivers/iio/adc/dln2-adc.c +++ b/drivers/iio/adc/dln2-adc.c @@ -488,8 +488,8 @@ static irqreturn_t dln2_adc_trigger_h(int irq, void *p) (void *)dev_data.values + t->from, t->length); } - iio_push_to_buffers_with_timestamp(indio_dev, &data, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &data, sizeof(data), + iio_get_time_ns(indio_dev)); done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/adc/envelope-detector.c b/drivers/iio/adc/envelope-detector.c index e911c25d106d..5b16fe737659 100644 --- a/drivers/iio/adc/envelope-detector.c +++ b/drivers/iio/adc/envelope-detector.c @@ -305,7 +305,7 @@ static const struct iio_chan_spec_ext_info envelope_detector_ext_info[] = { { .name = "compare_interval", .read = envelope_show_comp_interval, .write = envelope_store_comp_interval, }, - { /* sentinel */ } + { } }; static const struct iio_chan_spec envelope_detector_iio_channel = { @@ -390,7 +390,7 @@ static int envelope_detector_probe(struct platform_device *pdev) static const struct of_device_id envelope_detector_match[] = { { .compatible = "axentia,tse850-envelope-detector", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, envelope_detector_match); diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c index b3f037510e35..f8c220f6a7b4 100644 --- a/drivers/iio/adc/fsl-imx25-gcq.c +++ b/drivers/iio/adc/fsl-imx25-gcq.c @@ -372,7 +372,7 @@ static int mx25_gcq_probe(struct platform_device *pdev) static const struct of_device_id mx25_gcq_ids[] = { { .compatible = "fsl,imx25-gcq", }, - { /* Sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, mx25_gcq_ids); diff --git a/drivers/iio/adc/hi8435.c b/drivers/iio/adc/hi8435.c index 689e34f06987..b4562aae8477 100644 --- a/drivers/iio/adc/hi8435.c +++ b/drivers/iio/adc/hi8435.c @@ -351,7 +351,7 @@ static const struct iio_enum hi8435_sensing_mode = { static const struct iio_chan_spec_ext_info hi8435_ext_info[] = { IIO_ENUM("sensing_mode", IIO_SEPARATE, &hi8435_sensing_mode), IIO_ENUM_AVAILABLE("sensing_mode", IIO_SHARED_BY_TYPE, &hi8435_sensing_mode), - {}, + { } }; #define HI8435_VOLTAGE_CHANNEL(num) \ diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c index 8da0419ecfa3..7235fa9e13d5 100644 --- a/drivers/iio/adc/hx711.c +++ b/drivers/iio/adc/hx711.c @@ -87,7 +87,10 @@ struct hx711_data { * triggered buffer * 2x32-bit channel + 64-bit naturally aligned timestamp */ - u32 buffer[4] __aligned(8); + struct { + u32 channel[2]; + aligned_s64 timestamp; + } buffer; /* * delay after a rising edge on SCK until the data is ready DOUT * this is dependent on the hx711 where the datasheet tells a @@ -361,15 +364,15 @@ static irqreturn_t hx711_trigger(int irq, void *p) mutex_lock(&hx711_data->lock); - memset(hx711_data->buffer, 0, sizeof(hx711_data->buffer)); + memset(&hx711_data->buffer, 0, sizeof(hx711_data->buffer)); iio_for_each_active_channel(indio_dev, i) { - hx711_data->buffer[j] = hx711_reset_read(hx711_data, + hx711_data->buffer.channel[j] = hx711_reset_read(hx711_data, indio_dev->channels[i].channel); j++; } - iio_push_to_buffers_with_timestamp(indio_dev, hx711_data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &hx711_data->buffer, pf->timestamp); mutex_unlock(&hx711_data->lock); diff --git a/drivers/iio/adc/imx7d_adc.c b/drivers/iio/adc/imx7d_adc.c index 828d3fea6d43..09ce71f6e941 100644 --- a/drivers/iio/adc/imx7d_adc.c +++ b/drivers/iio/adc/imx7d_adc.c @@ -413,7 +413,7 @@ static const struct iio_info imx7d_adc_iio_info = { static const struct of_device_id imx7d_adc_match[] = { { .compatible = "fsl,imx7d-adc", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, imx7d_adc_match); diff --git a/drivers/iio/adc/imx8qxp-adc.c b/drivers/iio/adc/imx8qxp-adc.c index 3d19d7d744aa..be13a6ed7e00 100644 --- a/drivers/iio/adc/imx8qxp-adc.c +++ b/drivers/iio/adc/imx8qxp-adc.c @@ -481,7 +481,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(imx8qxp_adc_pm_ops, static const struct of_device_id imx8qxp_adc_match[] = { { .compatible = "nxp,imx8qxp-adc", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, imx8qxp_adc_match); diff --git a/drivers/iio/adc/imx93_adc.c b/drivers/iio/adc/imx93_adc.c index 002eb19587d6..7feaafd2316f 100644 --- a/drivers/iio/adc/imx93_adc.c +++ b/drivers/iio/adc/imx93_adc.c @@ -464,7 +464,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(imx93_adc_pm_ops, static const struct of_device_id imx93_adc_match[] = { { .compatible = "nxp,imx93-adc", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, imx93_adc_match); diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index 40d14faa71c5..857e1b69d6cd 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -766,7 +766,7 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) chip->scan.chan[i++] = val; } - iio_push_to_buffers_with_timestamp(indio_dev, &chip->scan, time); + iio_push_to_buffers_with_ts(indio_dev, &chip->scan, sizeof(chip->scan), time); return 0; }; diff --git a/drivers/iio/adc/industrialio-adc.c b/drivers/iio/adc/industrialio-adc.c new file mode 100644 index 000000000000..b4057230e749 --- /dev/null +++ b/drivers/iio/adc/industrialio-adc.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Helpers for parsing common ADC information from a firmware node. + * + * Copyright (c) 2025 Matti Vaittinen <mazziesaccount@gmail.com> + */ + +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/export.h> +#include <linux/module.h> +#include <linux/property.h> +#include <linux/types.h> + +#include <linux/iio/adc-helpers.h> +#include <linux/iio/iio.h> + +/** + * devm_iio_adc_device_alloc_chaninfo_se - allocate and fill iio_chan_spec for ADC + * + * Scan the device node for single-ended ADC channel information. Channel ID is + * expected to be found from the "reg" property. Allocate and populate the + * iio_chan_spec structure corresponding to channels that are found. The memory + * for iio_chan_spec structure will be freed upon device detach. + * + * @dev: Pointer to the ADC device. + * @template: Template iio_chan_spec from which the fields of all + * found and allocated channels are initialized. + * @max_chan_id: Maximum value of a channel ID. Use negative value if no + * checking is required. + * @cs: Location where pointer to allocated iio_chan_spec + * should be stored. + * + * Return: Number of found channels on success. Negative value to indicate + * failure. Specifically, -ENOENT if no channel nodes were found. + */ +int devm_iio_adc_device_alloc_chaninfo_se(struct device *dev, + const struct iio_chan_spec *template, + int max_chan_id, + struct iio_chan_spec **cs) +{ + struct iio_chan_spec *chan_array, *chan; + int num_chan, ret; + + num_chan = iio_adc_device_num_channels(dev); + if (num_chan < 0) + return num_chan; + + if (!num_chan) + return -ENOENT; + + chan_array = devm_kcalloc(dev, num_chan, sizeof(*chan_array), + GFP_KERNEL); + if (!chan_array) + return -ENOMEM; + + chan = &chan_array[0]; + + device_for_each_named_child_node_scoped(dev, child, "channel") { + u32 ch; + + ret = fwnode_property_read_u32(child, "reg", &ch); + if (ret) + return ret; + + if (max_chan_id >= 0 && ch > max_chan_id) + return -ERANGE; + + *chan = *template; + chan->channel = ch; + chan++; + } + + *cs = chan_array; + + return num_chan; +} +EXPORT_SYMBOL_NS_GPL(devm_iio_adc_device_alloc_chaninfo_se, "IIO_DRIVER"); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Matti Vaittinen <mazziesaccount@gmail.com>"); +MODULE_DESCRIPTION("IIO ADC fwnode parsing helpers"); diff --git a/drivers/iio/adc/intel_mrfld_adc.c b/drivers/iio/adc/intel_mrfld_adc.c index c178850eaaab..101c1a0ce591 100644 --- a/drivers/iio/adc/intel_mrfld_adc.c +++ b/drivers/iio/adc/intel_mrfld_adc.c @@ -174,7 +174,7 @@ static const struct iio_map iio_maps[] = { IIO_MAP("CH6", "bcove-temp", "SYSTEMP0"), IIO_MAP("CH7", "bcove-temp", "SYSTEMP1"), IIO_MAP("CH8", "bcove-temp", "SYSTEMP2"), - {} + { } }; static int mrfld_adc_probe(struct platform_device *pdev) @@ -222,7 +222,7 @@ static int mrfld_adc_probe(struct platform_device *pdev) static const struct platform_device_id mrfld_adc_id_table[] = { { .name = "mrfld_bcove_adc" }, - {} + { } }; MODULE_DEVICE_TABLE(platform, mrfld_adc_id_table); diff --git a/drivers/iio/adc/lpc18xx_adc.c b/drivers/iio/adc/lpc18xx_adc.c index 450a243d1f7c..7e5d181ff702 100644 --- a/drivers/iio/adc/lpc18xx_adc.c +++ b/drivers/iio/adc/lpc18xx_adc.c @@ -188,7 +188,7 @@ static int lpc18xx_adc_probe(struct platform_device *pdev) static const struct of_device_id lpc18xx_adc_match[] = { { .compatible = "nxp,lpc1850-adc" }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, lpc18xx_adc_match); diff --git a/drivers/iio/adc/ltc2471.c b/drivers/iio/adc/ltc2471.c index 97c417c3a4eb..a579107fd5c9 100644 --- a/drivers/iio/adc/ltc2471.c +++ b/drivers/iio/adc/ltc2471.c @@ -138,7 +138,7 @@ static int ltc2471_i2c_probe(struct i2c_client *client) static const struct i2c_device_id ltc2471_i2c_id[] = { { "ltc2471", ltc2471 }, { "ltc2473", ltc2473 }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, ltc2471_i2c_id); diff --git a/drivers/iio/adc/max1118.c b/drivers/iio/adc/max1118.c index 565ca2e21c0c..7d7001e8e3d9 100644 --- a/drivers/iio/adc/max1118.c +++ b/drivers/iio/adc/max1118.c @@ -188,8 +188,8 @@ static irqreturn_t max1118_trigger_handler(int irq, void *p) adc->scan.channels[i] = ret; i++; } - iio_push_to_buffers_with_timestamp(indio_dev, &adc->scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &adc->scan, sizeof(adc->scan), + iio_get_time_ns(indio_dev)); out: mutex_unlock(&adc->lock); diff --git a/drivers/iio/adc/max11410.c b/drivers/iio/adc/max11410.c index 437d9f24b5a1..511b2f14dfaf 100644 --- a/drivers/iio/adc/max11410.c +++ b/drivers/iio/adc/max11410.c @@ -632,8 +632,8 @@ static irqreturn_t max11410_trigger_handler(int irq, void *p) goto out; } - iio_push_to_buffers_with_timestamp(indio_dev, &st->scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &st->scan, sizeof(st->scan), + iio_get_time_ns(indio_dev)); out: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c index 35717ec082ce..a7e9912fb44a 100644 --- a/drivers/iio/adc/max1363.c +++ b/drivers/iio/adc/max1363.c @@ -1498,8 +1498,8 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p) if (b_sent < 0) goto done; - iio_push_to_buffers_with_timestamp(indio_dev, &st->data, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &st->data, sizeof(st->data), + iio_get_time_ns(indio_dev)); done: iio_trigger_notify_done(indio_dev->trig); @@ -1551,7 +1551,7 @@ static const struct of_device_id max1363_of_match[] = { MAX1363_COMPATIBLE("maxim,max11645", max11645), MAX1363_COMPATIBLE("maxim,max11646", max11646), MAX1363_COMPATIBLE("maxim,max11647", max11647), - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, max1363_of_match); @@ -1672,7 +1672,7 @@ static const struct i2c_device_id max1363_id[] = { MAX1363_ID_TABLE("max11645", max11645), MAX1363_ID_TABLE("max11646", max11646), MAX1363_ID_TABLE("max11647", max11647), - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(i2c, max1363_id); diff --git a/drivers/iio/adc/max77541-adc.c b/drivers/iio/adc/max77541-adc.c index 21d024bde16b..0aa04d143ad4 100644 --- a/drivers/iio/adc/max77541-adc.c +++ b/drivers/iio/adc/max77541-adc.c @@ -176,7 +176,7 @@ static int max77541_adc_probe(struct platform_device *pdev) static const struct platform_device_id max77541_adc_platform_id[] = { { "max77541-adc" }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(platform, max77541_adc_platform_id); diff --git a/drivers/iio/adc/mcp3911.c b/drivers/iio/adc/mcp3911.c index 6748b44d568d..a6f21791c685 100644 --- a/drivers/iio/adc/mcp3911.c +++ b/drivers/iio/adc/mcp3911.c @@ -6,11 +6,13 @@ * Copyright (C) 2018 Kent Gustavsson <kent@minoris.se> */ #include <linux/bitfield.h> -#include <linux/bits.h> +#include <linux/bitops.h> #include <linux/cleanup.h> #include <linux/clk.h> #include <linux/delay.h> +#include <linux/dev_printk.h> #include <linux/err.h> +#include <linux/gpio/consumer.h> #include <linux/module.h> #include <linux/mod_devicetable.h> #include <linux/property.h> @@ -79,6 +81,8 @@ #define MCP3910_CONFIG1_CLKEXT BIT(6) #define MCP3910_CONFIG1_VREFEXT BIT(7) +#define MCP3910_CHANNEL(ch) (MCP3911_REG_CHANNEL0 + (ch)) + #define MCP3910_REG_OFFCAL_CH0 0x0f #define MCP3910_OFFCAL(ch) (MCP3910_REG_OFFCAL_CH0 + (ch) * 6) @@ -110,6 +114,7 @@ struct mcp3911_chip_info { int (*get_offset)(struct mcp3911 *adc, int channel, int *val); int (*set_offset)(struct mcp3911 *adc, int channel, int val); int (*set_scale)(struct mcp3911 *adc, int channel, u32 val); + int (*get_raw)(struct mcp3911 *adc, int channel, int *val); }; struct mcp3911 { @@ -170,6 +175,18 @@ static int mcp3911_update(struct mcp3911 *adc, u8 reg, u32 mask, u32 val, u8 len return mcp3911_write(adc, reg, val, len); } +static int mcp3911_read_s24(struct mcp3911 *const adc, u8 const reg, s32 *const val) +{ + u32 uval; + int const ret = mcp3911_read(adc, reg, &uval, 3); + + if (ret) + return ret; + + *val = sign_extend32(uval, 23); + return ret; +} + static int mcp3910_enable_offset(struct mcp3911 *adc, bool enable) { unsigned int mask = MCP3910_CONFIG0_EN_OFFCAL; @@ -194,6 +211,11 @@ static int mcp3910_set_offset(struct mcp3911 *adc, int channel, int val) return adc->chip->enable_offset(adc, 1); } +static int mcp3910_get_raw(struct mcp3911 *adc, int channel, s32 *val) +{ + return mcp3911_read_s24(adc, MCP3910_CHANNEL(channel), val); +} + static int mcp3911_enable_offset(struct mcp3911 *adc, bool enable) { unsigned int mask = MCP3911_STATUSCOM_EN_OFFCAL; @@ -218,6 +240,11 @@ static int mcp3911_set_offset(struct mcp3911 *adc, int channel, int val) return adc->chip->enable_offset(adc, 1); } +static int mcp3911_get_raw(struct mcp3911 *adc, int channel, s32 *val) +{ + return mcp3911_read_s24(adc, MCP3911_CHANNEL(channel), val); +} + static int mcp3910_get_osr(struct mcp3911 *adc, u32 *val) { int ret; @@ -321,12 +348,9 @@ static int mcp3911_read_raw(struct iio_dev *indio_dev, guard(mutex)(&adc->lock); switch (mask) { case IIO_CHAN_INFO_RAW: - ret = mcp3911_read(adc, - MCP3911_CHANNEL(channel->channel), val, 3); + ret = adc->chip->get_raw(adc, channel->channel, val); if (ret) return ret; - - *val = sign_extend32(*val, 23); return IIO_VAL_INT; case IIO_CHAN_INFO_OFFSET: ret = adc->chip->get_offset(adc, channel->channel, val); @@ -516,8 +540,8 @@ static irqreturn_t mcp3911_trigger_handler(int irq, void *p) adc->scan.channels[i] = get_unaligned_be24(&adc->rx_buf[scan_chan->channel * 3]); i++; } - iio_push_to_buffers_with_timestamp(indio_dev, &adc->scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &adc->scan, sizeof(adc->scan), + iio_get_time_ns(indio_dev)); out: iio_trigger_notify_done(indio_dev->trig); @@ -684,6 +708,7 @@ static const struct iio_trigger_ops mcp3911_trigger_ops = { static int mcp3911_probe(struct spi_device *spi) { struct device *dev = &spi->dev; + struct gpio_desc *gpio_reset; struct iio_dev *indio_dev; struct mcp3911 *adc; bool external_vref; @@ -728,6 +753,22 @@ static int mcp3911_probe(struct spi_device *spi) } dev_dbg(dev, "use device address %i\n", adc->dev_addr); + gpio_reset = devm_gpiod_get_optional(&spi->dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(gpio_reset)) + return dev_err_probe(dev, PTR_ERR(gpio_reset), + "Cannot get reset GPIO\n"); + + if (gpio_reset) { + gpiod_set_value_cansleep(gpio_reset, 0); + + /* + * Settling time after Hard Reset Mode (determined experimentally): + * 330 micro-seconds are too few; 470 micro-seconds are sufficient. + * Just in case, we add some safety factor... + */ + fsleep(600); + } + ret = adc->chip->config(adc, external_vref); if (ret) return ret; @@ -799,6 +840,7 @@ static const struct mcp3911_chip_info mcp3911_chip_info[] = { .get_offset = mcp3910_get_offset, .set_offset = mcp3910_set_offset, .set_scale = mcp3910_set_scale, + .get_raw = mcp3910_get_raw, }, [MCP3911] = { .channels = mcp3911_channels, @@ -810,6 +852,7 @@ static const struct mcp3911_chip_info mcp3911_chip_info[] = { .get_offset = mcp3911_get_offset, .set_offset = mcp3911_set_offset, .set_scale = mcp3911_set_scale, + .get_raw = mcp3911_get_raw, }, [MCP3912] = { .channels = mcp3912_channels, @@ -821,6 +864,7 @@ static const struct mcp3911_chip_info mcp3911_chip_info[] = { .get_offset = mcp3910_get_offset, .set_offset = mcp3910_set_offset, .set_scale = mcp3910_set_scale, + .get_raw = mcp3910_get_raw, }, [MCP3913] = { .channels = mcp3913_channels, @@ -832,6 +876,7 @@ static const struct mcp3911_chip_info mcp3911_chip_info[] = { .get_offset = mcp3910_get_offset, .set_offset = mcp3910_set_offset, .set_scale = mcp3910_set_scale, + .get_raw = mcp3910_get_raw, }, [MCP3914] = { .channels = mcp3914_channels, @@ -843,6 +888,7 @@ static const struct mcp3911_chip_info mcp3911_chip_info[] = { .get_offset = mcp3910_get_offset, .set_offset = mcp3910_set_offset, .set_scale = mcp3910_set_scale, + .get_raw = mcp3910_get_raw, }, [MCP3918] = { .channels = mcp3918_channels, @@ -854,6 +900,7 @@ static const struct mcp3911_chip_info mcp3911_chip_info[] = { .get_offset = mcp3910_get_offset, .set_offset = mcp3910_set_offset, .set_scale = mcp3910_set_scale, + .get_raw = mcp3910_get_raw, }, [MCP3919] = { .channels = mcp3919_channels, @@ -865,6 +912,7 @@ static const struct mcp3911_chip_info mcp3911_chip_info[] = { .get_offset = mcp3910_get_offset, .set_offset = mcp3910_set_offset, .set_scale = mcp3910_set_scale, + .get_raw = mcp3910_get_raw, }, }; static const struct of_device_id mcp3911_dt_ids[] = { diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index 997def4a4d2f..4ff88603e4fc 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -160,6 +160,11 @@ #define MESON_SAR_ADC_REG11_EOC BIT(1) #define MESON_SAR_ADC_REG11_VREF_SEL BIT(0) +#define MESON_SAR_ADC_REG12 0x30 + #define MESON_SAR_ADC_REG12_MPLL0_UNKNOWN BIT(0) + #define MESON_SAR_ADC_REG12_MPLL1_UNKNOWN BIT(1) + #define MESON_SAR_ADC_REG12_MPLL2_UNKNOWN BIT(2) + #define MESON_SAR_ADC_REG13 0x34 #define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK GENMASK(13, 8) @@ -326,6 +331,7 @@ struct meson_sar_adc_param { u8 cmv_select; u8 adc_eoc; enum meson_sar_adc_vref_sel vref_voltage; + bool enable_mpll_clock_workaround; }; struct meson_sar_adc_data { @@ -995,6 +1001,15 @@ static int meson_sar_adc_init(struct iio_dev *indio_dev) priv->param->cmv_select); regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11, MESON_SAR_ADC_REG11_CMV_SEL, regval); + + if (priv->param->enable_mpll_clock_workaround) { + dev_warn(dev, + "Enabling unknown bits to make the MPLL clocks work. This may change so always update dtbs and kernel together\n"); + regmap_write(priv->regmap, MESON_SAR_ADC_REG12, + MESON_SAR_ADC_REG12_MPLL0_UNKNOWN | + MESON_SAR_ADC_REG12_MPLL1_UNKNOWN | + MESON_SAR_ADC_REG12_MPLL2_UNKNOWN); + } } ret = clk_set_parent(priv->adc_sel_clk, priv->clkin); @@ -1219,6 +1234,17 @@ static const struct meson_sar_adc_param meson_sar_adc_gxl_param = { .cmv_select = 1, }; +static const struct meson_sar_adc_param meson_sar_adc_gxlx_param = { + .has_bl30_integration = true, + .clock_rate = 1200000, + .regmap_config = &meson_sar_adc_regmap_config_gxbb, + .resolution = 12, + .disable_ring_counter = 1, + .vref_voltage = 1, + .cmv_select = true, + .enable_mpll_clock_workaround = true, +}; + static const struct meson_sar_adc_param meson_sar_adc_axg_param = { .has_bl30_integration = true, .clock_rate = 1200000, @@ -1267,6 +1293,11 @@ static const struct meson_sar_adc_data meson_sar_adc_gxl_data = { .name = "meson-gxl-saradc", }; +static const struct meson_sar_adc_data meson_sar_adc_gxlx_data = { + .param = &meson_sar_adc_gxlx_param, + .name = "meson-gxlx-saradc", +}; + static const struct meson_sar_adc_data meson_sar_adc_gxm_data = { .param = &meson_sar_adc_gxl_param, .name = "meson-gxm-saradc", @@ -1299,6 +1330,9 @@ static const struct of_device_id meson_sar_adc_of_match[] = { .compatible = "amlogic,meson-gxl-saradc", .data = &meson_sar_adc_gxl_data, }, { + .compatible = "amlogic,meson-gxlx-saradc", + .data = &meson_sar_adc_gxlx_data, + }, { .compatible = "amlogic,meson-gxm-saradc", .data = &meson_sar_adc_gxm_data, }, { @@ -1308,7 +1342,7 @@ static const struct of_device_id meson_sar_adc_of_match[] = { .compatible = "amlogic,meson-g12a-saradc", .data = &meson_sar_adc_g12a_data, }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, meson_sar_adc_of_match); diff --git a/drivers/iio/adc/mt6359-auxadc.c b/drivers/iio/adc/mt6359-auxadc.c index a4970cfb49a5..eecf88b05c6f 100644 --- a/drivers/iio/adc/mt6359-auxadc.c +++ b/drivers/iio/adc/mt6359-auxadc.c @@ -588,7 +588,7 @@ static const struct of_device_id mt6359_auxadc_of_match[] = { { .compatible = "mediatek,mt6357-auxadc", .data = &mt6357_chip_info }, { .compatible = "mediatek,mt6358-auxadc", .data = &mt6358_chip_info }, { .compatible = "mediatek,mt6359-auxadc", .data = &mt6359_chip_info }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, mt6359_auxadc_of_match); diff --git a/drivers/iio/adc/mt6360-adc.c b/drivers/iio/adc/mt6360-adc.c index 4eb2455d6ffa..f8e98b6fa7e9 100644 --- a/drivers/iio/adc/mt6360-adc.c +++ b/drivers/iio/adc/mt6360-adc.c @@ -263,8 +263,8 @@ static irqreturn_t mt6360_adc_trigger_handler(int irq, void *p) struct mt6360_adc_data *mad = iio_priv(indio_dev); struct { u16 values[MT6360_CHAN_MAX]; - int64_t timestamp; - } data __aligned(8); + aligned_s64 timestamp; + } data; int i = 0, bit, val, ret; memset(&data, 0, sizeof(data)); diff --git a/drivers/iio/adc/mt6370-adc.c b/drivers/iio/adc/mt6370-adc.c index 0bc112135bca..7c71fe5e8d31 100644 --- a/drivers/iio/adc/mt6370-adc.c +++ b/drivers/iio/adc/mt6370-adc.c @@ -336,7 +336,7 @@ static int mt6370_adc_probe(struct platform_device *pdev) static const struct of_device_id mt6370_adc_of_id[] = { { .compatible = "mediatek,mt6370-adc", }, - {} + { } }; MODULE_DEVICE_TABLE(of, mt6370_adc_of_id); diff --git a/drivers/iio/adc/mxs-lradc-adc.c b/drivers/iio/adc/mxs-lradc-adc.c index 152cbe265e1a..92baf3f5f560 100644 --- a/drivers/iio/adc/mxs-lradc-adc.c +++ b/drivers/iio/adc/mxs-lradc-adc.c @@ -141,9 +141,8 @@ static int mxs_lradc_adc_read_single(struct iio_dev *iio_dev, int chan, * the same time, yet the code becomes horribly complicated. Therefore I * applied KISS principle here. */ - ret = iio_device_claim_direct_mode(iio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(iio_dev)) + return -EBUSY; reinit_completion(&adc->completion); @@ -192,7 +191,7 @@ err: writel(LRADC_CTRL1_LRADC_IRQ_EN(0), adc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); - iio_device_release_direct_mode(iio_dev); + iio_device_release_direct(iio_dev); return ret; } @@ -275,9 +274,8 @@ static int mxs_lradc_adc_write_raw(struct iio_dev *iio_dev, adc->scale_avail[chan->channel]; int ret; - ret = iio_device_claim_direct_mode(iio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(iio_dev)) + return -EBUSY; switch (m) { case IIO_CHAN_INFO_SCALE: @@ -300,7 +298,7 @@ static int mxs_lradc_adc_write_raw(struct iio_dev *iio_dev, break; } - iio_device_release_direct_mode(iio_dev); + iio_device_release_direct(iio_dev); return ret; } @@ -427,7 +425,8 @@ static irqreturn_t mxs_lradc_adc_trigger_handler(int irq, void *p) j++; } - iio_push_to_buffers_with_timestamp(iio, adc->buffer, pf->timestamp); + iio_push_to_buffers_with_ts(iio, adc->buffer, sizeof(adc->buffer), + pf->timestamp); iio_trigger_notify_done(iio->trig); diff --git a/drivers/iio/adc/nct7201.c b/drivers/iio/adc/nct7201.c new file mode 100644 index 000000000000..d87824e5490f --- /dev/null +++ b/drivers/iio/adc/nct7201.c @@ -0,0 +1,501 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Driver for Nuvoton nct7201 and nct7202 power monitor chips. + * + * Copyright (c) 2024-2025 Nuvoton Technology corporation. + */ + +#include <linux/array_size.h> +#include <linux/bitfield.h> +#include <linux/bits.h> +#include <linux/delay.h> +#include <linux/dev_printk.h> +#include <linux/err.h> +#include <linux/i2c.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/time.h> +#include <linux/types.h> +#include <linux/unaligned.h> + +#include <linux/iio/events.h> +#include <linux/iio/iio.h> + +#define NCT7201_REG_INTERRUPT_STATUS 0x0C +#define NCT7201_REG_VOLT_LOW_BYTE 0x0F +#define NCT7201_REG_CONFIGURATION 0x10 +#define NCT7201_BIT_CONFIGURATION_START BIT(0) +#define NCT7201_BIT_CONFIGURATION_ALERT_MSK BIT(1) +#define NCT7201_BIT_CONFIGURATION_CONV_RATE BIT(2) +#define NCT7201_BIT_CONFIGURATION_RESET BIT(7) + +#define NCT7201_REG_ADVANCED_CONFIGURATION 0x11 +#define NCT7201_BIT_ADVANCED_CONF_MOD_ALERT BIT(0) +#define NCT7201_BIT_ADVANCED_CONF_MOD_STS BIT(1) +#define NCT7201_BIT_ADVANCED_CONF_FAULT_QUEUE BIT(2) +#define NCT7201_BIT_ADVANCED_CONF_EN_DEEP_SHUTDOWN BIT(4) +#define NCT7201_BIT_ADVANCED_CONF_EN_SMB_TIMEOUT BIT(5) +#define NCT7201_BIT_ADVANCED_CONF_MOD_RSTIN BIT(7) + +#define NCT7201_REG_CHANNEL_INPUT_MODE 0x12 +#define NCT7201_REG_CHANNEL_ENABLE 0x13 +#define NCT7201_REG_INTERRUPT_MASK_1 0x15 +#define NCT7201_REG_INTERRUPT_MASK_2 0x16 +#define NCT7201_REG_BUSY_STATUS 0x1E +#define NCT7201_BIT_BUSY BIT(0) +#define NCT7201_BIT_PWR_UP BIT(1) +#define NCT7201_REG_ONE_SHOT 0x1F +#define NCT7201_REG_SMUS_ADDRESS 0xFC +#define NCT7201_REG_VIN_MASK GENMASK(15, 3) + +#define NCT7201_REG_VIN(i) (0x00 + i) +#define NCT7201_REG_VIN_HIGH_LIMIT(i) (0x20 + (i) * 2) +#define NCT7201_REG_VIN_LOW_LIMIT(i) (0x21 + (i) * 2) +#define NCT7201_MAX_CHANNEL 12 + +static const struct regmap_range nct7201_read_reg_range[] = { + regmap_reg_range(NCT7201_REG_INTERRUPT_STATUS, NCT7201_REG_BUSY_STATUS), + regmap_reg_range(NCT7201_REG_SMUS_ADDRESS, NCT7201_REG_SMUS_ADDRESS), +}; + +static const struct regmap_access_table nct7201_readable_regs_tbl = { + .yes_ranges = nct7201_read_reg_range, + .n_yes_ranges = ARRAY_SIZE(nct7201_read_reg_range), +}; + +static const struct regmap_range nct7201_write_reg_range[] = { + regmap_reg_range(NCT7201_REG_CONFIGURATION, NCT7201_REG_INTERRUPT_MASK_2), + regmap_reg_range(NCT7201_REG_ONE_SHOT, NCT7201_REG_ONE_SHOT), +}; + +static const struct regmap_access_table nct7201_writeable_regs_tbl = { + .yes_ranges = nct7201_write_reg_range, + .n_yes_ranges = ARRAY_SIZE(nct7201_write_reg_range), +}; + +static const struct regmap_range nct7201_read_vin_reg_range[] = { + regmap_reg_range(NCT7201_REG_VIN(0), NCT7201_REG_VIN(NCT7201_MAX_CHANNEL - 1)), + regmap_reg_range(NCT7201_REG_VIN_HIGH_LIMIT(0), + NCT7201_REG_VIN_LOW_LIMIT(NCT7201_MAX_CHANNEL - 1)), +}; + +static const struct regmap_access_table nct7201_readable_vin_regs_tbl = { + .yes_ranges = nct7201_read_vin_reg_range, + .n_yes_ranges = ARRAY_SIZE(nct7201_read_vin_reg_range), +}; + +static const struct regmap_range nct7201_write_vin_reg_range[] = { + regmap_reg_range(NCT7201_REG_VIN_HIGH_LIMIT(0), + NCT7201_REG_VIN_LOW_LIMIT(NCT7201_MAX_CHANNEL - 1)), +}; + +static const struct regmap_access_table nct7201_writeable_vin_regs_tbl = { + .yes_ranges = nct7201_write_vin_reg_range, + .n_yes_ranges = ARRAY_SIZE(nct7201_write_vin_reg_range), +}; + +static const struct regmap_config nct7201_regmap8_config = { + .name = "vin-data-read-byte", + .reg_bits = 8, + .val_bits = 8, + .use_single_read = true, + .use_single_write = true, + .max_register = 0xff, + .rd_table = &nct7201_readable_regs_tbl, + .wr_table = &nct7201_writeable_regs_tbl, +}; + +static const struct regmap_config nct7201_regmap16_config = { + .name = "vin-data-read-word", + .reg_bits = 8, + .val_bits = 16, + .max_register = 0xff, + .rd_table = &nct7201_readable_vin_regs_tbl, + .wr_table = &nct7201_writeable_vin_regs_tbl, +}; + +struct nct7201_chip_info { + struct regmap *regmap; + struct regmap *regmap16; + int num_vin_channels; + __le16 vin_mask; +}; + +struct nct7201_adc_model_data { + const char *model_name; + const struct iio_chan_spec *channels; + unsigned int num_channels; + int num_vin_channels; +}; + +static const struct iio_event_spec nct7201_events[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, +}; + +#define NCT7201_VOLTAGE_CHANNEL(num) \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = num + 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .address = num, \ + .event_spec = nct7201_events, \ + .num_event_specs = ARRAY_SIZE(nct7201_events), \ + } + +static const struct iio_chan_spec nct7201_channels[] = { + NCT7201_VOLTAGE_CHANNEL(0), + NCT7201_VOLTAGE_CHANNEL(1), + NCT7201_VOLTAGE_CHANNEL(2), + NCT7201_VOLTAGE_CHANNEL(3), + NCT7201_VOLTAGE_CHANNEL(4), + NCT7201_VOLTAGE_CHANNEL(5), + NCT7201_VOLTAGE_CHANNEL(6), + NCT7201_VOLTAGE_CHANNEL(7), +}; + +static const struct iio_chan_spec nct7202_channels[] = { + NCT7201_VOLTAGE_CHANNEL(0), + NCT7201_VOLTAGE_CHANNEL(1), + NCT7201_VOLTAGE_CHANNEL(2), + NCT7201_VOLTAGE_CHANNEL(3), + NCT7201_VOLTAGE_CHANNEL(4), + NCT7201_VOLTAGE_CHANNEL(5), + NCT7201_VOLTAGE_CHANNEL(6), + NCT7201_VOLTAGE_CHANNEL(7), + NCT7201_VOLTAGE_CHANNEL(8), + NCT7201_VOLTAGE_CHANNEL(9), + NCT7201_VOLTAGE_CHANNEL(10), + NCT7201_VOLTAGE_CHANNEL(11), +}; + +static int nct7201_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct nct7201_chip_info *chip = iio_priv(indio_dev); + unsigned int value; + int err; + + if (chan->type != IIO_VOLTAGE) + return -EOPNOTSUPP; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + err = regmap_read(chip->regmap16, NCT7201_REG_VIN(chan->address), &value); + if (err) + return err; + *val = FIELD_GET(NCT7201_REG_VIN_MASK, value); + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + /* From the datasheet, we have to multiply by 0.0004995 */ + *val = 0; + *val2 = 499500; + return IIO_VAL_INT_PLUS_NANO; + default: + return -EINVAL; + } +} + +static int nct7201_read_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) +{ + struct nct7201_chip_info *chip = iio_priv(indio_dev); + unsigned int value; + int err; + + if (chan->type != IIO_VOLTAGE) + return -EOPNOTSUPP; + + if (info != IIO_EV_INFO_VALUE) + return -EINVAL; + + if (dir == IIO_EV_DIR_FALLING) + err = regmap_read(chip->regmap16, NCT7201_REG_VIN_LOW_LIMIT(chan->address), + &value); + else + err = regmap_read(chip->regmap16, NCT7201_REG_VIN_HIGH_LIMIT(chan->address), + &value); + if (err) + return err; + + *val = FIELD_GET(NCT7201_REG_VIN_MASK, value); + + return IIO_VAL_INT; +} + +static int nct7201_write_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) +{ + struct nct7201_chip_info *chip = iio_priv(indio_dev); + int err; + + if (chan->type != IIO_VOLTAGE) + return -EOPNOTSUPP; + + if (info != IIO_EV_INFO_VALUE) + return -EOPNOTSUPP; + + if (dir == IIO_EV_DIR_FALLING) + err = regmap_write(chip->regmap16, NCT7201_REG_VIN_LOW_LIMIT(chan->address), + FIELD_PREP(NCT7201_REG_VIN_MASK, val)); + else + err = regmap_write(chip->regmap16, NCT7201_REG_VIN_HIGH_LIMIT(chan->address), + FIELD_PREP(NCT7201_REG_VIN_MASK, val)); + + return err; +} + +static int nct7201_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct nct7201_chip_info *chip = iio_priv(indio_dev); + + if (chan->type != IIO_VOLTAGE) + return -EOPNOTSUPP; + + return !!(le16_to_cpu(chip->vin_mask) & BIT(chan->address)); +} + +static int nct7201_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + bool state) +{ + struct nct7201_chip_info *chip = iio_priv(indio_dev); + __le16 mask = cpu_to_le16(BIT(chan->address)); + int err; + + if (chan->type != IIO_VOLTAGE) + return -EOPNOTSUPP; + + if (state) + chip->vin_mask |= mask; + else + chip->vin_mask &= ~mask; + + if (chip->num_vin_channels <= 8) + err = regmap_write(chip->regmap, NCT7201_REG_CHANNEL_ENABLE, + le16_to_cpu(chip->vin_mask)); + else + err = regmap_bulk_write(chip->regmap, NCT7201_REG_CHANNEL_ENABLE, + &chip->vin_mask, sizeof(chip->vin_mask)); + + return err; +} + +static const struct iio_info nct7201_info = { + .read_raw = nct7201_read_raw, + .read_event_config = nct7201_read_event_config, + .write_event_config = nct7201_write_event_config, + .read_event_value = nct7201_read_event_value, + .write_event_value = nct7201_write_event_value, +}; + +static const struct iio_info nct7201_info_no_irq = { + .read_raw = nct7201_read_raw, +}; + +static const struct nct7201_adc_model_data nct7201_model_data = { + .model_name = "nct7201", + .channels = nct7201_channels, + .num_channels = ARRAY_SIZE(nct7201_channels), + .num_vin_channels = 8, +}; + +static const struct nct7201_adc_model_data nct7202_model_data = { + .model_name = "nct7202", + .channels = nct7202_channels, + .num_channels = ARRAY_SIZE(nct7202_channels), + .num_vin_channels = 12, +}; + +static int nct7201_init_chip(struct nct7201_chip_info *chip) +{ + struct device *dev = regmap_get_device(chip->regmap); + __le16 data = cpu_to_le16(GENMASK(chip->num_vin_channels - 1, 0)); + unsigned int value; + int err; + + err = regmap_write(chip->regmap, NCT7201_REG_CONFIGURATION, + NCT7201_BIT_CONFIGURATION_RESET); + if (err) + return dev_err_probe(dev, err, "Failed to reset chip\n"); + + /* + * After about 25 msecs, the device should be ready and then the power-up + * bit will be set to 1. + */ + fsleep(25 * USEC_PER_MSEC); + + err = regmap_read(chip->regmap, NCT7201_REG_BUSY_STATUS, &value); + if (err) + return dev_err_probe(dev, err, "Failed to read busy status\n"); + if (!(value & NCT7201_BIT_PWR_UP)) + return dev_err_probe(dev, -EIO, "Failed to power up after reset\n"); + + /* Enable Channels */ + if (chip->num_vin_channels <= 8) + err = regmap_write(chip->regmap, NCT7201_REG_CHANNEL_ENABLE, + le16_to_cpu(data)); + else + err = regmap_bulk_write(chip->regmap, NCT7201_REG_CHANNEL_ENABLE, + &data, sizeof(data)); + if (err) + return dev_err_probe(dev, err, "Failed to enable channels\n"); + + err = regmap_bulk_read(chip->regmap, NCT7201_REG_CHANNEL_ENABLE, + &chip->vin_mask, sizeof(chip->vin_mask)); + if (err) + return dev_err_probe(dev, err, + "Failed to read channel enable register\n"); + + /* Start monitoring if needed */ + err = regmap_set_bits(chip->regmap, NCT7201_REG_CONFIGURATION, + NCT7201_BIT_CONFIGURATION_START); + if (err) + return dev_err_probe(dev, err, "Failed to start monitoring\n"); + + return 0; +} + +static irqreturn_t nct7201_irq_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct nct7201_chip_info *chip = iio_priv(indio_dev); + __le16 data; + int err; + + err = regmap_bulk_read(chip->regmap, NCT7201_REG_INTERRUPT_STATUS, + &data, sizeof(data)); + if (err) + return IRQ_NONE; + + if (data) + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, + 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_EITHER), + iio_get_time_ns(indio_dev)); + + return IRQ_HANDLED; +} + +static int nct7201_probe(struct i2c_client *client) +{ + const struct nct7201_adc_model_data *model_data; + struct device *dev = &client->dev; + struct nct7201_chip_info *chip; + struct iio_dev *indio_dev; + int ret; + + model_data = i2c_get_match_data(client); + if (!model_data) + return -ENODEV; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*chip)); + if (!indio_dev) + return -ENOMEM; + chip = iio_priv(indio_dev); + + chip->regmap = devm_regmap_init_i2c(client, &nct7201_regmap8_config); + if (IS_ERR(chip->regmap)) + return dev_err_probe(dev, PTR_ERR(chip->regmap), + "Failed to init regmap\n"); + + chip->regmap16 = devm_regmap_init_i2c(client, &nct7201_regmap16_config); + if (IS_ERR(chip->regmap16)) + return dev_err_probe(dev, PTR_ERR(chip->regmap16), + "Failed to init regmap16\n"); + + chip->num_vin_channels = model_data->num_vin_channels; + + ret = nct7201_init_chip(chip); + if (ret) + return ret; + + indio_dev->name = model_data->model_name; + indio_dev->channels = model_data->channels; + indio_dev->num_channels = model_data->num_channels; + if (client->irq) { + /* Enable alert function */ + ret = regmap_clear_bits(chip->regmap, NCT7201_REG_CONFIGURATION, + NCT7201_BIT_CONFIGURATION_ALERT_MSK); + if (ret) + return dev_err_probe(dev, ret, + "Failed to enable alert function\n"); + + ret = devm_request_threaded_irq(dev, client->irq, + NULL, nct7201_irq_handler, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + client->name, indio_dev); + if (ret) + return dev_err_probe(dev, ret, + "Failed to assign interrupt.\n"); + + indio_dev->info = &nct7201_info; + } else { + indio_dev->info = &nct7201_info_no_irq; + } + indio_dev->modes = INDIO_DIRECT_MODE; + + return devm_iio_device_register(dev, indio_dev); +} + +static const struct i2c_device_id nct7201_id[] = { + { .name = "nct7201", .driver_data = (kernel_ulong_t)&nct7201_model_data }, + { .name = "nct7202", .driver_data = (kernel_ulong_t)&nct7202_model_data }, + { } +}; +MODULE_DEVICE_TABLE(i2c, nct7201_id); + +static const struct of_device_id nct7201_of_match[] = { + { + .compatible = "nuvoton,nct7201", + .data = &nct7201_model_data, + }, + { + .compatible = "nuvoton,nct7202", + .data = &nct7202_model_data, + }, + { } +}; +MODULE_DEVICE_TABLE(of, nct7201_of_match); + +static struct i2c_driver nct7201_driver = { + .driver = { + .name = "nct7201", + .of_match_table = nct7201_of_match, + }, + .probe = nct7201_probe, + .id_table = nct7201_id, +}; +module_i2c_driver(nct7201_driver); + +MODULE_AUTHOR("Eason Yang <j2anfernee@gmail.com>"); +MODULE_DESCRIPTION("Nuvoton NCT7201 voltage monitor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/adc/npcm_adc.c b/drivers/iio/adc/npcm_adc.c index 7c1511ee3a4b..c8283873cdee 100644 --- a/drivers/iio/adc/npcm_adc.c +++ b/drivers/iio/adc/npcm_adc.c @@ -196,7 +196,7 @@ static const struct iio_info npcm_adc_iio_info = { static const struct of_device_id npcm_adc_match[] = { { .compatible = "nuvoton,npcm750-adc", .data = &npxm7xx_adc_info}, { .compatible = "nuvoton,npcm845-adc", .data = &npxm8xx_adc_info}, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, npcm_adc_match); diff --git a/drivers/iio/adc/pac1921.c b/drivers/iio/adc/pac1921.c index beb5511c4504..72aa4ca2e5a4 100644 --- a/drivers/iio/adc/pac1921.c +++ b/drivers/iio/adc/pac1921.c @@ -900,7 +900,7 @@ static ssize_t pac1921_read_scale_avail(struct iio_dev *indio_dev, static const struct iio_chan_spec_ext_info pac1921_ext_info_voltage[] = { PAC1921_EXT_INFO_SCALE_AVAIL, - {} + { } }; static const struct iio_chan_spec_ext_info pac1921_ext_info_current[] = { @@ -911,7 +911,7 @@ static const struct iio_chan_spec_ext_info pac1921_ext_info_current[] = { .write = pac1921_write_shunt_resistor, .shared = IIO_SEPARATE, }, - {} + { } }; static const struct iio_event_spec pac1921_overflow_event[] = { @@ -1044,7 +1044,8 @@ static irqreturn_t pac1921_trigger_handler(int irq, void *p) priv->scan.chan[ch++] = val; } - iio_push_to_buffers_with_timestamp(idev, &priv->scan, pf->timestamp); + iio_push_to_buffers_with_ts(idev, &priv->scan, sizeof(priv->scan), + pf->timestamp); done: iio_trigger_notify_done(idev->trig); diff --git a/drivers/iio/adc/pac1934.c b/drivers/iio/adc/pac1934.c index 20802b7f49ea..09fe88eb3fb0 100644 --- a/drivers/iio/adc/pac1934.c +++ b/drivers/iio/adc/pac1934.c @@ -1081,7 +1081,7 @@ 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 + * https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ApplicationNotes/ApplicationNotes/PAC193X-Integration-Notes-for-Microsoft-Windows-10-and-Windows-11-Driver-Support-DS00002534.pdf */ static int pac1934_acpi_parse_channel_config(struct i2c_client *client, struct pac1934_chip_info *info) diff --git a/drivers/iio/adc/palmas_gpadc.c b/drivers/iio/adc/palmas_gpadc.c index d283ee8fb1d2..7c01e33be04c 100644 --- a/drivers/iio/adc/palmas_gpadc.c +++ b/drivers/iio/adc/palmas_gpadc.c @@ -1164,7 +1164,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(palmas_pm_ops, palmas_gpadc_suspend, static const struct of_device_id of_palmas_gpadc_match_tbl[] = { { .compatible = "ti,palmas-gpadc", }, - { /* end */ } + { } }; MODULE_DEVICE_TABLE(of, of_palmas_gpadc_match_tbl); diff --git a/drivers/iio/adc/rcar-gyroadc.c b/drivers/iio/adc/rcar-gyroadc.c index 11170b5852d1..cc326f21d398 100644 --- a/drivers/iio/adc/rcar-gyroadc.c +++ b/drivers/iio/adc/rcar-gyroadc.c @@ -199,13 +199,12 @@ static int rcar_gyroadc_read_raw(struct iio_dev *indio_dev, if (!consumer) return -EINVAL; - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = rcar_gyroadc_set_power(priv, true); if (ret < 0) { - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; } @@ -213,7 +212,7 @@ static int rcar_gyroadc_read_raw(struct iio_dev *indio_dev, *val &= BIT(priv->sample_width) - 1; ret = rcar_gyroadc_set_power(priv, false); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); if (ret < 0) return ret; @@ -308,7 +307,7 @@ static const struct of_device_id rcar_gyroadc_child_match[] __maybe_unused = { .compatible = "maxim,max11100", .data = (void *)RCAR_GYROADC_MODE_SELECT_3_MAX1162, }, - { /* sentinel */ } + { } }; static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev) diff --git a/drivers/iio/adc/rn5t618-adc.c b/drivers/iio/adc/rn5t618-adc.c index b33536157adc..d6f6b351f2af 100644 --- a/drivers/iio/adc/rn5t618-adc.c +++ b/drivers/iio/adc/rn5t618-adc.c @@ -188,7 +188,7 @@ static const struct iio_chan_spec rn5t618_adc_iio_channels[] = { static const struct iio_map rn5t618_maps[] = { IIO_MAP("VADP", "rn5t618-power", "vadp"), IIO_MAP("VUSB", "rn5t618-power", "vusb"), - { /* sentinel */ } + { } }; static int rn5t618_adc_probe(struct platform_device *pdev) diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index 5e28bd28b81a..325e3747a134 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -425,7 +425,8 @@ static irqreturn_t rockchip_saradc_trigger_handler(int irq, void *p) j++; } - iio_push_to_buffers_with_timestamp(i_dev, &data, iio_get_time_ns(i_dev)); + iio_push_to_buffers_with_ts(i_dev, &data, sizeof(data), + iio_get_time_ns(i_dev)); out: mutex_unlock(&info->lock); diff --git a/drivers/iio/adc/rohm-bd79124.c b/drivers/iio/adc/rohm-bd79124.c new file mode 100644 index 000000000000..bb7c93ae4055 --- /dev/null +++ b/drivers/iio/adc/rohm-bd79124.c @@ -0,0 +1,1146 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * ROHM ADC driver for BD79124 ADC/GPO device + * https://fscdn.rohm.com/en/products/databook/datasheet/ic/data_converter/dac/bd79124muf-c-e.pdf + * + * Copyright (c) 2025, ROHM Semiconductor. + */ + +#include <linux/array_size.h> +#include <linux/bitfield.h> +#include <linux/bitmap.h> +#include <linux/bits.h> +#include <linux/device.h> +#include <linux/delay.h> +#include <linux/devm-helpers.h> +#include <linux/err.h> +#include <linux/gpio/driver.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/irqreturn.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/regmap.h> +#include <linux/types.h> + +#include <asm/byteorder.h> + +#include <linux/iio/events.h> +#include <linux/iio/iio.h> +#include <linux/iio/adc-helpers.h> + +#define BD79124_I2C_MULTI_READ 0x30 +#define BD79124_I2C_MULTI_WRITE 0x28 +#define BD79124_REG_MAX 0xaf + +#define BD79124_REG_SYSTEM_STATUS 0x00 +#define BD79124_REG_GEN_CFG 0x01 +#define BD79124_REG_OPMODE_CFG 0x04 +#define BD79124_REG_PINCFG 0x05 +#define BD79124_REG_GPO_VAL 0x0B +#define BD79124_REG_SEQ_CFG 0x10 +#define BD79124_REG_MANUAL_CHANNELS 0x11 +#define BD79124_REG_AUTO_CHANNELS 0x12 +#define BD79124_REG_ALERT_CH_SEL 0x14 +#define BD79124_REG_EVENT_FLAG 0x18 +#define BD79124_REG_EVENT_FLAG_HI 0x1a +#define BD79124_REG_EVENT_FLAG_LO 0x1c +#define BD79124_REG_HYSTERESIS_CH0 0x20 +#define BD79124_REG_EVENTCOUNT_CH0 0x22 +#define BD79124_REG_RECENT_CH0_LSB 0xa0 +#define BD79124_REG_RECENT_CH7_MSB 0xaf + +#define BD79124_ADC_BITS 12 + +/* Masks for the BD79124_REG_OPMODE_CFG */ +#define BD79124_MSK_CONV_MODE GENMASK(6, 5) +#define BD79124_CONV_MODE_MANSEQ 0 +#define BD79124_CONV_MODE_AUTO 1 +#define BD79124_MSK_AUTO_INTERVAL GENMASK(1, 0) +#define BD79124_INTERVAL_750_US 0 + +/* Masks for the BD79124_REG_GEN_CFG */ +#define BD79124_MSK_DWC_EN BIT(4) +#define BD79124_MSK_STATS_EN BIT(5) + +/* Masks for the BD79124_REG_SEQ_CFG */ +#define BD79124_MSK_SEQ_START BIT(4) +#define BD79124_MSK_SEQ_MODE GENMASK(1, 0) +#define BD79124_MSK_SEQ_MANUAL 0 +#define BD79124_MSK_SEQ_SEQ 1 + +#define BD79124_MSK_HYSTERESIS GENMASK(3, 0) +#define BD79124_LOW_LIMIT_MIN 0 +#define BD79124_HIGH_LIMIT_MAX GENMASK(11, 0) + +/* + * The high limit, low limit and last measurement result are each stored in + * 2 consequtive registers. 4 bits are in the high bits of the first register + * and 8 bits in the next register. + * + * These macros return the address of the first reg for the given channel. + */ +#define BD79124_GET_HIGH_LIMIT_REG(ch) (BD79124_REG_HYSTERESIS_CH0 + (ch) * 4) +#define BD79124_GET_LOW_LIMIT_REG(ch) (BD79124_REG_EVENTCOUNT_CH0 + (ch) * 4) +#define BD79124_GET_LIMIT_REG(ch, dir) ((dir) == IIO_EV_DIR_RISING ? \ + BD79124_GET_HIGH_LIMIT_REG(ch) : BD79124_GET_LOW_LIMIT_REG(ch)) +#define BD79124_GET_RECENT_RES_REG(ch) (BD79124_REG_RECENT_CH0_LSB + (ch) * 2) + +/* + * The hysteresis for a channel is stored in the same register where the + * 4 bits of high limit reside. + */ +#define BD79124_GET_HYSTERESIS_REG(ch) BD79124_GET_HIGH_LIMIT_REG(ch) + +#define BD79124_MAX_NUM_CHANNELS 8 + +struct bd79124_data { + s64 timestamp; + struct regmap *map; + struct device *dev; + int vmax; + /* + * Keep measurement status so read_raw() knows if the measurement needs + * to be started. + */ + int alarm_monitored[BD79124_MAX_NUM_CHANNELS]; + /* + * The BD79124 does not allow disabling/enabling limit separately for + * one direction only. Hence, we do the disabling by changing the limit + * to maximum/minimum measurable value. This means we need to cache + * the limit in order to maintain it over the time limit is disabled. + */ + u16 alarm_r_limit[BD79124_MAX_NUM_CHANNELS]; + u16 alarm_f_limit[BD79124_MAX_NUM_CHANNELS]; + /* Bitmask of disabled events (for rate limiting) for each channel. */ + int alarm_suppressed[BD79124_MAX_NUM_CHANNELS]; + /* + * The BD79124 is configured to run the measurements in the background. + * This is done for the event monitoring as well as for the read_raw(). + * Protect the measurement starting/stopping using a mutex. + */ + struct mutex mutex; + struct delayed_work alm_enable_work; + struct gpio_chip gc; + u8 gpio_valid_mask; +}; + +static const struct regmap_range bd79124_ro_ranges[] = { + { + .range_min = BD79124_REG_EVENT_FLAG, + .range_max = BD79124_REG_EVENT_FLAG, + }, { + .range_min = BD79124_REG_RECENT_CH0_LSB, + .range_max = BD79124_REG_RECENT_CH7_MSB, + }, +}; + +static const struct regmap_access_table bd79124_ro_regs = { + .no_ranges = &bd79124_ro_ranges[0], + .n_no_ranges = ARRAY_SIZE(bd79124_ro_ranges), +}; + +static const struct regmap_range bd79124_volatile_ranges[] = { + { + .range_min = BD79124_REG_RECENT_CH0_LSB, + .range_max = BD79124_REG_RECENT_CH7_MSB, + }, { + .range_min = BD79124_REG_EVENT_FLAG, + .range_max = BD79124_REG_EVENT_FLAG, + }, { + .range_min = BD79124_REG_EVENT_FLAG_HI, + .range_max = BD79124_REG_EVENT_FLAG_HI, + }, { + .range_min = BD79124_REG_EVENT_FLAG_LO, + .range_max = BD79124_REG_EVENT_FLAG_LO, + }, { + .range_min = BD79124_REG_SYSTEM_STATUS, + .range_max = BD79124_REG_SYSTEM_STATUS, + }, +}; + +static const struct regmap_access_table bd79124_volatile_regs = { + .yes_ranges = &bd79124_volatile_ranges[0], + .n_yes_ranges = ARRAY_SIZE(bd79124_volatile_ranges), +}; + +static const struct regmap_range bd79124_precious_ranges[] = { + { + .range_min = BD79124_REG_EVENT_FLAG_HI, + .range_max = BD79124_REG_EVENT_FLAG_HI, + }, { + .range_min = BD79124_REG_EVENT_FLAG_LO, + .range_max = BD79124_REG_EVENT_FLAG_LO, + }, +}; + +static const struct regmap_access_table bd79124_precious_regs = { + .yes_ranges = &bd79124_precious_ranges[0], + .n_yes_ranges = ARRAY_SIZE(bd79124_precious_ranges), +}; + +static const struct regmap_config bd79124_regmap = { + .reg_bits = 16, + .val_bits = 8, + .read_flag_mask = BD79124_I2C_MULTI_READ, + .write_flag_mask = BD79124_I2C_MULTI_WRITE, + .max_register = BD79124_REG_MAX, + .cache_type = REGCACHE_MAPLE, + .volatile_table = &bd79124_volatile_regs, + .wr_table = &bd79124_ro_regs, + .precious_table = &bd79124_precious_regs, +}; + +static int bd79124gpo_direction_get(struct gpio_chip *gc, unsigned int offset) +{ + return GPIO_LINE_DIRECTION_OUT; +} + +static int bd79124gpo_set(struct gpio_chip *gc, unsigned int offset, int value) +{ + struct bd79124_data *data = gpiochip_get_data(gc); + + return regmap_assign_bits(data->map, BD79124_REG_GPO_VAL, BIT(offset), + value); +} + +static int bd79124gpo_set_multiple(struct gpio_chip *gc, unsigned long *mask, + unsigned long *bits) +{ + unsigned int all_gpos; + int ret; + struct bd79124_data *data = gpiochip_get_data(gc); + + /* + * Ensure all GPIOs in 'mask' are set to be GPIOs + * The valid_mask was not obeyed by the gpiolib in all cases prior the + * https://lore.kernel.org/all/cd5e067b80e1bb590027bc3bfa817e7f794f21c3.1741180097.git.mazziesaccount@gmail.com/ + * + * Keep this check here for a couple of cycles. + */ + ret = regmap_read(data->map, BD79124_REG_PINCFG, &all_gpos); + if (ret) + return ret; + + if (all_gpos ^ *mask) { + dev_dbg(data->dev, "Invalid mux config. Can't set value.\n"); + + return -EINVAL; + } + + return regmap_update_bits(data->map, BD79124_REG_GPO_VAL, *mask, *bits); +} + +static int bd79124_init_valid_mask(struct gpio_chip *gc, + unsigned long *valid_mask, + unsigned int ngpios) +{ + struct bd79124_data *data = gpiochip_get_data(gc); + + *valid_mask = data->gpio_valid_mask; + + return 0; +} + +/* Template for GPIO chip */ +static const struct gpio_chip bd79124gpo_chip = { + .label = "bd79124-gpo", + .get_direction = bd79124gpo_direction_get, + .set_rv = bd79124gpo_set, + .set_multiple_rv = bd79124gpo_set_multiple, + .init_valid_mask = bd79124_init_valid_mask, + .can_sleep = true, + .ngpio = 8, + .base = -1, +}; + +struct bd79124_raw { + u8 val_bit3_0; /* Is set in high bits of the byte */ + u8 val_bit11_4; +}; +#define BD79124_RAW_TO_INT(r) ((r.val_bit11_4 << 4) | (r.val_bit3_0 >> 4)) +#define BD79124_INT_TO_RAW(val) { \ + .val_bit11_4 = (val) >> 4, \ + .val_bit3_0 = (val) << 4, \ +} + +/* + * The high and low limits as well as the recent result values are stored in + * the same way in 2 consequent registers. The first register contains 4 bits + * of the value. These bits are stored in the high bits [7:4] of register, but + * they represent the low bits [3:0] of the value. + * The value bits [11:4] are stored in the next register. + * + * Read data from register and convert to integer. + */ +static int bd79124_read_reg_to_int(struct bd79124_data *data, int reg, + unsigned int *val) +{ + int ret; + struct bd79124_raw raw; + + ret = regmap_bulk_read(data->map, reg, &raw, sizeof(raw)); + if (ret) { + dev_dbg(data->dev, "bulk_read failed %d\n", ret); + + return ret; + } + + *val = BD79124_RAW_TO_INT(raw); + + return 0; +} + +/* + * The high and low limits as well as the recent result values are stored in + * the same way in 2 consequent registers. The first register contains 4 bits + * of the value. These bits are stored in the high bits [7:4] of register, but + * they represent the low bits [3:0] of the value. + * The value bits [11:4] are stored in the next register. + * + * Convert the integer to register format and write it using rmw cycle. + */ +static int bd79124_write_int_to_reg(struct bd79124_data *data, int reg, + unsigned int val) +{ + struct bd79124_raw raw = BD79124_INT_TO_RAW(val); + unsigned int tmp; + int ret; + + ret = regmap_read(data->map, reg, &tmp); + if (ret) + return ret; + + raw.val_bit3_0 |= (tmp & 0xf); + + return regmap_bulk_write(data->map, reg, &raw, sizeof(raw)); +} + +static const struct iio_event_spec bd79124_events[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_HYSTERESIS), + }, +}; + +static const struct iio_chan_spec bd79124_chan_template_noirq = { + .type = IIO_VOLTAGE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .indexed = 1, +}; + +static const struct iio_chan_spec bd79124_chan_template = { + .type = IIO_VOLTAGE, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .indexed = 1, + .event_spec = bd79124_events, + .num_event_specs = ARRAY_SIZE(bd79124_events), +}; + +static int bd79124_read_event_value(struct iio_dev *iio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, int *val, + int *val2) +{ + struct bd79124_data *data = iio_priv(iio_dev); + int ret, reg; + + if (chan->channel >= BD79124_MAX_NUM_CHANNELS) + return -EINVAL; + + switch (info) { + case IIO_EV_INFO_VALUE: + if (dir == IIO_EV_DIR_RISING) + *val = data->alarm_r_limit[chan->channel]; + else if (dir == IIO_EV_DIR_FALLING) + *val = data->alarm_f_limit[chan->channel]; + else + return -EINVAL; + + return IIO_VAL_INT; + + case IIO_EV_INFO_HYSTERESIS: + reg = BD79124_GET_HYSTERESIS_REG(chan->channel); + ret = regmap_read(data->map, reg, val); + if (ret) + return ret; + + *val &= BD79124_MSK_HYSTERESIS; + /* + * The data-sheet says the hysteresis register value needs to be + * shifted left by 3. + */ + *val <<= 3; + + return IIO_VAL_INT; + + default: + return -EINVAL; + } +} + +static int bd79124_start_measurement(struct bd79124_data *data, int chan) +{ + unsigned int val, regval; + int ret; + + /* See if already started */ + ret = regmap_read(data->map, BD79124_REG_AUTO_CHANNELS, &val); + if (val & BIT(chan)) + return 0; + + /* + * The sequencer must be stopped when channels are added/removed from + * the list of the measured channels to ensure the new channel + * configuration is used. + */ + ret = regmap_clear_bits(data->map, BD79124_REG_SEQ_CFG, + BD79124_MSK_SEQ_START); + if (ret) + return ret; + + ret = regmap_write(data->map, BD79124_REG_AUTO_CHANNELS, val | BIT(chan)); + if (ret) + return ret; + + ret = regmap_set_bits(data->map, BD79124_REG_SEQ_CFG, + BD79124_MSK_SEQ_START); + if (ret) + return ret; + + /* + * Start the measurement at the background. Don't bother checking if + * it was started, regmap has cache. + */ + regval = FIELD_PREP(BD79124_MSK_CONV_MODE, BD79124_CONV_MODE_AUTO); + + return regmap_update_bits(data->map, BD79124_REG_OPMODE_CFG, + BD79124_MSK_CONV_MODE, regval); +} + +static int bd79124_stop_measurement(struct bd79124_data *data, int chan) +{ + unsigned int enabled_chans; + int ret; + + /* See if already stopped */ + ret = regmap_read(data->map, BD79124_REG_AUTO_CHANNELS, &enabled_chans); + if (!(enabled_chans & BIT(chan))) + return 0; + + ret = regmap_clear_bits(data->map, BD79124_REG_SEQ_CFG, + BD79124_MSK_SEQ_START); + + /* Clear the channel from the measured channels */ + enabled_chans &= ~BIT(chan); + ret = regmap_write(data->map, BD79124_REG_AUTO_CHANNELS, + enabled_chans); + if (ret) + return ret; + + /* + * Stop background conversion for power saving if it was the last + * channel. + */ + if (!enabled_chans) { + int regval = FIELD_PREP(BD79124_MSK_CONV_MODE, + BD79124_CONV_MODE_MANSEQ); + + ret = regmap_update_bits(data->map, BD79124_REG_OPMODE_CFG, + BD79124_MSK_CONV_MODE, regval); + if (ret) + return ret; + } + + return regmap_set_bits(data->map, BD79124_REG_SEQ_CFG, + BD79124_MSK_SEQ_START); +} + +static int bd79124_read_event_config(struct iio_dev *iio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct bd79124_data *data = iio_priv(iio_dev); + + if (chan->channel >= BD79124_MAX_NUM_CHANNELS) + return -EINVAL; + + return !!(data->alarm_monitored[chan->channel] & BIT(dir)); +} + +static int bd79124_disable_event(struct bd79124_data *data, + enum iio_event_direction dir, int channel) +{ + int dir_bit = BIT(dir); + int reg; + unsigned int limit; + + guard(mutex)(&data->mutex); + + /* + * Set thresholds either to 0 or to 2^12 - 1 as appropriate to prevent + * alerts and thus disable event generation. + */ + if (dir == IIO_EV_DIR_RISING) { + reg = BD79124_GET_HIGH_LIMIT_REG(channel); + limit = BD79124_HIGH_LIMIT_MAX; + } else if (dir == IIO_EV_DIR_FALLING) { + reg = BD79124_GET_LOW_LIMIT_REG(channel); + limit = BD79124_LOW_LIMIT_MIN; + } else { + return -EINVAL; + } + + data->alarm_monitored[channel] &= ~dir_bit; + + /* + * Stop measurement if there is no more events to monitor. + * We don't bother checking the retval because the limit + * setting should in any case effectively disable the alarm. + */ + if (!data->alarm_monitored[channel]) { + bd79124_stop_measurement(data, channel); + regmap_clear_bits(data->map, BD79124_REG_ALERT_CH_SEL, + BIT(channel)); + } + + return bd79124_write_int_to_reg(data, reg, limit); +} + +static int bd79124_enable_event(struct bd79124_data *data, + enum iio_event_direction dir, + unsigned int channel) +{ + int dir_bit = BIT(dir); + int reg, ret; + u16 *limit; + + guard(mutex)(&data->mutex); + ret = bd79124_start_measurement(data, channel); + if (ret) + return ret; + + data->alarm_monitored[channel] |= dir_bit; + + /* Add the channel to the list of monitored channels */ + ret = regmap_set_bits(data->map, BD79124_REG_ALERT_CH_SEL, BIT(channel)); + if (ret) + return ret; + + if (dir == IIO_EV_DIR_RISING) { + limit = &data->alarm_f_limit[channel]; + reg = BD79124_GET_HIGH_LIMIT_REG(channel); + } else { + limit = &data->alarm_f_limit[channel]; + reg = BD79124_GET_LOW_LIMIT_REG(channel); + } + /* + * Don't write the new limit to the hardware if we are in the + * rate-limit period. The timer which re-enables the event will set + * the limit. + */ + if (!(data->alarm_suppressed[channel] & dir_bit)) { + ret = bd79124_write_int_to_reg(data, reg, *limit); + if (ret) + return ret; + } + + /* + * Enable comparator. Trust the regmap cache, no need to check + * if it was already enabled. + * + * We could do this in the hw-init, but there may be users who + * never enable alarms and for them it makes sense to not + * enable the comparator at probe. + */ + return regmap_set_bits(data->map, BD79124_REG_GEN_CFG, + BD79124_MSK_DWC_EN); +} + +static int bd79124_write_event_config(struct iio_dev *iio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, bool state) +{ + struct bd79124_data *data = iio_priv(iio_dev); + + if (chan->channel >= BD79124_MAX_NUM_CHANNELS) + return -EINVAL; + + if (state) + return bd79124_enable_event(data, dir, chan->channel); + + return bd79124_disable_event(data, dir, chan->channel); +} + +static int bd79124_write_event_value(struct iio_dev *iio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, int val, + int val2) +{ + struct bd79124_data *data = iio_priv(iio_dev); + int reg; + + if (chan->channel >= BD79124_MAX_NUM_CHANNELS) + return -EINVAL; + + switch (info) { + case IIO_EV_INFO_VALUE: + { + guard(mutex)(&data->mutex); + + if (dir == IIO_EV_DIR_RISING) { + data->alarm_r_limit[chan->channel] = val; + reg = BD79124_GET_HIGH_LIMIT_REG(chan->channel); + } else if (dir == IIO_EV_DIR_FALLING) { + data->alarm_f_limit[chan->channel] = val; + reg = BD79124_GET_LOW_LIMIT_REG(chan->channel); + } else { + return -EINVAL; + } + /* + * We don't want to enable the alarm if it is not enabled or + * if it is suppressed. In that case skip writing to the + * register. + */ + if (!(data->alarm_monitored[chan->channel] & BIT(dir)) || + data->alarm_suppressed[chan->channel] & BIT(dir)) + return 0; + + return bd79124_write_int_to_reg(data, reg, val); + } + case IIO_EV_INFO_HYSTERESIS: + reg = BD79124_GET_HYSTERESIS_REG(chan->channel); + val >>= 3; + + return regmap_update_bits(data->map, reg, BD79124_MSK_HYSTERESIS, + val); + default: + return -EINVAL; + } +} + +static int bd79124_single_chan_seq(struct bd79124_data *data, int chan, unsigned int *old) +{ + int ret; + + ret = regmap_clear_bits(data->map, BD79124_REG_SEQ_CFG, + BD79124_MSK_SEQ_START); + if (ret) + return ret; + + /* + * It may be we have some channels monitored for alarms so we want to + * cache the old config and return it when the single channel + * measurement has been completed. + */ + ret = regmap_read(data->map, BD79124_REG_AUTO_CHANNELS, old); + if (ret) + return ret; + + ret = regmap_write(data->map, BD79124_REG_AUTO_CHANNELS, BIT(chan)); + if (ret) + return ret; + + /* Restart the sequencer */ + return regmap_set_bits(data->map, BD79124_REG_SEQ_CFG, + BD79124_MSK_SEQ_START); +} + +static int bd79124_single_chan_seq_end(struct bd79124_data *data, unsigned int old) +{ + int ret; + + ret = regmap_clear_bits(data->map, BD79124_REG_SEQ_CFG, + BD79124_MSK_SEQ_START); + if (ret) + return ret; + + ret = regmap_write(data->map, BD79124_REG_AUTO_CHANNELS, old); + if (ret) + return ret; + + return regmap_set_bits(data->map, BD79124_REG_SEQ_CFG, + BD79124_MSK_SEQ_START); +} + +static int bd79124_read_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long m) +{ + struct bd79124_data *data = iio_priv(iio_dev); + int ret; + + if (chan->channel >= BD79124_MAX_NUM_CHANNELS) + return -EINVAL; + + switch (m) { + case IIO_CHAN_INFO_RAW: + { + unsigned int old_chan_cfg, regval; + int tmp; + + guard(mutex)(&data->mutex); + + /* + * Start the automatic conversion. This is needed here if no + * events have been enabled. + */ + regval = FIELD_PREP(BD79124_MSK_CONV_MODE, + BD79124_CONV_MODE_AUTO); + ret = regmap_update_bits(data->map, BD79124_REG_OPMODE_CFG, + BD79124_MSK_CONV_MODE, regval); + if (ret) + return ret; + + ret = bd79124_single_chan_seq(data, chan->channel, &old_chan_cfg); + if (ret) + return ret; + + /* The maximum conversion time is 6 uS. */ + udelay(6); + + ret = bd79124_read_reg_to_int(data, + BD79124_GET_RECENT_RES_REG(chan->channel), val); + /* + * Return the old chan config even if data reading failed in + * order to re-enable the event monitoring. + */ + tmp = bd79124_single_chan_seq_end(data, old_chan_cfg); + if (tmp) + dev_err(data->dev, + "Failed to return config. Alarms may be disabled\n"); + + if (ret) + return ret; + + return IIO_VAL_INT; + } + case IIO_CHAN_INFO_SCALE: + *val = data->vmax / 1000; + *val2 = BD79124_ADC_BITS; + return IIO_VAL_FRACTIONAL_LOG2; + default: + return -EINVAL; + } +} + +static const struct iio_info bd79124_info = { + .read_raw = bd79124_read_raw, + .read_event_config = &bd79124_read_event_config, + .write_event_config = &bd79124_write_event_config, + .read_event_value = &bd79124_read_event_value, + .write_event_value = &bd79124_write_event_value, +}; + +static void bd79124_re_enable_lo(struct bd79124_data *data, unsigned int channel) +{ + int ret, evbit = BIT(IIO_EV_DIR_FALLING); + + /* + * We should not re-enable the event if user has disabled it while + * rate-limiting was enabled. + */ + if (!(data->alarm_suppressed[channel] & evbit)) + return; + + data->alarm_suppressed[channel] &= ~evbit; + + if (!(data->alarm_monitored[channel] & evbit)) + return; + + ret = bd79124_write_int_to_reg(data, BD79124_GET_LOW_LIMIT_REG(channel), + data->alarm_f_limit[channel]); + if (ret) + dev_warn(data->dev, "Low limit enabling failed for channel%d\n", + channel); +} + +static void bd79124_re_enable_hi(struct bd79124_data *data, unsigned int channel) +{ + int ret, evbit = BIT(IIO_EV_DIR_RISING); + + /* + * We should not re-enable the event if user has disabled it while + * rate-limiting was enabled. + */ + if (!(data->alarm_suppressed[channel] & evbit)) + return; + + data->alarm_suppressed[channel] &= ~evbit; + + if (!(data->alarm_monitored[channel] & evbit)) + return; + + ret = bd79124_write_int_to_reg(data, BD79124_GET_HIGH_LIMIT_REG(channel), + data->alarm_r_limit[channel]); + if (ret) + dev_warn(data->dev, "High limit enabling failed for channel%d\n", + channel); +} + +static void bd79124_alm_enable_worker(struct work_struct *work) +{ + int i; + struct bd79124_data *data = container_of(work, struct bd79124_data, + alm_enable_work.work); + + /* Take the mutex so there is no race with user disabling the alarm */ + guard(mutex)(&data->mutex); + for (i = 0; i < BD79124_MAX_NUM_CHANNELS; i++) { + bd79124_re_enable_hi(data, i); + bd79124_re_enable_lo(data, i); + } +} + +static int __bd79124_event_ratelimit(struct bd79124_data *data, int reg, + unsigned int limit) +{ + int ret; + + if (limit > BD79124_HIGH_LIMIT_MAX) + return -EINVAL; + + ret = bd79124_write_int_to_reg(data, reg, limit); + if (ret) + return ret; + + /* + * We use 1 sec 'grace period'. At the moment I see no reason to make + * this user configurable. We need an ABI for this if configuration is + * needed. + */ + schedule_delayed_work(&data->alm_enable_work, msecs_to_jiffies(1000)); + + return 0; +} + +static int bd79124_event_ratelimit_hi(struct bd79124_data *data, + unsigned int channel) +{ + guard(mutex)(&data->mutex); + data->alarm_suppressed[channel] |= BIT(IIO_EV_DIR_RISING); + + return __bd79124_event_ratelimit(data, + BD79124_GET_HIGH_LIMIT_REG(channel), + BD79124_HIGH_LIMIT_MAX); +} + +static int bd79124_event_ratelimit_lo(struct bd79124_data *data, + unsigned int channel) +{ + guard(mutex)(&data->mutex); + data->alarm_suppressed[channel] |= BIT(IIO_EV_DIR_FALLING); + + return __bd79124_event_ratelimit(data, + BD79124_GET_LOW_LIMIT_REG(channel), + BD79124_LOW_LIMIT_MIN); +} + +static irqreturn_t bd79124_event_handler(int irq, void *priv) +{ + unsigned int i_hi, i_lo; + int i, ret; + struct iio_dev *iio_dev = priv; + struct bd79124_data *data = iio_priv(iio_dev); + + /* + * Return IRQ_NONE if bailing-out without acking. This allows the IRQ + * subsystem to disable the offending IRQ line if we get a hardware + * problem. This behaviour has saved my poor bottom a few times in the + * past as, instead of getting unusably unresponsive, the system has + * spilled out the magic words "...nobody cared". + */ + ret = regmap_read(data->map, BD79124_REG_EVENT_FLAG_HI, &i_hi); + if (ret) + return IRQ_NONE; + + ret = regmap_read(data->map, BD79124_REG_EVENT_FLAG_LO, &i_lo); + if (ret) + return IRQ_NONE; + + if (!i_lo && !i_hi) + return IRQ_NONE; + + for (i = 0; i < BD79124_MAX_NUM_CHANNELS; i++) { + u64 ecode; + + if (BIT(i) & i_hi) { + ecode = IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING); + + iio_push_event(iio_dev, ecode, data->timestamp); + /* + * The BD79124 keeps the IRQ asserted for as long as + * the voltage exceeds the threshold. It causes the IRQ + * to keep firing. + * + * Disable the event for the channel and schedule the + * re-enabling the event later to prevent storm of + * events. + */ + ret = bd79124_event_ratelimit_hi(data, i); + if (ret) + return IRQ_NONE; + } + if (BIT(i) & i_lo) { + ecode = IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING); + + iio_push_event(iio_dev, ecode, data->timestamp); + ret = bd79124_event_ratelimit_lo(data, i); + if (ret) + return IRQ_NONE; + } + } + + ret = regmap_write(data->map, BD79124_REG_EVENT_FLAG_HI, i_hi); + if (ret) + return IRQ_NONE; + + ret = regmap_write(data->map, BD79124_REG_EVENT_FLAG_LO, i_lo); + if (ret) + return IRQ_NONE; + + return IRQ_HANDLED; +} + +static irqreturn_t bd79124_irq_handler(int irq, void *priv) +{ + struct iio_dev *iio_dev = priv; + struct bd79124_data *data = iio_priv(iio_dev); + + data->timestamp = iio_get_time_ns(iio_dev); + + return IRQ_WAKE_THREAD; +} + +static int bd79124_chan_init(struct bd79124_data *data, int channel) +{ + int ret; + + ret = regmap_write(data->map, BD79124_GET_HIGH_LIMIT_REG(channel), + BD79124_HIGH_LIMIT_MAX); + if (ret) + return ret; + + return regmap_write(data->map, BD79124_GET_LOW_LIMIT_REG(channel), + BD79124_LOW_LIMIT_MIN); +} + +static int bd79124_get_gpio_pins(const struct iio_chan_spec *cs, int num_channels) +{ + int i, gpio_channels; + + /* + * Let's initialize the mux config to say that all 8 channels are + * GPIOs. Then we can just loop through the iio_chan_spec and clear the + * bits for found ADC channels. + */ + gpio_channels = GENMASK(7, 0); + for (i = 0; i < num_channels; i++) + gpio_channels &= ~BIT(cs[i].channel); + + return gpio_channels; +} + +static int bd79124_hw_init(struct bd79124_data *data) +{ + unsigned int regval; + int ret, i; + + for (i = 0; i < BD79124_MAX_NUM_CHANNELS; i++) { + ret = bd79124_chan_init(data, i); + if (ret) + return ret; + data->alarm_r_limit[i] = BD79124_HIGH_LIMIT_MAX; + } + /* Stop auto sequencer */ + ret = regmap_clear_bits(data->map, BD79124_REG_SEQ_CFG, + BD79124_MSK_SEQ_START); + if (ret) + return ret; + + /* Enable writing the measured values to the regsters */ + ret = regmap_set_bits(data->map, BD79124_REG_GEN_CFG, + BD79124_MSK_STATS_EN); + if (ret) + return ret; + + /* Set no channels to be auto-measured */ + ret = regmap_write(data->map, BD79124_REG_AUTO_CHANNELS, 0x0); + if (ret) + return ret; + + /* Set no channels to be manually measured */ + ret = regmap_write(data->map, BD79124_REG_MANUAL_CHANNELS, 0x0); + if (ret) + return ret; + + regval = FIELD_PREP(BD79124_MSK_AUTO_INTERVAL, BD79124_INTERVAL_750_US); + ret = regmap_update_bits(data->map, BD79124_REG_OPMODE_CFG, + BD79124_MSK_AUTO_INTERVAL, regval); + if (ret) + return ret; + + /* Sequencer mode to auto */ + ret = regmap_set_bits(data->map, BD79124_REG_SEQ_CFG, + BD79124_MSK_SEQ_SEQ); + if (ret) + return ret; + + /* Don't start the measurement */ + regval = FIELD_PREP(BD79124_MSK_CONV_MODE, BD79124_CONV_MODE_MANSEQ); + return regmap_update_bits(data->map, BD79124_REG_OPMODE_CFG, + BD79124_MSK_CONV_MODE, regval); +} + +static int bd79124_probe(struct i2c_client *i2c) +{ + struct bd79124_data *data; + struct iio_dev *iio_dev; + const struct iio_chan_spec *template; + struct iio_chan_spec *cs; + struct device *dev = &i2c->dev; + unsigned int gpio_pins; + int ret; + + iio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!iio_dev) + return -ENOMEM; + + data = iio_priv(iio_dev); + data->dev = dev; + data->map = devm_regmap_init_i2c(i2c, &bd79124_regmap); + if (IS_ERR(data->map)) + return dev_err_probe(dev, PTR_ERR(data->map), + "Failed to initialize Regmap\n"); + + ret = devm_regulator_get_enable_read_voltage(dev, "vdd"); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to get the Vdd\n"); + + data->vmax = ret; + + ret = devm_regulator_get_enable(dev, "iovdd"); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to enable I/O voltage\n"); + + ret = devm_delayed_work_autocancel(dev, &data->alm_enable_work, + bd79124_alm_enable_worker); + if (ret) + return ret; + + if (i2c->irq) { + template = &bd79124_chan_template; + } else { + template = &bd79124_chan_template_noirq; + dev_dbg(dev, "No IRQ found, events disabled\n"); + } + + ret = devm_mutex_init(dev, &data->mutex); + if (ret) + return ret; + + ret = devm_iio_adc_device_alloc_chaninfo_se(dev, template, + BD79124_MAX_NUM_CHANNELS - 1, &cs); + if (ret < 0) { + /* Register all pins as GPOs if there are no ADC channels */ + if (ret == -ENOENT) + goto register_gpios; + return ret; + } + iio_dev->channels = cs; + iio_dev->num_channels = ret; + iio_dev->info = &bd79124_info; + iio_dev->name = "bd79124"; + iio_dev->modes = INDIO_DIRECT_MODE; + + ret = bd79124_hw_init(data); + if (ret) + return ret; + + if (i2c->irq > 0) { + ret = devm_request_threaded_irq(dev, i2c->irq, + bd79124_irq_handler, &bd79124_event_handler, + IRQF_ONESHOT, "adc-thresh-alert", iio_dev); + if (ret) + return dev_err_probe(data->dev, ret, + "Failed to register IRQ\n"); + } + + ret = devm_iio_device_register(data->dev, iio_dev); + if (ret) + return dev_err_probe(data->dev, ret, "Failed to register ADC\n"); + +register_gpios: + gpio_pins = bd79124_get_gpio_pins(iio_dev->channels, + iio_dev->num_channels); + + /* + * The mux should default to "all ADCs", but better to not trust it. + * Thus we do set the mux even when we have only ADCs and no GPOs. + */ + ret = regmap_write(data->map, BD79124_REG_PINCFG, gpio_pins); + if (ret) + return ret; + + /* No GPOs if all channels are reserved for ADC, so we're done. */ + if (!gpio_pins) + return 0; + + data->gpio_valid_mask = gpio_pins; + data->gc = bd79124gpo_chip; + data->gc.parent = dev; + + return devm_gpiochip_add_data(dev, &data->gc, data); +} + +static const struct of_device_id bd79124_of_match[] = { + { .compatible = "rohm,bd79124" }, + { } +}; +MODULE_DEVICE_TABLE(of, bd79124_of_match); + +static const struct i2c_device_id bd79124_id[] = { + { "bd79124" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, bd79124_id); + +static struct i2c_driver bd79124_driver = { + .driver = { + .name = "bd79124", + .of_match_table = bd79124_of_match, + }, + .probe = bd79124_probe, + .id_table = bd79124_id, +}; +module_i2c_driver(bd79124_driver); + +MODULE_AUTHOR("Matti Vaittinen <mazziesaccount@gmail.com>"); +MODULE_DESCRIPTION("Driver for ROHM BD79124 ADC"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("IIO_DRIVER"); diff --git a/drivers/iio/adc/rtq6056.c b/drivers/iio/adc/rtq6056.c index 54239df61d86..6ff47415a222 100644 --- a/drivers/iio/adc/rtq6056.c +++ b/drivers/iio/adc/rtq6056.c @@ -666,7 +666,8 @@ static irqreturn_t rtq6056_buffer_trigger_handler(int irq, void *p) data.vals[i++] = raw; } - iio_push_to_buffers_with_timestamp(indio_dev, &data, iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &data, sizeof(data), + iio_get_time_ns(indio_dev)); out: pm_runtime_mark_last_busy(dev); diff --git a/drivers/iio/adc/rzg2l_adc.c b/drivers/iio/adc/rzg2l_adc.c index 883c167c0670..9674d48074c9 100644 --- a/drivers/iio/adc/rzg2l_adc.c +++ b/drivers/iio/adc/rzg2l_adc.c @@ -11,6 +11,7 @@ #include <linux/cleanup.h> #include <linux/completion.h> #include <linux/delay.h> +#include <linux/iio/adc-helpers.h> #include <linux/iio/iio.h> #include <linux/interrupt.h> #include <linux/io.h> @@ -324,48 +325,39 @@ static irqreturn_t rzg2l_adc_isr(int irq, void *dev_id) return IRQ_HANDLED; } +static const struct iio_chan_spec rzg2l_adc_chan_template = { + .indexed = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), +}; + static int rzg2l_adc_parse_properties(struct platform_device *pdev, struct rzg2l_adc *adc) { const struct rzg2l_adc_hw_params *hw_params = adc->hw_params; struct iio_chan_spec *chan_array; struct rzg2l_adc_data *data; - unsigned int channel; int num_channels; - int ret; u8 i; data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; - num_channels = device_get_child_node_count(&pdev->dev); - if (!num_channels) - return dev_err_probe(&pdev->dev, -ENODEV, "no channel children\n"); + num_channels = devm_iio_adc_device_alloc_chaninfo_se(&pdev->dev, + &rzg2l_adc_chan_template, + hw_params->num_channels - 1, + &chan_array); + if (num_channels < 0) + return num_channels; if (num_channels > hw_params->num_channels) return dev_err_probe(&pdev->dev, -EINVAL, "num of channel children out of range\n"); - chan_array = devm_kcalloc(&pdev->dev, num_channels, sizeof(*chan_array), - GFP_KERNEL); - if (!chan_array) - return -ENOMEM; + for (i = 0; i < num_channels; i++) { + int channel = chan_array[i].channel; - i = 0; - device_for_each_child_node_scoped(&pdev->dev, fwnode) { - ret = fwnode_property_read_u32(fwnode, "reg", &channel); - if (ret) - return ret; - - if (channel >= hw_params->num_channels) - return -EINVAL; - - chan_array[i].type = rzg2l_adc_channels[channel].type; - chan_array[i].indexed = 1; - chan_array[i].channel = channel; - chan_array[i].info_mask_separate = BIT(IIO_CHAN_INFO_RAW); chan_array[i].datasheet_name = rzg2l_adc_channels[channel].name; - i++; + chan_array[i].type = rzg2l_adc_channels[channel].type; } data->num_channels = num_channels; @@ -515,7 +507,7 @@ static const struct rzg2l_adc_hw_params rzg3s_hw_params = { static const struct of_device_id rzg2l_adc_match[] = { { .compatible = "renesas,r9a08g045-adc", .data = &rzg3s_hw_params }, { .compatible = "renesas,rzg2l-adc", .data = &rzg2l_hw_params }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, rzg2l_adc_match); @@ -626,3 +618,4 @@ module_platform_driver(rzg2l_adc_driver); MODULE_AUTHOR("Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>"); MODULE_DESCRIPTION("Renesas RZ/G2L ADC driver"); MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS("IIO_DRIVER"); diff --git a/drivers/iio/adc/spear_adc.c b/drivers/iio/adc/spear_adc.c index b6dd096391c1..e3a865c79686 100644 --- a/drivers/iio/adc/spear_adc.c +++ b/drivers/iio/adc/spear_adc.c @@ -345,7 +345,7 @@ static int spear_adc_probe(struct platform_device *pdev) static const struct of_device_id spear_adc_dt_ids[] = { { .compatible = "st,spear600-adc", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, spear_adc_dt_ids); diff --git a/drivers/iio/adc/stm32-adc-core.h b/drivers/iio/adc/stm32-adc-core.h index 73b2c2e91c08..db50a9f3b922 100644 --- a/drivers/iio/adc/stm32-adc-core.h +++ b/drivers/iio/adc/stm32-adc-core.h @@ -10,6 +10,9 @@ #ifndef __STM32_ADC_H #define __STM32_ADC_H +#include <linux/bitfield.h> +#include <linux/bits.h> + /* * STM32 - ADC global register map * ________________________________________________________ @@ -91,6 +94,7 @@ #define STM32H7_ADC_IER 0x04 #define STM32H7_ADC_CR 0x08 #define STM32H7_ADC_CFGR 0x0C +#define STM32H7_ADC_CFGR2 0x10 #define STM32H7_ADC_SMPR1 0x14 #define STM32H7_ADC_SMPR2 0x18 #define STM32H7_ADC_PCSEL 0x1C @@ -160,6 +164,13 @@ #define STM32H7_DMNGT_SHIFT 0 #define STM32H7_DMNGT_MASK GENMASK(1, 0) +/* STM32H7_ADC_CFGR2 bit fields */ +#define STM32H7_OVSR_MASK GENMASK(25, 16) /* Correspond to OSVR field in datasheet */ +#define STM32H7_OVSR(v) FIELD_PREP(STM32H7_OVSR_MASK, v) +#define STM32H7_OVSS_MASK GENMASK(8, 5) +#define STM32H7_OVSS(v) FIELD_PREP(STM32H7_OVSS_MASK, v) +#define STM32H7_ROVSE BIT(0) + enum stm32h7_adc_dmngt { STM32H7_DMNGT_DR_ONLY, /* Regular data in DR only */ STM32H7_DMNGT_DMA_ONESHOT, /* DMA one shot mode */ @@ -226,6 +237,12 @@ enum stm32h7_adc_dmngt { #define STM32MP13_RES_SHIFT 3 #define STM32MP13_RES_MASK GENMASK(4, 3) +/* STM32MP13_ADC_CFGR2 bit fields */ +#define STM32MP13_OVSR_MASK GENMASK(4, 2) +#define STM32MP13_OVSR(v) FIELD_PREP(STM32MP13_OVSR_MASK, v) +#define STM32MP13_OVSS_MASK GENMASK(8, 5) +#define STM32MP13_OVSS(v) FIELD_PREP(STM32MP13_OVSS_MASK, v) + /* STM32MP13_ADC_DIFSEL - bit fields */ #define STM32MP13_DIFSEL_MASK GENMASK(18, 0) diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index 5dbf5f136768..e84babf43385 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -6,6 +6,7 @@ * Author: Fabrice Gasnier <fabrice.gasnier@st.com>. */ +#include <linux/array_size.h> #include <linux/clk.h> #include <linux/debugfs.h> #include <linux/delay.h> @@ -202,11 +203,13 @@ struct stm32_adc; * @has_boostmode: boost mode support flag * @has_linearcal: linear calibration support flag * @has_presel: channel preselection support flag + * @has_oversampling: oversampling support flag * @prepare: optional prepare routine (power-up, enable) * @start_conv: routine to start conversions * @stop_conv: routine to stop conversions * @unprepare: optional unprepare routine (disable, power-down) * @irq_clear: routine to clear irqs + * @set_ovs: routine to set oversampling configuration * @smp_cycles: programmable sampling time (ADC clock cycles) * @ts_int_ch: pointer to array of internal channels minimum sampling time in ns */ @@ -219,11 +222,13 @@ struct stm32_adc_cfg { bool has_boostmode; bool has_linearcal; bool has_presel; + bool has_oversampling; int (*prepare)(struct iio_dev *); void (*start_conv)(struct iio_dev *, bool dma); void (*stop_conv)(struct iio_dev *); void (*unprepare)(struct iio_dev *); void (*irq_clear)(struct iio_dev *indio_dev, u32 msk); + void (*set_ovs)(struct iio_dev *indio_dev, u32 ovs_idx); const unsigned int *smp_cycles; const unsigned int *ts_int_ch; }; @@ -255,6 +260,7 @@ struct stm32_adc_cfg { * @num_diff: number of differential channels * @int_ch: internal channel indexes array * @nsmps: number of channels with optional sample time + * @ovs_idx: current oversampling ratio index (in oversampling array) */ struct stm32_adc { struct stm32_adc_common *common; @@ -282,6 +288,7 @@ struct stm32_adc { u32 num_diff; int int_ch[STM32_ADC_INT_CH_NB]; int nsmps; + int ovs_idx; }; struct stm32_adc_diff_channel { @@ -293,12 +300,24 @@ struct stm32_adc_diff_channel { * struct stm32_adc_info - stm32 ADC, per instance config data * @max_channels: Number of channels * @resolutions: available resolutions + * @oversampling: available oversampling ratios * @num_res: number of available resolutions + * @num_ovs: number of available oversampling ratios */ struct stm32_adc_info { int max_channels; const unsigned int *resolutions; + const unsigned int *oversampling; const unsigned int num_res; + const unsigned int num_ovs; +}; + +static const unsigned int stm32h7_adc_oversampling_avail[] = { + 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, +}; + +static const unsigned int stm32mp13_adc_oversampling_avail[] = { + 1, 2, 4, 8, 16, 32, 64, 128, 256, }; static const unsigned int stm32f4_adc_resolutions[] = { @@ -322,14 +341,18 @@ static const unsigned int stm32h7_adc_resolutions[] = { static const struct stm32_adc_info stm32h7_adc_info = { .max_channels = STM32_ADC_CH_MAX, .resolutions = stm32h7_adc_resolutions, + .oversampling = stm32h7_adc_oversampling_avail, .num_res = ARRAY_SIZE(stm32h7_adc_resolutions), + .num_ovs = ARRAY_SIZE(stm32h7_adc_oversampling_avail), }; /* stm32mp13 can have up to 19 channels */ static const struct stm32_adc_info stm32mp13_adc_info = { .max_channels = 19, .resolutions = stm32f4_adc_resolutions, + .oversampling = stm32mp13_adc_oversampling_avail, .num_res = ARRAY_SIZE(stm32f4_adc_resolutions), + .num_ovs = ARRAY_SIZE(stm32mp13_adc_oversampling_avail), }; /* @@ -469,7 +492,7 @@ static struct stm32_adc_trig_info stm32h7_adc_trigs[] = { { LPTIM1_OUT, STM32_EXT18 }, { LPTIM2_OUT, STM32_EXT19 }, { LPTIM3_OUT, STM32_EXT20 }, - {}, + { } }; /* @@ -889,6 +912,56 @@ static void stm32mp13_adc_start_conv(struct iio_dev *indio_dev, bool dma) stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADSTART); } +static void stm32h7_adc_set_ovs(struct iio_dev *indio_dev, u32 ovs_idx) +{ + struct stm32_adc *adc = iio_priv(indio_dev); + u32 ovsr_bits, bits, msk; + + msk = STM32H7_ROVSE | STM32H7_OVSR_MASK | STM32H7_OVSS_MASK; + stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR2, msk); + + if (!ovs_idx) + return; + + /* + * Only the oversampling ratios corresponding to 2^ovs_idx are exposed in sysfs. + * Oversampling ratios [2,3,...,1024] are mapped on OVSR register values [1,2,...,1023]. + * OVSR = 2^ovs_idx - 1 + * These ratio increase the resolution by ovs_idx bits. Apply a right shift to keep initial + * resolution given by "assigned-resolution-bits" property. + * OVSS = ovs_idx + */ + ovsr_bits = GENMASK(ovs_idx - 1, 0); + bits = STM32H7_ROVSE | STM32H7_OVSS(ovs_idx) | STM32H7_OVSR(ovsr_bits); + + stm32_adc_set_bits(adc, STM32H7_ADC_CFGR2, bits & msk); +} + +static void stm32mp13_adc_set_ovs(struct iio_dev *indio_dev, u32 ovs_idx) +{ + struct stm32_adc *adc = iio_priv(indio_dev); + u32 bits, msk; + + msk = STM32H7_ROVSE | STM32MP13_OVSR_MASK | STM32MP13_OVSS_MASK; + stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR2, msk); + + if (!ovs_idx) + return; + + /* + * The oversampling ratios [2,4,8,..,256] are mapped on OVSR register values [0,1,...,7]. + * OVSR = ovs_idx - 1 + * These ratio increase the resolution by ovs_idx bits. Apply a right shift to keep initial + * resolution given by "assigned-resolution-bits" property. + * OVSS = ovs_idx + */ + bits = STM32H7_ROVSE | STM32MP13_OVSS(ovs_idx); + if (ovs_idx - 1) + bits |= STM32MP13_OVSR(ovs_idx - 1); + + stm32_adc_set_bits(adc, STM32H7_ADC_CFGR2, bits & msk); +} + static int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev) { struct stm32_adc *adc = iio_priv(indio_dev); @@ -1461,6 +1534,67 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev, return ret; } +static int stm32_adc_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct stm32_adc *adc = iio_priv(indio_dev); + struct device *dev = indio_dev->dev.parent; + int nb = adc->cfg->adc_info->num_ovs; + unsigned int idx; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + if (val2) + return -EINVAL; + + for (idx = 0; idx < nb; idx++) + if (adc->cfg->adc_info->oversampling[idx] == val) + break; + if (idx >= nb) + return -EINVAL; + + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) + goto err; + + adc->cfg->set_ovs(indio_dev, idx); + + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + adc->ovs_idx = idx; + +err: + iio_device_release_direct(indio_dev); + + return ret; + default: + return -EINVAL; + } +} + +static int stm32_adc_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, long m) +{ + struct stm32_adc *adc = iio_priv(indio_dev); + + switch (m) { + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + *type = IIO_VAL_INT; + *length = adc->cfg->adc_info->num_ovs; + *vals = adc->cfg->adc_info->oversampling; + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + static int stm32_adc_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -1502,6 +1636,10 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev, *val = 0; return IIO_VAL_INT; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + *val = adc->cfg->adc_info->oversampling[adc->ovs_idx]; + return IIO_VAL_INT; + default: return -EINVAL; } @@ -1678,6 +1816,8 @@ static int stm32_adc_debugfs_reg_access(struct iio_dev *indio_dev, static const struct iio_info stm32_adc_iio_info = { .read_raw = stm32_adc_read_raw, + .write_raw = stm32_adc_write_raw, + .read_avail = stm32_adc_read_avail, .validate_trigger = stm32_adc_validate_trigger, .hwfifo_set_watermark = stm32_adc_set_watermark, .update_scan_mode = stm32_adc_update_scan_mode, @@ -1858,8 +1998,8 @@ static irqreturn_t stm32_adc_trigger_handler(int irq, void *p) /* reset buffer index */ adc->bufi = 0; - iio_push_to_buffers_with_timestamp(indio_dev, adc->buffer, - pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, adc->buffer, sizeof(adc->buffer), + pf->timestamp); iio_trigger_notify_done(indio_dev->trig); /* re-enable eoc irq */ @@ -1876,7 +2016,7 @@ static const struct iio_chan_spec_ext_info stm32_adc_ext_info[] = { .read = iio_enum_available_read, .private = (uintptr_t)&stm32_adc_trig_pol, }, - {}, + { } }; static void stm32_adc_debugfs_init(struct iio_dev *indio_dev) @@ -1971,6 +2111,10 @@ static void stm32_adc_chan_init_one(struct iio_dev *indio_dev, chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET); + if (adc->cfg->has_oversampling) { + chan->info_mask_shared_by_all |= BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); + chan->info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); + } chan->scan_type.sign = 'u'; chan->scan_type.realbits = adc->cfg->adc_info->resolutions[adc->res]; chan->scan_type.storagebits = 16; @@ -2587,6 +2731,7 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = { .has_boostmode = true, .has_linearcal = true, .has_presel = true, + .has_oversampling = true, .start_conv = stm32h7_adc_start_conv, .stop_conv = stm32h7_adc_stop_conv, .prepare = stm32h7_adc_prepare, @@ -2594,6 +2739,7 @@ static const struct stm32_adc_cfg stm32h7_adc_cfg = { .smp_cycles = stm32h7_adc_smp_cycles, .irq_clear = stm32h7_adc_irq_clear, .ts_int_ch = stm32_adc_min_ts_h7, + .set_ovs = stm32h7_adc_set_ovs, }; static const unsigned int stm32_adc_min_ts_mp1[] = { 100, 100, 100, 4300, 9800 }; @@ -2607,6 +2753,7 @@ static const struct stm32_adc_cfg stm32mp1_adc_cfg = { .has_boostmode = true, .has_linearcal = true, .has_presel = true, + .has_oversampling = true, .start_conv = stm32h7_adc_start_conv, .stop_conv = stm32h7_adc_stop_conv, .prepare = stm32h7_adc_prepare, @@ -2614,6 +2761,7 @@ static const struct stm32_adc_cfg stm32mp1_adc_cfg = { .smp_cycles = stm32h7_adc_smp_cycles, .irq_clear = stm32h7_adc_irq_clear, .ts_int_ch = stm32_adc_min_ts_mp1, + .set_ovs = stm32h7_adc_set_ovs, }; static const unsigned int stm32_adc_min_ts_mp13[] = { 100, 0, 0, 4300, 9800 }; @@ -2623,6 +2771,7 @@ static const struct stm32_adc_cfg stm32mp13_adc_cfg = { .regs = &stm32mp13_adc_regspec, .adc_info = &stm32mp13_adc_info, .trigs = stm32h7_adc_trigs, + .has_oversampling = true, .start_conv = stm32mp13_adc_start_conv, .stop_conv = stm32h7_adc_stop_conv, .prepare = stm32h7_adc_prepare, @@ -2630,6 +2779,7 @@ static const struct stm32_adc_cfg stm32mp13_adc_cfg = { .smp_cycles = stm32mp13_adc_smp_cycles, .irq_clear = stm32h7_adc_irq_clear, .ts_int_ch = stm32_adc_min_ts_mp13, + .set_ovs = stm32mp13_adc_set_ovs, }; static const struct of_device_id stm32_adc_of_match[] = { diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index 726ddafc9f6d..f583924eb16b 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -108,7 +108,7 @@ static const struct stm32_dfsdm_str2field stm32_dfsdm_chan_type[] = { { "SPI_F", 1 }, /* SPI with data on falling edge */ { "MANCH_R", 2 }, /* Manchester codec, rising edge = logic 0 */ { "MANCH_F", 3 }, /* Manchester codec, falling edge = logic 1 */ - {}, + { } }; /* DFSDM channel clock source */ @@ -121,7 +121,7 @@ static const struct stm32_dfsdm_str2field stm32_dfsdm_chan_src[] = { { "CLKOUT_F", DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_FALLING }, /* Internal SPI clock divided by 2 (falling edge) */ { "CLKOUT_R", DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_RISING }, - {}, + { } }; static int stm32_dfsdm_str2val(const char *str, @@ -167,7 +167,7 @@ static const struct stm32_dfsdm_trig_info stm32_dfsdm_trigs[] = { { LPTIM1_OUT, 26 }, { LPTIM2_OUT, 27 }, { LPTIM3_OUT, 28 }, - {}, + { } }; static int stm32_dfsdm_get_jextsel(struct iio_dev *indio_dev, @@ -1747,7 +1747,7 @@ static const struct of_device_id stm32_dfsdm_adc_match[] = { .compatible = "st,stm32-dfsdm-dmic", .data = &stm32h7_dfsdm_audio_data, }, - {} + { } }; MODULE_DEVICE_TABLE(of, stm32_dfsdm_adc_match); diff --git a/drivers/iio/adc/sun20i-gpadc-iio.c b/drivers/iio/adc/sun20i-gpadc-iio.c index 136b8d9c294f..e4dfe76e6362 100644 --- a/drivers/iio/adc/sun20i-gpadc-iio.c +++ b/drivers/iio/adc/sun20i-gpadc-iio.c @@ -15,6 +15,7 @@ #include <linux/property.h> #include <linux/reset.h> +#include <linux/iio/adc-helpers.h> #include <linux/iio/iio.h> #define SUN20I_GPADC_DRIVER_NAME "sun20i-gpadc" @@ -149,36 +150,23 @@ static void sun20i_gpadc_reset_assert(void *data) reset_control_assert(rst); } +static const struct iio_chan_spec sun20i_gpadc_chan_template = { + .type = IIO_VOLTAGE, + .indexed = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), +}; + static int sun20i_gpadc_alloc_channels(struct iio_dev *indio_dev, struct device *dev) { - unsigned int channel; - int num_channels, i, ret; + int num_channels; struct iio_chan_spec *channels; - num_channels = device_get_child_node_count(dev); - if (num_channels == 0) - return dev_err_probe(dev, -ENODEV, "no channel children\n"); - - channels = devm_kcalloc(dev, num_channels, sizeof(*channels), - GFP_KERNEL); - if (!channels) - return -ENOMEM; - - i = 0; - device_for_each_child_node_scoped(dev, node) { - ret = fwnode_property_read_u32(node, "reg", &channel); - if (ret) - return dev_err_probe(dev, ret, "invalid channel number\n"); - - channels[i].type = IIO_VOLTAGE; - channels[i].indexed = 1; - channels[i].channel = channel; - channels[i].info_mask_separate = BIT(IIO_CHAN_INFO_RAW); - channels[i].info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); - - i++; - } + num_channels = devm_iio_adc_device_alloc_chaninfo_se(dev, + &sun20i_gpadc_chan_template, -1, &channels); + if (num_channels < 0) + return num_channels; indio_dev->channels = channels; indio_dev->num_channels = num_channels; @@ -255,7 +243,7 @@ static int sun20i_gpadc_probe(struct platform_device *pdev) static const struct of_device_id sun20i_gpadc_of_id[] = { { .compatible = "allwinner,sun20i-d1-gpadc" }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, sun20i_gpadc_of_id); @@ -271,3 +259,4 @@ module_platform_driver(sun20i_gpadc_driver); MODULE_DESCRIPTION("ADC driver for sunxi platforms"); MODULE_AUTHOR("Maksim Kiselev <bigunclemax@gmail.com>"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("IIO_DRIVER"); diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c index 8b27458dcd66..6b8d6bee1873 100644 --- a/drivers/iio/adc/sun4i-gpadc-iio.c +++ b/drivers/iio/adc/sun4i-gpadc-iio.c @@ -116,7 +116,7 @@ struct sun4i_gpadc_iio { static const struct iio_map sun4i_gpadc_hwmon_maps[] = { IIO_MAP("temp_adc", "iio_hwmon.0", NULL), - { /* sentinel */ }, + { } }; static const struct iio_chan_spec sun4i_gpadc_channels[] = { @@ -485,7 +485,7 @@ static const struct of_device_id sun4i_gpadc_of_id[] = { .compatible = "allwinner,sun8i-a33-ths", .data = &sun8i_a33_gpadc_data, }, - { /* sentinel */ } + { } }; static int sun4i_gpadc_probe_dt(struct platform_device *pdev, @@ -685,7 +685,7 @@ static const struct platform_device_id sun4i_gpadc_id[] = { { "sun4i-a10-gpadc-iio", (kernel_ulong_t)&sun4i_gpadc_data }, { "sun5i-a13-gpadc-iio", (kernel_ulong_t)&sun5i_gpadc_data }, { "sun6i-a31-gpadc-iio", (kernel_ulong_t)&sun6i_gpadc_data }, - { /* sentinel */ }, + { } }; MODULE_DEVICE_TABLE(platform, sun4i_gpadc_id); diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c index 1af9be071d8d..4f514db5c26e 100644 --- a/drivers/iio/adc/ti-adc081c.c +++ b/drivers/iio/adc/ti-adc081c.c @@ -140,8 +140,8 @@ static irqreturn_t adc081c_trigger_handler(int irq, void *p) if (ret < 0) goto out; data->scan.channel = ret; - iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), + iio_get_time_ns(indio_dev)); out: iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; diff --git a/drivers/iio/adc/ti-adc0832.c b/drivers/iio/adc/ti-adc0832.c index e2dbd070c7c4..cfcdafbe284b 100644 --- a/drivers/iio/adc/ti-adc0832.c +++ b/drivers/iio/adc/ti-adc0832.c @@ -225,8 +225,8 @@ static irqreturn_t adc0832_trigger_handler(int irq, void *p) adc->data[i] = ret; i++; } - iio_push_to_buffers_with_timestamp(indio_dev, adc->data, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, adc->data, sizeof(adc->data), + iio_get_time_ns(indio_dev)); out: mutex_unlock(&adc->lock); diff --git a/drivers/iio/adc/ti-adc084s021.c b/drivers/iio/adc/ti-adc084s021.c index 9c845ee01697..50a474f4d9f5 100644 --- a/drivers/iio/adc/ti-adc084s021.c +++ b/drivers/iio/adc/ti-adc084s021.c @@ -151,8 +151,8 @@ static irqreturn_t adc084s021_buffer_trigger_handler(int irq, void *pollfunc) if (adc084s021_adc_conversion(adc, adc->scan.channels) < 0) dev_err(&adc->spi->dev, "Failed to read data\n"); - iio_push_to_buffers_with_timestamp(indio_dev, &adc->scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &adc->scan, sizeof(adc->scan), + iio_get_time_ns(indio_dev)); mutex_unlock(&adc->lock); iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/adc/ti-adc12138.c b/drivers/iio/adc/ti-adc12138.c index 7f065f457b36..9dc465a10ffc 100644 --- a/drivers/iio/adc/ti-adc12138.c +++ b/drivers/iio/adc/ti-adc12138.c @@ -376,8 +376,8 @@ static irqreturn_t adc12138_trigger_handler(int irq, void *p) } } - iio_push_to_buffers_with_timestamp(indio_dev, adc->data, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, adc->data, sizeof(adc->data), + iio_get_time_ns(indio_dev)); out: mutex_unlock(&adc->lock); diff --git a/drivers/iio/adc/ti-adc128s052.c b/drivers/iio/adc/ti-adc128s052.c index a456ea78462f..1b46a8155803 100644 --- a/drivers/iio/adc/ti-adc128s052.c +++ b/drivers/iio/adc/ti-adc128s052.c @@ -9,6 +9,7 @@ * https://www.ti.com/lit/ds/symlink/adc124s021.pdf */ +#include <linux/cleanup.h> #include <linux/err.h> #include <linux/iio/iio.h> #include <linux/mod_devicetable.h> @@ -20,40 +21,44 @@ struct adc128_configuration { const struct iio_chan_spec *channels; u8 num_channels; + const char *refname; + int num_other_regulators; + const char * const (*other_regulators)[]; }; struct adc128 { struct spi_device *spi; - struct regulator *reg; + /* + * Serialize the SPI 'write-channel + read data' accesses and protect + * the shared buffer. + */ struct mutex lock; - - u8 buffer[2] __aligned(IIO_DMA_MINALIGN); + int vref_mv; + union { + __be16 buffer16; + u8 buffer[2]; + } __aligned(IIO_DMA_MINALIGN); }; static int adc128_adc_conversion(struct adc128 *adc, u8 channel) { int ret; - mutex_lock(&adc->lock); + guard(mutex)(&adc->lock); adc->buffer[0] = channel << 3; adc->buffer[1] = 0; - ret = spi_write(adc->spi, &adc->buffer, 2); - if (ret < 0) { - mutex_unlock(&adc->lock); + ret = spi_write(adc->spi, &adc->buffer, sizeof(adc->buffer)); + if (ret < 0) return ret; - } - - ret = spi_read(adc->spi, &adc->buffer, 2); - - mutex_unlock(&adc->lock); + ret = spi_read(adc->spi, &adc->buffer16, sizeof(adc->buffer16)); if (ret < 0) return ret; - return ((adc->buffer[0] << 8 | adc->buffer[1]) & 0xFFF); + return be16_to_cpu(adc->buffer16) & 0xFFF; } static int adc128_read_raw(struct iio_dev *indio_dev, @@ -75,11 +80,7 @@ static int adc128_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: - ret = regulator_get_voltage(adc->reg); - if (ret < 0) - return ret; - - *val = ret / 1000; + *val = adc->vref_mv; *val2 = 12; return IIO_VAL_FRACTIONAL_LOG2; @@ -121,21 +122,34 @@ static const struct iio_chan_spec adc124s021_channels[] = { ADC128_VOLTAGE_CHANNEL(3), }; +static const char * const bd79104_regulators[] = { "iovdd" }; + static const struct adc128_configuration adc128_config[] = { - { adc128s052_channels, ARRAY_SIZE(adc128s052_channels) }, - { adc122s021_channels, ARRAY_SIZE(adc122s021_channels) }, - { adc124s021_channels, ARRAY_SIZE(adc124s021_channels) }, + { + .channels = adc128s052_channels, + .num_channels = ARRAY_SIZE(adc128s052_channels), + .refname = "vref", + }, { + .channels = adc122s021_channels, + .num_channels = ARRAY_SIZE(adc122s021_channels), + .refname = "vref", + }, { + .channels = adc124s021_channels, + .num_channels = ARRAY_SIZE(adc124s021_channels), + .refname = "vref", + }, { + .channels = adc128s052_channels, + .num_channels = ARRAY_SIZE(adc128s052_channels), + .refname = "vdd", + .other_regulators = &bd79104_regulators, + .num_other_regulators = 1, + }, }; static const struct iio_info adc128_info = { .read_raw = adc128_read_raw, }; -static void adc128_disable_regulator(void *reg) -{ - regulator_disable(reg); -} - static int adc128_probe(struct spi_device *spi) { const struct adc128_configuration *config; @@ -159,20 +173,28 @@ static int adc128_probe(struct spi_device *spi) indio_dev->channels = config->channels; indio_dev->num_channels = config->num_channels; - adc->reg = devm_regulator_get(&spi->dev, "vref"); - if (IS_ERR(adc->reg)) - return PTR_ERR(adc->reg); - - ret = regulator_enable(adc->reg); + ret = devm_regulator_get_enable_read_voltage(&spi->dev, + config->refname); if (ret < 0) - return ret; - ret = devm_add_action_or_reset(&spi->dev, adc128_disable_regulator, - adc->reg); + return dev_err_probe(&spi->dev, ret, + "failed to read '%s' voltage", + config->refname); + + adc->vref_mv = ret / 1000; + + if (config->num_other_regulators) { + ret = devm_regulator_bulk_get_enable(&spi->dev, + config->num_other_regulators, + *config->other_regulators); + if (ret) + return dev_err_probe(&spi->dev, ret, + "Failed to enable regulators\n"); + } + + ret = devm_mutex_init(&spi->dev, &adc->lock); if (ret) return ret; - mutex_init(&adc->lock); - return devm_iio_device_register(&spi->dev, indio_dev); } @@ -184,7 +206,8 @@ static const struct of_device_id adc128_of_match[] = { { .compatible = "ti,adc124s021", .data = &adc128_config[2] }, { .compatible = "ti,adc124s051", .data = &adc128_config[2] }, { .compatible = "ti,adc124s101", .data = &adc128_config[2] }, - { /* sentinel */ }, + { .compatible = "rohm,bd79104", .data = &adc128_config[3] }, + { } }; MODULE_DEVICE_TABLE(of, adc128_of_match); @@ -196,6 +219,7 @@ static const struct spi_device_id adc128_id[] = { { "adc124s021", (kernel_ulong_t)&adc128_config[2] }, { "adc124s051", (kernel_ulong_t)&adc128_config[2] }, { "adc124s101", (kernel_ulong_t)&adc128_config[2] }, + { "bd79104", (kernel_ulong_t)&adc128_config[3] }, { } }; MODULE_DEVICE_TABLE(spi, adc128_id); diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c index 4355726b373a..21181cc3bd85 100644 --- a/drivers/iio/adc/ti-ads1015.c +++ b/drivers/iio/adc/ti-ads1015.c @@ -12,6 +12,7 @@ */ #include <linux/module.h> +#include <linux/cleanup.h> #include <linux/init.h> #include <linux/irq.h> #include <linux/i2c.h> @@ -466,8 +467,8 @@ static irqreturn_t ads1015_trigger_handler(int irq, void *p) scan.chan = res; mutex_unlock(&data->lock); - iio_push_to_buffers_with_timestamp(indio_dev, &scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &scan, sizeof(scan), + iio_get_time_ns(indio_dev)); err: iio_trigger_notify_done(indio_dev->trig); @@ -533,6 +534,31 @@ static int ads1015_read_avail(struct iio_dev *indio_dev, } } +static int __ads1015_read_info_raw(struct ads1015_data *data, + struct iio_chan_spec const *chan, int *val) +{ + int ret; + + if (ads1015_event_channel_enabled(data) && + data->event_channel != chan->address) + return -EBUSY; + + ret = ads1015_set_power_state(data, true); + if (ret < 0) + return ret; + + ret = ads1015_get_adc_result(data, chan->address, val); + if (ret < 0) { + ads1015_set_power_state(data, false); + return ret; + } + + *val = sign_extend32(*val >> chan->scan_type.shift, + chan->scan_type.realbits - 1); + + return ads1015_set_power_state(data, false); +} + static int ads1015_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -540,58 +566,29 @@ static int ads1015_read_raw(struct iio_dev *indio_dev, int ret, idx; struct ads1015_data *data = iio_priv(indio_dev); - mutex_lock(&data->lock); + guard(mutex)(&data->lock); switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + ret = __ads1015_read_info_raw(data, chan, val); + iio_device_release_direct(indio_dev); if (ret) - break; - - if (ads1015_event_channel_enabled(data) && - data->event_channel != chan->address) { - ret = -EBUSY; - goto release_direct; - } - - ret = ads1015_set_power_state(data, true); - if (ret < 0) - goto release_direct; - - ret = ads1015_get_adc_result(data, chan->address, val); - if (ret < 0) { - ads1015_set_power_state(data, false); - goto release_direct; - } - - *val = sign_extend32(*val >> chan->scan_type.shift, - chan->scan_type.realbits - 1); - - ret = ads1015_set_power_state(data, false); - if (ret < 0) - goto release_direct; + return ret; - ret = IIO_VAL_INT; -release_direct: - iio_device_release_direct_mode(indio_dev); - break; + return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: idx = data->channel_data[chan->address].pga; *val = ads1015_fullscale_range[idx]; *val2 = chan->scan_type.realbits - 1; - ret = IIO_VAL_FRACTIONAL_LOG2; - break; + return IIO_VAL_FRACTIONAL_LOG2; case IIO_CHAN_INFO_SAMP_FREQ: idx = data->channel_data[chan->address].data_rate; *val = data->chip->data_rate[idx]; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; default: - ret = -EINVAL; - break; + return -EINVAL; } - mutex_unlock(&data->lock); - - return ret; } static int ads1015_write_raw(struct iio_dev *indio_dev, @@ -599,23 +596,16 @@ static int ads1015_write_raw(struct iio_dev *indio_dev, int val2, long mask) { struct ads1015_data *data = iio_priv(indio_dev); - int ret; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); switch (mask) { case IIO_CHAN_INFO_SCALE: - ret = ads1015_set_scale(data, chan, val, val2); - break; + return ads1015_set_scale(data, chan, val, val2); case IIO_CHAN_INFO_SAMP_FREQ: - ret = ads1015_set_data_rate(data, chan->address, val); - break; + return ads1015_set_data_rate(data, chan->address, val); default: - ret = -EINVAL; - break; + return -EINVAL; } - mutex_unlock(&data->lock); - - return ret; } static int ads1015_read_event(struct iio_dev *indio_dev, @@ -624,20 +614,18 @@ static int ads1015_read_event(struct iio_dev *indio_dev, int *val2) { struct ads1015_data *data = iio_priv(indio_dev); - int ret; unsigned int comp_queue; int period; int dr; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); switch (info) { case IIO_EV_INFO_VALUE: *val = (dir == IIO_EV_DIR_RISING) ? data->thresh_data[chan->address].high_thresh : data->thresh_data[chan->address].low_thresh; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; case IIO_EV_INFO_PERIOD: dr = data->channel_data[chan->address].data_rate; comp_queue = data->thresh_data[chan->address].comp_queue; @@ -646,16 +634,10 @@ static int ads1015_read_event(struct iio_dev *indio_dev, *val = period / USEC_PER_SEC; *val2 = period % USEC_PER_SEC; - ret = IIO_VAL_INT_PLUS_MICRO; - break; + return IIO_VAL_INT_PLUS_MICRO; default: - ret = -EINVAL; - break; + return -EINVAL; } - - mutex_unlock(&data->lock); - - return ret; } static int ads1015_write_event(struct iio_dev *indio_dev, @@ -666,24 +648,22 @@ static int ads1015_write_event(struct iio_dev *indio_dev, struct ads1015_data *data = iio_priv(indio_dev); const int *data_rate = data->chip->data_rate; int realbits = chan->scan_type.realbits; - int ret = 0; long long period; int i; int dr; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); switch (info) { case IIO_EV_INFO_VALUE: - if (val >= 1 << (realbits - 1) || val < -1 << (realbits - 1)) { - ret = -EINVAL; - break; - } + if (val >= 1 << (realbits - 1) || val < -1 << (realbits - 1)) + return -EINVAL; + if (dir == IIO_EV_DIR_RISING) data->thresh_data[chan->address].high_thresh = val; else data->thresh_data[chan->address].low_thresh = val; - break; + return 0; case IIO_EV_INFO_PERIOD: dr = data->channel_data[chan->address].data_rate; period = val * USEC_PER_SEC + val2; @@ -694,15 +674,10 @@ static int ads1015_write_event(struct iio_dev *indio_dev, break; } data->thresh_data[chan->address].comp_queue = i; - break; + return 0; default: - ret = -EINVAL; - break; + return -EINVAL; } - - mutex_unlock(&data->lock); - - return ret; } static int ads1015_read_event_config(struct iio_dev *indio_dev, @@ -710,25 +685,19 @@ static int ads1015_read_event_config(struct iio_dev *indio_dev, enum iio_event_direction dir) { struct ads1015_data *data = iio_priv(indio_dev); - int ret = 0; - mutex_lock(&data->lock); - if (data->event_channel == chan->address) { - switch (dir) { - case IIO_EV_DIR_RISING: - ret = 1; - break; - case IIO_EV_DIR_EITHER: - ret = (data->comp_mode == ADS1015_CFG_COMP_MODE_WINDOW); - break; - default: - ret = -EINVAL; - break; - } - } - mutex_unlock(&data->lock); + guard(mutex)(&data->lock); + if (data->event_channel != chan->address) + return 0; - return ret; + switch (dir) { + case IIO_EV_DIR_RISING: + return 1; + case IIO_EV_DIR_EITHER: + return (data->comp_mode == ADS1015_CFG_COMP_MODE_WINDOW); + default: + return -EINVAL; + } } static int ads1015_enable_event_config(struct ads1015_data *data, @@ -813,23 +782,18 @@ static int ads1015_write_event_config(struct iio_dev *indio_dev, int comp_mode = (dir == IIO_EV_DIR_EITHER) ? ADS1015_CFG_COMP_MODE_WINDOW : ADS1015_CFG_COMP_MODE_TRAD; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); /* Prevent from enabling both buffer and event at a time */ - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) { - mutex_unlock(&data->lock); - return ret; - } + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; if (state) ret = ads1015_enable_event_config(data, chan, comp_mode); else ret = ads1015_disable_event_config(data, chan, comp_mode); - iio_device_release_direct_mode(indio_dev); - mutex_unlock(&data->lock); - + iio_device_release_direct(indio_dev); return ret; } diff --git a/drivers/iio/adc/ti-ads1100.c b/drivers/iio/adc/ti-ads1100.c index 1e46f07a9ca6..b0790e300b18 100644 --- a/drivers/iio/adc/ti-ads1100.c +++ b/drivers/iio/adc/ti-ads1100.c @@ -10,6 +10,7 @@ #include <linux/bitfield.h> #include <linux/bits.h> +#include <linux/cleanup.h> #include <linux/delay.h> #include <linux/module.h> #include <linux/init.h> @@ -219,36 +220,30 @@ static int ads1100_read_raw(struct iio_dev *indio_dev, int ret; struct ads1100_data *data = iio_priv(indio_dev); - mutex_lock(&data->lock); + guard(mutex)(&data->lock); switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - break; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = ads1100_get_adc_result(data, chan->address, val); - if (ret >= 0) - ret = IIO_VAL_INT; - iio_device_release_direct_mode(indio_dev); - break; + iio_device_release_direct(indio_dev); + if (ret < 0) + return ret; + + return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: /* full-scale is the supply voltage in millivolts */ *val = ads1100_get_vdd_millivolts(data); *val2 = 15 + FIELD_GET(ADS1100_PGA_MASK, data->config); - ret = IIO_VAL_FRACTIONAL_LOG2; - break; + return IIO_VAL_FRACTIONAL_LOG2; case IIO_CHAN_INFO_SAMP_FREQ: *val = ads1100_data_rate[FIELD_GET(ADS1100_DR_MASK, data->config)]; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; default: - ret = -EINVAL; - break; + return -EINVAL; } - mutex_unlock(&data->lock); - - return ret; } static int ads1100_write_raw(struct iio_dev *indio_dev, @@ -256,23 +251,16 @@ static int ads1100_write_raw(struct iio_dev *indio_dev, int val2, long mask) { struct ads1100_data *data = iio_priv(indio_dev); - int ret; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); switch (mask) { case IIO_CHAN_INFO_SCALE: - ret = ads1100_set_scale(data, val, val2); - break; + return ads1100_set_scale(data, val, val2); case IIO_CHAN_INFO_SAMP_FREQ: - ret = ads1100_set_data_rate(data, chan->address, val); - break; + return ads1100_set_data_rate(data, chan->address, val); default: - ret = -EINVAL; - break; + return -EINVAL; } - mutex_unlock(&data->lock); - - return ret; } static const struct iio_info ads1100_info = { diff --git a/drivers/iio/adc/ti-ads1119.c b/drivers/iio/adc/ti-ads1119.c index f120e7e21cff..d280c949cf47 100644 --- a/drivers/iio/adc/ti-ads1119.c +++ b/drivers/iio/adc/ti-ads1119.c @@ -534,8 +534,8 @@ static irqreturn_t ads1119_trigger_handler(int irq, void *private) scan.sample = ret; - iio_push_to_buffers_with_timestamp(indio_dev, &scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &scan, sizeof(scan), + iio_get_time_ns(indio_dev)); done: iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; diff --git a/drivers/iio/adc/ti-ads124s08.c b/drivers/iio/adc/ti-ads124s08.c index 77c299bb4ebc..8ea1269f74db 100644 --- a/drivers/iio/adc/ti-ads124s08.c +++ b/drivers/iio/adc/ti-ads124s08.c @@ -297,8 +297,8 @@ static irqreturn_t ads124s_trigger_handler(int irq, void *p) j++; } - iio_push_to_buffers_with_timestamp(indio_dev, priv->buffer, - pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, priv->buffer, sizeof(priv->buffer), + pf->timestamp); iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/adc/ti-ads131e08.c b/drivers/iio/adc/ti-ads131e08.c index c6096b64664e..085f0d6fb39e 100644 --- a/drivers/iio/adc/ti-ads131e08.c +++ b/drivers/iio/adc/ti-ads131e08.c @@ -664,8 +664,8 @@ static irqreturn_t ads131e08_trigger_handler(int irq, void *private) i++; } - iio_push_to_buffers_with_timestamp(indio_dev, st->tmp_buf.data, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &st->tmp_buf, sizeof(st->tmp_buf), + iio_get_time_ns(indio_dev)); out: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c index af28672aa803..0356ccf23fea 100644 --- a/drivers/iio/adc/ti-ads7950.c +++ b/drivers/iio/adc/ti-ads7950.c @@ -403,10 +403,11 @@ static const struct iio_info ti_ads7950_info = { .update_scan_mode = ti_ads7950_update_scan_mode, }; -static void ti_ads7950_set(struct gpio_chip *chip, unsigned int offset, - int value) +static int ti_ads7950_set(struct gpio_chip *chip, unsigned int offset, + int value) { struct ti_ads7950_state *st = gpiochip_get_data(chip); + int ret; mutex_lock(&st->slock); @@ -416,9 +417,11 @@ static void ti_ads7950_set(struct gpio_chip *chip, unsigned int offset, st->cmd_settings_bitmask &= ~BIT(offset); st->single_tx = TI_ADS7950_MAN_CMD_SETTINGS(st); - spi_sync(st->spi, &st->scan_single_msg); + ret = spi_sync(st->spi, &st->scan_single_msg); mutex_unlock(&st->slock); + + return ret; } static int ti_ads7950_get(struct gpio_chip *chip, unsigned int offset) @@ -499,7 +502,11 @@ static int ti_ads7950_direction_input(struct gpio_chip *chip, static int ti_ads7950_direction_output(struct gpio_chip *chip, unsigned int offset, int value) { - ti_ads7950_set(chip, offset, value); + int ret; + + ret = ti_ads7950_set(chip, offset, value); + if (ret) + return ret; return _ti_ads7950_set_direction(chip, offset, 0); } @@ -641,7 +648,7 @@ static int ti_ads7950_probe(struct spi_device *spi) st->chip.direction_input = ti_ads7950_direction_input; st->chip.direction_output = ti_ads7950_direction_output; st->chip.get = ti_ads7950_get; - st->chip.set = ti_ads7950_set; + st->chip.set_rv = ti_ads7950_set; ret = gpiochip_add_data(&st->chip, st); if (ret) { diff --git a/drivers/iio/adc/ti-ads8688.c b/drivers/iio/adc/ti-ads8688.c index a31658b760a4..b0bf46cae0b6 100644 --- a/drivers/iio/adc/ti-ads8688.c +++ b/drivers/iio/adc/ti-ads8688.c @@ -389,8 +389,8 @@ static irqreturn_t ads8688_trigger_handler(int irq, void *p) j++; } - iio_push_to_buffers_with_timestamp(indio_dev, buffer, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, buffer, sizeof(buffer), + iio_get_time_ns(indio_dev)); iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/adc/ti-lmp92064.c b/drivers/iio/adc/ti-lmp92064.c index 1e4a78677fe5..3f375c1f586c 100644 --- a/drivers/iio/adc/ti-lmp92064.c +++ b/drivers/iio/adc/ti-lmp92064.c @@ -209,8 +209,8 @@ static irqreturn_t lmp92064_trigger_handler(int irq, void *p) if (ret) goto err; - iio_push_to_buffers_with_timestamp(indio_dev, &data, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &data, sizeof(data), + iio_get_time_ns(indio_dev)); err: iio_trigger_notify_done(indio_dev->trig); @@ -366,7 +366,7 @@ MODULE_DEVICE_TABLE(spi, lmp92064_id_table); static const struct of_device_id lmp92064_of_table[] = { { .compatible = "ti,lmp92064" }, - {} + { } }; MODULE_DEVICE_TABLE(of, lmp92064_of_table); diff --git a/drivers/iio/adc/ti-tlc4541.c b/drivers/iio/adc/ti-tlc4541.c index 5a138be983ed..f67945c62c99 100644 --- a/drivers/iio/adc/ti-tlc4541.c +++ b/drivers/iio/adc/ti-tlc4541.c @@ -99,8 +99,8 @@ static irqreturn_t tlc4541_trigger_handler(int irq, void *p) if (ret < 0) goto done; - iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, st->rx_buf, sizeof(st->rx_buf), + iio_get_time_ns(indio_dev)); done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/adc/ti-tsc2046.c b/drivers/iio/adc/ti-tsc2046.c index 49560059f4b7..c2d2aada6772 100644 --- a/drivers/iio/adc/ti-tsc2046.c +++ b/drivers/iio/adc/ti-tsc2046.c @@ -418,8 +418,9 @@ static int tsc2046_adc_scan(struct iio_dev *indio_dev) for (group = 0; group < priv->groups; group++) priv->scan_buf.data[group] = tsc2046_adc_get_val(priv, group); - ret = iio_push_to_buffers_with_timestamp(indio_dev, &priv->scan_buf, - iio_get_time_ns(indio_dev)); + ret = iio_push_to_buffers_with_ts(indio_dev, &priv->scan_buf, + sizeof(priv->scan_buf), + iio_get_time_ns(indio_dev)); /* If the consumer is kfifo, we may get a EBUSY here - ignore it. */ if (ret < 0 && ret != -EBUSY) { dev_err_ratelimited(dev, "Failed to push scan buffer %pe\n", @@ -760,7 +761,6 @@ static int tsc2046_adc_probe(struct spi_device *spi) if (!dcfg) return -EINVAL; - spi->bits_per_word = 8; spi->mode &= ~SPI_MODE_X_MASK; spi->mode |= SPI_MODE_0; ret = spi_setup(spi); diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c index ef7430e6877d..3ac774ebf678 100644 --- a/drivers/iio/adc/twl6030-gpadc.c +++ b/drivers/iio/adc/twl6030-gpadc.c @@ -871,7 +871,7 @@ static const struct of_device_id of_twl6030_match_tbl[] = { .compatible = "ti,twl6032-gpadc", .data = &twl6032_pdata, }, - { /* end */ } + { } }; MODULE_DEVICE_TABLE(of, of_twl6030_match_tbl); diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c index 513365d42aa5..6404b015234a 100644 --- a/drivers/iio/adc/vf610_adc.c +++ b/drivers/iio/adc/vf610_adc.c @@ -11,6 +11,7 @@ #include <linux/property.h> #include <linux/platform_device.h> #include <linux/interrupt.h> +#include <linux/cleanup.h> #include <linux/delay.h> #include <linux/kernel.h> #include <linux/slab.h> @@ -504,7 +505,7 @@ static const struct iio_enum vf610_conversion_mode = { static const struct iio_chan_spec_ext_info vf610_ext_info[] = { IIO_ENUM("conversion_mode", IIO_SHARED_BY_DIR, &vf610_conversion_mode), - {}, + { } }; #define VF610_ADC_CHAN(_idx, _chan_type) { \ @@ -591,9 +592,9 @@ static irqreturn_t vf610_adc_isr(int irq, void *dev_id) info->value = vf610_adc_read_data(info); if (iio_buffer_enabled(indio_dev)) { info->scan.chan = info->value; - iio_push_to_buffers_with_timestamp(indio_dev, - &info->scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &info->scan, + sizeof(info->scan), + iio_get_time_ns(indio_dev)); iio_trigger_notify_done(indio_dev->trig); } else complete(&info->completion); @@ -630,36 +631,29 @@ static const struct attribute_group vf610_attribute_group = { .attrs = vf610_attributes, }; -static int vf610_read_sample(struct iio_dev *indio_dev, +static int vf610_read_sample(struct vf610_adc *info, struct iio_chan_spec const *chan, int *val) { - struct vf610_adc *info = iio_priv(indio_dev); unsigned int hc_cfg; int ret; - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; - - mutex_lock(&info->lock); + guard(mutex)(&info->lock); reinit_completion(&info->completion); hc_cfg = VF610_ADC_ADCHC(chan->channel); hc_cfg |= VF610_ADC_AIEN; writel(hc_cfg, info->regs + VF610_REG_ADC_HC0); ret = wait_for_completion_interruptible_timeout(&info->completion, VF610_ADC_TIMEOUT); - if (ret == 0) { - ret = -ETIMEDOUT; - goto out_unlock; - } + if (ret == 0) + return -ETIMEDOUT; if (ret < 0) - goto out_unlock; + return ret; switch (chan->type) { case IIO_VOLTAGE: *val = info->value; - break; + return 0; case IIO_TEMP: /* * Calculate in degree Celsius times 1000 @@ -669,17 +663,10 @@ static int vf610_read_sample(struct iio_dev *indio_dev, *val = 25000 - ((int)info->value - VF610_VTEMP25_3V3) * 1000000 / VF610_TEMP_SLOPE_COEFF; - break; + return 0; default: - ret = -EINVAL; - break; + return -EINVAL; } - -out_unlock: - mutex_unlock(&info->lock); - iio_device_release_direct_mode(indio_dev); - - return ret; } static int vf610_read_raw(struct iio_dev *indio_dev, @@ -694,7 +681,10 @@ static int vf610_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_PROCESSED: - ret = vf610_read_sample(indio_dev, chan, val); + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + ret = vf610_read_sample(info, chan, val); + iio_device_release_direct(indio_dev); if (ret < 0) return ret; @@ -823,7 +813,7 @@ static const struct vf610_chip_info imx6sx_chip_info = { static const struct of_device_id vf610_adc_match[] = { { .compatible = "fsl,imx6sx-adc", .data = &imx6sx_chip_info}, { .compatible = "fsl,vf610-adc", .data = &vf610_chip_info}, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, vf610_adc_match); diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c index e1f8740ae688..e257c1b94a5f 100644 --- a/drivers/iio/adc/xilinx-xadc-core.c +++ b/drivers/iio/adc/xilinx-xadc-core.c @@ -1186,7 +1186,7 @@ static const struct of_device_id xadc_of_match_table[] = { .compatible = "xlnx,system-management-wiz-1.3", .data = &xadc_us_axi_ops }, - { }, + { } }; MODULE_DEVICE_TABLE(of, xadc_of_match_table); diff --git a/drivers/iio/addac/ad74115.c b/drivers/iio/addac/ad74115.c index a7e480f2472d..4d8b64048e4f 100644 --- a/drivers/iio/addac/ad74115.c +++ b/drivers/iio/addac/ad74115.c @@ -542,18 +542,16 @@ static int ad74115_gpio_get(struct gpio_chip *gc, unsigned int offset) return FIELD_GET(AD74115_GPIO_CONFIG_GPI_DATA, val); } -static void ad74115_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) +static int ad74115_gpio_set(struct gpio_chip *gc, unsigned int offset, + int value) { struct ad74115_state *st = gpiochip_get_data(gc); - struct device *dev = &st->spi->dev; - int ret; - ret = regmap_update_bits(st->regmap, AD74115_GPIO_CONFIG_X_REG(offset), - AD74115_GPIO_CONFIG_GPO_DATA, - FIELD_PREP(AD74115_GPIO_CONFIG_GPO_DATA, value)); - if (ret) - dev_err(dev, "Failed to set GPIO %u output value, err: %d\n", - offset, ret); + return regmap_update_bits(st->regmap, + AD74115_GPIO_CONFIG_X_REG(offset), + AD74115_GPIO_CONFIG_GPO_DATA, + FIELD_PREP(AD74115_GPIO_CONFIG_GPO_DATA, + value)); } static int ad74115_set_comp_debounce(struct ad74115_state *st, unsigned int val) @@ -866,15 +864,14 @@ static int ad74115_get_adc_code(struct iio_dev *indio_dev, struct ad74115_state *st = iio_priv(indio_dev); int ret; - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; mutex_lock(&st->lock); ret = _ad74115_get_adc_code(st, channel, val); mutex_unlock(&st->lock); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; } @@ -1580,7 +1577,7 @@ static int ad74115_setup_gpio_chip(struct ad74115_state *st) .direction_input = ad74115_gpio_direction_input, .direction_output = ad74115_gpio_direction_output, .get = ad74115_gpio_get, - .set = ad74115_gpio_set, + .set_rv = ad74115_gpio_set, }; return devm_gpiochip_add_data(dev, &st->gc, st); diff --git a/drivers/iio/addac/ad74413r.c b/drivers/iio/addac/ad74413r.c index f14d12b03da6..a0bb1dbcb7ad 100644 --- a/drivers/iio/addac/ad74413r.c +++ b/drivers/iio/addac/ad74413r.c @@ -4,7 +4,6 @@ * Author: Cosmin Tanislav <cosmin.tanislav@analog.com> */ -#include <linux/unaligned.h> #include <linux/bitfield.h> #include <linux/cleanup.h> #include <linux/crc8.h> @@ -24,6 +23,8 @@ #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/spi/spi.h> +#include <linux/types.h> +#include <linux/unaligned.h> #include <dt-bindings/iio/addac/adi,ad74413r.h> @@ -84,7 +85,7 @@ struct ad74413r_state { */ struct { u8 rx_buf[AD74413R_FRAME_SIZE * AD74413R_CHANNEL_MAX]; - s64 timestamp; + aligned_s64 timestamp; } adc_samples_buf __aligned(IIO_DMA_MINALIGN); u8 adc_samples_tx_buf[AD74413R_FRAME_SIZE * AD74413R_CHANNEL_MAX]; @@ -276,8 +277,8 @@ static int ad74413r_set_comp_drive_strength(struct ad74413r_state *st, } -static void ad74413r_gpio_set(struct gpio_chip *chip, - unsigned int offset, int val) +static int ad74413r_gpio_set(struct gpio_chip *chip, unsigned int offset, + int val) { struct ad74413r_state *st = gpiochip_get_data(chip); unsigned int real_offset = st->gpo_gpio_offsets[offset]; @@ -286,16 +287,16 @@ static void ad74413r_gpio_set(struct gpio_chip *chip, ret = ad74413r_set_gpo_config(st, real_offset, AD74413R_GPO_CONFIG_LOGIC); if (ret) - return; + return ret; - regmap_update_bits(st->regmap, AD74413R_REG_GPO_CONFIG_X(real_offset), - AD74413R_GPO_CONFIG_DATA_MASK, - val ? AD74413R_GPO_CONFIG_DATA_MASK : 0); + return regmap_update_bits(st->regmap, + AD74413R_REG_GPO_CONFIG_X(real_offset), + AD74413R_GPO_CONFIG_DATA_MASK, + val ? AD74413R_GPO_CONFIG_DATA_MASK : 0); } -static void ad74413r_gpio_set_multiple(struct gpio_chip *chip, - unsigned long *mask, - unsigned long *bits) +static int ad74413r_gpio_set_multiple(struct gpio_chip *chip, + unsigned long *mask, unsigned long *bits) { struct ad74413r_state *st = gpiochip_get_data(chip); unsigned long real_mask = 0; @@ -309,15 +310,15 @@ static void ad74413r_gpio_set_multiple(struct gpio_chip *chip, ret = ad74413r_set_gpo_config(st, real_offset, AD74413R_GPO_CONFIG_LOGIC_PARALLEL); if (ret) - return; + return ret; real_mask |= BIT(real_offset); if (*bits & offset) real_bits |= BIT(real_offset); } - regmap_update_bits(st->regmap, AD74413R_REG_GPO_PAR_DATA, - real_mask, real_bits); + return regmap_update_bits(st->regmap, AD74413R_REG_GPO_PAR_DATA, + real_mask, real_bits); } static int ad74413r_gpio_get(struct gpio_chip *chip, unsigned int offset) @@ -1424,8 +1425,8 @@ static int ad74413r_probe(struct spi_device *spi) st->gpo_gpiochip.ngpio = st->num_gpo_gpios; st->gpo_gpiochip.parent = st->dev; st->gpo_gpiochip.can_sleep = true; - st->gpo_gpiochip.set = ad74413r_gpio_set; - st->gpo_gpiochip.set_multiple = ad74413r_gpio_set_multiple; + st->gpo_gpiochip.set_rv = ad74413r_gpio_set; + st->gpo_gpiochip.set_multiple_rv = ad74413r_gpio_set_multiple; st->gpo_gpiochip.set_config = ad74413r_gpio_set_gpo_config; st->gpo_gpiochip.get_direction = ad74413r_gpio_get_gpo_direction; @@ -1505,14 +1506,14 @@ static const struct of_device_id ad74413r_dt_id[] = { .compatible = "adi,ad74413r", .data = &ad74413r_chip_info_data, }, - {}, + { } }; MODULE_DEVICE_TABLE(of, ad74413r_dt_id); static const struct spi_device_id ad74413r_spi_id[] = { { .name = "ad74412r", .driver_data = (kernel_ulong_t)&ad74412r_chip_info_data }, { .name = "ad74413r", .driver_data = (kernel_ulong_t)&ad74413r_chip_info_data }, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad74413r_spi_id); diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c index b6a46036d5ea..ecaf59278c6f 100644 --- a/drivers/iio/afe/iio-rescale.c +++ b/drivers/iio/afe/iio-rescale.c @@ -514,7 +514,7 @@ static const struct of_device_id rescale_match[] = { .data = &rescale_cfg[TEMP_SENSE_RTD], }, { .compatible = "temperature-transducer", .data = &rescale_cfg[TEMP_TRANSDUCER], }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, rescale_match); diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c index 31564afb13a2..e73c9b983395 100644 --- a/drivers/iio/amplifiers/ad8366.c +++ b/drivers/iio/amplifiers/ad8366.c @@ -330,7 +330,7 @@ static const struct spi_device_id ad8366_id[] = { {"adl5240", ID_ADL5240}, {"hmc792a", ID_HMC792}, {"hmc1119", ID_HMC1119}, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad8366_id); diff --git a/drivers/iio/amplifiers/ada4250.c b/drivers/iio/amplifiers/ada4250.c index 566f0e1c98a5..74f8429d652b 100644 --- a/drivers/iio/amplifiers/ada4250.c +++ b/drivers/iio/amplifiers/ada4250.c @@ -378,13 +378,13 @@ static int ada4250_probe(struct spi_device *spi) static const struct spi_device_id ada4250_id[] = { { "ada4250", 0 }, - {} + { } }; MODULE_DEVICE_TABLE(spi, ada4250_id); static const struct of_device_id ada4250_of_match[] = { { .compatible = "adi,ada4250" }, - {}, + { } }; MODULE_DEVICE_TABLE(of, ada4250_of_match); diff --git a/drivers/iio/amplifiers/hmc425a.c b/drivers/iio/amplifiers/hmc425a.c index d9a359e1388a..4dbf894c7e3b 100644 --- a/drivers/iio/amplifiers/hmc425a.c +++ b/drivers/iio/amplifiers/hmc425a.c @@ -270,7 +270,7 @@ static const struct iio_chan_spec_ext_info ltc6373_ext_info[] = { .write = ltc6373_write_powerdown, .shared = IIO_SEPARATE, }, - {} + { } }; #define HMC425A_CHAN(_channel) \ @@ -398,7 +398,6 @@ static int hmc425a_probe(struct platform_device *pdev) return devm_iio_device_register(&pdev->dev, indio_dev); } -/* Match table for of_platform binding */ static const struct of_device_id hmc425a_of_match[] = { { .compatible = "adi,hmc425a", .data = &hmc425a_chip_info_tbl[ID_HMC425A]}, @@ -408,7 +407,7 @@ static const struct of_device_id hmc425a_of_match[] = { .data = &hmc425a_chip_info_tbl[ID_ADRF5740]}, { .compatible = "adi,ltc6373", .data = &hmc425a_chip_info_tbl[ID_LTC6373]}, - {} + { } }; MODULE_DEVICE_TABLE(of, hmc425a_of_match); diff --git a/drivers/iio/cdc/ad7150.c b/drivers/iio/cdc/ad7150.c index e64a41bae32c..427d32e398b3 100644 --- a/drivers/iio/cdc/ad7150.c +++ b/drivers/iio/cdc/ad7150.c @@ -631,7 +631,7 @@ static const struct i2c_device_id ad7150_id[] = { { "ad7150", AD7150 }, { "ad7151", AD7151 }, { "ad7156", AD7150 }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, ad7150_id); @@ -640,7 +640,7 @@ static const struct of_device_id ad7150_of_match[] = { { "adi,ad7150" }, { "adi,ad7151" }, { "adi,ad7156" }, - {} + { } }; static struct i2c_driver ad7150_driver = { .driver = { diff --git a/drivers/iio/cdc/ad7746.c b/drivers/iio/cdc/ad7746.c index ba18dbbe0940..8a306d55c72a 100644 --- a/drivers/iio/cdc/ad7746.c +++ b/drivers/iio/cdc/ad7746.c @@ -792,7 +792,7 @@ static const struct i2c_device_id ad7746_id[] = { { "ad7745", 7745 }, { "ad7746", 7746 }, { "ad7747", 7747 }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, ad7746_id); @@ -800,7 +800,7 @@ static const struct of_device_id ad7746_of_match[] = { { .compatible = "adi,ad7745" }, { .compatible = "adi,ad7746" }, { .compatible = "adi,ad7747" }, - { }, + { } }; MODULE_DEVICE_TABLE(of, ad7746_of_match); diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig index 330fe0af946f..b22afa1f6d59 100644 --- a/drivers/iio/chemical/Kconfig +++ b/drivers/iio/chemical/Kconfig @@ -108,6 +108,16 @@ config IAQCORE iAQ-Core Continuous/Pulsed VOC (Volatile Organic Compounds) sensors +config MHZ19B + tristate "Winsen MHZ19B CO2 sensor" + depends on SERIAL_DEV_BUS + help + Say Y here to build Serdev interface support for the Winsen + MHZ19B CO2 sensor. + + To compile this driver as a module, choose M here: the module will + be called mhz19b. + config PMS7003 tristate "Plantower PMS7003 particulate matter sensor" depends on SERIAL_DEV_BUS @@ -166,6 +176,16 @@ config SCD4X To compile this driver as a module, choose M here: the module will be called scd4x. +config SEN0322 + tristate "SEN0322 oxygen sensor" + depends on I2C + select REGMAP_I2C + help + Say Y here to build support for the DFRobot SEN0322 oxygen sensor. + + To compile this driver as a module, choose M here: the module will + be called sen0322. + config SENSIRION_SGP30 tristate "Sensirion SGPxx gas sensors" depends on I2C diff --git a/drivers/iio/chemical/Makefile b/drivers/iio/chemical/Makefile index 4866db06bdc9..2287a00a6b75 100644 --- a/drivers/iio/chemical/Makefile +++ b/drivers/iio/chemical/Makefile @@ -15,11 +15,13 @@ obj-$(CONFIG_ENS160) += ens160_core.o obj-$(CONFIG_ENS160_I2C) += ens160_i2c.o obj-$(CONFIG_ENS160_SPI) += ens160_spi.o obj-$(CONFIG_IAQCORE) += ams-iaq-core.o +obj-$(CONFIG_MHZ19B) += mhz19b.o obj-$(CONFIG_PMS7003) += pms7003.o obj-$(CONFIG_SCD30_CORE) += scd30_core.o obj-$(CONFIG_SCD30_I2C) += scd30_i2c.o obj-$(CONFIG_SCD30_SERIAL) += scd30_serial.o obj-$(CONFIG_SCD4X) += scd4x.o +obj-$(CONFIG_SEN0322) += sen0322.o obj-$(CONFIG_SENSEAIR_SUNRISE_CO2) += sunrise_co2.o obj-$(CONFIG_SENSIRION_SGP30) += sgp30.o obj-$(CONFIG_SENSIRION_SGP40) += sgp40.o diff --git a/drivers/iio/chemical/ags02ma.c b/drivers/iio/chemical/ags02ma.c index 8fcd80946543..151178d4e8f4 100644 --- a/drivers/iio/chemical/ags02ma.c +++ b/drivers/iio/chemical/ags02ma.c @@ -140,13 +140,13 @@ static int ags02ma_probe(struct i2c_client *client) static const struct i2c_device_id ags02ma_id_table[] = { { "ags02ma" }, - { /* Sentinel */ } + { } }; MODULE_DEVICE_TABLE(i2c, ags02ma_id_table); static const struct of_device_id ags02ma_of_table[] = { { .compatible = "aosong,ags02ma" }, - { /* Sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, ags02ma_of_table); diff --git a/drivers/iio/chemical/atlas-ezo-sensor.c b/drivers/iio/chemical/atlas-ezo-sensor.c index 761a853a4d17..de0b87edd188 100644 --- a/drivers/iio/chemical/atlas-ezo-sensor.c +++ b/drivers/iio/chemical/atlas-ezo-sensor.c @@ -189,7 +189,7 @@ static const struct i2c_device_id atlas_ezo_id[] = { { "atlas-co2-ezo", (kernel_ulong_t)&atlas_ezo_devices[ATLAS_CO2_EZO] }, { "atlas-o2-ezo", (kernel_ulong_t)&atlas_ezo_devices[ATLAS_O2_EZO] }, { "atlas-hum-ezo", (kernel_ulong_t)&atlas_ezo_devices[ATLAS_HUM_EZO] }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, atlas_ezo_id); @@ -197,7 +197,7 @@ static const struct of_device_id atlas_ezo_dt_ids[] = { { .compatible = "atlas,co2-ezo", .data = &atlas_ezo_devices[ATLAS_CO2_EZO], }, { .compatible = "atlas,o2-ezo", .data = &atlas_ezo_devices[ATLAS_O2_EZO], }, { .compatible = "atlas,hum-ezo", .data = &atlas_ezo_devices[ATLAS_HUM_EZO], }, - {} + { } }; MODULE_DEVICE_TABLE(of, atlas_ezo_dt_ids); diff --git a/drivers/iio/chemical/atlas-sensor.c b/drivers/iio/chemical/atlas-sensor.c index baf93e5e3ca7..cb6662b92137 100644 --- a/drivers/iio/chemical/atlas-sensor.c +++ b/drivers/iio/chemical/atlas-sensor.c @@ -458,8 +458,9 @@ static irqreturn_t atlas_trigger_handler(int irq, void *private) &data->buffer, sizeof(__be32) * channels); if (!ret) - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, data->buffer, + sizeof(data->buffer), + iio_get_time_ns(indio_dev)); iio_trigger_notify_done(indio_dev->trig); @@ -518,13 +519,12 @@ static int atlas_read_raw(struct iio_dev *indio_dev, case IIO_CONCENTRATION: case IIO_ELECTRICALCONDUCTIVITY: case IIO_VOLTAGE: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = atlas_read_measurement(data, chan->address, ®); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); break; default: ret = -EINVAL; @@ -594,7 +594,7 @@ static const struct i2c_device_id atlas_id[] = { { "atlas-orp-sm", (kernel_ulong_t)&atlas_devices[ATLAS_ORP_SM] }, { "atlas-do-sm", (kernel_ulong_t)&atlas_devices[ATLAS_DO_SM] }, { "atlas-rtd-sm", (kernel_ulong_t)&atlas_devices[ATLAS_RTD_SM] }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, atlas_id); diff --git a/drivers/iio/chemical/bme680_core.c b/drivers/iio/chemical/bme680_core.c index 9d73fd2cf52c..3e850562ab00 100644 --- a/drivers/iio/chemical/bme680_core.c +++ b/drivers/iio/chemical/bme680_core.c @@ -1120,8 +1120,8 @@ static irqreturn_t bme680_trigger_handler(int irq, void *p) gas_range = FIELD_GET(BME680_GAS_RANGE_MASK, gas_regs_val); data->scan.chan[3] = bme680_compensate_gas(data, adc_gas_res, gas_range); - iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), + iio_get_time_ns(indio_dev)); out: iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; diff --git a/drivers/iio/chemical/bme680_i2c.c b/drivers/iio/chemical/bme680_i2c.c index ac7763f98a6a..5560ea708b36 100644 --- a/drivers/iio/chemical/bme680_i2c.c +++ b/drivers/iio/chemical/bme680_i2c.c @@ -37,13 +37,13 @@ static int bme680_i2c_probe(struct i2c_client *client) static const struct i2c_device_id bme680_i2c_id[] = { { "bme680" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, bme680_i2c_id); static const struct of_device_id bme680_of_i2c_match[] = { { .compatible = "bosch,bme680", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, bme680_of_i2c_match); diff --git a/drivers/iio/chemical/bme680_spi.c b/drivers/iio/chemical/bme680_spi.c index ecb24ba0ebc9..aa97645ba539 100644 --- a/drivers/iio/chemical/bme680_spi.c +++ b/drivers/iio/chemical/bme680_spi.c @@ -112,14 +112,6 @@ static int bme680_spi_probe(struct spi_device *spi) const struct spi_device_id *id = spi_get_device_id(spi); struct bme680_spi_bus_context *bus_context; struct regmap *regmap; - int ret; - - spi->bits_per_word = 8; - ret = spi_setup(spi); - if (ret < 0) { - dev_err(&spi->dev, "spi_setup failed!\n"); - return ret; - } bus_context = devm_kzalloc(&spi->dev, sizeof(*bus_context), GFP_KERNEL); if (!bus_context) @@ -140,13 +132,13 @@ static int bme680_spi_probe(struct spi_device *spi) static const struct spi_device_id bme680_spi_id[] = { {"bme680", 0}, - {}, + { } }; MODULE_DEVICE_TABLE(spi, bme680_spi_id); static const struct of_device_id bme680_of_spi_match[] = { { .compatible = "bosch,bme680", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, bme680_of_spi_match); diff --git a/drivers/iio/chemical/ccs811.c b/drivers/iio/chemical/ccs811.c index 451fb65dbe60..998c9239c4c7 100644 --- a/drivers/iio/chemical/ccs811.c +++ b/drivers/iio/chemical/ccs811.c @@ -15,6 +15,7 @@ * 4. Read error register and put the information in logs */ +#include <linux/cleanup.h> #include <linux/delay.h> #include <linux/gpio/consumer.h> #include <linux/i2c.h> @@ -214,6 +215,40 @@ static int ccs811_get_measurement(struct ccs811_data *data) return ret; } +static int ccs811_read_info_raw(struct ccs811_data *data, + struct iio_chan_spec const *chan, + int *val, int mask) +{ + int ret; + + guard(mutex)(&data->lock); + ret = ccs811_get_measurement(data); + if (ret < 0) + return ret; + + switch (chan->type) { + case IIO_VOLTAGE: + *val = be16_to_cpu(data->buffer.raw_data) & CCS811_VOLTAGE_MASK; + return IIO_VAL_INT; + case IIO_CURRENT: + *val = be16_to_cpu(data->buffer.raw_data) >> 10; + return IIO_VAL_INT; + case IIO_CONCENTRATION: + switch (chan->channel2) { + case IIO_MOD_CO2: + *val = be16_to_cpu(data->buffer.co2); + return IIO_VAL_INT; + case IIO_MOD_VOC: + *val = be16_to_cpu(data->buffer.voc); + return IIO_VAL_INT; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + static int ccs811_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -223,46 +258,12 @@ static int ccs811_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; - mutex_lock(&data->lock); - ret = ccs811_get_measurement(data); - if (ret < 0) { - mutex_unlock(&data->lock); - iio_device_release_direct_mode(indio_dev); - return ret; - } + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; - switch (chan->type) { - case IIO_VOLTAGE: - *val = be16_to_cpu(data->buffer.raw_data) & - CCS811_VOLTAGE_MASK; - ret = IIO_VAL_INT; - break; - case IIO_CURRENT: - *val = be16_to_cpu(data->buffer.raw_data) >> 10; - ret = IIO_VAL_INT; - break; - case IIO_CONCENTRATION: - switch (chan->channel2) { - case IIO_MOD_CO2: - *val = be16_to_cpu(data->buffer.co2); - ret = IIO_VAL_INT; - break; - case IIO_MOD_VOC: - *val = be16_to_cpu(data->buffer.voc); - ret = IIO_VAL_INT; - break; - default: - ret = -EINVAL; - } - break; - default: - ret = -EINVAL; - } - mutex_unlock(&data->lock); - iio_device_release_direct_mode(indio_dev); + ret = ccs811_read_info_raw(data, chan, val, mask); + + iio_device_release_direct(indio_dev); return ret; @@ -342,8 +343,8 @@ static irqreturn_t ccs811_trigger_handler(int irq, void *p) goto err; } - iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), + iio_get_time_ns(indio_dev)); err: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/chemical/ens160_core.c b/drivers/iio/chemical/ens160_core.c index 152f81ff57e3..6cec60074827 100644 --- a/drivers/iio/chemical/ens160_core.c +++ b/drivers/iio/chemical/ens160_core.c @@ -267,8 +267,8 @@ static irqreturn_t ens160_trigger_handler(int irq, void *p) if (ret) goto err; - iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, - pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), + pf->timestamp); err: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/chemical/mhz19b.c b/drivers/iio/chemical/mhz19b.c new file mode 100644 index 000000000000..3c64154918b1 --- /dev/null +++ b/drivers/iio/chemical/mhz19b.c @@ -0,0 +1,316 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * mh-z19b COâ‚‚ sensor driver + * + * Copyright (c) 2025 Gyeyoung Baek <gye976@gmail.com> + * + * Datasheet: + * https://www.winsen-sensor.com/d/files/infrared-gas-sensor/mh-z19b-co2-ver1_0.pdf + */ + +#include <linux/array_size.h> +#include <linux/completion.h> +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/iio/iio.h> +#include <linux/iio/sysfs.h> +#include <linux/jiffies.h> +#include <linux/kstrtox.h> +#include <linux/minmax.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/regulator/consumer.h> +#include <linux/serdev.h> +#include <linux/string.h> +#include <linux/types.h> +#include <linux/unaligned.h> + +/* + * Commands have following format: + * + * +------+------+-----+------+------+------+------+------+-------+ + * | 0xFF | 0x01 | cmd | arg0 | arg1 | 0x00 | 0x00 | 0x00 | cksum | + * +------+------+-----+------+------+------+------+------+-------+ + */ +#define MHZ19B_CMD_SIZE 9 + +/* ABC logic in MHZ19B means auto calibration. */ +#define MHZ19B_ABC_LOGIC_CMD 0x79 +#define MHZ19B_READ_CO2_CMD 0x86 +#define MHZ19B_SPAN_POINT_CMD 0x88 +#define MHZ19B_ZERO_POINT_CMD 0x87 + +#define MHZ19B_SPAN_POINT_PPM_MIN 1000 +#define MHZ19B_SPAN_POINT_PPM_MAX 5000 + +#define MHZ19B_SERDEV_TIMEOUT msecs_to_jiffies(100) + +struct mhz19b_state { + struct serdev_device *serdev; + + /* Must wait until the 'buf' is filled with 9 bytes.*/ + struct completion buf_ready; + + u8 buf_idx; + /* + * Serdev receive buffer. + * When data is received from the MH-Z19B, + * the 'mhz19b_receive_buf' callback function is called and fills this buffer. + */ + u8 buf[MHZ19B_CMD_SIZE] __aligned(IIO_DMA_MINALIGN); +}; + +static u8 mhz19b_get_checksum(u8 *cmd_buf) +{ + u8 i, checksum = 0; + +/* + * +------+------+-----+------+------+------+------+------+-------+ + * | 0xFF | 0x01 | cmd | arg0 | arg1 | 0x00 | 0x00 | 0x00 | cksum | + * +------+------+-----+------+------+------+------+------+-------+ + * i:1 2 3 4 5 6 7 + * + * Sum all cmd_buf elements from index 1 to 7. + */ + for (i = 1; i < 8; i++) + checksum += cmd_buf[i]; + + return -checksum; +} + +static int mhz19b_serdev_cmd(struct iio_dev *indio_dev, int cmd, u16 arg) +{ + struct mhz19b_state *st = iio_priv(indio_dev); + struct serdev_device *serdev = st->serdev; + struct device *dev = &indio_dev->dev; + int ret; + + /* + * cmd_buf[3,4] : arg0,1 + * cmd_buf[8] : checksum + */ + u8 cmd_buf[MHZ19B_CMD_SIZE] = { + 0xFF, 0x01, cmd, + }; + + switch (cmd) { + case MHZ19B_ABC_LOGIC_CMD: + cmd_buf[3] = arg ? 0xA0 : 0; + break; + case MHZ19B_SPAN_POINT_CMD: + put_unaligned_be16(arg, &cmd_buf[3]); + break; + default: + break; + } + cmd_buf[8] = mhz19b_get_checksum(cmd_buf); + + /* Write buf to uart ctrl synchronously */ + ret = serdev_device_write(serdev, cmd_buf, MHZ19B_CMD_SIZE, 0); + if (ret < 0) + return ret; + if (ret != MHZ19B_CMD_SIZE) + return -EIO; + + switch (cmd) { + case MHZ19B_READ_CO2_CMD: + ret = wait_for_completion_interruptible_timeout(&st->buf_ready, + MHZ19B_SERDEV_TIMEOUT); + if (ret < 0) + return ret; + if (!ret) + return -ETIMEDOUT; + + if (st->buf[8] != mhz19b_get_checksum(st->buf)) { + dev_err(dev, "checksum err"); + return -EINVAL; + } + + return get_unaligned_be16(&st->buf[2]); + default: + /* No response commands. */ + return 0; + } +} + +static int mhz19b_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + int ret; + + ret = mhz19b_serdev_cmd(indio_dev, MHZ19B_READ_CO2_CMD, 0); + if (ret < 0) + return ret; + + *val = ret; + return IIO_VAL_INT; +} + +/* + * echo 0 > calibration_auto_enable : ABC logic off + * echo 1 > calibration_auto_enable : ABC logic on + */ +static ssize_t calibration_auto_enable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + bool enable; + int ret; + + ret = kstrtobool(buf, &enable); + if (ret) + return ret; + + ret = mhz19b_serdev_cmd(indio_dev, MHZ19B_ABC_LOGIC_CMD, enable); + if (ret < 0) + return ret; + + return len; +} +static IIO_DEVICE_ATTR_WO(calibration_auto_enable, 0); + +/* + * echo 0 > calibration_forced_value : zero point calibration + * (make sure the sensor has been working under 400ppm for over 20 minutes.) + * echo [1000 1 5000] > calibration_forced_value : span point calibration + * (make sure the sensor has been working under a certain level COâ‚‚ for over 20 minutes.) + */ +static ssize_t calibration_forced_value_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + u16 ppm; + int cmd, ret; + + ret = kstrtou16(buf, 0, &ppm); + if (ret) + return ret; + + if (ppm) { + if (!in_range(ppm, MHZ19B_SPAN_POINT_PPM_MIN, + MHZ19B_SPAN_POINT_PPM_MAX - MHZ19B_SPAN_POINT_PPM_MIN + 1)) { + dev_dbg(&indio_dev->dev, + "span point ppm should be in a range [%d-%d]\n", + MHZ19B_SPAN_POINT_PPM_MIN, MHZ19B_SPAN_POINT_PPM_MAX); + return -EINVAL; + } + + cmd = MHZ19B_SPAN_POINT_CMD; + } else { + cmd = MHZ19B_ZERO_POINT_CMD; + } + + ret = mhz19b_serdev_cmd(indio_dev, cmd, ppm); + if (ret < 0) + return ret; + + return len; +} +static IIO_DEVICE_ATTR_WO(calibration_forced_value, 0); + +static struct attribute *mhz19b_attrs[] = { + &iio_dev_attr_calibration_auto_enable.dev_attr.attr, + &iio_dev_attr_calibration_forced_value.dev_attr.attr, + NULL +}; + +static const struct attribute_group mhz19b_attr_group = { + .attrs = mhz19b_attrs, +}; + +static const struct iio_info mhz19b_info = { + .attrs = &mhz19b_attr_group, + .read_raw = mhz19b_read_raw, +}; + +static const struct iio_chan_spec mhz19b_channels[] = { + { + .type = IIO_CONCENTRATION, + .channel2 = IIO_MOD_CO2, + .modified = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + }, +}; + +static size_t mhz19b_receive_buf(struct serdev_device *serdev, + const u8 *data, size_t len) +{ + struct iio_dev *indio_dev = dev_get_drvdata(&serdev->dev); + struct mhz19b_state *st = iio_priv(indio_dev); + + memcpy(st->buf + st->buf_idx, data, len); + st->buf_idx += len; + + if (st->buf_idx == MHZ19B_CMD_SIZE) { + st->buf_idx = 0; + complete(&st->buf_ready); + } + + return len; +} + +static const struct serdev_device_ops mhz19b_ops = { + .receive_buf = mhz19b_receive_buf, + .write_wakeup = serdev_device_write_wakeup, +}; + +static int mhz19b_probe(struct serdev_device *serdev) +{ + int ret; + struct device *dev = &serdev->dev; + struct iio_dev *indio_dev; + struct mhz19b_state *st; + + serdev_device_set_client_ops(serdev, &mhz19b_ops); + ret = devm_serdev_device_open(dev, serdev); + if (ret) + return ret; + serdev_device_set_baudrate(serdev, 9600); + serdev_device_set_flow_control(serdev, false); + ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE); + if (ret) + return ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + serdev_device_set_drvdata(serdev, indio_dev); + + st = iio_priv(indio_dev); + st->serdev = serdev; + + init_completion(&st->buf_ready); + + ret = devm_regulator_get_enable(dev, "vin"); + if (ret) + return ret; + + indio_dev->name = "mh-z19b"; + indio_dev->channels = mhz19b_channels; + indio_dev->num_channels = ARRAY_SIZE(mhz19b_channels); + indio_dev->info = &mhz19b_info; + + return devm_iio_device_register(dev, indio_dev); +} + +static const struct of_device_id mhz19b_of_match[] = { + { .compatible = "winsen,mhz19b", }, + { } +}; +MODULE_DEVICE_TABLE(of, mhz19b_of_match); + +static struct serdev_device_driver mhz19b_driver = { + .driver = { + .name = "mhz19b", + .of_match_table = mhz19b_of_match, + }, + .probe = mhz19b_probe, +}; +module_serdev_device_driver(mhz19b_driver); + +MODULE_AUTHOR("Gyeyoung Baek"); +MODULE_DESCRIPTION("MH-Z19B CO2 sensor driver using serdev interface"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/chemical/pms7003.c b/drivers/iio/chemical/pms7003.c index e05ce1f12065..656d4a12c58f 100644 --- a/drivers/iio/chemical/pms7003.c +++ b/drivers/iio/chemical/pms7003.c @@ -127,8 +127,8 @@ static irqreturn_t pms7003_trigger_handler(int irq, void *p) pms7003_get_pm(frame->data + PMS7003_PM10_OFFSET); mutex_unlock(&state->lock); - iio_push_to_buffers_with_timestamp(indio_dev, &state->scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &state->scan, sizeof(state->scan), + iio_get_time_ns(indio_dev)); err: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/chemical/scd30_core.c b/drivers/iio/chemical/scd30_core.c index 3fed6b63710f..8316720b1fa3 100644 --- a/drivers/iio/chemical/scd30_core.c +++ b/drivers/iio/chemical/scd30_core.c @@ -601,7 +601,8 @@ static irqreturn_t scd30_trigger_handler(int irq, void *p) if (ret) goto out; - iio_push_to_buffers_with_timestamp(indio_dev, &scan, iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &scan, sizeof(scan), + iio_get_time_ns(indio_dev)); out: iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; diff --git a/drivers/iio/chemical/scd4x.c b/drivers/iio/chemical/scd4x.c index 50e3ac44422b..2463149519b6 100644 --- a/drivers/iio/chemical/scd4x.c +++ b/drivers/iio/chemical/scd4x.c @@ -358,15 +358,14 @@ static int scd4x_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; } - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; mutex_lock(&state->lock); ret = scd4x_read_channel(state, chan->address); mutex_unlock(&state->lock); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); if (ret < 0) return ret; @@ -676,7 +675,8 @@ static irqreturn_t scd4x_trigger_handler(int irq, void *p) if (ret) goto out; - iio_push_to_buffers_with_timestamp(indio_dev, &scan, iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &scan, sizeof(scan), + iio_get_time_ns(indio_dev)); out: iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; diff --git a/drivers/iio/chemical/sen0322.c b/drivers/iio/chemical/sen0322.c new file mode 100644 index 000000000000..96c6fc1203ad --- /dev/null +++ b/drivers/iio/chemical/sen0322.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for the DFRobot SEN0322 oxygen sensor. + * + * Datasheet: + * https://wiki.dfrobot.com/Gravity_I2C_Oxygen_Sensor_SKU_SEN0322 + * + * Possible I2C slave addresses: + * 0x70 + * 0x71 + * 0x72 + * 0x73 + * + * Copyright (C) 2025 Tóth János <gomba007@gmail.com> + */ + +#include <linux/i2c.h> +#include <linux/regmap.h> + +#include <linux/iio/iio.h> + +#define SEN0322_REG_DATA 0x03 +#define SEN0322_REG_COEFF 0x0A + +struct sen0322 { + struct regmap *regmap; +}; + +static int sen0322_read_data(struct sen0322 *sen0322) +{ + u8 data[3] = { }; + int ret; + + ret = regmap_bulk_read(sen0322->regmap, SEN0322_REG_DATA, data, + sizeof(data)); + if (ret < 0) + return ret; + + /* + * The actual value in the registers is: + * val = data[0] + data[1] / 10 + data[2] / 100 + * but it is multiplied by 100 here to avoid floating-point math + * and the scale is divided by 100 to compensate this. + */ + return data[0] * 100 + data[1] * 10 + data[2]; +} + +static int sen0322_read_scale(struct sen0322 *sen0322, int *num, int *den) +{ + u32 val; + int ret; + + ret = regmap_read(sen0322->regmap, SEN0322_REG_COEFF, &val); + if (ret < 0) + return ret; + + if (val) { + *num = val; + *den = 100000; /* Coeff is scaled by 1000 at calibration. */ + } else { /* The device is not calibrated, using the factory-defaults. */ + *num = 209; /* Oxygen content in the atmosphere is 20.9%. */ + *den = 120000; /* Output of the sensor at 20.9% is 120 uA. */ + } + + dev_dbg(regmap_get_device(sen0322->regmap), "scale: %d/%d\n", + *num, *den); + + return 0; +} + +static int sen0322_read_raw(struct iio_dev *iio_dev, + const struct iio_chan_spec *chan, + int *val, int *val2, long mask) +{ + struct sen0322 *sen0322 = iio_priv(iio_dev); + int ret; + + if (chan->type != IIO_CONCENTRATION) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = sen0322_read_data(sen0322); + if (ret < 0) + return ret; + + *val = ret; + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + ret = sen0322_read_scale(sen0322, val, val2); + if (ret < 0) + return ret; + + return IIO_VAL_FRACTIONAL; + + default: + return -EINVAL; + } +} + +static const struct iio_info sen0322_info = { + .read_raw = sen0322_read_raw, +}; + +static const struct regmap_config sen0322_regmap_conf = { + .reg_bits = 8, + .val_bits = 8, +}; + +static const struct iio_chan_spec sen0322_channel = { + .type = IIO_CONCENTRATION, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), +}; + +static int sen0322_probe(struct i2c_client *client) +{ + struct sen0322 *sen0322; + struct iio_dev *iio_dev; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -ENODEV; + + iio_dev = devm_iio_device_alloc(&client->dev, sizeof(*sen0322)); + if (!iio_dev) + return -ENOMEM; + + sen0322 = iio_priv(iio_dev); + + sen0322->regmap = devm_regmap_init_i2c(client, &sen0322_regmap_conf); + if (IS_ERR(sen0322->regmap)) + return PTR_ERR(sen0322->regmap); + + iio_dev->info = &sen0322_info; + iio_dev->name = "sen0322"; + iio_dev->channels = &sen0322_channel; + iio_dev->num_channels = 1; + iio_dev->modes = INDIO_DIRECT_MODE; + + return devm_iio_device_register(&client->dev, iio_dev); +} + +static const struct of_device_id sen0322_of_match[] = { + { .compatible = "dfrobot,sen0322" }, + { } +}; +MODULE_DEVICE_TABLE(of, sen0322_of_match); + +static struct i2c_driver sen0322_driver = { + .driver = { + .name = "sen0322", + .of_match_table = sen0322_of_match, + }, + .probe = sen0322_probe, +}; +module_i2c_driver(sen0322_driver); + +MODULE_AUTHOR("Tóth János <gomba007@gmail.com>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SEN0322 oxygen sensor driver"); diff --git a/drivers/iio/chemical/sps30.c b/drivers/iio/chemical/sps30.c index a7888146188d..a934bf0298dd 100644 --- a/drivers/iio/chemical/sps30.c +++ b/drivers/iio/chemical/sps30.c @@ -117,8 +117,8 @@ static irqreturn_t sps30_trigger_handler(int irq, void *p) if (ret) goto err; - iio_push_to_buffers_with_timestamp(indio_dev, &scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &scan, sizeof(scan), + iio_get_time_ns(indio_dev)); err: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/chemical/sunrise_co2.c b/drivers/iio/chemical/sunrise_co2.c index cdb8696a4e81..af79efde37e8 100644 --- a/drivers/iio/chemical/sunrise_co2.c +++ b/drivers/iio/chemical/sunrise_co2.c @@ -373,7 +373,7 @@ static const struct iio_chan_spec_ext_info sunrise_concentration_ext_info[] = { .read = iio_enum_available_read, .private = (uintptr_t)&sunrise_error_statuses_enum, }, - {} + { } }; static const struct iio_chan_spec sunrise_channels[] = { @@ -519,7 +519,7 @@ static int sunrise_probe(struct i2c_client *client) static const struct of_device_id sunrise_of_match[] = { { .compatible = "senseair,sunrise-006-0-0007" }, - {} + { } }; MODULE_DEVICE_TABLE(of, sunrise_of_match); diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c b/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c index 119acb078af3..2d3d148b4206 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c @@ -121,7 +121,7 @@ static const struct platform_device_id cros_ec_lid_angle_ids[] = { { .name = DRV_NAME, }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(platform, cros_ec_lid_angle_ids); diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c index 66153b1850f1..82cef4a12442 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c @@ -311,7 +311,7 @@ static const struct platform_device_id cros_ec_sensors_ids[] = { { .name = "cros-ec-mag", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(platform, cros_ec_sensors_ids); diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c index 7751d6f69b12..700ebcd68ff4 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c @@ -34,25 +34,19 @@ static int cros_ec_get_host_cmd_version_mask(struct cros_ec_device *ec_dev, u16 cmd_offset, u16 cmd, u32 *mask) { + DEFINE_RAW_FLEX(struct cros_ec_command, buf, data, + MAX(sizeof(struct ec_response_get_cmd_versions), + sizeof(struct ec_params_get_cmd_versions))); int ret; - struct { - struct cros_ec_command msg; - union { - struct ec_params_get_cmd_versions params; - struct ec_response_get_cmd_versions resp; - }; - } __packed buf = { - .msg = { - .command = EC_CMD_GET_CMD_VERSIONS + cmd_offset, - .insize = sizeof(struct ec_response_get_cmd_versions), - .outsize = sizeof(struct ec_params_get_cmd_versions) - }, - .params = {.cmd = cmd} - }; - - ret = cros_ec_cmd_xfer_status(ec_dev, &buf.msg); + + buf->command = EC_CMD_GET_CMD_VERSIONS + cmd_offset; + buf->insize = sizeof(struct ec_response_get_cmd_versions); + buf->outsize = sizeof(struct ec_params_get_cmd_versions); + ((struct ec_params_get_cmd_versions *)buf->data)->cmd = cmd; + + ret = cros_ec_cmd_xfer_status(ec_dev, buf); if (ret >= 0) - *mask = buf.resp.version_mask; + *mask = ((struct ec_response_get_cmd_versions *)buf->data)->version_mask; return ret; } @@ -97,22 +91,6 @@ static void get_default_min_max_freq(enum motionsensor_type type, } } -static int cros_ec_sensor_set_ec_rate(struct cros_ec_sensors_core_state *st, - int rate) -{ - int ret; - - if (rate > U16_MAX) - rate = U16_MAX; - - mutex_lock(&st->cmd_lock); - st->param.cmd = MOTIONSENSE_CMD_EC_RATE; - st->param.ec_rate.data = rate; - ret = cros_ec_motion_send_host_cmd(st, 0); - mutex_unlock(&st->cmd_lock); - return ret; -} - static ssize_t cros_ec_sensor_set_report_latency(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) @@ -128,7 +106,25 @@ static ssize_t cros_ec_sensor_set_report_latency(struct device *dev, /* EC rate is in ms. */ latency = integer * 1000 + fract / 1000; - ret = cros_ec_sensor_set_ec_rate(st, latency); + + mutex_lock(&st->cmd_lock); + st->param.cmd = MOTIONSENSE_CMD_EC_RATE; + st->param.ec_rate.data = min(U16_MAX, latency); + ret = cros_ec_motion_send_host_cmd(st, 0); + if (ret < 0) { + mutex_unlock(&st->cmd_lock); + return ret; + } + + /* + * Flush samples currently in the FIFO, especially when the new latency + * is shorter than the old one: new timeout value is only considered when + * there is a new sample available. It can take a while for a slow + * sensor. + */ + st->param.cmd = MOTIONSENSE_CMD_FIFO_FLUSH; + ret = cros_ec_motion_send_host_cmd(st, 0); + mutex_unlock(&st->cmd_lock); if (ret < 0) return ret; @@ -486,7 +482,7 @@ const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[] = { .shared = IIO_SHARED_BY_ALL, .read = cros_ec_sensors_id }, - { }, + { } }; EXPORT_SYMBOL_GPL(cros_ec_sensors_ext_info); @@ -838,6 +834,18 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st, st->param.sensor_odr.roundup = 1; ret = cros_ec_motion_send_host_cmd(st, 0); + if (ret) + break; + + /* Flush the FIFO when a sensor is stopped. + * If the FIFO has just been emptied, pending samples will be + * stuck until new samples are available. It will not happen + * when all the sensors are stopped. + */ + if (frequency == 0) { + st->param.cmd = MOTIONSENSE_CMD_FIFO_FLUSH; + ret = cros_ec_motion_send_host_cmd(st, 0); + } break; default: ret = -EINVAL; diff --git a/drivers/iio/common/scmi_sensors/scmi_iio.c b/drivers/iio/common/scmi_sensors/scmi_iio.c index ed15dcbf4cf6..da516c46e057 100644 --- a/drivers/iio/common/scmi_sensors/scmi_iio.c +++ b/drivers/iio/common/scmi_sensors/scmi_iio.c @@ -351,12 +351,11 @@ static int scmi_iio_read_raw(struct iio_dev *iio_dev, ret = scmi_iio_get_odr_val(iio_dev, val, val2); return ret ? ret : IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(iio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(iio_dev)) + return -EBUSY; ret = scmi_iio_read_channel_data(iio_dev, ch, val, val2); - iio_device_release_direct_mode(iio_dev); + iio_device_release_direct(iio_dev); return ret; default: return -EINVAL; @@ -418,7 +417,7 @@ static const struct iio_chan_spec_ext_info scmi_iio_ext_info[] = { .read = scmi_iio_get_raw_available, .shared = IIO_SHARED_BY_TYPE, }, - {}, + { } }; static void scmi_iio_set_timestamp_channel(struct iio_chan_spec *iio_chan, @@ -705,7 +704,7 @@ static int scmi_iio_dev_probe(struct scmi_device *sdev) static const struct scmi_device_id scmi_id_table[] = { { SCMI_PROTOCOL_SENSOR, "iiodev" }, - {}, + { } }; MODULE_DEVICE_TABLE(scmi, scmi_id_table); diff --git a/drivers/iio/common/ssp_sensors/ssp_dev.c b/drivers/iio/common/ssp_sensors/ssp_dev.c index 22ea10eb48ae..7c488672936f 100644 --- a/drivers/iio/common/ssp_sensors/ssp_dev.c +++ b/drivers/iio/common/ssp_sensors/ssp_dev.c @@ -434,7 +434,7 @@ static const struct of_device_id ssp_of_match[] = { .compatible = "samsung,sensorhub-thermostat", .data = &ssp_thermostat_info, }, - {}, + { } }; MODULE_DEVICE_TABLE(of, ssp_of_match); diff --git a/drivers/iio/common/ssp_sensors/ssp_spi.c b/drivers/iio/common/ssp_sensors/ssp_spi.c index f32b04b63ea1..b7f093d7345b 100644 --- a/drivers/iio/common/ssp_sensors/ssp_spi.c +++ b/drivers/iio/common/ssp_sensors/ssp_spi.c @@ -104,7 +104,7 @@ static struct ssp_msg *ssp_create_msg(u8 cmd, u16 len, u16 opt, u32 data) /* * It is a bit heavy to do it this way but often the function is used to compose * the message from smaller chunks which are placed on the stack. Often the - * chunks are small so memcpy should be optimalized. + * chunks are small so memcpy should be optimized. */ static inline void ssp_fill_buffer(struct ssp_msg *m, unsigned int offset, const void *src, unsigned int len) diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index e4f5a7ff7e74..8ce1dccfea4f 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -530,9 +530,8 @@ int st_sensors_read_info_raw(struct iio_dev *indio_dev, int err; struct st_sensor_data *sdata = iio_priv(indio_dev); - err = iio_device_claim_direct_mode(indio_dev); - if (err) - return err; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; mutex_lock(&sdata->odr_lock); @@ -551,7 +550,7 @@ int st_sensors_read_info_raw(struct iio_dev *indio_dev, out: mutex_unlock(&sdata->odr_lock); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return err; } diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index 4811ea973125..e0996dc014a3 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -6,6 +6,17 @@ menu "Digital to analog converters" +config AD3530R + tristate "Analog Devices AD3530R and Similar DACs driver" + depends on SPI + select REGMAP_SPI + help + Say yes here to build support for Analog Devices AD3530R, AD3531R + Digital to Analog Converter. + + To compile this driver as a module, choose M here: the + module will be called ad3530r. + config AD3552R_HS tristate "Analog Devices AD3552R DAC High Speed driver" select AD3552R_LIB diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index 8dd6cce81ed1..3684cd52b7fa 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -4,6 +4,7 @@ # # When adding new entries keep the list in alphabetical order +obj-$(CONFIG_AD3530R) += ad3530r.o obj-$(CONFIG_AD3552R_HS) += ad3552r-hs.o obj-$(CONFIG_AD3552R_LIB) += ad3552r-common.o obj-$(CONFIG_AD3552R) += ad3552r.o diff --git a/drivers/iio/dac/ad3530r.c b/drivers/iio/dac/ad3530r.c new file mode 100644 index 000000000000..f9752a571aa5 --- /dev/null +++ b/drivers/iio/dac/ad3530r.c @@ -0,0 +1,517 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * AD3530R/AD3530 8-channel, 16-bit Voltage Output DAC Driver + * AD3531R/AD3531 4-channel, 16-bit Voltage Output DAC Driver + * + * Copyright 2025 Analog Devices Inc. + */ + +#include <linux/array_size.h> +#include <linux/bitfield.h> +#include <linux/bits.h> +#include <linux/cleanup.h> +#include <linux/delay.h> +#include <linux/dev_printk.h> +#include <linux/err.h> +#include <linux/gpio/consumer.h> +#include <linux/iio/iio.h> +#include <linux/kstrtox.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/property.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/spi/spi.h> +#include <linux/sysfs.h> +#include <linux/types.h> +#include <linux/units.h> + +#define AD3530R_INTERFACE_CONFIG_A 0x00 +#define AD3530R_OUTPUT_OPERATING_MODE_0 0x20 +#define AD3530R_OUTPUT_OPERATING_MODE_1 0x21 +#define AD3530R_OUTPUT_CONTROL_0 0x2A +#define AD3530R_REFERENCE_CONTROL_0 0x3C +#define AD3530R_SW_LDAC_TRIG_A 0xE5 +#define AD3530R_INPUT_CH 0xEB +#define AD3530R_MAX_REG_ADDR 0xF9 + +#define AD3531R_SW_LDAC_TRIG_A 0xDD +#define AD3531R_INPUT_CH 0xE3 + +#define AD3530R_SLD_TRIG_A BIT(7) +#define AD3530R_OUTPUT_CONTROL_RANGE BIT(2) +#define AD3530R_REFERENCE_CONTROL_SEL BIT(0) +#define AD3530R_REG_VAL_MASK GENMASK(15, 0) +#define AD3530R_OP_MODE_CHAN_MSK(chan) (GENMASK(1, 0) << 2 * (chan)) + +#define AD3530R_SW_RESET (BIT(7) | BIT(0)) +#define AD3530R_INTERNAL_VREF_mV 2500 +#define AD3530R_LDAC_PULSE_US 100 + +#define AD3530R_DAC_MAX_VAL GENMASK(15, 0) +#define AD3530R_MAX_CHANNELS 8 +#define AD3531R_MAX_CHANNELS 4 + +/* Non-constant mask variant of FIELD_PREP() */ +#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask)) + +enum ad3530r_mode { + AD3530R_NORMAL_OP, + AD3530R_POWERDOWN_1K, + AD3530R_POWERDOWN_7K7, + AD3530R_POWERDOWN_32K, +}; + +struct ad3530r_chan { + enum ad3530r_mode powerdown_mode; + bool powerdown; +}; + +struct ad3530r_chip_info { + const char *name; + const struct iio_chan_spec *channels; + int (*input_ch_reg)(unsigned int channel); + unsigned int num_channels; + unsigned int sw_ldac_trig_reg; + bool internal_ref_support; +}; + +struct ad3530r_state { + struct regmap *regmap; + /* lock to protect against multiple access to the device and shared data */ + struct mutex lock; + struct ad3530r_chan chan[AD3530R_MAX_CHANNELS]; + const struct ad3530r_chip_info *chip_info; + struct gpio_desc *ldac_gpio; + int vref_mV; + /* + * DMA (thus cache coherency maintenance) may require the transfer + * buffers to live in their own cache lines. + */ + __be16 buf __aligned(IIO_DMA_MINALIGN); +}; + +static int ad3530r_input_ch_reg(unsigned int channel) +{ + return 2 * channel + AD3530R_INPUT_CH; +} + +static int ad3531r_input_ch_reg(unsigned int channel) +{ + return 2 * channel + AD3531R_INPUT_CH; +} + +static const char * const ad3530r_powerdown_modes[] = { + "1kohm_to_gnd", + "7.7kohm_to_gnd", + "32kohm_to_gnd", +}; + +static int ad3530r_get_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct ad3530r_state *st = iio_priv(indio_dev); + + guard(mutex)(&st->lock); + return st->chan[chan->channel].powerdown_mode - 1; +} + +static int ad3530r_set_powerdown_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + unsigned int mode) +{ + struct ad3530r_state *st = iio_priv(indio_dev); + + guard(mutex)(&st->lock); + st->chan[chan->channel].powerdown_mode = mode + 1; + + return 0; +} + +static const struct iio_enum ad3530r_powerdown_mode_enum = { + .items = ad3530r_powerdown_modes, + .num_items = ARRAY_SIZE(ad3530r_powerdown_modes), + .get = ad3530r_get_powerdown_mode, + .set = ad3530r_set_powerdown_mode, +}; + +static ssize_t ad3530r_get_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + char *buf) +{ + struct ad3530r_state *st = iio_priv(indio_dev); + + guard(mutex)(&st->lock); + return sysfs_emit(buf, "%d\n", st->chan[chan->channel].powerdown); +} + +static ssize_t ad3530r_set_dac_powerdown(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + const char *buf, size_t len) +{ + struct ad3530r_state *st = iio_priv(indio_dev); + int ret; + unsigned int reg, pdmode, mask, val; + bool powerdown; + + ret = kstrtobool(buf, &powerdown); + if (ret) + return ret; + + guard(mutex)(&st->lock); + reg = chan->channel < AD3531R_MAX_CHANNELS ? + AD3530R_OUTPUT_OPERATING_MODE_0 : + AD3530R_OUTPUT_OPERATING_MODE_1; + pdmode = powerdown ? st->chan[chan->channel].powerdown_mode : 0; + mask = AD3530R_OP_MODE_CHAN_MSK(chan->channel); + val = field_prep(mask, pdmode); + + ret = regmap_update_bits(st->regmap, reg, mask, val); + if (ret) + return ret; + + st->chan[chan->channel].powerdown = powerdown; + + return len; +} + +static int ad3530r_trigger_hw_ldac(struct gpio_desc *ldac_gpio) +{ + gpiod_set_value_cansleep(ldac_gpio, 1); + fsleep(AD3530R_LDAC_PULSE_US); + gpiod_set_value_cansleep(ldac_gpio, 0); + + return 0; +} + +static int ad3530r_dac_write(struct ad3530r_state *st, unsigned int chan, + unsigned int val) +{ + int ret; + + guard(mutex)(&st->lock); + st->buf = cpu_to_be16(val); + + ret = regmap_bulk_write(st->regmap, st->chip_info->input_ch_reg(chan), + &st->buf, sizeof(st->buf)); + if (ret) + return ret; + + if (st->ldac_gpio) + return ad3530r_trigger_hw_ldac(st->ldac_gpio); + + return regmap_set_bits(st->regmap, st->chip_info->sw_ldac_trig_reg, + AD3530R_SLD_TRIG_A); +} + +static int ad3530r_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long info) +{ + struct ad3530r_state *st = iio_priv(indio_dev); + int ret; + + guard(mutex)(&st->lock); + switch (info) { + case IIO_CHAN_INFO_RAW: + ret = regmap_bulk_read(st->regmap, + st->chip_info->input_ch_reg(chan->channel), + &st->buf, sizeof(st->buf)); + if (ret) + return ret; + + *val = FIELD_GET(AD3530R_REG_VAL_MASK, be16_to_cpu(st->buf)); + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = st->vref_mV; + *val2 = 16; + + return IIO_VAL_FRACTIONAL_LOG2; + default: + return -EINVAL; + } +} + +static int ad3530r_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long info) +{ + struct ad3530r_state *st = iio_priv(indio_dev); + + switch (info) { + case IIO_CHAN_INFO_RAW: + if (val < 0 || val > AD3530R_DAC_MAX_VAL) + return -EINVAL; + + return ad3530r_dac_write(st, chan->channel, val); + default: + return -EINVAL; + } +} + +static int ad3530r_reg_access(struct iio_dev *indio_dev, unsigned int reg, + unsigned int writeval, unsigned int *readval) +{ + struct ad3530r_state *st = iio_priv(indio_dev); + + if (readval) + return regmap_read(st->regmap, reg, readval); + + return regmap_write(st->regmap, reg, writeval); +} + +static const struct iio_chan_spec_ext_info ad3530r_ext_info[] = { + { + .name = "powerdown", + .shared = IIO_SEPARATE, + .read = ad3530r_get_dac_powerdown, + .write = ad3530r_set_dac_powerdown, + }, + IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad3530r_powerdown_mode_enum), + IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, + &ad3530r_powerdown_mode_enum), + { } +}; + +#define AD3530R_CHAN(_chan) \ +{ \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = _chan, \ + .output = 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .ext_info = ad3530r_ext_info, \ +} + +static const struct iio_chan_spec ad3530r_channels[] = { + AD3530R_CHAN(0), + AD3530R_CHAN(1), + AD3530R_CHAN(2), + AD3530R_CHAN(3), + AD3530R_CHAN(4), + AD3530R_CHAN(5), + AD3530R_CHAN(6), + AD3530R_CHAN(7), +}; + +static const struct iio_chan_spec ad3531r_channels[] = { + AD3530R_CHAN(0), + AD3530R_CHAN(1), + AD3530R_CHAN(2), + AD3530R_CHAN(3), +}; + +static const struct ad3530r_chip_info ad3530_chip = { + .name = "ad3530", + .channels = ad3530r_channels, + .num_channels = ARRAY_SIZE(ad3530r_channels), + .sw_ldac_trig_reg = AD3530R_SW_LDAC_TRIG_A, + .input_ch_reg = ad3530r_input_ch_reg, + .internal_ref_support = false, +}; + +static const struct ad3530r_chip_info ad3530r_chip = { + .name = "ad3530r", + .channels = ad3530r_channels, + .num_channels = ARRAY_SIZE(ad3530r_channels), + .sw_ldac_trig_reg = AD3530R_SW_LDAC_TRIG_A, + .input_ch_reg = ad3530r_input_ch_reg, + .internal_ref_support = true, +}; + +static const struct ad3530r_chip_info ad3531_chip = { + .name = "ad3531", + .channels = ad3531r_channels, + .num_channels = ARRAY_SIZE(ad3531r_channels), + .sw_ldac_trig_reg = AD3531R_SW_LDAC_TRIG_A, + .input_ch_reg = ad3531r_input_ch_reg, + .internal_ref_support = false, +}; + +static const struct ad3530r_chip_info ad3531r_chip = { + .name = "ad3531r", + .channels = ad3531r_channels, + .num_channels = ARRAY_SIZE(ad3531r_channels), + .sw_ldac_trig_reg = AD3531R_SW_LDAC_TRIG_A, + .input_ch_reg = ad3531r_input_ch_reg, + .internal_ref_support = true, +}; + +static int ad3530r_setup(struct ad3530r_state *st, int external_vref_uV) +{ + struct device *dev = regmap_get_device(st->regmap); + struct gpio_desc *reset_gpio; + int i, ret; + u8 range_multiplier, val; + + reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(reset_gpio)) + return dev_err_probe(dev, PTR_ERR(reset_gpio), + "Failed to get reset GPIO\n"); + + if (reset_gpio) { + /* Perform hardware reset */ + fsleep(1 * USEC_PER_MSEC); + gpiod_set_value_cansleep(reset_gpio, 0); + } else { + /* Perform software reset */ + ret = regmap_update_bits(st->regmap, AD3530R_INTERFACE_CONFIG_A, + AD3530R_SW_RESET, AD3530R_SW_RESET); + if (ret) + return ret; + } + + fsleep(10 * USEC_PER_MSEC); + + range_multiplier = 1; + if (device_property_read_bool(dev, "adi,range-double")) { + ret = regmap_set_bits(st->regmap, AD3530R_OUTPUT_CONTROL_0, + AD3530R_OUTPUT_CONTROL_RANGE); + if (ret) + return ret; + + range_multiplier = 2; + } + + if (external_vref_uV) { + st->vref_mV = range_multiplier * external_vref_uV / MILLI; + } else { + ret = regmap_set_bits(st->regmap, AD3530R_REFERENCE_CONTROL_0, + AD3530R_REFERENCE_CONTROL_SEL); + if (ret) + return ret; + + st->vref_mV = range_multiplier * AD3530R_INTERNAL_VREF_mV; + } + + /* Set normal operating mode for all channels */ + val = FIELD_PREP(AD3530R_OP_MODE_CHAN_MSK(0), AD3530R_NORMAL_OP) | + FIELD_PREP(AD3530R_OP_MODE_CHAN_MSK(1), AD3530R_NORMAL_OP) | + FIELD_PREP(AD3530R_OP_MODE_CHAN_MSK(2), AD3530R_NORMAL_OP) | + FIELD_PREP(AD3530R_OP_MODE_CHAN_MSK(3), AD3530R_NORMAL_OP); + + ret = regmap_write(st->regmap, AD3530R_OUTPUT_OPERATING_MODE_0, val); + if (ret) + return ret; + + if (st->chip_info->num_channels > 4) { + ret = regmap_write(st->regmap, AD3530R_OUTPUT_OPERATING_MODE_1, + val); + if (ret) + return ret; + } + + for (i = 0; i < st->chip_info->num_channels; i++) + st->chan[i].powerdown_mode = AD3530R_POWERDOWN_32K; + + st->ldac_gpio = devm_gpiod_get_optional(dev, "ldac", GPIOD_OUT_LOW); + if (IS_ERR(st->ldac_gpio)) + return dev_err_probe(dev, PTR_ERR(st->ldac_gpio), + "Failed to get ldac GPIO\n"); + + return 0; +} + +static const struct regmap_config ad3530r_regmap_config = { + .reg_bits = 16, + .val_bits = 8, + .max_register = AD3530R_MAX_REG_ADDR, +}; + +static const struct iio_info ad3530r_info = { + .read_raw = ad3530r_read_raw, + .write_raw = ad3530r_write_raw, + .debugfs_reg_access = ad3530r_reg_access, +}; + +static int ad3530r_probe(struct spi_device *spi) +{ + static const char * const regulators[] = { "vdd", "iovdd" }; + struct device *dev = &spi->dev; + struct iio_dev *indio_dev; + struct ad3530r_state *st; + int ret, external_vref_uV; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st = iio_priv(indio_dev); + + st->regmap = devm_regmap_init_spi(spi, &ad3530r_regmap_config); + if (IS_ERR(st->regmap)) + return dev_err_probe(dev, PTR_ERR(st->regmap), + "Failed to init regmap"); + + ret = devm_mutex_init(dev, &st->lock); + if (ret) + return ret; + + st->chip_info = spi_get_device_match_data(spi); + if (!st->chip_info) + return -ENODEV; + + ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulators), + regulators); + if (ret) + return dev_err_probe(dev, ret, "Failed to enable regulators\n"); + + external_vref_uV = devm_regulator_get_enable_read_voltage(dev, "ref"); + if (external_vref_uV < 0 && external_vref_uV != -ENODEV) + return external_vref_uV; + + if (external_vref_uV == -ENODEV) + external_vref_uV = 0; + + if (!st->chip_info->internal_ref_support && external_vref_uV == 0) + return -ENODEV; + + ret = ad3530r_setup(st, external_vref_uV); + if (ret) + return ret; + + indio_dev->name = st->chip_info->name; + indio_dev->info = &ad3530r_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = st->chip_info->channels; + indio_dev->num_channels = st->chip_info->num_channels; + + return devm_iio_device_register(&spi->dev, indio_dev); +} + +static const struct spi_device_id ad3530r_id[] = { + { "ad3530", (kernel_ulong_t)&ad3530_chip }, + { "ad3530r", (kernel_ulong_t)&ad3530r_chip }, + { "ad3531", (kernel_ulong_t)&ad3531_chip }, + { "ad3531r", (kernel_ulong_t)&ad3531r_chip }, + { } +}; +MODULE_DEVICE_TABLE(spi, ad3530r_id); + +static const struct of_device_id ad3530r_of_match[] = { + { .compatible = "adi,ad3530", .data = &ad3530_chip }, + { .compatible = "adi,ad3530r", .data = &ad3530r_chip }, + { .compatible = "adi,ad3531", .data = &ad3531_chip }, + { .compatible = "adi,ad3531r", .data = &ad3531r_chip }, + { } +}; +MODULE_DEVICE_TABLE(of, ad3530r_of_match); + +static struct spi_driver ad3530r_driver = { + .driver = { + .name = "ad3530r", + .of_match_table = ad3530r_of_match, + }, + .probe = ad3530r_probe, + .id_table = ad3530r_id, +}; +module_spi_driver(ad3530r_driver); + +MODULE_AUTHOR("Kim Seer Paller <kimseer.paller@analog.com>"); +MODULE_DESCRIPTION("Analog Devices AD3530R and Similar DACs Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/dac/ad3552r-common.c b/drivers/iio/dac/ad3552r-common.c index b8807e54fa05..38baaea0e6c8 100644 --- a/drivers/iio/dac/ad3552r-common.c +++ b/drivers/iio/dac/ad3552r-common.c @@ -43,6 +43,7 @@ const struct ad3552r_model_data ad3541r_model_data = { .num_ranges = ARRAY_SIZE(ad3542r_ch_ranges), .requires_output_range = true, .num_spi_data_lanes = 2, + .max_reg_addr = 0x46, }; EXPORT_SYMBOL_NS_GPL(ad3541r_model_data, "IIO_AD3552R"); @@ -54,6 +55,7 @@ const struct ad3552r_model_data ad3542r_model_data = { .num_ranges = ARRAY_SIZE(ad3542r_ch_ranges), .requires_output_range = true, .num_spi_data_lanes = 2, + .max_reg_addr = 0x49, }; EXPORT_SYMBOL_NS_GPL(ad3542r_model_data, "IIO_AD3552R"); @@ -65,6 +67,7 @@ const struct ad3552r_model_data ad3551r_model_data = { .num_ranges = ARRAY_SIZE(ad3552r_ch_ranges), .requires_output_range = false, .num_spi_data_lanes = 4, + .max_reg_addr = 0x46, }; EXPORT_SYMBOL_NS_GPL(ad3551r_model_data, "IIO_AD3552R"); @@ -76,6 +79,7 @@ const struct ad3552r_model_data ad3552r_model_data = { .num_ranges = ARRAY_SIZE(ad3552r_ch_ranges), .requires_output_range = false, .num_spi_data_lanes = 4, + .max_reg_addr = 0x49, }; EXPORT_SYMBOL_NS_GPL(ad3552r_model_data, "IIO_AD3552R"); diff --git a/drivers/iio/dac/ad3552r-hs.c b/drivers/iio/dac/ad3552r-hs.c index cd8dabb60c55..41b96b48ba98 100644 --- a/drivers/iio/dac/ad3552r-hs.c +++ b/drivers/iio/dac/ad3552r-hs.c @@ -7,6 +7,7 @@ */ #include <linux/bitfield.h> +#include <linux/debugfs.h> #include <linux/delay.h> #include <linux/gpio/consumer.h> #include <linux/iio/backend.h> @@ -54,6 +55,18 @@ struct ad3552r_hs_state { struct ad3552r_hs_platform_data *data; /* INTERFACE_CONFIG_D register cache, in DDR we cannot read values. */ u32 config_d; + /* Protects backend I/O operations from concurrent accesses. */ + struct mutex lock; +}; + +enum ad3552r_sources { + AD3552R_SRC_NORMAL, + AD3552R_SRC_RAMP_16BIT, +}; + +static const char * const dbgfs_attr_source[] = { + [AD3552R_SRC_NORMAL] = "normal", + [AD3552R_SRC_RAMP_16BIT] = "ramp-16bit", }; static int ad3552r_hs_reg_read(struct ad3552r_hs_state *st, u32 reg, u32 *val, @@ -65,6 +78,20 @@ static int ad3552r_hs_reg_read(struct ad3552r_hs_state *st, u32 reg, u32 *val, return st->data->bus_reg_read(st->back, reg, val, xfer_size); } +static int ad3552r_hs_set_data_source(struct ad3552r_hs_state *st, + enum iio_backend_data_source type) +{ + int i, ret; + + for (i = 0; i < st->model_data->num_hw_channels; ++i) { + ret = iio_backend_data_source_set(st->back, i, type); + if (ret) + return ret; + } + + return 0; +} + static int ad3552r_hs_update_reg_bits(struct ad3552r_hs_state *st, u32 reg, u32 mask, u32 val, size_t xfer_size) { @@ -464,6 +491,122 @@ static int ad3552r_hs_setup_custom_gain(struct ad3552r_hs_state *st, gain, 1); } +static int ad3552r_hs_reg_access(struct iio_dev *indio_dev, unsigned int reg, + unsigned int writeval, unsigned int *readval) +{ + struct ad3552r_hs_state *st = iio_priv(indio_dev); + + if (reg > st->model_data->max_reg_addr) + return -EINVAL; + + /* + * There are 8, 16 or 24 bit registers, but HDL supports only reading 8 + * or 16 bit data, not 24. So, also to avoid to check any proper read + * alignment, supporting only 8-bit readings here. + */ + if (readval) + return ad3552r_hs_reg_read(st, reg, readval, 1); + + return st->data->bus_reg_write(st->back, reg, writeval, 1); +} + +static ssize_t ad3552r_hs_show_data_source(struct file *f, char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct ad3552r_hs_state *st = file_inode(f)->i_private; + enum iio_backend_data_source type; + int idx, ret; + + guard(mutex)(&st->lock); + + ret = iio_backend_data_source_get(st->back, 0, &type); + if (ret) + return ret; + + switch (type) { + case IIO_BACKEND_INTERNAL_RAMP_16BIT: + idx = AD3552R_SRC_RAMP_16BIT; + break; + case IIO_BACKEND_EXTERNAL: + idx = AD3552R_SRC_NORMAL; + break; + default: + return -EINVAL; + } + + return simple_read_from_buffer(userbuf, count, ppos, + dbgfs_attr_source[idx], + strlen(dbgfs_attr_source[idx])); +} + +static ssize_t ad3552r_hs_write_data_source(struct file *f, + const char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct ad3552r_hs_state *st = file_inode(f)->i_private; + char buf[64]; + int ret, source; + + guard(mutex)(&st->lock); + + ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, userbuf, + count); + if (ret < 0) + return ret; + + buf[count] = '\0'; + + ret = match_string(dbgfs_attr_source, ARRAY_SIZE(dbgfs_attr_source), + buf); + if (ret < 0) + return ret; + + switch (ret) { + case AD3552R_SRC_RAMP_16BIT: + source = IIO_BACKEND_INTERNAL_RAMP_16BIT; + break; + case AD3552R_SRC_NORMAL: + source = IIO_BACKEND_EXTERNAL; + break; + default: + return -EINVAL; + } + + ret = ad3552r_hs_set_data_source(st, source); + if (ret) + return ret; + + return count; +} + +static ssize_t ad3552r_hs_show_data_source_avail(struct file *f, + char __user *userbuf, + size_t count, loff_t *ppos) +{ + ssize_t len = 0; + char buf[128]; + int i; + + for (i = 0; i < ARRAY_SIZE(dbgfs_attr_source); i++) { + len += scnprintf(buf + len, PAGE_SIZE - len, "%s ", + dbgfs_attr_source[i]); + } + buf[len - 1] = '\n'; + + return simple_read_from_buffer(userbuf, count, ppos, buf, len); +} + +static const struct file_operations ad3552r_hs_data_source_fops = { + .owner = THIS_MODULE, + .write = ad3552r_hs_write_data_source, + .read = ad3552r_hs_show_data_source, +}; + +static const struct file_operations ad3552r_hs_data_source_avail_fops = { + .owner = THIS_MODULE, + .read = ad3552r_hs_show_data_source_avail, +}; + static int ad3552r_hs_setup(struct ad3552r_hs_state *st) { u16 id; @@ -531,11 +674,7 @@ static int ad3552r_hs_setup(struct ad3552r_hs_state *st) if (ret) return ret; - ret = iio_backend_data_source_set(st->back, 0, IIO_BACKEND_EXTERNAL); - if (ret) - return ret; - - ret = iio_backend_data_source_set(st->back, 1, IIO_BACKEND_EXTERNAL); + ret = ad3552r_hs_set_data_source(st, IIO_BACKEND_EXTERNAL); if (ret) return ret; @@ -639,8 +778,29 @@ static const struct iio_chan_spec ad3552r_hs_channels[] = { static const struct iio_info ad3552r_hs_info = { .read_raw = &ad3552r_hs_read_raw, .write_raw = &ad3552r_hs_write_raw, + .debugfs_reg_access = &ad3552r_hs_reg_access, }; +static void ad3552r_hs_debugfs_init(struct iio_dev *indio_dev) +{ + struct ad3552r_hs_state *st = iio_priv(indio_dev); + struct dentry *d = iio_get_debugfs_dentry(indio_dev); + + if (!IS_ENABLED(CONFIG_DEBUG_FS)) + return; + + d = iio_get_debugfs_dentry(indio_dev); + if (!d) { + dev_warn(st->dev, "can't set debugfs in driver dir\n"); + return; + } + + debugfs_create_file("data_source", 0600, d, st, + &ad3552r_hs_data_source_fops); + debugfs_create_file("data_source_available", 0600, d, st, + &ad3552r_hs_data_source_avail_fops); +} + static int ad3552r_hs_probe(struct platform_device *pdev) { struct ad3552r_hs_state *st; @@ -685,7 +845,17 @@ static int ad3552r_hs_probe(struct platform_device *pdev) if (ret) return ret; - return devm_iio_device_register(&pdev->dev, indio_dev); + ret = devm_iio_device_register(&pdev->dev, indio_dev); + if (ret) + return ret; + + ret = devm_mutex_init(&pdev->dev, &st->lock); + if (ret) + return ret; + + ad3552r_hs_debugfs_init(indio_dev); + + return ret; } static const struct of_device_id ad3552r_hs_of_id[] = { diff --git a/drivers/iio/dac/ad3552r.h b/drivers/iio/dac/ad3552r.h index 768fa264d39e..9bb46a9e07a5 100644 --- a/drivers/iio/dac/ad3552r.h +++ b/drivers/iio/dac/ad3552r.h @@ -156,6 +156,7 @@ struct ad3552r_model_data { int num_ranges; bool requires_output_range; int num_spi_data_lanes; + int max_reg_addr; }; struct ad3552r_ch_data { diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c index 905988724f27..84be5174babd 100644 --- a/drivers/iio/dac/ad5064.c +++ b/drivers/iio/dac/ad5064.c @@ -378,7 +378,7 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info[] = { }, IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5064_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5064_powerdown_mode_enum), - { }, + { } }; static const struct iio_chan_spec_ext_info ltc2617_ext_info[] = { @@ -390,7 +390,7 @@ static const struct iio_chan_spec_ext_info ltc2617_ext_info[] = { }, IIO_ENUM("powerdown_mode", IIO_SEPARATE, <c2617_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, <c2617_powerdown_mode_enum), - { }, + { } }; #define AD5064_CHANNEL(chan, addr, bits, _shift, _ext_info) { \ @@ -936,7 +936,7 @@ static const struct spi_device_id ad5064_spi_ids[] = { {"ad5668-1", ID_AD5668_1}, {"ad5668-2", ID_AD5668_2}, {"ad5668-3", ID_AD5668_2}, /* similar enough to ad5668-2 */ - {} + { } }; MODULE_DEVICE_TABLE(spi, ad5064_spi_ids); @@ -1048,7 +1048,7 @@ static const struct i2c_device_id ad5064_i2c_ids[] = { {"ltc2635-h10", ID_LTC2635_H10}, {"ltc2635-l8", ID_LTC2635_L8}, {"ltc2635-h8", ID_LTC2635_H8}, - {} + { } }; MODULE_DEVICE_TABLE(i2c, ad5064_i2c_ids); diff --git a/drivers/iio/dac/ad5360.c b/drivers/iio/dac/ad5360.c index e0b7f658d611..a57b0a093112 100644 --- a/drivers/iio/dac/ad5360.c +++ b/drivers/iio/dac/ad5360.c @@ -542,7 +542,7 @@ static const struct spi_device_id ad5360_ids[] = { { "ad5371", ID_AD5371 }, { "ad5372", ID_AD5372 }, { "ad5373", ID_AD5373 }, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad5360_ids); diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c index 392a1c7aee03..f63af704b77e 100644 --- a/drivers/iio/dac/ad5380.c +++ b/drivers/iio/dac/ad5380.c @@ -246,7 +246,7 @@ static const struct iio_chan_spec_ext_info ad5380_ext_info[] = { IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5380_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5380_powerdown_mode_enum), - { }, + { } }; #define AD5380_CHANNEL(_bits) { \ diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c index 6ad99f97eed5..ad304b0fec08 100644 --- a/drivers/iio/dac/ad5446.c +++ b/drivers/iio/dac/ad5446.c @@ -141,7 +141,7 @@ static const struct iio_chan_spec_ext_info ad5446_ext_info_powerdown[] = { }, IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5446_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5446_powerdown_mode_enum), - { }, + { } }; #define _AD5446_CHANNEL(bits, storage, _shift, ext) { \ @@ -440,7 +440,7 @@ static const struct spi_device_id ad5446_spi_ids[] = { {"dac101s101", ID_AD5310}, {"dac121s101", ID_AD5320}, {"dac7512", ID_AD5320}, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad5446_spi_ids); @@ -543,7 +543,7 @@ static const struct i2c_device_id ad5446_i2c_ids[] = { {"ad5602", ID_AD5602}, {"ad5612", ID_AD5612}, {"ad5622", ID_AD5622}, - {} + { } }; MODULE_DEVICE_TABLE(i2c, ad5446_i2c_ids); diff --git a/drivers/iio/dac/ad5449.c b/drivers/iio/dac/ad5449.c index 1c996016756a..d8c325260259 100644 --- a/drivers/iio/dac/ad5449.c +++ b/drivers/iio/dac/ad5449.c @@ -337,7 +337,7 @@ static const struct spi_device_id ad5449_spi_ids[] = { { "ad5439", ID_AD5439 }, { "ad5443", ID_AD5443 }, { "ad5449", ID_AD5449 }, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad5449_spi_ids); diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c index ff0765c8af47..355bcb6a8ba0 100644 --- a/drivers/iio/dac/ad5504.c +++ b/drivers/iio/dac/ad5504.c @@ -242,7 +242,7 @@ static const struct iio_chan_spec_ext_info ad5504_ext_info[] = { IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5504_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5504_powerdown_mode_enum), - { }, + { } }; #define AD5504_CHANNEL(_chan) { \ @@ -320,7 +320,7 @@ static int ad5504_probe(struct spi_device *spi) static const struct spi_device_id ad5504_id[] = { {"ad5504", ID_AD5504}, {"ad5501", ID_AD5501}, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad5504_id); diff --git a/drivers/iio/dac/ad5592r-base.c b/drivers/iio/dac/ad5592r-base.c index 50d19304bacb..5f2cd51723f6 100644 --- a/drivers/iio/dac/ad5592r-base.c +++ b/drivers/iio/dac/ad5592r-base.c @@ -7,6 +7,7 @@ */ #include <linux/bitops.h> +#include <linux/cleanup.h> #include <linux/delay.h> #include <linux/iio/iio.h> #include <linux/module.h> @@ -24,16 +25,14 @@ static int ad5592r_gpio_get(struct gpio_chip *chip, unsigned offset) { struct ad5592r_state *st = gpiochip_get_data(chip); int ret = 0; - u8 val; + u8 val = 0; - mutex_lock(&st->gpio_lock); - - if (st->gpio_out & BIT(offset)) - val = st->gpio_val; - else - ret = st->ops->gpio_read(st, &val); - - mutex_unlock(&st->gpio_lock); + scoped_guard(mutex, &st->gpio_lock) { + if (st->gpio_out & BIT(offset)) + val = st->gpio_val; + else + ret = st->ops->gpio_read(st, &val); + } if (ret < 0) return ret; @@ -41,20 +40,19 @@ static int ad5592r_gpio_get(struct gpio_chip *chip, unsigned offset) return !!(val & BIT(offset)); } -static void ad5592r_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +static int ad5592r_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) { struct ad5592r_state *st = gpiochip_get_data(chip); - mutex_lock(&st->gpio_lock); + guard(mutex)(&st->gpio_lock); if (value) st->gpio_val |= BIT(offset); else st->gpio_val &= ~BIT(offset); - st->ops->reg_write(st, AD5592R_REG_GPIO_SET, st->gpio_val); - - mutex_unlock(&st->gpio_lock); + return st->ops->reg_write(st, AD5592R_REG_GPIO_SET, st->gpio_val); } static int ad5592r_gpio_direction_input(struct gpio_chip *chip, unsigned offset) @@ -62,21 +60,16 @@ static int ad5592r_gpio_direction_input(struct gpio_chip *chip, unsigned offset) struct ad5592r_state *st = gpiochip_get_data(chip); int ret; - mutex_lock(&st->gpio_lock); + guard(mutex)(&st->gpio_lock); st->gpio_out &= ~BIT(offset); st->gpio_in |= BIT(offset); ret = st->ops->reg_write(st, AD5592R_REG_GPIO_OUT_EN, st->gpio_out); if (ret < 0) - goto err_unlock; - - ret = st->ops->reg_write(st, AD5592R_REG_GPIO_IN_EN, st->gpio_in); - -err_unlock: - mutex_unlock(&st->gpio_lock); + return ret; - return ret; + return st->ops->reg_write(st, AD5592R_REG_GPIO_IN_EN, st->gpio_in); } static int ad5592r_gpio_direction_output(struct gpio_chip *chip, @@ -85,7 +78,7 @@ static int ad5592r_gpio_direction_output(struct gpio_chip *chip, struct ad5592r_state *st = gpiochip_get_data(chip); int ret; - mutex_lock(&st->gpio_lock); + guard(mutex)(&st->gpio_lock); if (value) st->gpio_val |= BIT(offset); @@ -97,18 +90,13 @@ static int ad5592r_gpio_direction_output(struct gpio_chip *chip, ret = st->ops->reg_write(st, AD5592R_REG_GPIO_SET, st->gpio_val); if (ret < 0) - goto err_unlock; + return ret; ret = st->ops->reg_write(st, AD5592R_REG_GPIO_OUT_EN, st->gpio_out); if (ret < 0) - goto err_unlock; - - ret = st->ops->reg_write(st, AD5592R_REG_GPIO_IN_EN, st->gpio_in); - -err_unlock: - mutex_unlock(&st->gpio_lock); + return ret; - return ret; + return st->ops->reg_write(st, AD5592R_REG_GPIO_IN_EN, st->gpio_in); } static int ad5592r_gpio_request(struct gpio_chip *chip, unsigned offset) @@ -141,7 +129,7 @@ static int ad5592r_gpio_init(struct ad5592r_state *st) st->gpiochip.direction_input = ad5592r_gpio_direction_input; st->gpiochip.direction_output = ad5592r_gpio_direction_output; st->gpiochip.get = ad5592r_gpio_get; - st->gpiochip.set = ad5592r_gpio_set; + st->gpiochip.set_rv = ad5592r_gpio_set; st->gpiochip.request = ad5592r_gpio_request; st->gpiochip.owner = THIS_MODULE; st->gpiochip.names = ad5592r_gpio_names; @@ -155,6 +143,8 @@ static void ad5592r_gpio_cleanup(struct ad5592r_state *st) { if (st->gpio_map) gpiochip_remove(&st->gpiochip); + + mutex_destroy(&st->gpio_lock); } static int ad5592r_reset(struct ad5592r_state *st) @@ -169,10 +159,9 @@ static int ad5592r_reset(struct ad5592r_state *st) udelay(1); gpiod_set_value(gpio, 1); } else { - mutex_lock(&st->lock); - /* Writing this magic value resets the device */ - st->ops->reg_write(st, AD5592R_REG_RESET, 0xdac); - mutex_unlock(&st->lock); + scoped_guard(mutex, &st->lock) + /* Writing this magic value resets the device */ + st->ops->reg_write(st, AD5592R_REG_RESET, 0xdac); } udelay(250); @@ -247,46 +236,44 @@ static int ad5592r_set_channel_modes(struct ad5592r_state *st) } } - mutex_lock(&st->lock); + guard(mutex)(&st->lock); /* Pull down unused pins to GND */ ret = ops->reg_write(st, AD5592R_REG_PULLDOWN, pulldown); if (ret) - goto err_unlock; + return ret; ret = ops->reg_write(st, AD5592R_REG_TRISTATE, tristate); if (ret) - goto err_unlock; + return ret; /* Configure pins that we use */ ret = ops->reg_write(st, AD5592R_REG_DAC_EN, dac); if (ret) - goto err_unlock; + return ret; ret = ops->reg_write(st, AD5592R_REG_ADC_EN, adc); if (ret) - goto err_unlock; + return ret; ret = ops->reg_write(st, AD5592R_REG_GPIO_SET, st->gpio_val); if (ret) - goto err_unlock; + return ret; ret = ops->reg_write(st, AD5592R_REG_GPIO_OUT_EN, st->gpio_out); if (ret) - goto err_unlock; + return ret; ret = ops->reg_write(st, AD5592R_REG_GPIO_IN_EN, st->gpio_in); if (ret) - goto err_unlock; + return ret; /* Verify that we can read back at least one register */ ret = ops->reg_read(st, AD5592R_REG_ADC_EN, &read_back); if (!ret && (read_back & 0xff) != adc) - ret = -EIO; + return -EIO; -err_unlock: - mutex_unlock(&st->lock); - return ret; + return 0; } static int ad5592r_reset_channel_modes(struct ad5592r_state *st) @@ -303,7 +290,7 @@ static int ad5592r_write_raw(struct iio_dev *iio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) { struct ad5592r_state *st = iio_priv(iio_dev); - int ret; + int ret = 0; switch (mask) { case IIO_CHAN_INFO_RAW: @@ -314,11 +301,11 @@ static int ad5592r_write_raw(struct iio_dev *iio_dev, if (!chan->output) return -EINVAL; - mutex_lock(&st->lock); - ret = st->ops->write_dac(st, chan->channel, val); - if (!ret) - st->cached_dac[chan->channel] = val; - mutex_unlock(&st->lock); + scoped_guard(mutex, &st->lock) { + ret = st->ops->write_dac(st, chan->channel, val); + if (!ret) + st->cached_dac[chan->channel] = val; + } return ret; case IIO_CHAN_INFO_SCALE: if (chan->type == IIO_VOLTAGE) { @@ -333,14 +320,12 @@ static int ad5592r_write_raw(struct iio_dev *iio_dev, else return -EINVAL; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); ret = st->ops->reg_read(st, AD5592R_REG_CTRL, &st->cached_gp_ctrl); - if (ret < 0) { - mutex_unlock(&st->lock); + if (ret < 0) return ret; - } if (chan->output) { if (gain) @@ -358,11 +343,8 @@ static int ad5592r_write_raw(struct iio_dev *iio_dev, ~AD5592R_REG_CTRL_ADC_RANGE; } - ret = st->ops->reg_write(st, AD5592R_REG_CTRL, - st->cached_gp_ctrl); - mutex_unlock(&st->lock); - - return ret; + return st->ops->reg_write(st, AD5592R_REG_CTRL, + st->cached_gp_ctrl); } break; default: @@ -377,15 +359,15 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev, int *val, int *val2, long m) { struct ad5592r_state *st = iio_priv(iio_dev); - u16 read_val; - int ret, mult; + u16 read_val = 0; + int ret = 0, mult = 0; switch (m) { case IIO_CHAN_INFO_RAW: if (!chan->output) { - mutex_lock(&st->lock); - ret = st->ops->read_adc(st, chan->channel, &read_val); - mutex_unlock(&st->lock); + scoped_guard(mutex, &st->lock) + ret = st->ops->read_adc(st, chan->channel, + &read_val); if (ret) return ret; @@ -398,9 +380,8 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev, read_val &= GENMASK(11, 0); } else { - mutex_lock(&st->lock); - read_val = st->cached_dac[chan->channel]; - mutex_unlock(&st->lock); + scoped_guard(mutex, &st->lock) + read_val = st->cached_dac[chan->channel]; } dev_dbg(st->dev, "Channel %u read: 0x%04hX\n", @@ -418,35 +399,32 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev, return IIO_VAL_INT_PLUS_NANO; } - mutex_lock(&st->lock); - - if (chan->output) - mult = !!(st->cached_gp_ctrl & - AD5592R_REG_CTRL_DAC_RANGE); - else - mult = !!(st->cached_gp_ctrl & - AD5592R_REG_CTRL_ADC_RANGE); - - mutex_unlock(&st->lock); + scoped_guard(mutex, &st->lock) { + if (chan->output) + mult = !!(st->cached_gp_ctrl & + AD5592R_REG_CTRL_DAC_RANGE); + else + mult = !!(st->cached_gp_ctrl & + AD5592R_REG_CTRL_ADC_RANGE); + } *val *= ++mult; *val2 = chan->scan_type.realbits; return IIO_VAL_FRACTIONAL_LOG2; - case IIO_CHAN_INFO_OFFSET: + case IIO_CHAN_INFO_OFFSET: { ret = ad5592r_get_vref(st); - mutex_lock(&st->lock); + guard(mutex)(&st->lock); if (st->cached_gp_ctrl & AD5592R_REG_CTRL_ADC_RANGE) *val = (-34365 * 25) / ret; else *val = (-75365 * 25) / ret; - mutex_unlock(&st->lock); - return IIO_VAL_INT; + } default: return -EINVAL; } @@ -490,7 +468,7 @@ static const struct iio_chan_spec_ext_info ad5592r_ext_info[] = { .read = ad5592r_show_scale_available, .shared = IIO_SHARED_BY_TYPE, }, - {}, + { } }; static void ad5592r_setup_channel(struct iio_dev *iio_dev, @@ -606,6 +584,10 @@ int ad5592r_probe(struct device *dev, const char *name, st->num_channels = 8; dev_set_drvdata(dev, iio_dev); + ret = devm_mutex_init(dev, &st->lock); + if (ret) + return ret; + st->reg = devm_regulator_get_optional(dev, "vref"); if (IS_ERR(st->reg)) { if ((PTR_ERR(st->reg) != -ENODEV) && dev_fwnode(dev)) @@ -622,8 +604,6 @@ int ad5592r_probe(struct device *dev, const char *name, iio_dev->info = &ad5592r_info; iio_dev->modes = INDIO_DIRECT_MODE; - mutex_init(&st->lock); - ad5592r_init_scales(st, ad5592r_get_vref(st)); ret = ad5592r_reset(st); diff --git a/drivers/iio/dac/ad5592r.c b/drivers/iio/dac/ad5592r.c index fd82d8701322..92d1b629b85d 100644 --- a/drivers/iio/dac/ad5592r.c +++ b/drivers/iio/dac/ad5592r.c @@ -137,19 +137,19 @@ static void ad5592r_spi_remove(struct spi_device *spi) static const struct spi_device_id ad5592r_spi_ids[] = { { .name = "ad5592r", }, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad5592r_spi_ids); static const struct of_device_id ad5592r_of_match[] = { { .compatible = "adi,ad5592r", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, ad5592r_of_match); static const struct acpi_device_id ad5592r_acpi_match[] = { {"ADS5592", }, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, ad5592r_acpi_match); diff --git a/drivers/iio/dac/ad5593r.c b/drivers/iio/dac/ad5593r.c index ddd13ad821a7..9a8525c61173 100644 --- a/drivers/iio/dac/ad5593r.c +++ b/drivers/iio/dac/ad5593r.c @@ -116,19 +116,19 @@ static void ad5593r_i2c_remove(struct i2c_client *i2c) static const struct i2c_device_id ad5593r_i2c_ids[] = { { .name = "ad5593r", }, - {}, + { } }; MODULE_DEVICE_TABLE(i2c, ad5593r_i2c_ids); static const struct of_device_id ad5593r_of_match[] = { { .compatible = "adi,ad5593r", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, ad5593r_of_match); static const struct acpi_device_id ad5593r_acpi_match[] = { {"ADS5593", }, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, ad5593r_acpi_match); diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c index 2fd38ac8f698..13aefe769bad 100644 --- a/drivers/iio/dac/ad5624r_spi.c +++ b/drivers/iio/dac/ad5624r_spi.c @@ -160,7 +160,7 @@ static const struct iio_chan_spec_ext_info ad5624r_ext_info[] = { IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5624r_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5624r_powerdown_mode_enum), - { }, + { } }; #define AD5624R_CHANNEL(_chan, _bits) { \ @@ -266,7 +266,7 @@ static const struct spi_device_id ad5624r_id[] = { {"ad5624r5", ID_AD5624R5}, {"ad5644r5", ID_AD5644R5}, {"ad5664r5", ID_AD5664R5}, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad5624r_id); diff --git a/drivers/iio/dac/ad5686-spi.c b/drivers/iio/dac/ad5686-spi.c index 9c727aa6ea18..df8619e0c092 100644 --- a/drivers/iio/dac/ad5686-spi.c +++ b/drivers/iio/dac/ad5686-spi.c @@ -112,7 +112,7 @@ static const struct spi_device_id ad5686_spi_id[] = { {"ad5685r", ID_AD5685R}, {"ad5686", ID_AD5686}, {"ad5686r", ID_AD5686R}, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad5686_spi_id); diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c index 763af690c444..d9cae9555e5d 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c @@ -185,7 +185,7 @@ static const struct iio_chan_spec_ext_info ad5686_ext_info[] = { }, IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5686_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5686_powerdown_mode_enum), - { }, + { } }; #define AD5868_CHANNEL(chan, addr, bits, _shift) { \ diff --git a/drivers/iio/dac/ad5696-i2c.c b/drivers/iio/dac/ad5696-i2c.c index 0156f32c12c8..d3327bca0e07 100644 --- a/drivers/iio/dac/ad5696-i2c.c +++ b/drivers/iio/dac/ad5696-i2c.c @@ -82,7 +82,7 @@ static const struct i2c_device_id ad5686_i2c_id[] = { {"ad5695r", ID_AD5695R}, {"ad5696", ID_AD5696}, {"ad5696r", ID_AD5696R}, - {} + { } }; MODULE_DEVICE_TABLE(i2c, ad5686_i2c_id); @@ -101,7 +101,7 @@ static const struct of_device_id ad5686_of_match[] = { { .compatible = "adi,ad5695r" }, { .compatible = "adi,ad5696" }, { .compatible = "adi,ad5696r" }, - {} + { } }; MODULE_DEVICE_TABLE(of, ad5686_of_match); diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c index 05e80b6ae2cc..d0e5f35462b1 100644 --- a/drivers/iio/dac/ad5755.c +++ b/drivers/iio/dac/ad5755.c @@ -522,7 +522,7 @@ static const struct iio_chan_spec_ext_info ad5755_ext_info[] = { .write = ad5755_write_powerdown, .shared = IIO_SEPARATE, }, - { }, + { } }; #define AD5755_CHANNEL(_bits) { \ @@ -853,7 +853,7 @@ static const struct spi_device_id ad5755_id[] = { { "ad5757", (kernel_ulong_t)&ad5755_chip_info_tbl[ID_AD5757] }, { "ad5735", (kernel_ulong_t)&ad5755_chip_info_tbl[ID_AD5735] }, { "ad5737", (kernel_ulong_t)&ad5755_chip_info_tbl[ID_AD5737] }, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad5755_id); diff --git a/drivers/iio/dac/ad5758.c b/drivers/iio/dac/ad5758.c index 98771e37a7b5..4ed4fda76ea9 100644 --- a/drivers/iio/dac/ad5758.c +++ b/drivers/iio/dac/ad5758.c @@ -878,7 +878,7 @@ static int ad5758_probe(struct spi_device *spi) static const struct spi_device_id ad5758_id[] = { { "ad5758", 0 }, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad5758_id); diff --git a/drivers/iio/dac/ad5761.c b/drivers/iio/dac/ad5761.c index 0aa5ba7f4654..b5d20f04f070 100644 --- a/drivers/iio/dac/ad5761.c +++ b/drivers/iio/dac/ad5761.c @@ -137,13 +137,11 @@ static int _ad5761_spi_read(struct ad5761_state *st, u8 addr, u16 *val) struct spi_transfer xfers[] = { { .tx_buf = &st->data[0].d8[1], - .bits_per_word = 8, .len = 3, .cs_change = true, }, { .tx_buf = &st->data[1].d8[1], .rx_buf = &st->data[2].d8[1], - .bits_per_word = 8, .len = 3, }, }; @@ -348,7 +346,7 @@ static const struct spi_device_id ad5761_id[] = { {"ad5721r", ID_AD5721R}, {"ad5761", ID_AD5761}, {"ad5761r", ID_AD5761R}, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad5761_id); diff --git a/drivers/iio/dac/ad5766.c b/drivers/iio/dac/ad5766.c index f658ac8086aa..f6a0a0d84fef 100644 --- a/drivers/iio/dac/ad5766.c +++ b/drivers/iio/dac/ad5766.c @@ -148,13 +148,11 @@ static int __ad5766_spi_read(struct ad5766_state *st, u8 dac, int *val) struct spi_transfer xfers[] = { { .tx_buf = &st->data[0].d32, - .bits_per_word = 8, .len = 3, .cs_change = 1, }, { .tx_buf = &st->data[1].d32, .rx_buf = &st->data[2].d32, - .bits_per_word = 8, .len = 3, }, }; @@ -437,7 +435,7 @@ static const struct iio_chan_spec_ext_info ad5766_ext_info[] = { IIO_ENUM("dither_scale", IIO_SEPARATE, &ad5766_dither_scale_enum), IIO_ENUM_AVAILABLE("dither_scale", IIO_SEPARATE, &ad5766_dither_scale_enum), - {} + { } }; #define AD576x_CHANNEL(_chan, _bits) { \ @@ -648,14 +646,14 @@ static int ad5766_probe(struct spi_device *spi) static const struct of_device_id ad5766_dt_match[] = { { .compatible = "adi,ad5766" }, { .compatible = "adi,ad5767" }, - {} + { } }; MODULE_DEVICE_TABLE(of, ad5766_dt_match); static const struct spi_device_id ad5766_spi_ids[] = { { "ad5766", ID_AD5766 }, { "ad5767", ID_AD5767 }, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad5766_spi_ids); diff --git a/drivers/iio/dac/ad5770r.c b/drivers/iio/dac/ad5770r.c index 25cf11d0471b..6eb4027a44fb 100644 --- a/drivers/iio/dac/ad5770r.c +++ b/drivers/iio/dac/ad5770r.c @@ -637,13 +637,13 @@ static int ad5770r_probe(struct spi_device *spi) static const struct of_device_id ad5770r_of_id[] = { { .compatible = "adi,ad5770r", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, ad5770r_of_id); static const struct spi_device_id ad5770r_id[] = { { "ad5770r", 0 }, - {}, + { } }; MODULE_DEVICE_TABLE(spi, ad5770r_id); diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c index 07848be3f8d5..41582f2b90fb 100644 --- a/drivers/iio/dac/ad5791.c +++ b/drivers/iio/dac/ad5791.c @@ -138,13 +138,11 @@ static int ad5791_spi_read(struct ad5791_state *st, u8 addr, u32 *val) struct spi_transfer xfers[] = { { .tx_buf = &st->data[0].d8[1], - .bits_per_word = 8, .len = 3, .cs_change = 1, }, { .tx_buf = &st->data[1].d8[1], .rx_buf = &st->data[2].d8[1], - .bits_per_word = 8, .len = 3, }, }; @@ -312,7 +310,7 @@ static const struct iio_chan_spec_ext_info ad5791_ext_info[] = { IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5791_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5791_powerdown_mode_enum), - { }, + { } }; #define AD5791_DEFINE_CHIP_INFO(_name, bits, _shift, _lin_comp) \ diff --git a/drivers/iio/dac/ad7293.c b/drivers/iio/dac/ad7293.c index d3f49b5337d2..c3797e40cdd9 100644 --- a/drivers/iio/dac/ad7293.c +++ b/drivers/iio/dac/ad7293.c @@ -114,6 +114,7 @@ #define AD7293_REG_DATA_RAW_MSK GENMASK(15, 4) #define AD7293_REG_VINX_RANGE_GET_CH_MSK(x, ch) (((x) >> (ch)) & 0x1) #define AD7293_REG_VINX_RANGE_SET_CH_MSK(x, ch) (((x) & 0x1) << (ch)) +#define AD7293_GENERAL_ADC_REF_MSK BIT(7) #define AD7293_CHIP_ID 0x18 enum ad7293_ch_type { @@ -141,6 +142,7 @@ struct ad7293_state { /* Protect against concurrent accesses to the device, page selection and data content */ struct mutex lock; struct gpio_desc *gpio_reset; + bool vrefin_en; u8 page_select; u8 data[3] __aligned(IIO_DMA_MINALIGN); }; @@ -785,6 +787,12 @@ static int ad7293_properties_parse(struct ad7293_state *st) if (ret) return dev_err_probe(&spi->dev, ret, "failed to enable VDRIVE\n"); + ret = devm_regulator_get_enable_optional(&spi->dev, "vrefin"); + if (ret < 0 && ret != -ENODEV) + return dev_err_probe(&spi->dev, ret, "failed to enable VREFIN\n"); + + st->vrefin_en = ret != -ENODEV; + st->gpio_reset = devm_gpiod_get_optional(&st->spi->dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(st->gpio_reset)) @@ -818,6 +826,11 @@ static int ad7293_init(struct ad7293_state *st) return -EINVAL; } + if (!st->vrefin_en) + return __ad7293_spi_update_bits(st, AD7293_REG_GENERAL, + AD7293_GENERAL_ADC_REF_MSK, + AD7293_GENERAL_ADC_REF_MSK); + return 0; } @@ -859,13 +872,13 @@ static int ad7293_probe(struct spi_device *spi) static const struct spi_device_id ad7293_id[] = { { "ad7293", 0 }, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad7293_id); static const struct of_device_id ad7293_of_match[] = { { .compatible = "adi,ad7293" }, - {} + { } }; MODULE_DEVICE_TABLE(of, ad7293_of_match); diff --git a/drivers/iio/dac/ad7303.c b/drivers/iio/dac/ad7303.c index bff6bf697d9c..a88cc639047d 100644 --- a/drivers/iio/dac/ad7303.c +++ b/drivers/iio/dac/ad7303.c @@ -173,7 +173,7 @@ static const struct iio_chan_spec_ext_info ad7303_ext_info[] = { .write = ad7303_write_dac_powerdown, .shared = IIO_SEPARATE, }, - { }, + { } }; #define AD7303_CHANNEL(chan) { \ @@ -264,13 +264,13 @@ static int ad7303_probe(struct spi_device *spi) static const struct of_device_id ad7303_spi_of_match[] = { { .compatible = "adi,ad7303", }, - { /* sentinel */ }, + { } }; MODULE_DEVICE_TABLE(of, ad7303_spi_of_match); static const struct spi_device_id ad7303_spi_ids[] = { { "ad7303", 0 }, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad7303_spi_ids); diff --git a/drivers/iio/dac/ad8801.c b/drivers/iio/dac/ad8801.c index 8a362fae2eca..60e663af1cc1 100644 --- a/drivers/iio/dac/ad8801.c +++ b/drivers/iio/dac/ad8801.c @@ -153,7 +153,7 @@ static int ad8801_probe(struct spi_device *spi) static const struct spi_device_id ad8801_ids[] = { {"ad8801", ID_AD8801}, {"ad8803", ID_AD8803}, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad8801_ids); diff --git a/drivers/iio/dac/ad9739a.c b/drivers/iio/dac/ad9739a.c index b6a65359b0b4..d77b46d83bd4 100644 --- a/drivers/iio/dac/ad9739a.c +++ b/drivers/iio/dac/ad9739a.c @@ -442,13 +442,13 @@ static int ad9739a_probe(struct spi_device *spi) static const struct of_device_id ad9739a_of_match[] = { { .compatible = "adi,ad9739a" }, - {} + { } }; MODULE_DEVICE_TABLE(of, ad9739a_of_match); static const struct spi_device_id ad9739a_id[] = { {"ad9739a"}, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad9739a_id); diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c index 892d770aec69..33faba4b02c2 100644 --- a/drivers/iio/dac/adi-axi-dac.c +++ b/drivers/iio/dac/adi-axi-dac.c @@ -84,6 +84,7 @@ #define AXI_DAC_CHAN_CNTRL_7_REG(c) (0x0418 + (c) * 0x40) #define AXI_DAC_CHAN_CNTRL_7_DATA_SEL GENMASK(3, 0) +#define AXI_DAC_CHAN_CNTRL_MAX 15 #define AXI_DAC_RD_ADDR(x) (BIT(7) | (x)) /* 360 degrees in rad */ @@ -186,6 +187,9 @@ static int __axi_dac_frequency_get(struct axi_dac_state *st, unsigned int chan, u32 reg, raw; int ret; + if (chan > AXI_DAC_CHAN_CNTRL_MAX) + return -EINVAL; + if (!st->dac_clk) { dev_err(st->dev, "Sampling rate is 0...\n"); return -EINVAL; @@ -230,6 +234,9 @@ static int axi_dac_scale_get(struct axi_dac_state *st, int ret, vals[2]; u32 reg, raw; + if (chan->channel > AXI_DAC_CHAN_CNTRL_MAX) + return -EINVAL; + if (tone_2) reg = AXI_DAC_CHAN_CNTRL_3_REG(chan->channel); else @@ -264,6 +271,9 @@ static int axi_dac_phase_get(struct axi_dac_state *st, u32 reg, raw, phase; int ret, vals[2]; + if (chan->channel > AXI_DAC_CHAN_CNTRL_MAX) + return -EINVAL; + if (tone_2) reg = AXI_DAC_CHAN_CNTRL_4_REG(chan->channel); else @@ -291,6 +301,9 @@ static int __axi_dac_frequency_set(struct axi_dac_state *st, unsigned int chan, u16 raw; int ret; + if (chan > AXI_DAC_CHAN_CNTRL_MAX) + return -EINVAL; + if (!sample_rate || freq > sample_rate / 2) { dev_err(st->dev, "Invalid frequency(%u) dac_clk(%llu)\n", freq, sample_rate); @@ -342,6 +355,9 @@ static int axi_dac_scale_set(struct axi_dac_state *st, u32 raw = 0, reg; int ret; + if (chan->channel > AXI_DAC_CHAN_CNTRL_MAX) + return -EINVAL; + ret = iio_str_to_fixpoint(buf, 100000, &integer, &frac); if (ret) return ret; @@ -385,6 +401,9 @@ static int axi_dac_phase_set(struct axi_dac_state *st, u32 raw, reg; int ret; + if (chan->channel > AXI_DAC_CHAN_CNTRL_MAX) + return -EINVAL; + ret = iio_str_to_fixpoint(buf, 100000, &integer, &frac); if (ret) return ret; @@ -469,7 +488,7 @@ static const struct iio_chan_spec_ext_info axi_dac_ext_info[] = { IIO_BACKEND_EX_INFO("scale1", IIO_SEPARATE, AXI_DAC_SCALE_TONE_2), IIO_BACKEND_EX_INFO("phase0", IIO_SEPARATE, AXI_DAC_PHASE_TONE_1), IIO_BACKEND_EX_INFO("phase1", IIO_SEPARATE, AXI_DAC_PHASE_TONE_2), - {} + { } }; static int axi_dac_extend_chan(struct iio_backend *back, @@ -493,6 +512,9 @@ static int axi_dac_data_source_set(struct iio_backend *back, unsigned int chan, { struct axi_dac_state *st = iio_backend_get_priv(back); + if (chan > AXI_DAC_CHAN_CNTRL_MAX) + return -EINVAL; + switch (data) { case IIO_BACKEND_INTERNAL_CONTINUOUS_WAVE: return regmap_update_bits(st->regmap, @@ -514,6 +536,35 @@ static int axi_dac_data_source_set(struct iio_backend *back, unsigned int chan, } } +static int axi_dac_data_source_get(struct iio_backend *back, unsigned int chan, + enum iio_backend_data_source *data) +{ + struct axi_dac_state *st = iio_backend_get_priv(back); + int ret; + u32 val; + + if (chan > AXI_DAC_CHAN_CNTRL_MAX) + return -EINVAL; + + ret = regmap_read(st->regmap, AXI_DAC_CHAN_CNTRL_7_REG(chan), &val); + if (ret) + return ret; + + switch (val) { + case AXI_DAC_DATA_INTERNAL_TONE: + *data = IIO_BACKEND_INTERNAL_CONTINUOUS_WAVE; + return 0; + case AXI_DAC_DATA_DMA: + *data = IIO_BACKEND_EXTERNAL; + return 0; + case AXI_DAC_DATA_INTERNAL_RAMP_16BIT: + *data = IIO_BACKEND_INTERNAL_RAMP_16BIT; + return 0; + default: + return -EIO; + } +} + static int axi_dac_set_sample_rate(struct iio_backend *back, unsigned int chan, u64 sample_rate) { @@ -521,6 +572,8 @@ static int axi_dac_set_sample_rate(struct iio_backend *back, unsigned int chan, unsigned int freq; int ret, tone; + if (chan > AXI_DAC_CHAN_CNTRL_MAX) + return -EINVAL; if (!sample_rate) return -EINVAL; if (st->reg_config & AXI_DAC_CONFIG_DDS_DISABLE) @@ -707,6 +760,7 @@ static int axi_dac_bus_reg_read(struct iio_backend *back, u32 reg, u32 *val, { struct axi_dac_state *st = iio_backend_get_priv(back); int ret; + u32 ival; guard(mutex)(&st->lock); @@ -719,6 +773,13 @@ static int axi_dac_bus_reg_read(struct iio_backend *back, u32 reg, u32 *val, if (ret) return ret; + ret = regmap_read_poll_timeout(st->regmap, + AXI_DAC_UI_STATUS_REG, ival, + FIELD_GET(AXI_DAC_UI_STATUS_IF_BUSY, ival) == 0, + 10, 100 * KILO); + if (ret) + return ret; + return regmap_read(st->regmap, AXI_DAC_CUSTOM_RD_REG, val); } @@ -794,6 +855,7 @@ static const struct iio_backend_ops axi_ad3552r_ops = { .request_buffer = axi_dac_request_buffer, .free_buffer = axi_dac_free_buffer, .data_source_set = axi_dac_data_source_set, + .data_source_get = axi_dac_data_source_get, .ddr_enable = axi_dac_ddr_enable, .ddr_disable = axi_dac_ddr_disable, .data_stream_enable = axi_dac_data_stream_enable, @@ -961,7 +1023,7 @@ static const struct axi_dac_info dac_ad3552r = { static const struct of_device_id axi_dac_of_match[] = { { .compatible = "adi,axi-dac-9.1.b", .data = &dac_generic }, { .compatible = "adi,axi-ad3552r", .data = &dac_ad3552r }, - {} + { } }; MODULE_DEVICE_TABLE(of, axi_dac_of_match); diff --git a/drivers/iio/dac/dpot-dac.c b/drivers/iio/dac/dpot-dac.c index f36f10bfb6be..d1b8441051ae 100644 --- a/drivers/iio/dac/dpot-dac.c +++ b/drivers/iio/dac/dpot-dac.c @@ -237,7 +237,7 @@ static void dpot_dac_remove(struct platform_device *pdev) static const struct of_device_id dpot_dac_match[] = { { .compatible = "dpot-dac" }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, dpot_dac_match); diff --git a/drivers/iio/dac/ds4424.c b/drivers/iio/dac/ds4424.c index e89e4c054653..a26a99753418 100644 --- a/drivers/iio/dac/ds4424.c +++ b/drivers/iio/dac/ds4424.c @@ -301,7 +301,7 @@ MODULE_DEVICE_TABLE(i2c, ds4424_id); static const struct of_device_id ds4424_of_match[] = { { .compatible = "maxim,ds4422" }, { .compatible = "maxim,ds4424" }, - { }, + { } }; MODULE_DEVICE_TABLE(of, ds4424_of_match); diff --git a/drivers/iio/dac/lpc18xx_dac.c b/drivers/iio/dac/lpc18xx_dac.c index 2332b0c22691..aa1c73f8429d 100644 --- a/drivers/iio/dac/lpc18xx_dac.c +++ b/drivers/iio/dac/lpc18xx_dac.c @@ -179,7 +179,7 @@ static void lpc18xx_dac_remove(struct platform_device *pdev) static const struct of_device_id lpc18xx_dac_match[] = { { .compatible = "nxp,lpc1850-dac" }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, lpc18xx_dac_match); diff --git a/drivers/iio/dac/ltc1660.c b/drivers/iio/dac/ltc1660.c index 2758fc8a5ad5..6e80b49f4665 100644 --- a/drivers/iio/dac/ltc1660.c +++ b/drivers/iio/dac/ltc1660.c @@ -219,14 +219,14 @@ static void ltc1660_remove(struct spi_device *spi) static const struct of_device_id ltc1660_dt_ids[] = { { .compatible = "lltc,ltc1660", .data = (void *)ID_LTC1660 }, { .compatible = "lltc,ltc1665", .data = (void *)ID_LTC1665 }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, ltc1660_dt_ids); static const struct spi_device_id ltc1660_id[] = { {"ltc1660", ID_LTC1660}, {"ltc1665", ID_LTC1665}, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(spi, ltc1660_id); diff --git a/drivers/iio/dac/ltc2632.c b/drivers/iio/dac/ltc2632.c index 999348836d87..105f939f7e54 100644 --- a/drivers/iio/dac/ltc2632.c +++ b/drivers/iio/dac/ltc2632.c @@ -176,7 +176,7 @@ static const struct iio_chan_spec_ext_info ltc2632_ext_info[] = { .write = ltc2632_write_dac_powerdown, .shared = IIO_SEPARATE, }, - { }, + { } }; #define LTC2632_CHANNEL(_chan, _bits) { \ @@ -372,7 +372,7 @@ static const struct spi_device_id ltc2632_id[] = { { "ltc2636-h12", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636H12] }, { "ltc2636-h10", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636H10] }, { "ltc2636-h8", (kernel_ulong_t)<c2632_chip_info_tbl[ID_LTC2636H8] }, - {} + { } }; MODULE_DEVICE_TABLE(spi, ltc2632_id); @@ -432,7 +432,7 @@ static const struct of_device_id ltc2632_of_match[] = { .compatible = "lltc,ltc2636-h8", .data = <c2632_chip_info_tbl[ID_LTC2636H8] }, - {} + { } }; MODULE_DEVICE_TABLE(of, ltc2632_of_match); diff --git a/drivers/iio/dac/ltc2688.c b/drivers/iio/dac/ltc2688.c index bdc857c7fa6d..1f24f07d1ad2 100644 --- a/drivers/iio/dac/ltc2688.c +++ b/drivers/iio/dac/ltc2688.c @@ -104,13 +104,11 @@ static int ltc2688_spi_read(void *context, const void *reg, size_t reg_size, struct spi_transfer xfers[] = { { .tx_buf = st->tx_data, - .bits_per_word = 8, .len = reg_size + val_size, .cs_change = 1, }, { .tx_buf = st->tx_data + 3, .rx_buf = st->rx_data, - .bits_per_word = 8, .len = reg_size + val_size, }, }; @@ -608,7 +606,7 @@ static const struct iio_chan_spec_ext_info ltc2688_toggle_sym_ext_info[] = { ltc2688_reg_bool_get, ltc2688_reg_bool_set), LTC2688_CHAN_EXT_INFO("symbol", LTC2688_CMD_SW_TOGGLE, IIO_SEPARATE, ltc2688_reg_bool_get, ltc2688_reg_bool_set), - {} + { } }; static const struct iio_chan_spec_ext_info ltc2688_toggle_ext_info[] = { @@ -621,7 +619,7 @@ static const struct iio_chan_spec_ext_info ltc2688_toggle_ext_info[] = { ltc2688_dither_toggle_set), LTC2688_CHAN_EXT_INFO("powerdown", LTC2688_CMD_POWERDOWN, IIO_SEPARATE, ltc2688_reg_bool_get, ltc2688_reg_bool_set), - {} + { } }; static struct iio_chan_spec_ext_info ltc2688_dither_ext_info[] = { @@ -649,13 +647,13 @@ static struct iio_chan_spec_ext_info ltc2688_dither_ext_info[] = { ltc2688_dither_toggle_set), LTC2688_CHAN_EXT_INFO("powerdown", LTC2688_CMD_POWERDOWN, IIO_SEPARATE, ltc2688_reg_bool_get, ltc2688_reg_bool_set), - {} + { } }; static const struct iio_chan_spec_ext_info ltc2688_ext_info[] = { LTC2688_CHAN_EXT_INFO("powerdown", LTC2688_CMD_POWERDOWN, IIO_SEPARATE, ltc2688_reg_bool_get, ltc2688_reg_bool_set), - {} + { } }; #define LTC2688_CHANNEL(_chan) { \ @@ -991,13 +989,13 @@ static int ltc2688_probe(struct spi_device *spi) static const struct of_device_id ltc2688_of_id[] = { { .compatible = "adi,ltc2688" }, - {} + { } }; MODULE_DEVICE_TABLE(of, ltc2688_of_id); static const struct spi_device_id ltc2688_id[] = { { "ltc2688" }, - {} + { } }; MODULE_DEVICE_TABLE(spi, ltc2688_id); diff --git a/drivers/iio/dac/max5522.c b/drivers/iio/dac/max5522.c index 9f72155dcbc7..1b8fe6b8d26e 100644 --- a/drivers/iio/dac/max5522.c +++ b/drivers/iio/dac/max5522.c @@ -174,7 +174,7 @@ static int max5522_spi_probe(struct spi_device *spi) static const struct spi_device_id max5522_ids[] = { { "max5522", (kernel_ulong_t)&max5522_chip_info_tbl[ID_MAX5522] }, - {} + { } }; MODULE_DEVICE_TABLE(spi, max5522_ids); @@ -183,7 +183,7 @@ static const struct of_device_id max5522_of_match[] = { .compatible = "maxim,max5522", .data = &max5522_chip_info_tbl[ID_MAX5522], }, - {} + { } }; MODULE_DEVICE_TABLE(of, max5522_of_match); diff --git a/drivers/iio/dac/max5821.c b/drivers/iio/dac/max5821.c index b062a18be5e7..e7e29359f8fe 100644 --- a/drivers/iio/dac/max5821.c +++ b/drivers/iio/dac/max5821.c @@ -137,7 +137,7 @@ static const struct iio_chan_spec_ext_info max5821_ext_info[] = { }, IIO_ENUM("powerdown_mode", IIO_SEPARATE, &max5821_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &max5821_powerdown_mode_enum), - { }, + { } }; #define MAX5821_CHANNEL(chan) { \ diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c index 1337fb02ccf5..62972494a229 100644 --- a/drivers/iio/dac/mcp4725.c +++ b/drivers/iio/dac/mcp4725.c @@ -241,7 +241,7 @@ static const struct iio_chan_spec_ext_info mcp4725_ext_info[] = { &mcp472x_powerdown_mode_enum[MCP4725]), IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &mcp472x_powerdown_mode_enum[MCP4725]), - { }, + { } }; static const struct iio_chan_spec_ext_info mcp4726_ext_info[] = { @@ -255,7 +255,7 @@ static const struct iio_chan_spec_ext_info mcp4726_ext_info[] = { &mcp472x_powerdown_mode_enum[MCP4726]), IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &mcp472x_powerdown_mode_enum[MCP4726]), - { }, + { } }; static const struct iio_chan_spec mcp472x_channel[] = { diff --git a/drivers/iio/dac/mcp4728.c b/drivers/iio/dac/mcp4728.c index 192175dc6419..4f30b99110b7 100644 --- a/drivers/iio/dac/mcp4728.c +++ b/drivers/iio/dac/mcp4728.c @@ -286,7 +286,7 @@ static const struct iio_chan_spec_ext_info mcp4728_ext_info[] = { IIO_ENUM("powerdown_mode", IIO_SEPARATE, &mcp4728_powerdown_mode_enum), IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &mcp4728_powerdown_mode_enum), - {}, + { } }; static const struct iio_chan_spec mcp4728_channels[MCP4728_N_CHANNELS] = { @@ -573,13 +573,13 @@ static int mcp4728_probe(struct i2c_client *client) static const struct i2c_device_id mcp4728_id[] = { { "mcp4728" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, mcp4728_id); static const struct of_device_id mcp4728_of_match[] = { { .compatible = "microchip,mcp4728" }, - {} + { } }; MODULE_DEVICE_TABLE(of, mcp4728_of_match); diff --git a/drivers/iio/dac/mcp4821.c b/drivers/iio/dac/mcp4821.c index c1a59bbbba3c..748bdca9a964 100644 --- a/drivers/iio/dac/mcp4821.c +++ b/drivers/iio/dac/mcp4821.c @@ -206,7 +206,7 @@ static const struct of_device_id mcp4821_of_table[] = { MCP4821_COMPATIBLE("microchip,mcp4812", ID_MCP4812), MCP4821_COMPATIBLE("microchip,mcp4821", ID_MCP4821), MCP4821_COMPATIBLE("microchip,mcp4822", ID_MCP4822), - { /* Sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, mcp4821_of_table); @@ -217,7 +217,7 @@ static const struct spi_device_id mcp4821_id_table[] = { { "mcp4812", (kernel_ulong_t)&mcp4821_chip_info_table[ID_MCP4812]}, { "mcp4821", (kernel_ulong_t)&mcp4821_chip_info_table[ID_MCP4821]}, { "mcp4822", (kernel_ulong_t)&mcp4821_chip_info_table[ID_MCP4822]}, - { /* Sentinel */ } + { } }; MODULE_DEVICE_TABLE(spi, mcp4821_id_table); diff --git a/drivers/iio/dac/mcp4922.c b/drivers/iio/dac/mcp4922.c index 26aa99059813..74f338afcab9 100644 --- a/drivers/iio/dac/mcp4922.c +++ b/drivers/iio/dac/mcp4922.c @@ -161,7 +161,7 @@ static const struct spi_device_id mcp4922_id[] = { {"mcp4912", ID_MCP4912}, {"mcp4921", ID_MCP4921}, {"mcp4922", ID_MCP4922}, - {} + { } }; MODULE_DEVICE_TABLE(spi, mcp4922_id); diff --git a/drivers/iio/dac/rohm-bd79703.c b/drivers/iio/dac/rohm-bd79703.c index e998ab51052e..a35c37d2261d 100644 --- a/drivers/iio/dac/rohm-bd79703.c +++ b/drivers/iio/dac/rohm-bd79703.c @@ -38,11 +38,20 @@ static const struct regmap_config bd79703_regmap_config = { .cache_type = REGCACHE_RBTREE, }; +/* Dynamic driver private data */ struct bd79703_data { struct regmap *regmap; int vfs; }; +/* Static, IC type specific data for different variants */ +struct bd7970x_chip_data { + const char *name; + const struct iio_chan_spec *channels; + int num_channels; + bool has_vfs; +}; + static int bd79703_read_raw(struct iio_dev *idev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -67,7 +76,7 @@ static int bd79703_write_raw(struct iio_dev *idev, if (val < 0 || val >= 1 << BD79703_DAC_BITS) return -EINVAL; - return regmap_write(data->regmap, chan->channel + 1, val); + return regmap_write(data->regmap, chan->address, val); }; static const struct iio_info bd79703_info = { @@ -75,16 +84,42 @@ static const struct iio_info bd79703_info = { .write_raw = bd79703_write_raw, }; -#define BD79703_CHAN(_chan) { \ +#define BD79703_CHAN_ADDR(_chan, _addr) { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ .output = 1, \ .channel = (_chan), \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ - .address = (_chan), \ + .address = (_addr), \ } +#define BD79703_CHAN(_chan) BD79703_CHAN_ADDR((_chan), (_chan) + 1) + +static const struct iio_chan_spec bd79700_channels[] = { + BD79703_CHAN(0), + BD79703_CHAN(1), +}; + +static const struct iio_chan_spec bd79701_channels[] = { + BD79703_CHAN(0), + BD79703_CHAN(1), + BD79703_CHAN(2), +}; + +/* + * The BD79702 has 4 channels. They aren't mapped to BD79703 channels 0, 1, 2 + * and 3, but to the channels 0, 1, 4, 5. So the addressing used with SPI + * accesses is 1, 2, 5 and 6 for them. Thus, they're not constant offset to + * the channel number as with other IC variants. + */ +static const struct iio_chan_spec bd79702_channels[] = { + BD79703_CHAN_ADDR(0, 1), + BD79703_CHAN_ADDR(1, 2), + BD79703_CHAN_ADDR(2, 5), + BD79703_CHAN_ADDR(3, 6), +}; + static const struct iio_chan_spec bd79703_channels[] = { BD79703_CHAN(0), BD79703_CHAN(1), @@ -94,13 +129,46 @@ static const struct iio_chan_spec bd79703_channels[] = { BD79703_CHAN(5), }; +static const struct bd7970x_chip_data bd79700_chip_data = { + .name = "bd79700", + .channels = bd79700_channels, + .num_channels = ARRAY_SIZE(bd79700_channels), + .has_vfs = false, +}; + +static const struct bd7970x_chip_data bd79701_chip_data = { + .name = "bd79701", + .channels = bd79701_channels, + .num_channels = ARRAY_SIZE(bd79701_channels), + .has_vfs = false, +}; + +static const struct bd7970x_chip_data bd79702_chip_data = { + .name = "bd79702", + .channels = bd79702_channels, + .num_channels = ARRAY_SIZE(bd79702_channels), + .has_vfs = true, +}; + +static const struct bd7970x_chip_data bd79703_chip_data = { + .name = "bd79703", + .channels = bd79703_channels, + .num_channels = ARRAY_SIZE(bd79703_channels), + .has_vfs = true, +}; + static int bd79703_probe(struct spi_device *spi) { + const struct bd7970x_chip_data *cd; struct device *dev = &spi->dev; struct bd79703_data *data; struct iio_dev *idev; int ret; + cd = spi_get_device_match_data(spi); + if (!cd) + return -ENODEV; + idev = devm_iio_device_alloc(dev, sizeof(*data)); if (!idev) return -ENOMEM; @@ -112,20 +180,30 @@ static int bd79703_probe(struct spi_device *spi) return dev_err_probe(dev, PTR_ERR(data->regmap), "Failed to initialize Regmap\n"); - ret = devm_regulator_get_enable(dev, "vcc"); - if (ret) - return dev_err_probe(dev, ret, "Failed to enable VCC\n"); - - ret = devm_regulator_get_enable_read_voltage(dev, "vfs"); - if (ret < 0) - return dev_err_probe(dev, ret, "Failed to get Vfs\n"); - + /* + * BD79703 has a separate VFS pin, whereas the BD79700 and BD79701 use + * VCC for their full-scale output voltage. + */ + if (cd->has_vfs) { + ret = devm_regulator_get_enable(dev, "vcc"); + if (ret) + return dev_err_probe(dev, ret, "Failed to enable VCC\n"); + + ret = devm_regulator_get_enable_read_voltage(dev, "vfs"); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to get Vfs\n"); + } else { + ret = devm_regulator_get_enable_read_voltage(dev, "vcc"); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to get VCC\n"); + } data->vfs = ret; - idev->channels = bd79703_channels; - idev->num_channels = ARRAY_SIZE(bd79703_channels); + + idev->channels = cd->channels; + idev->num_channels = cd->num_channels; idev->modes = INDIO_DIRECT_MODE; idev->info = &bd79703_info; - idev->name = "bd79703"; + idev->name = cd->name; /* Initialize all to output zero */ ret = regmap_write(data->regmap, BD79703_REG_OUT_ALL, 0); @@ -136,13 +214,19 @@ static int bd79703_probe(struct spi_device *spi) } static const struct spi_device_id bd79703_id[] = { - { "bd79703", }, + { "bd79700", (kernel_ulong_t)&bd79700_chip_data }, + { "bd79701", (kernel_ulong_t)&bd79701_chip_data }, + { "bd79702", (kernel_ulong_t)&bd79702_chip_data }, + { "bd79703", (kernel_ulong_t)&bd79703_chip_data }, { } }; MODULE_DEVICE_TABLE(spi, bd79703_id); static const struct of_device_id bd79703_of_match[] = { - { .compatible = "rohm,bd79703", }, + { .compatible = "rohm,bd79700", .data = &bd79700_chip_data }, + { .compatible = "rohm,bd79701", .data = &bd79701_chip_data }, + { .compatible = "rohm,bd79702", .data = &bd79702_chip_data }, + { .compatible = "rohm,bd79703", .data = &bd79703_chip_data }, { } }; MODULE_DEVICE_TABLE(of, bd79703_of_match); diff --git a/drivers/iio/dac/stm32-dac-core.c b/drivers/iio/dac/stm32-dac-core.c index 95ed5197d16f..8ef702917060 100644 --- a/drivers/iio/dac/stm32-dac-core.c +++ b/drivers/iio/dac/stm32-dac-core.c @@ -239,7 +239,7 @@ static const struct of_device_id stm32_dac_of_match[] = { .compatible = "st,stm32h7-dac-core", .data = (void *)&stm32h7_dac_cfg, }, - {}, + { } }; MODULE_DEVICE_TABLE(of, stm32_dac_of_match); diff --git a/drivers/iio/dac/stm32-dac.c b/drivers/iio/dac/stm32-dac.c index 3bfb368b3a23..344388338d9b 100644 --- a/drivers/iio/dac/stm32-dac.c +++ b/drivers/iio/dac/stm32-dac.c @@ -250,7 +250,7 @@ static const struct iio_chan_spec_ext_info stm32_dac_ext_info[] = { }, IIO_ENUM("powerdown_mode", IIO_SEPARATE, &stm32_dac_powerdown_mode_en), IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &stm32_dac_powerdown_mode_en), - {}, + { } }; #define STM32_DAC_CHANNEL(chan, name) { \ @@ -392,7 +392,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(stm32_dac_pm_ops, stm32_dac_suspend, static const struct of_device_id stm32_dac_of_match[] = { { .compatible = "st,stm32-dac", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, stm32_dac_of_match); diff --git a/drivers/iio/dac/ti-dac082s085.c b/drivers/iio/dac/ti-dac082s085.c index 8e1590e3cc8b..715870c8a9c4 100644 --- a/drivers/iio/dac/ti-dac082s085.c +++ b/drivers/iio/dac/ti-dac082s085.c @@ -161,7 +161,7 @@ static const struct iio_chan_spec_ext_info ti_dac_ext_info[] = { }, IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE, &ti_dac_powerdown_mode), IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ti_dac_powerdown_mode), - { }, + { } }; #define TI_DAC_CHANNEL(chan) { \ diff --git a/drivers/iio/dac/ti-dac5571.c b/drivers/iio/dac/ti-dac5571.c index c5162b72951a..bdc3f94aef98 100644 --- a/drivers/iio/dac/ti-dac5571.c +++ b/drivers/iio/dac/ti-dac5571.c @@ -216,7 +216,7 @@ static const struct iio_chan_spec_ext_info dac5571_ext_info[] = { }, IIO_ENUM("powerdown_mode", IIO_SEPARATE, &dac5571_powerdown_mode), IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &dac5571_powerdown_mode), - {}, + { } }; #define dac5571_CHANNEL(chan, name) { \ @@ -398,7 +398,7 @@ static const struct of_device_id dac5571_of_id[] = { {.compatible = "ti,dac5573", .data = &dac5571_spec[quad_8bit] }, {.compatible = "ti,dac6573", .data = &dac5571_spec[quad_10bit] }, {.compatible = "ti,dac7573", .data = &dac5571_spec[quad_12bit] }, - {} + { } }; MODULE_DEVICE_TABLE(of, dac5571_of_id); @@ -414,7 +414,7 @@ static const struct i2c_device_id dac5571_id[] = { {"dac5573", (kernel_ulong_t)&dac5571_spec[quad_8bit] }, {"dac6573", (kernel_ulong_t)&dac5571_spec[quad_10bit] }, {"dac7573", (kernel_ulong_t)&dac5571_spec[quad_12bit] }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, dac5571_id); diff --git a/drivers/iio/dac/ti-dac7311.c b/drivers/iio/dac/ti-dac7311.c index 6f4aa4794a0c..3d2ce61f0db6 100644 --- a/drivers/iio/dac/ti-dac7311.c +++ b/drivers/iio/dac/ti-dac7311.c @@ -147,7 +147,7 @@ static const struct iio_chan_spec_ext_info ti_dac_ext_info[] = { }, IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE, &ti_dac_powerdown_mode), IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ti_dac_powerdown_mode), - { }, + { } }; #define TI_DAC_CHANNEL(chan) { \ diff --git a/drivers/iio/dac/ti-dac7612.c b/drivers/iio/dac/ti-dac7612.c index 8195815de26f..c308eca02b88 100644 --- a/drivers/iio/dac/ti-dac7612.c +++ b/drivers/iio/dac/ti-dac7612.c @@ -166,7 +166,7 @@ static int dac7612_probe(struct spi_device *spi) static const struct spi_device_id dac7612_id[] = { {"ti-dac7612"}, - {} + { } }; MODULE_DEVICE_TABLE(spi, dac7612_id); @@ -174,7 +174,7 @@ static const struct of_device_id dac7612_of_match[] = { { .compatible = "ti,dac7612" }, { .compatible = "ti,dac7612u" }, { .compatible = "ti,dac7612ub" }, - { }, + { } }; MODULE_DEVICE_TABLE(of, dac7612_of_match); diff --git a/drivers/iio/dac/vf610_dac.c b/drivers/iio/dac/vf610_dac.c index 82a078fa98ad..b30ff7bb4400 100644 --- a/drivers/iio/dac/vf610_dac.c +++ b/drivers/iio/dac/vf610_dac.c @@ -99,7 +99,7 @@ static const struct iio_enum vf610_conversion_mode = { static const struct iio_chan_spec_ext_info vf610_ext_info[] = { IIO_ENUM("conversion_mode", IIO_SHARED_BY_DIR, &vf610_conversion_mode), - {}, + { } }; #define VF610_DAC_CHAN(_chan_type) { \ @@ -166,7 +166,7 @@ static const struct iio_info vf610_dac_iio_info = { static const struct of_device_id vf610_dac_match[] = { { .compatible = "fsl,vf610-dac", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, vf610_dac_match); diff --git a/drivers/iio/dummy/iio_simple_dummy_buffer.c b/drivers/iio/dummy/iio_simple_dummy_buffer.c index 288880346707..e35e0596cbfb 100644 --- a/drivers/iio/dummy/iio_simple_dummy_buffer.c +++ b/drivers/iio/dummy/iio_simple_dummy_buffer.c @@ -31,6 +31,11 @@ static const s16 fakedata[] = { [DUMMY_INDEX_ACCELX] = 344, }; +struct dummy_scan { + s16 data[ARRAY_SIZE(fakedata)]; + aligned_s64 timestamp; +}; + /** * iio_simple_dummy_trigger_h() - the trigger handler function * @irq: the interrupt number @@ -45,11 +50,18 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) { struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; + struct dummy_scan *scan; int i = 0, j; - u16 *data; - data = kzalloc(indio_dev->scan_bytes, GFP_KERNEL); - if (!data) + /* + * Note that some buses such as SPI require DMA safe buffers which + * cannot be on the stack. Two easy ways to do this: + * - Local kzalloc (as done here) + * - A buffer at the end of the structure accessed via iio_priv() + * that is marked __aligned(IIO_DMA_MINALIGN). + */ + scan = kzalloc(sizeof(*scan), GFP_KERNEL); + if (!scan) goto done; /* @@ -69,13 +81,12 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) * constant table fakedata. */ iio_for_each_active_channel(indio_dev, j) - data[i++] = fakedata[j]; - - iio_push_to_buffers_with_timestamp(indio_dev, data, - iio_get_time_ns(indio_dev)); + scan->data[i++] = fakedata[j]; - kfree(data); + iio_push_to_buffers_with_ts(indio_dev, scan, sizeof(*scan), + iio_get_time_ns(indio_dev)); + kfree(scan); done: /* * Tell the core we are done with this trigger and ready for the diff --git a/drivers/iio/filter/admv8818.c b/drivers/iio/filter/admv8818.c index d85b7d3de866..19f823446cda 100644 --- a/drivers/iio/filter/admv8818.c +++ b/drivers/iio/filter/admv8818.c @@ -14,6 +14,7 @@ #include <linux/mod_devicetable.h> #include <linux/mutex.h> #include <linux/notifier.h> +#include <linux/property.h> #include <linux/regmap.h> #include <linux/spi/spi.h> #include <linux/units.h> @@ -70,6 +71,16 @@ #define ADMV8818_HPF_WR0_MSK GENMASK(7, 4) #define ADMV8818_LPF_WR0_MSK GENMASK(3, 0) +#define ADMV8818_BAND_BYPASS 0 +#define ADMV8818_BAND_MIN 1 +#define ADMV8818_BAND_MAX 4 +#define ADMV8818_BAND_CORNER_LOW 0 +#define ADMV8818_BAND_CORNER_HIGH 1 + +#define ADMV8818_STATE_MIN 0 +#define ADMV8818_STATE_MAX 15 +#define ADMV8818_NUM_STATES 16 + enum { ADMV8818_BW_FREQ, ADMV8818_CENTER_FREQ @@ -90,20 +101,24 @@ struct admv8818_state { struct mutex lock; unsigned int filter_mode; u64 cf_hz; + u64 lpf_margin_hz; + u64 hpf_margin_hz; }; -static const unsigned long long freq_range_hpf[4][2] = { +static const unsigned long long freq_range_hpf[5][2] = { + {0ULL, 0ULL}, /* bypass */ {1750000000ULL, 3550000000ULL}, {3400000000ULL, 7250000000ULL}, {6600000000, 12000000000}, {12500000000, 19900000000} }; -static const unsigned long long freq_range_lpf[4][2] = { +static const unsigned long long freq_range_lpf[5][2] = { + {U64_MAX, U64_MAX}, /* bypass */ {2050000000ULL, 3850000000ULL}, {3350000000ULL, 7250000000ULL}, {7000000000, 13000000000}, - {12550000000, 18500000000} + {12550000000, 18850000000} }; static const struct regmap_config admv8818_regmap_config = { @@ -121,44 +136,59 @@ static const char * const admv8818_modes[] = { static int __admv8818_hpf_select(struct admv8818_state *st, u64 freq) { - unsigned int hpf_step = 0, hpf_band = 0, i, j; - u64 freq_step; - int ret; + int band, state, ret; + unsigned int hpf_state = ADMV8818_STATE_MIN, hpf_band = ADMV8818_BAND_BYPASS; + u64 freq_error, min_freq_error, freq_corner, freq_step; - if (freq < freq_range_hpf[0][0]) + if (freq < freq_range_hpf[ADMV8818_BAND_MIN][ADMV8818_BAND_CORNER_LOW]) goto hpf_write; - if (freq > freq_range_hpf[3][1]) { - hpf_step = 15; - hpf_band = 4; - + if (freq >= freq_range_hpf[ADMV8818_BAND_MAX][ADMV8818_BAND_CORNER_HIGH]) { + hpf_state = ADMV8818_STATE_MAX; + hpf_band = ADMV8818_BAND_MAX; goto hpf_write; } - for (i = 0; i < 4; i++) { - freq_step = div_u64((freq_range_hpf[i][1] - - freq_range_hpf[i][0]), 15); + /* Close HPF frequency gap between 12 and 12.5 GHz */ + if (freq >= 12000ULL * HZ_PER_MHZ && freq < 12500ULL * HZ_PER_MHZ) { + hpf_state = ADMV8818_STATE_MAX; + hpf_band = 3; + goto hpf_write; + } - if (freq > freq_range_hpf[i][0] && - (freq < freq_range_hpf[i][1] + freq_step)) { - hpf_band = i + 1; + min_freq_error = U64_MAX; + for (band = ADMV8818_BAND_MIN; band <= ADMV8818_BAND_MAX; band++) { + /* + * This (and therefore all other ranges) have a corner + * frequency higher than the target frequency. + */ + if (freq_range_hpf[band][ADMV8818_BAND_CORNER_LOW] > freq) + break; - for (j = 1; j <= 16; j++) { - if (freq < (freq_range_hpf[i][0] + (freq_step * j))) { - hpf_step = j - 1; - break; - } + freq_step = freq_range_hpf[band][ADMV8818_BAND_CORNER_HIGH] - + freq_range_hpf[band][ADMV8818_BAND_CORNER_LOW]; + freq_step = div_u64(freq_step, ADMV8818_NUM_STATES - 1); + + for (state = ADMV8818_STATE_MIN; state <= ADMV8818_STATE_MAX; state++) { + freq_corner = freq_range_hpf[band][ADMV8818_BAND_CORNER_LOW] + + freq_step * state; + + /* + * This (and therefore all other states) have a corner + * frequency higher than the target frequency. + */ + if (freq_corner > freq) + break; + + freq_error = freq - freq_corner; + if (freq_error < min_freq_error) { + min_freq_error = freq_error; + hpf_state = state; + hpf_band = band; } - break; } } - /* Close HPF frequency gap between 12 and 12.5 GHz */ - if (freq >= 12000 * HZ_PER_MHZ && freq <= 12500 * HZ_PER_MHZ) { - hpf_band = 3; - hpf_step = 15; - } - hpf_write: ret = regmap_update_bits(st->regmap, ADMV8818_REG_WR0_SW, ADMV8818_SW_IN_SET_WR0_MSK | @@ -170,7 +200,7 @@ hpf_write: return regmap_update_bits(st->regmap, ADMV8818_REG_WR0_FILTER, ADMV8818_HPF_WR0_MSK, - FIELD_PREP(ADMV8818_HPF_WR0_MSK, hpf_step)); + FIELD_PREP(ADMV8818_HPF_WR0_MSK, hpf_state)); } static int admv8818_hpf_select(struct admv8818_state *st, u64 freq) @@ -186,31 +216,52 @@ static int admv8818_hpf_select(struct admv8818_state *st, u64 freq) static int __admv8818_lpf_select(struct admv8818_state *st, u64 freq) { - unsigned int lpf_step = 0, lpf_band = 0, i, j; - u64 freq_step; - int ret; + int band, state, ret; + unsigned int lpf_state = ADMV8818_STATE_MIN, lpf_band = ADMV8818_BAND_BYPASS; + u64 freq_error, min_freq_error, freq_corner, freq_step; - if (freq > freq_range_lpf[3][1]) + if (freq > freq_range_lpf[ADMV8818_BAND_MAX][ADMV8818_BAND_CORNER_HIGH]) goto lpf_write; - if (freq < freq_range_lpf[0][0]) { - lpf_band = 1; - + if (freq < freq_range_lpf[ADMV8818_BAND_MIN][ADMV8818_BAND_CORNER_LOW]) { + lpf_state = ADMV8818_STATE_MIN; + lpf_band = ADMV8818_BAND_MIN; goto lpf_write; } - for (i = 0; i < 4; i++) { - if (freq > freq_range_lpf[i][0] && freq < freq_range_lpf[i][1]) { - lpf_band = i + 1; - freq_step = div_u64((freq_range_lpf[i][1] - freq_range_lpf[i][0]), 15); + min_freq_error = U64_MAX; + for (band = ADMV8818_BAND_MAX; band >= ADMV8818_BAND_MIN; --band) { + /* + * At this point the highest corner frequency of + * all remaining ranges is below the target. + * LPF corner should be >= the target. + */ + if (freq > freq_range_lpf[band][ADMV8818_BAND_CORNER_HIGH]) + break; + + freq_step = freq_range_lpf[band][ADMV8818_BAND_CORNER_HIGH] - + freq_range_lpf[band][ADMV8818_BAND_CORNER_LOW]; + freq_step = div_u64(freq_step, ADMV8818_NUM_STATES - 1); + + for (state = ADMV8818_STATE_MAX; state >= ADMV8818_STATE_MIN; --state) { + + freq_corner = freq_range_lpf[band][ADMV8818_BAND_CORNER_LOW] + + state * freq_step; - for (j = 0; j <= 15; j++) { - if (freq < (freq_range_lpf[i][0] + (freq_step * j))) { - lpf_step = j; - break; - } + /* + * At this point all other states in range will + * place the corner frequency below the target + * LPF corner should >= the target. + */ + if (freq > freq_corner) + break; + + freq_error = freq_corner - freq; + if (freq_error < min_freq_error) { + min_freq_error = freq_error; + lpf_state = state; + lpf_band = band; } - break; } } @@ -225,7 +276,7 @@ lpf_write: return regmap_update_bits(st->regmap, ADMV8818_REG_WR0_FILTER, ADMV8818_LPF_WR0_MSK, - FIELD_PREP(ADMV8818_LPF_WR0_MSK, lpf_step)); + FIELD_PREP(ADMV8818_LPF_WR0_MSK, lpf_state)); } static int admv8818_lpf_select(struct admv8818_state *st, u64 freq) @@ -242,16 +293,28 @@ static int admv8818_lpf_select(struct admv8818_state *st, u64 freq) static int admv8818_rfin_band_select(struct admv8818_state *st) { int ret; + u64 hpf_corner_target, lpf_corner_target; st->cf_hz = clk_get_rate(st->clkin); + /* Check for underflow */ + if (st->cf_hz > st->hpf_margin_hz) + hpf_corner_target = st->cf_hz - st->hpf_margin_hz; + else + hpf_corner_target = 0; + + /* Check for overflow */ + lpf_corner_target = st->cf_hz + st->lpf_margin_hz; + if (lpf_corner_target < st->cf_hz) + lpf_corner_target = U64_MAX; + mutex_lock(&st->lock); - ret = __admv8818_hpf_select(st, st->cf_hz); + ret = __admv8818_hpf_select(st, hpf_corner_target); if (ret) goto exit; - ret = __admv8818_lpf_select(st, st->cf_hz); + ret = __admv8818_lpf_select(st, lpf_corner_target); exit: mutex_unlock(&st->lock); return ret; @@ -278,8 +341,11 @@ static int __admv8818_read_hpf_freq(struct admv8818_state *st, u64 *hpf_freq) hpf_state = FIELD_GET(ADMV8818_HPF_WR0_MSK, data); - *hpf_freq = div_u64(freq_range_hpf[hpf_band - 1][1] - freq_range_hpf[hpf_band - 1][0], 15); - *hpf_freq = freq_range_hpf[hpf_band - 1][0] + (*hpf_freq * hpf_state); + *hpf_freq = freq_range_hpf[hpf_band][ADMV8818_BAND_CORNER_HIGH] - + freq_range_hpf[hpf_band][ADMV8818_BAND_CORNER_LOW]; + *hpf_freq = div_u64(*hpf_freq, ADMV8818_NUM_STATES - 1); + *hpf_freq = freq_range_hpf[hpf_band][ADMV8818_BAND_CORNER_LOW] + + (*hpf_freq * hpf_state); return ret; } @@ -316,8 +382,11 @@ static int __admv8818_read_lpf_freq(struct admv8818_state *st, u64 *lpf_freq) lpf_state = FIELD_GET(ADMV8818_LPF_WR0_MSK, data); - *lpf_freq = div_u64(freq_range_lpf[lpf_band - 1][1] - freq_range_lpf[lpf_band - 1][0], 15); - *lpf_freq = freq_range_lpf[lpf_band - 1][0] + (*lpf_freq * lpf_state); + *lpf_freq = freq_range_lpf[lpf_band][ADMV8818_BAND_CORNER_HIGH] - + freq_range_lpf[lpf_band][ADMV8818_BAND_CORNER_LOW]; + *lpf_freq = div_u64(*lpf_freq, ADMV8818_NUM_STATES - 1); + *lpf_freq = freq_range_lpf[lpf_band][ADMV8818_BAND_CORNER_LOW] + + (*lpf_freq * lpf_state); return ret; } @@ -333,6 +402,19 @@ static int admv8818_read_lpf_freq(struct admv8818_state *st, u64 *lpf_freq) return ret; } +static int admv8818_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: + return IIO_VAL_INT_64; + default: + return -EINVAL; + } +} + static int admv8818_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long info) @@ -341,6 +423,9 @@ static int admv8818_write_raw(struct iio_dev *indio_dev, u64 freq = ((u64)val2 << 32 | (u32)val); + if ((s64)freq < 0) + return -EINVAL; + switch (info) { case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: return admv8818_lpf_select(st, freq); @@ -502,6 +587,7 @@ set_mode: static const struct iio_info admv8818_info = { .write_raw = admv8818_write_raw, + .write_raw_get_fmt = admv8818_write_raw_get_fmt, .read_raw = admv8818_read_raw, .debugfs_reg_access = &admv8818_reg_access, }; @@ -516,7 +602,7 @@ static const struct iio_enum admv8818_mode_enum = { static const struct iio_chan_spec_ext_info admv8818_ext_info[] = { IIO_ENUM("filter_mode", IIO_SHARED_BY_ALL, &admv8818_mode_enum), IIO_ENUM_AVAILABLE("filter_mode", IIO_SHARED_BY_ALL, &admv8818_mode_enum), - { }, + { } }; #define ADMV8818_CHAN(_channel) { \ @@ -641,6 +727,32 @@ static int admv8818_clk_setup(struct admv8818_state *st) return devm_add_action_or_reset(&spi->dev, admv8818_clk_notifier_unreg, st); } +static int admv8818_read_properties(struct admv8818_state *st) +{ + struct spi_device *spi = st->spi; + u32 mhz; + int ret; + + ret = device_property_read_u32(&spi->dev, "adi,lpf-margin-mhz", &mhz); + if (ret == 0) + st->lpf_margin_hz = (u64)mhz * HZ_PER_MHZ; + else if (ret == -EINVAL) + st->lpf_margin_hz = 0; + else + return ret; + + + ret = device_property_read_u32(&spi->dev, "adi,hpf-margin-mhz", &mhz); + if (ret == 0) + st->hpf_margin_hz = (u64)mhz * HZ_PER_MHZ; + else if (ret == -EINVAL) + st->hpf_margin_hz = 0; + else if (ret < 0) + return ret; + + return 0; +} + static int admv8818_probe(struct spi_device *spi) { struct iio_dev *indio_dev; @@ -672,6 +784,10 @@ static int admv8818_probe(struct spi_device *spi) mutex_init(&st->lock); + ret = admv8818_read_properties(st); + if (ret) + return ret; + ret = admv8818_init(st); if (ret) return ret; @@ -681,13 +797,13 @@ static int admv8818_probe(struct spi_device *spi) static const struct spi_device_id admv8818_id[] = { { "admv8818", 0 }, - {} + { } }; MODULE_DEVICE_TABLE(spi, admv8818_id); static const struct of_device_id admv8818_of_match[] = { { .compatible = "adi,admv8818" }, - {} + { } }; MODULE_DEVICE_TABLE(of, admv8818_of_match); diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c index b1554ced7a26..63c485e9e44c 100644 --- a/drivers/iio/frequency/ad9523.c +++ b/drivers/iio/frequency/ad9523.c @@ -1032,7 +1032,7 @@ static int ad9523_probe(struct spi_device *spi) static const struct spi_device_id ad9523_id[] = { {"ad9523-1", 9523}, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad9523_id); diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index 61828e61e275..47f1c7e9efa9 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -373,7 +373,7 @@ static const struct iio_chan_spec_ext_info adf4350_ext_info[] = { _ADF4350_EXT_INFO("frequency_resolution", ADF4350_FREQ_RESOLUTION), _ADF4350_EXT_INFO("refin_frequency", ADF4350_FREQ_REFIN), _ADF4350_EXT_INFO("powerdown", ADF4350_PWRDOWN), - { }, + { } }; static const struct iio_chan_spec adf4350_chan = { @@ -682,14 +682,14 @@ static int adf4350_probe(struct spi_device *spi) static const struct of_device_id adf4350_of_match[] = { { .compatible = "adi,adf4350", }, { .compatible = "adi,adf4351", }, - { /* sentinel */ }, + { } }; MODULE_DEVICE_TABLE(of, adf4350_of_match); static const struct spi_device_id adf4350_id[] = { {"adf4350", 4350}, {"adf4351", 4351}, - {} + { } }; MODULE_DEVICE_TABLE(spi, adf4350_id); diff --git a/drivers/iio/frequency/adf4371.c b/drivers/iio/frequency/adf4371.c index 9a84e81787b1..d6dc7827fb41 100644 --- a/drivers/iio/frequency/adf4371.c +++ b/drivers/iio/frequency/adf4371.c @@ -438,7 +438,7 @@ static const struct iio_chan_spec_ext_info adf4371_ext_info[] = { _ADF4371_EXT_INFO("frequency", ADF4371_FREQ), _ADF4371_EXT_INFO("powerdown", ADF4371_POWER_DOWN), _ADF4371_EXT_INFO("name", ADF4371_CHANNEL_NAME), - { }, + { } }; #define ADF4371_CHANNEL(index) { \ @@ -626,14 +626,14 @@ static int adf4371_probe(struct spi_device *spi) static const struct spi_device_id adf4371_id_table[] = { { "adf4371", (kernel_ulong_t)&adf4371_chip_info }, { "adf4372", (kernel_ulong_t)&adf4372_chip_info }, - {} + { } }; MODULE_DEVICE_TABLE(spi, adf4371_id_table); static const struct of_device_id adf4371_of_match[] = { { .compatible = "adi,adf4371", .data = &adf4371_chip_info }, { .compatible = "adi,adf4372", .data = &adf4372_chip_info}, - { }, + { } }; MODULE_DEVICE_TABLE(of, adf4371_of_match); diff --git a/drivers/iio/frequency/adf4377.c b/drivers/iio/frequency/adf4377.c index 45ceeb828d6b..08833b7035e4 100644 --- a/drivers/iio/frequency/adf4377.c +++ b/drivers/iio/frequency/adf4377.c @@ -985,14 +985,14 @@ static int adf4377_probe(struct spi_device *spi) static const struct spi_device_id adf4377_id[] = { { "adf4377", (kernel_ulong_t)&adf4377_chip_info }, { "adf4378", (kernel_ulong_t)&adf4378_chip_info }, - {} + { } }; MODULE_DEVICE_TABLE(spi, adf4377_id); static const struct of_device_id adf4377_of_match[] = { { .compatible = "adi,adf4377", .data = &adf4377_chip_info }, { .compatible = "adi,adf4378", .data = &adf4378_chip_info }, - {} + { } }; MODULE_DEVICE_TABLE(of, adf4377_of_match); diff --git a/drivers/iio/frequency/admv1013.c b/drivers/iio/frequency/admv1013.c index 8ef583680ad0..d8e8d541990f 100644 --- a/drivers/iio/frequency/admv1013.c +++ b/drivers/iio/frequency/admv1013.c @@ -319,7 +319,7 @@ static ssize_t admv1013_write(struct iio_dev *indio_dev, return -EINVAL; } - return ret ? ret : len; + return len; } static int admv1013_update_quad_filters(struct admv1013_state *st) @@ -407,7 +407,7 @@ static int admv1013_freq_change(struct notifier_block *nb, unsigned long action, static const struct iio_chan_spec_ext_info admv1013_ext_info[] = { _ADMV1013_EXT_INFO("i_calibphase", IIO_SEPARATE, ADMV1013_RFMOD_I_CALIBPHASE), _ADMV1013_EXT_INFO("q_calibphase", IIO_SEPARATE, ADMV1013_RFMOD_Q_CALIBPHASE), - { }, + { } }; #define ADMV1013_CHAN_PHASE(_channel, _channel2, _admv1013_ext_info) { \ @@ -615,13 +615,13 @@ static int admv1013_probe(struct spi_device *spi) static const struct spi_device_id admv1013_id[] = { { "admv1013", 0 }, - {} + { } }; MODULE_DEVICE_TABLE(spi, admv1013_id); static const struct of_device_id admv1013_of_match[] = { { .compatible = "adi,admv1013" }, - {}, + { } }; MODULE_DEVICE_TABLE(of, admv1013_of_match); diff --git a/drivers/iio/frequency/admv1014.c b/drivers/iio/frequency/admv1014.c index 986b87a72577..7a8f92ec80a2 100644 --- a/drivers/iio/frequency/admv1014.c +++ b/drivers/iio/frequency/admv1014.c @@ -792,13 +792,13 @@ static int admv1014_probe(struct spi_device *spi) static const struct spi_device_id admv1014_id[] = { { "admv1014", 0 }, - {} + { } }; MODULE_DEVICE_TABLE(spi, admv1014_id); static const struct of_device_id admv1014_of_match[] = { { .compatible = "adi,admv1014" }, - {} + { } }; MODULE_DEVICE_TABLE(of, admv1014_of_match); diff --git a/drivers/iio/frequency/adrf6780.c b/drivers/iio/frequency/adrf6780.c index 57ee908fc747..a7a21f929970 100644 --- a/drivers/iio/frequency/adrf6780.c +++ b/drivers/iio/frequency/adrf6780.c @@ -487,13 +487,13 @@ static int adrf6780_probe(struct spi_device *spi) static const struct spi_device_id adrf6780_id[] = { { "adrf6780", 0 }, - {} + { } }; MODULE_DEVICE_TABLE(spi, adrf6780_id); static const struct of_device_id adrf6780_of_match[] = { { .compatible = "adi,adrf6780" }, - {} + { } }; MODULE_DEVICE_TABLE(of, adrf6780_of_match); diff --git a/drivers/iio/gyro/adis16080.c b/drivers/iio/gyro/adis16080.c index 14b3abf6dce9..178bba95a709 100644 --- a/drivers/iio/gyro/adis16080.c +++ b/drivers/iio/gyro/adis16080.c @@ -214,7 +214,7 @@ static int adis16080_probe(struct spi_device *spi) static const struct spi_device_id adis16080_ids[] = { { "adis16080", ID_ADIS16080 }, { "adis16100", ID_ADIS16100 }, - {}, + { } }; MODULE_DEVICE_TABLE(spi, adis16080_ids); diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c index c151fbb59ffe..586e6cfa14a9 100644 --- a/drivers/iio/gyro/adis16260.c +++ b/drivers/iio/gyro/adis16260.c @@ -414,7 +414,7 @@ static const struct spi_device_id adis16260_id[] = { {"adis16250", ADIS16260}, {"adis16255", ADIS16260}, {"adis16251", ADIS16251}, - {} + { } }; MODULE_DEVICE_TABLE(spi, adis16260_id); diff --git a/drivers/iio/gyro/adxrs290.c b/drivers/iio/gyro/adxrs290.c index 223fc181109c..8fcb41f45baa 100644 --- a/drivers/iio/gyro/adxrs290.c +++ b/drivers/iio/gyro/adxrs290.c @@ -290,9 +290,8 @@ static int adxrs290_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; switch (chan->type) { case IIO_ANGL_VEL: @@ -316,7 +315,7 @@ static int adxrs290_read_raw(struct iio_dev *indio_dev, break; } - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; case IIO_CHAN_INFO_SCALE: switch (chan->type) { @@ -366,9 +365,8 @@ static int adxrs290_write_raw(struct iio_dev *indio_dev, struct adxrs290_state *st = iio_priv(indio_dev); int ret, lpf_idx, hpf_idx; - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; switch (mask) { case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: @@ -408,7 +406,7 @@ static int adxrs290_write_raw(struct iio_dev *indio_dev, break; } - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; } diff --git a/drivers/iio/gyro/adxrs450.c b/drivers/iio/gyro/adxrs450.c index f84438e0c42c..a1d8d3cb301b 100644 --- a/drivers/iio/gyro/adxrs450.c +++ b/drivers/iio/gyro/adxrs450.c @@ -95,12 +95,10 @@ static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev, struct spi_transfer xfers[] = { { .tx_buf = &st->tx, - .bits_per_word = 8, .len = sizeof(st->tx), .cs_change = 1, }, { .rx_buf = &st->rx, - .bits_per_word = 8, .len = sizeof(st->rx), }, }; @@ -169,12 +167,10 @@ static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val) struct spi_transfer xfers[] = { { .tx_buf = &st->tx, - .bits_per_word = 8, .len = sizeof(st->tx), .cs_change = 1, }, { .rx_buf = &st->rx, - .bits_per_word = 8, .len = sizeof(st->rx), }, }; @@ -209,7 +205,6 @@ static int adxrs450_spi_initial(struct adxrs450_state *st, struct spi_transfer xfers = { .tx_buf = &st->tx, .rx_buf = &st->rx, - .bits_per_word = 8, .len = sizeof(st->tx), }; @@ -446,7 +441,7 @@ static int adxrs450_probe(struct spi_device *spi) static const struct spi_device_id adxrs450_id[] = { {"adxrs450", ID_ADXRS450}, {"adxrs453", ID_ADXRS453}, - {} + { } }; MODULE_DEVICE_TABLE(spi, adxrs450_id); diff --git a/drivers/iio/gyro/bmg160_i2c.c b/drivers/iio/gyro/bmg160_i2c.c index e6caab49f98a..1fb8a7969c25 100644 --- a/drivers/iio/gyro/bmg160_i2c.c +++ b/drivers/iio/gyro/bmg160_i2c.c @@ -41,7 +41,7 @@ static void bmg160_i2c_remove(struct i2c_client *client) static const struct acpi_device_id bmg160_acpi_match[] = { {"BMG0160", 0}, - {}, + { } }; MODULE_DEVICE_TABLE(acpi, bmg160_acpi_match); @@ -50,7 +50,7 @@ static const struct i2c_device_id bmg160_i2c_id[] = { { "bmg160" }, { "bmi055_gyro" }, { "bmi088_gyro" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, bmg160_i2c_id); diff --git a/drivers/iio/gyro/bmg160_spi.c b/drivers/iio/gyro/bmg160_spi.c index ac04b3b1b554..6aecc5eb8347 100644 --- a/drivers/iio/gyro/bmg160_spi.c +++ b/drivers/iio/gyro/bmg160_spi.c @@ -36,7 +36,7 @@ static const struct spi_device_id bmg160_spi_id[] = { {"bmg160", 0}, {"bmi055_gyro", 0}, {"bmi088_gyro", 0}, - {} + { } }; MODULE_DEVICE_TABLE(spi, bmg160_spi_id); diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c index 54b6f6fbdcaa..c43990c518f7 100644 --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c @@ -375,7 +375,7 @@ static const struct platform_device_id hid_gyro_3d_ids[] = { /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ .name = "HID-SENSOR-200076", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(platform, hid_gyro_3d_ids); diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c index d66224bed8e3..16553948c5c3 100644 --- a/drivers/iio/gyro/mpu3050-core.c +++ b/drivers/iio/gyro/mpu3050-core.c @@ -684,7 +684,7 @@ mpu3050_get_mount_matrix(const struct iio_dev *indio_dev, static const struct iio_chan_spec_ext_info mpu3050_ext_info[] = { IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE, mpu3050_get_mount_matrix), - { }, + { } }; #define MPU3050_AXIS_CHANNEL(axis, index) \ diff --git a/drivers/iio/gyro/mpu3050-i2c.c b/drivers/iio/gyro/mpu3050-i2c.c index 29ecfa6fd633..8e284f47242c 100644 --- a/drivers/iio/gyro/mpu3050-i2c.c +++ b/drivers/iio/gyro/mpu3050-i2c.c @@ -95,7 +95,7 @@ static void mpu3050_i2c_remove(struct i2c_client *client) */ static const struct i2c_device_id mpu3050_i2c_id[] = { { "mpu3050" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, mpu3050_i2c_id); @@ -103,7 +103,7 @@ static const struct of_device_id mpu3050_i2c_of_match[] = { { .compatible = "invensense,mpu3050", .data = "mpu3050" }, /* Deprecated vendor ID from the Input driver */ { .compatible = "invn,mpu3050", .data = "mpu3050" }, - { }, + { } }; MODULE_DEVICE_TABLE(of, mpu3050_i2c_of_match); diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c index d4b11bdba666..aef5ec8f9dee 100644 --- a/drivers/iio/gyro/st_gyro_i2c.c +++ b/drivers/iio/gyro/st_gyro_i2c.c @@ -54,7 +54,7 @@ static const struct of_device_id st_gyro_of_match[] = { .compatible = "st,lsm9ds0-gyro", .data = LSM9DS0_GYRO_DEV_NAME, }, - {}, + { } }; MODULE_DEVICE_TABLE(of, st_gyro_of_match); @@ -102,7 +102,7 @@ static const struct i2c_device_id st_gyro_id_table[] = { { L3G4IS_GYRO_DEV_NAME }, { LSM330_GYRO_DEV_NAME }, { LSM9DS0_GYRO_DEV_NAME }, - {}, + { } }; MODULE_DEVICE_TABLE(i2c, st_gyro_id_table); diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c index 811f712711f5..f645da157372 100644 --- a/drivers/iio/gyro/st_gyro_spi.c +++ b/drivers/iio/gyro/st_gyro_spi.c @@ -59,7 +59,7 @@ static const struct of_device_id st_gyro_of_match[] = { .compatible = "st,lsm9ds0-gyro", .data = LSM9DS0_GYRO_DEV_NAME, }, - {}, + { } }; MODULE_DEVICE_TABLE(of, st_gyro_of_match); @@ -107,7 +107,7 @@ static const struct spi_device_id st_gyro_id_table[] = { { L3G4IS_GYRO_DEV_NAME }, { LSM330_GYRO_DEV_NAME }, { LSM9DS0_GYRO_DEV_NAME }, - {}, + { } }; MODULE_DEVICE_TABLE(spi, st_gyro_id_table); diff --git a/drivers/iio/health/afe4403.c b/drivers/iio/health/afe4403.c index 13e1dd4dd62c..1582cfc03579 100644 --- a/drivers/iio/health/afe4403.c +++ b/drivers/iio/health/afe4403.c @@ -411,7 +411,7 @@ static const struct regmap_config afe4403_regmap_config = { static const struct of_device_id afe4403_of_match[] = { { .compatible = "ti,afe4403", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, afe4403_of_match); @@ -574,7 +574,7 @@ static int afe4403_probe(struct spi_device *spi) static const struct spi_device_id afe4403_ids[] = { { "afe4403", 0 }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(spi, afe4403_ids); diff --git a/drivers/iio/health/afe4404.c b/drivers/iio/health/afe4404.c index d49e1572a439..99ff68aed27c 100644 --- a/drivers/iio/health/afe4404.c +++ b/drivers/iio/health/afe4404.c @@ -419,7 +419,7 @@ static const struct regmap_config afe4404_regmap_config = { static const struct of_device_id afe4404_of_match[] = { { .compatible = "ti,afe4404", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, afe4404_of_match); @@ -581,7 +581,7 @@ static int afe4404_probe(struct i2c_client *client) static const struct i2c_device_id afe4404_ids[] = { { "afe4404" }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(i2c, afe4404_ids); diff --git a/drivers/iio/health/max30100.c b/drivers/iio/health/max30100.c index e08d143a707c..846664a4ee90 100644 --- a/drivers/iio/health/max30100.c +++ b/drivers/iio/health/max30100.c @@ -483,7 +483,7 @@ static void max30100_remove(struct i2c_client *client) static const struct i2c_device_id max30100_id[] = { { "max30100" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, max30100_id); diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c index 1d074eb6a8c5..f5f29d2fec57 100644 --- a/drivers/iio/health/max30102.c +++ b/drivers/iio/health/max30102.c @@ -484,11 +484,11 @@ any_mode_retry: * things cannot concurrently change. And we just keep * trying until we get one of the modes... */ - if (iio_device_claim_direct_mode(indio_dev)) + if (!iio_device_claim_direct(indio_dev)) goto any_mode_retry; ret = max30102_get_temp(data, val, true); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); } else { ret = max30102_get_temp(data, val, false); iio_device_release_buffer_mode(indio_dev); @@ -615,7 +615,7 @@ static const struct i2c_device_id max30102_id[] = { { "max30101", max30105 }, { "max30102", max30102 }, { "max30105", max30105 }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, max30102_id); diff --git a/drivers/iio/humidity/am2315.c b/drivers/iio/humidity/am2315.c index 2323974b805c..f021c3e6d886 100644 --- a/drivers/iio/humidity/am2315.c +++ b/drivers/iio/humidity/am2315.c @@ -253,7 +253,7 @@ static int am2315_probe(struct i2c_client *client) static const struct i2c_device_id am2315_i2c_id[] = { { "am2315" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, am2315_i2c_id); diff --git a/drivers/iio/humidity/hdc100x.c b/drivers/iio/humidity/hdc100x.c index a303f704b7ed..c2b36e682e06 100644 --- a/drivers/iio/humidity/hdc100x.c +++ b/drivers/iio/humidity/hdc100x.c @@ -13,6 +13,7 @@ * https://www.ti.com/product/HDC1080/datasheet */ +#include <linux/cleanup.h> #include <linux/delay.h> #include <linux/module.h> #include <linux/mod_devicetable.h> @@ -206,26 +207,20 @@ static int hdc100x_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_RAW: { int ret; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); if (chan->type == IIO_CURRENT) { *val = hdc100x_get_heater_status(data); - ret = IIO_VAL_INT; - } else { - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) { - mutex_unlock(&data->lock); - return ret; - } - - ret = hdc100x_get_measurement(data, chan); - iio_device_release_direct_mode(indio_dev); - if (ret >= 0) { - *val = ret; - ret = IIO_VAL_INT; - } + return IIO_VAL_INT; } - mutex_unlock(&data->lock); - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + + ret = hdc100x_get_measurement(data, chan); + iio_device_release_direct(indio_dev); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; } case IIO_CHAN_INFO_INT_TIME: *val = 0; @@ -256,26 +251,23 @@ static int hdc100x_write_raw(struct iio_dev *indio_dev, int val, int val2, long mask) { struct hdc100x_data *data = iio_priv(indio_dev); - int ret = -EINVAL; switch (mask) { - case IIO_CHAN_INFO_INT_TIME: + case IIO_CHAN_INFO_INT_TIME: { if (val != 0) return -EINVAL; - mutex_lock(&data->lock); - ret = hdc100x_set_it_time(data, chan->address, val2); - mutex_unlock(&data->lock); - return ret; - case IIO_CHAN_INFO_RAW: + guard(mutex)(&data->lock); + return hdc100x_set_it_time(data, chan->address, val2); + } + case IIO_CHAN_INFO_RAW: { if (chan->type != IIO_CURRENT || val2 != 0) return -EINVAL; - mutex_lock(&data->lock); - ret = hdc100x_update_config(data, HDC100X_REG_CONFIG_HEATER_EN, - val ? HDC100X_REG_CONFIG_HEATER_EN : 0); - mutex_unlock(&data->lock); - return ret; + guard(mutex)(&data->lock); + return hdc100x_update_config(data, HDC100X_REG_CONFIG_HEATER_EN, + val ? HDC100X_REG_CONFIG_HEATER_EN : 0); + } default: return -EINVAL; } @@ -284,27 +276,19 @@ static int hdc100x_write_raw(struct iio_dev *indio_dev, static int hdc100x_buffer_postenable(struct iio_dev *indio_dev) { struct hdc100x_data *data = iio_priv(indio_dev); - int ret; /* Buffer is enabled. First set ACQ Mode, then attach poll func */ - mutex_lock(&data->lock); - ret = hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE, - HDC100X_REG_CONFIG_ACQ_MODE); - mutex_unlock(&data->lock); - - return ret; + guard(mutex)(&data->lock); + return hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE, + HDC100X_REG_CONFIG_ACQ_MODE); } static int hdc100x_buffer_predisable(struct iio_dev *indio_dev) { struct hdc100x_data *data = iio_priv(indio_dev); - int ret; - mutex_lock(&data->lock); - ret = hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE, 0); - mutex_unlock(&data->lock); - - return ret; + guard(mutex)(&data->lock); + return hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE, 0); } static const struct iio_buffer_setup_ops hdc_buffer_setup_ops = { diff --git a/drivers/iio/humidity/hdc2010.c b/drivers/iio/humidity/hdc2010.c index f5867659e00f..894a8b4ab193 100644 --- a/drivers/iio/humidity/hdc2010.c +++ b/drivers/iio/humidity/hdc2010.c @@ -169,13 +169,12 @@ static int hdc2010_read_raw(struct iio_dev *indio_dev, *val = hdc2010_get_heater_status(data); return IIO_VAL_INT; } - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; mutex_lock(&data->lock); ret = hdc2010_get_prim_measurement_word(data, chan); mutex_unlock(&data->lock); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); if (ret < 0) return ret; *val = ret; @@ -184,13 +183,12 @@ static int hdc2010_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_PEAK: { int ret; - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; mutex_lock(&data->lock); ret = hdc2010_get_peak_measurement_byte(data, chan); mutex_unlock(&data->lock); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); if (ret < 0) return ret; /* Scaling up the value so we can use same offset as RAW */ diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c index a40e1eb6e98c..be2338d5f407 100644 --- a/drivers/iio/humidity/hid-sensor-humidity.c +++ b/drivers/iio/humidity/hid-sensor-humidity.c @@ -276,7 +276,7 @@ static const struct platform_device_id hid_humidity_ids[] = { /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ .name = "HID-SENSOR-200032", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(platform, hid_humidity_ids); diff --git a/drivers/iio/humidity/hts221_core.c b/drivers/iio/humidity/hts221_core.c index 0be11470730c..bfeb0a60d3af 100644 --- a/drivers/iio/humidity/hts221_core.c +++ b/drivers/iio/humidity/hts221_core.c @@ -418,31 +418,22 @@ static int hts221_read_oneshot(struct hts221_hw *hw, u8 addr, int *val) return IIO_VAL_INT; } -static int hts221_read_raw(struct iio_dev *iio_dev, - struct iio_chan_spec const *ch, - int *val, int *val2, long mask) +static int __hts221_read_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *ch, + int *val, int *val2, long mask) { struct hts221_hw *hw = iio_priv(iio_dev); - int ret; - - ret = iio_device_claim_direct_mode(iio_dev); - if (ret) - return ret; switch (mask) { case IIO_CHAN_INFO_RAW: - ret = hts221_read_oneshot(hw, ch->address, val); - break; + return hts221_read_oneshot(hw, ch->address, val); case IIO_CHAN_INFO_SCALE: - ret = hts221_get_sensor_scale(hw, ch->type, val, val2); - break; + return hts221_get_sensor_scale(hw, ch->type, val, val2); case IIO_CHAN_INFO_OFFSET: - ret = hts221_get_sensor_offset(hw, ch->type, val, val2); - break; + return hts221_get_sensor_offset(hw, ch->type, val, val2); case IIO_CHAN_INFO_SAMP_FREQ: *val = hw->odr; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; case IIO_CHAN_INFO_OVERSAMPLING_RATIO: { u8 idx; const struct hts221_avg *avg; @@ -452,64 +443,72 @@ static int hts221_read_raw(struct iio_dev *iio_dev, avg = &hts221_avg_list[HTS221_SENSOR_H]; idx = hw->sensors[HTS221_SENSOR_H].cur_avg_idx; *val = avg->avg_avl[idx]; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; case IIO_TEMP: avg = &hts221_avg_list[HTS221_SENSOR_T]; idx = hw->sensors[HTS221_SENSOR_T].cur_avg_idx; *val = avg->avg_avl[idx]; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; default: - ret = -EINVAL; - break; + return -EINVAL; } - break; } default: - ret = -EINVAL; - break; + return -EINVAL; } +} + +static int hts221_read_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *ch, + int *val, int *val2, long mask) +{ + int ret; + + if (!iio_device_claim_direct(iio_dev)) + return -EBUSY; - iio_device_release_direct_mode(iio_dev); + ret = __hts221_read_raw(iio_dev, ch, val, val2, mask); + + iio_device_release_direct(iio_dev); return ret; } -static int hts221_write_raw(struct iio_dev *iio_dev, - struct iio_chan_spec const *chan, - int val, int val2, long mask) +static int __hts221_write_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *chan, + int val, long mask) { struct hts221_hw *hw = iio_priv(iio_dev); - int ret; - - ret = iio_device_claim_direct_mode(iio_dev); - if (ret) - return ret; switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: - ret = hts221_update_odr(hw, val); - break; + return hts221_update_odr(hw, val); case IIO_CHAN_INFO_OVERSAMPLING_RATIO: switch (chan->type) { case IIO_HUMIDITYRELATIVE: - ret = hts221_update_avg(hw, HTS221_SENSOR_H, val); - break; + return hts221_update_avg(hw, HTS221_SENSOR_H, val); case IIO_TEMP: - ret = hts221_update_avg(hw, HTS221_SENSOR_T, val); - break; + return hts221_update_avg(hw, HTS221_SENSOR_T, val); default: - ret = -EINVAL; - break; + return -EINVAL; } - break; default: - ret = -EINVAL; - break; + return -EINVAL; } +} + +static int hts221_write_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + int ret; + + if (!iio_device_claim_direct(iio_dev)) + return -EBUSY; + + ret = __hts221_write_raw(iio_dev, chan, val, mask); - iio_device_release_direct_mode(iio_dev); + iio_device_release_direct(iio_dev); return ret; } diff --git a/drivers/iio/humidity/hts221_i2c.c b/drivers/iio/humidity/hts221_i2c.c index 87a8e3c8d277..cbaa7d1af6c4 100644 --- a/drivers/iio/humidity/hts221_i2c.c +++ b/drivers/iio/humidity/hts221_i2c.c @@ -42,19 +42,19 @@ static int hts221_i2c_probe(struct i2c_client *client) static const struct acpi_device_id hts221_acpi_match[] = { {"SMO9100", 0}, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, hts221_acpi_match); static const struct of_device_id hts221_i2c_of_match[] = { { .compatible = "st,hts221", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, hts221_i2c_of_match); static const struct i2c_device_id hts221_i2c_id_table[] = { { HTS221_DEV_NAME }, - {}, + { } }; MODULE_DEVICE_TABLE(i2c, hts221_i2c_id_table); diff --git a/drivers/iio/humidity/hts221_spi.c b/drivers/iio/humidity/hts221_spi.c index 00154b9d66b5..e6fef2acd523 100644 --- a/drivers/iio/humidity/hts221_spi.c +++ b/drivers/iio/humidity/hts221_spi.c @@ -42,13 +42,13 @@ static int hts221_spi_probe(struct spi_device *spi) static const struct of_device_id hts221_spi_of_match[] = { { .compatible = "st,hts221", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, hts221_spi_of_match); static const struct spi_device_id hts221_spi_id_table[] = { { HTS221_DEV_NAME }, - {}, + { } }; MODULE_DEVICE_TABLE(spi, hts221_spi_id_table); diff --git a/drivers/iio/humidity/htu21.c b/drivers/iio/humidity/htu21.c index 6402e393edb8..7f1775bd26fd 100644 --- a/drivers/iio/humidity/htu21.c +++ b/drivers/iio/humidity/htu21.c @@ -232,14 +232,14 @@ static int htu21_probe(struct i2c_client *client) static const struct i2c_device_id htu21_id[] = { {"htu21", HTU21}, {"ms8607-humidity", MS8607}, - {} + { } }; MODULE_DEVICE_TABLE(i2c, htu21_id); static const struct of_device_id htu21_of_match[] = { { .compatible = "meas,htu21", }, { .compatible = "meas,ms8607-humidity", }, - { }, + { } }; MODULE_DEVICE_TABLE(of, htu21_of_match); diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 0ea072a4c966..d160147cce0b 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -39,34 +39,29 @@ int __adis_write_reg(struct adis *adis, unsigned int reg, unsigned int value, struct spi_transfer xfers[] = { { .tx_buf = adis->tx, - .bits_per_word = 8, .len = 2, .cs_change = 1, .delay.value = adis->data->write_delay, .delay.unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 2, - .bits_per_word = 8, .len = 2, .cs_change = 1, .delay.value = adis->data->write_delay, .delay.unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 4, - .bits_per_word = 8, .len = 2, .cs_change = 1, .delay.value = adis->data->write_delay, .delay.unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 6, - .bits_per_word = 8, .len = 2, .delay.value = adis->data->write_delay, .delay.unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 8, - .bits_per_word = 8, .len = 2, .delay.value = adis->data->write_delay, .delay.unit = SPI_DELAY_UNIT_USECS, @@ -133,14 +128,12 @@ int __adis_read_reg(struct adis *adis, unsigned int reg, unsigned int *val, struct spi_transfer xfers[] = { { .tx_buf = adis->tx, - .bits_per_word = 8, .len = 2, .cs_change = 1, .delay.value = adis->data->write_delay, .delay.unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 2, - .bits_per_word = 8, .len = 2, .cs_change = 1, .delay.value = adis->data->read_delay, @@ -148,14 +141,12 @@ int __adis_read_reg(struct adis *adis, unsigned int reg, unsigned int *val, }, { .tx_buf = adis->tx + 4, .rx_buf = adis->rx, - .bits_per_word = 8, .len = 2, .cs_change = 1, .delay.value = adis->data->read_delay, .delay.unit = SPI_DELAY_UNIT_USECS, }, { .rx_buf = adis->rx + 2, - .bits_per_word = 8, .len = 2, .delay.value = adis->data->read_delay, .delay.unit = SPI_DELAY_UNIT_USECS, diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c index 3086dd536203..90ed3f9bb39c 100644 --- a/drivers/iio/imu/adis16400.c +++ b/drivers/iio/imu/adis16400.c @@ -1212,7 +1212,7 @@ static const struct spi_device_id adis16400_id[] = { {"adis16405", ADIS16400}, {"adis16445", ADIS16445}, {"adis16448", ADIS16448}, - {} + { } }; MODULE_DEVICE_TABLE(spi, adis16400_id); diff --git a/drivers/iio/imu/adis16460.c b/drivers/iio/imu/adis16460.c index ecf74046fde1..ba1887d36577 100644 --- a/drivers/iio/imu/adis16460.c +++ b/drivers/iio/imu/adis16460.c @@ -395,13 +395,13 @@ static int adis16460_probe(struct spi_device *spi) static const struct spi_device_id adis16460_ids[] = { { "adis16460", 0 }, - {} + { } }; MODULE_DEVICE_TABLE(spi, adis16460_ids); static const struct of_device_id adis16460_of_match[] = { { .compatible = "adi,adis16460" }, - {} + { } }; MODULE_DEVICE_TABLE(of, adis16460_of_match); diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c index df8c6cd91169..924395b7e3b4 100644 --- a/drivers/iio/imu/adis16475.c +++ b/drivers/iio/imu/adis16475.c @@ -2058,7 +2058,7 @@ static const struct of_device_id adis16475_of_match[] = { .data = &adis16475_chip_info[ADIS16577_2] }, { .compatible = "adi,adis16577-3", .data = &adis16475_chip_info[ADIS16577_3] }, - { }, + { } }; MODULE_DEVICE_TABLE(of, adis16475_of_match); diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c index 727e0a11eac1..543d5c4bfb11 100644 --- a/drivers/iio/imu/adis16480.c +++ b/drivers/iio/imu/adis16480.c @@ -1852,7 +1852,7 @@ static const struct of_device_id adis16480_of_match[] = { { .compatible = "adi,adis16547-1" }, { .compatible = "adi,adis16547-2" }, { .compatible = "adi,adis16547-3" }, - { }, + { } }; MODULE_DEVICE_TABLE(of, adis16480_of_match); diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c index fdfc0538734c..cd3db2388164 100644 --- a/drivers/iio/imu/adis_buffer.c +++ b/drivers/iio/imu/adis_buffer.c @@ -49,12 +49,10 @@ static int adis_update_scan_mode_burst(struct iio_dev *indio_dev, tx[1] = 0; adis->xfer[0].tx_buf = tx; - adis->xfer[0].bits_per_word = 8; adis->xfer[0].len = 2; if (adis->data->burst_max_speed_hz) adis->xfer[0].speed_hz = adis->data->burst_max_speed_hz; adis->xfer[1].rx_buf = adis->buffer; - adis->xfer[1].bits_per_word = 8; adis->xfer[1].len = burst_length; if (adis->data->burst_max_speed_hz) adis->xfer[1].speed_hz = adis->data->burst_max_speed_hz; @@ -100,7 +98,6 @@ int adis_update_scan_mode(struct iio_dev *indio_dev, spi_message_init(&adis->msg); for (j = 0; j <= scan_count; j++) { - adis->xfer[j].bits_per_word = 8; if (j != scan_count) adis->xfer[j].cs_change = 1; adis->xfer[j].len = 2; diff --git a/drivers/iio/imu/bmi160/bmi160_i2c.c b/drivers/iio/imu/bmi160/bmi160_i2c.c index 214503fa4af5..9fa3a19a8977 100644 --- a/drivers/iio/imu/bmi160/bmi160_i2c.c +++ b/drivers/iio/imu/bmi160/bmi160_i2c.c @@ -39,7 +39,7 @@ static int bmi160_i2c_probe(struct i2c_client *client) static const struct i2c_device_id bmi160_i2c_id[] = { { "bmi120" }, { "bmi160" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, bmi160_i2c_id); @@ -55,14 +55,14 @@ static const struct acpi_device_id bmi160_acpi_match[] = { {"10EC5280", 0}, {"BMI0120", 0}, {"BMI0160", 0}, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, bmi160_acpi_match); static const struct of_device_id bmi160_of_match[] = { { .compatible = "bosch,bmi120" }, { .compatible = "bosch,bmi160" }, - { }, + { } }; MODULE_DEVICE_TABLE(of, bmi160_of_match); diff --git a/drivers/iio/imu/bmi160/bmi160_spi.c b/drivers/iio/imu/bmi160/bmi160_spi.c index 8fbaab22db81..ebb586904215 100644 --- a/drivers/iio/imu/bmi160/bmi160_spi.c +++ b/drivers/iio/imu/bmi160/bmi160_spi.c @@ -36,21 +36,21 @@ static int bmi160_spi_probe(struct spi_device *spi) static const struct spi_device_id bmi160_spi_id[] = { {"bmi120", 0}, {"bmi160", 0}, - {} + { } }; MODULE_DEVICE_TABLE(spi, bmi160_spi_id); static const struct acpi_device_id bmi160_acpi_match[] = { {"BMI0120", 0}, {"BMI0160", 0}, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, bmi160_acpi_match); static const struct of_device_id bmi160_of_match[] = { { .compatible = "bosch,bmi120" }, { .compatible = "bosch,bmi160" }, - { }, + { } }; MODULE_DEVICE_TABLE(of, bmi160_of_match); diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h b/drivers/iio/imu/inv_icm42600/inv_icm42600.h index 18787a43477b..f893dbe69965 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h @@ -426,7 +426,7 @@ int inv_icm42600_set_temp_conf(struct inv_icm42600_state *st, bool enable, int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg, unsigned int writeval, unsigned int *readval); -int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq, +int inv_icm42600_core_probe(struct regmap *regmap, int chip, inv_icm42600_bus_setup bus_setup); struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st); diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c index 388520ec60b5..e6cd9dcb0687 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c @@ -157,7 +157,7 @@ static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = { &inv_icm42600_accel_power_mode_enum), IIO_ENUM("power_mode", IIO_SHARED_BY_TYPE, &inv_icm42600_accel_power_mode_enum), - {}, + { } }; static const struct iio_chan_spec inv_icm42600_accel_channels[] = { @@ -685,11 +685,10 @@ static int inv_icm42600_accel_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = inv_icm42600_accel_read_sensor(indio_dev, chan, &data); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); if (ret) return ret; *val = data; @@ -747,20 +746,18 @@ static int inv_icm42600_accel_write_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_SCALE: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = inv_icm42600_accel_write_scale(indio_dev, val, val2); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; case IIO_CHAN_INFO_SAMP_FREQ: return inv_icm42600_accel_write_odr(indio_dev, val, val2); case IIO_CHAN_INFO_CALIBBIAS: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = inv_icm42600_accel_write_offset(st, chan, val, val2); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; default: return -EINVAL; diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c index ef9875d3b79d..63d46619ebfa 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c @@ -683,12 +683,13 @@ static void inv_icm42600_disable_pm(void *_data) pm_runtime_disable(dev); } -int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq, +int inv_icm42600_core_probe(struct regmap *regmap, int chip, inv_icm42600_bus_setup bus_setup) { struct device *dev = regmap_get_device(regmap); + struct fwnode_handle *fwnode = dev_fwnode(dev); struct inv_icm42600_state *st; - int irq_type; + int irq, irq_type; bool open_drain; int ret; @@ -697,6 +698,15 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq, return -ENODEV; } + /* get INT1 only supported interrupt or fallback to first interrupt */ + irq = fwnode_irq_get_byname(fwnode, "INT1"); + if (irq < 0 && irq != -EPROBE_DEFER) { + dev_info(dev, "no INT1 interrupt defined, fallback to first interrupt\n"); + irq = fwnode_irq_get(fwnode, 0); + } + if (irq < 0) + return dev_err_probe(dev, irq, "error missing INT1 interrupt\n"); + irq_type = irq_get_trigger_type(irq); if (!irq_type) irq_type = IRQF_TRIGGER_FALLING; diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c index 591ed78a55bb..b4d7ce1432a4 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c @@ -57,7 +57,7 @@ enum inv_icm42600_gyro_scan { static const struct iio_chan_spec_ext_info inv_icm42600_gyro_ext_infos[] = { IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, inv_icm42600_get_mount_matrix), - {}, + { } }; static const struct iio_chan_spec inv_icm42600_gyro_channels[] = { @@ -591,11 +591,10 @@ static int inv_icm42600_gyro_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = inv_icm42600_gyro_read_sensor(st, chan, &data); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); if (ret) return ret; *val = data; @@ -653,20 +652,18 @@ static int inv_icm42600_gyro_write_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_SCALE: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = inv_icm42600_gyro_write_scale(indio_dev, val, val2); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; case IIO_CHAN_INFO_SAMP_FREQ: return inv_icm42600_gyro_write_odr(indio_dev, val, val2); case IIO_CHAN_INFO_CALIBBIAS: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = inv_icm42600_gyro_write_offset(st, chan, val, val2); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; default: return -EINVAL; diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c index 04e440fe023a..7e4d3ea68721 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c @@ -67,8 +67,7 @@ static int inv_icm42600_probe(struct i2c_client *client) if (IS_ERR(regmap)) return PTR_ERR(regmap); - return inv_icm42600_core_probe(regmap, chip, client->irq, - inv_icm42600_i2c_bus_setup); + return inv_icm42600_core_probe(regmap, chip, inv_icm42600_i2c_bus_setup); } /* @@ -110,7 +109,7 @@ static const struct of_device_id inv_icm42600_of_matches[] = { .compatible = "invensense,icm42631", .data = (void *)INV_CHIP_ICM42631, }, - {} + { } }; MODULE_DEVICE_TABLE(of, inv_icm42600_of_matches); diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c index 2bd2c4c8e50c..13e2e7d38638 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c @@ -64,8 +64,7 @@ static int inv_icm42600_probe(struct spi_device *spi) if (IS_ERR(regmap)) return PTR_ERR(regmap); - return inv_icm42600_core_probe(regmap, chip, spi->irq, - inv_icm42600_spi_bus_setup); + return inv_icm42600_core_probe(regmap, chip, inv_icm42600_spi_bus_setup); } /* @@ -107,7 +106,7 @@ static const struct of_device_id inv_icm42600_of_matches[] = { .compatible = "invensense,icm42631", .data = (void *)INV_CHIP_ICM42631, }, - {} + { } }; MODULE_DEVICE_TABLE(of, inv_icm42600_of_matches); diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c index 213cce1c3111..988f227f6563 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c @@ -56,27 +56,28 @@ int inv_icm42600_temp_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = inv_icm42600_temp_read(st, &temp); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); if (ret) return ret; *val = temp; return IIO_VAL_INT; /* * T°C = (temp / 132.48) + 25 - * Tm°C = 1000 * ((temp * 100 / 13248) + 25) + * Tm°C = 1000 * ((temp / 132.48) + 25) + * Tm°C = 7.548309 * temp + 25000 + * Tm°C = (temp + 3312) * 7.548309 * scale: 100000 / 13248 ~= 7.548309 - * offset: 25000 + * offset: 3312 */ case IIO_CHAN_INFO_SCALE: *val = 7; *val2 = 548309; return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_OFFSET: - *val = 25000; + *val = 3312; return IIO_VAL_INT; default: return -EINVAL; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c index 373e59f6d91a..a9bcf02e5b43 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c @@ -39,7 +39,7 @@ static const struct dmi_system_id inv_mpu_dev_list[] = { }, }, /* Add more matching tables here..*/ - {} + { } }; static int asus_acpi_get_sensor_info(struct acpi_device *adev, diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 5bcd5e797046..b8656c02354a 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -755,13 +755,12 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; mutex_lock(&st->lock); ret = inv_mpu6050_read_channel_data(indio_dev, chan, val); mutex_unlock(&st->lock); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; case IIO_CHAN_INFO_SCALE: switch (chan->type) { @@ -895,9 +894,8 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev, * we should only update scale when the chip is disabled, i.e. * not running */ - result = iio_device_claim_direct_mode(indio_dev); - if (result) - return result; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; mutex_lock(&st->lock); result = pm_runtime_resume_and_get(pdev); @@ -944,7 +942,7 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev, pm_runtime_put_autosuspend(pdev); error_write_raw_unlock: mutex_unlock(&st->lock); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return result; } diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c index 91d77f94d204..8dc61812a8fc 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c @@ -192,7 +192,7 @@ static const struct i2c_device_id inv_mpu_id[] = { {"iam20680", INV_IAM20680}, {"iam20680hp", INV_IAM20680HP}, {"iam20680ht", INV_IAM20680HT}, - {} + { } }; MODULE_DEVICE_TABLE(i2c, inv_mpu_id); @@ -276,7 +276,7 @@ MODULE_DEVICE_TABLE(of, inv_of_match); static const struct acpi_device_id inv_acpi_match[] = { {"INVN6500", INV_MPU6500}, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, inv_acpi_match); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c index 20de6eb5cd35..1f4c62142b60 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c @@ -83,7 +83,7 @@ static const struct spi_device_id inv_mpu_id[] = { {"iam20680", INV_IAM20680}, {"iam20680hp", INV_IAM20680HP}, {"iam20680ht", INV_IAM20680HT}, - {} + { } }; MODULE_DEVICE_TABLE(spi, inv_mpu_id); @@ -163,7 +163,7 @@ MODULE_DEVICE_TABLE(of, inv_of_match); static const struct acpi_device_id inv_acpi_match[] = { {"INVN6000", INV_MPU6000}, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, inv_acpi_match); diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index e19c5d3137c6..2bdfb2619137 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -1487,7 +1487,7 @@ static const struct dev_pm_ops kmx61_pm_ops = { static const struct i2c_device_id kmx61_id[] = { { "kmx611021" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, kmx61_id); diff --git a/drivers/iio/imu/smi240.c b/drivers/iio/imu/smi240.c index 4492c4d013bd..d159ee59acdd 100644 --- a/drivers/iio/imu/smi240.c +++ b/drivers/iio/imu/smi240.c @@ -414,11 +414,10 @@ static int smi240_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = smi240_get_data(data, chan->type, chan->channel2, val); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); if (ret) return ret; return IIO_VAL_INT; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index 96c6106b95ee..c65ad49829e7 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -1804,12 +1804,11 @@ static int st_lsm6dsx_read_raw(struct iio_dev *iio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(iio_dev); - if (ret) - break; + if (!iio_device_claim_direct(iio_dev)) + return -EBUSY; ret = st_lsm6dsx_read_oneshot(sensor, ch->address, val); - iio_device_release_direct_mode(iio_dev); + iio_device_release_direct(iio_dev); break; case IIO_CHAN_INFO_SAMP_FREQ: *val = sensor->odr / 1000; @@ -1834,11 +1833,10 @@ static int st_lsm6dsx_write_raw(struct iio_dev *iio_dev, int val, int val2, long mask) { struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); - int err; + int err = 0; - err = iio_device_claim_direct_mode(iio_dev); - if (err) - return err; + if (!iio_device_claim_direct(iio_dev)) + return -EBUSY; switch (mask) { case IIO_CHAN_INFO_SCALE: @@ -1860,7 +1858,7 @@ static int st_lsm6dsx_write_raw(struct iio_dev *iio_dev, break; } - iio_device_release_direct_mode(iio_dev); + iio_device_release_direct(iio_dev); return err; } diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c index 25e1de89b6e4..7c933218036b 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c @@ -138,13 +138,13 @@ static const struct of_device_id st_lsm6dsx_i2c_of_match[] = { .compatible = "st,asm330lhhxg1", .data = (void *)ST_ASM330LHHXG1_ID, }, - {}, + { } }; MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match); static const struct acpi_device_id st_lsm6dsx_i2c_acpi_match[] = { { "SMO8B30", ST_LSM6DS3TRC_ID, }, - {} + { } }; MODULE_DEVICE_TABLE(acpi, st_lsm6dsx_i2c_acpi_match); @@ -173,7 +173,7 @@ static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = { { ST_ISM330IS_DEV_NAME, ST_ISM330IS_ID }, { ST_ASM330LHB_DEV_NAME, ST_ASM330LHB_ID }, { ST_ASM330LHHXG1_DEV_NAME, ST_ASM330LHHXG1_ID }, - {}, + { } }; MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table); diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c index f968f32890d1..cb5c5d7e1f3d 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c @@ -17,7 +17,7 @@ static const struct i3c_device_id st_lsm6dsx_i3c_ids[] = { I3C_DEVICE(0x0104, 0x006C, (void *)ST_LSM6DSO_ID), I3C_DEVICE(0x0104, 0x006B, (void *)ST_LSM6DSR_ID), - { /* sentinel */ }, + { } }; MODULE_DEVICE_TABLE(i3c, st_lsm6dsx_i3c_ids); diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c index c1b444520d2a..3c5e65dc0f97 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c @@ -558,12 +558,11 @@ st_lsm6dsx_shub_read_raw(struct iio_dev *iio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(iio_dev); - if (ret) - break; + if (!iio_device_claim_direct(iio_dev)) + return -EBUSY; ret = st_lsm6dsx_shub_read_oneshot(sensor, ch, val); - iio_device_release_direct_mode(iio_dev); + iio_device_release_direct(iio_dev); break; case IIO_CHAN_INFO_SAMP_FREQ: *val = sensor->ext_info.slv_odr / 1000; @@ -614,53 +613,57 @@ st_lsm6dsx_shub_set_full_scale(struct st_lsm6dsx_sensor *sensor, } static int -st_lsm6dsx_shub_write_raw(struct iio_dev *iio_dev, - struct iio_chan_spec const *chan, - int val, int val2, long mask) +__st_lsm6dsx_shub_write_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) { struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); int err; - err = iio_device_claim_direct_mode(iio_dev); - if (err) - return err; - switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: { + struct st_lsm6dsx_hw *hw = sensor->hw; + struct st_lsm6dsx_sensor *ref_sensor; + u8 odr_val; u16 data; + int odr; val = val * 1000 + val2 / 1000; err = st_lsm6dsx_shub_get_odr_val(sensor, val, &data); - if (!err) { - struct st_lsm6dsx_hw *hw = sensor->hw; - struct st_lsm6dsx_sensor *ref_sensor; - u8 odr_val; - int odr; - - ref_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]); - odr = st_lsm6dsx_check_odr(ref_sensor, val, &odr_val); - if (odr < 0) { - err = odr; - goto release; - } - - sensor->ext_info.slv_odr = val; - sensor->odr = odr; - } - break; + if (err) + return err; + + ref_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]); + odr = st_lsm6dsx_check_odr(ref_sensor, val, &odr_val); + if (odr < 0) + return odr; + + sensor->ext_info.slv_odr = val; + sensor->odr = odr; + return 0; } case IIO_CHAN_INFO_SCALE: - err = st_lsm6dsx_shub_set_full_scale(sensor, val2); - break; + return st_lsm6dsx_shub_set_full_scale(sensor, val2); default: - err = -EINVAL; - break; + return -EINVAL; } +} + +static int +st_lsm6dsx_shub_write_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + int ret; -release: - iio_device_release_direct_mode(iio_dev); + if (!iio_device_claim_direct(iio_dev)) + return -EBUSY; - return err; + ret = __st_lsm6dsx_shub_write_raw(iio_dev, chan, val, val2, mask); + + iio_device_release_direct(iio_dev); + + return ret; } static ssize_t diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c index 4b4b6d45524f..3389b15df0bc 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c @@ -133,7 +133,7 @@ static const struct of_device_id st_lsm6dsx_spi_of_match[] = { .compatible = "st,asm330lhhxg1", .data = (void *)ST_ASM330LHHXG1_ID, }, - {}, + { } }; MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match); @@ -162,7 +162,7 @@ static const struct spi_device_id st_lsm6dsx_spi_id_table[] = { { ST_ISM330IS_DEV_NAME, ST_ISM330IS_ID }, { ST_ASM330LHB_DEV_NAME, ST_ASM330LHB_ID }, { ST_ASM330LHHXG1_DEV_NAME, ST_ASM330LHHXG1_ID }, - {}, + { } }; MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table); diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c index 8cc071463249..4232a9d800fc 100644 --- a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c +++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c @@ -28,20 +28,20 @@ static const struct of_device_id st_lsm9ds0_of_match[] = { .compatible = "st,lsm9ds0-imu", .data = LSM9DS0_IMU_DEV_NAME, }, - {} + { } }; MODULE_DEVICE_TABLE(of, st_lsm9ds0_of_match); static const struct i2c_device_id st_lsm9ds0_id_table[] = { { LSM303D_IMU_DEV_NAME }, { LSM9DS0_IMU_DEV_NAME }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, st_lsm9ds0_id_table); static const struct acpi_device_id st_lsm9ds0_acpi_match[] = { {"ACCL0001", (kernel_ulong_t)LSM303D_IMU_DEV_NAME}, - {} + { } }; MODULE_DEVICE_TABLE(acpi, st_lsm9ds0_acpi_match); diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c index 806e55f75f65..acea8a0757d7 100644 --- a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c +++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c @@ -28,14 +28,14 @@ static const struct of_device_id st_lsm9ds0_of_match[] = { .compatible = "st,lsm9ds0-imu", .data = LSM9DS0_IMU_DEV_NAME, }, - {} + { } }; MODULE_DEVICE_TABLE(of, st_lsm9ds0_of_match); static const struct spi_device_id st_lsm9ds0_id_table[] = { { LSM303D_IMU_DEV_NAME }, { LSM9DS0_IMU_DEV_NAME }, - {} + { } }; MODULE_DEVICE_TABLE(spi, st_lsm9ds0_id_table); diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c index a43c8d1bb3d0..c1eb9ef9db08 100644 --- a/drivers/iio/industrialio-backend.c +++ b/drivers/iio/industrialio-backend.c @@ -381,6 +381,34 @@ int iio_backend_data_source_set(struct iio_backend *back, unsigned int chan, EXPORT_SYMBOL_NS_GPL(iio_backend_data_source_set, "IIO_BACKEND"); /** + * iio_backend_data_source_get - Get current data source + * @back: Backend device + * @chan: Channel number + * @data: Pointer to receive the current source value + * + * A given backend may have different sources to stream/sync data. This allows + * to know what source is in use. + * + * RETURNS: + * 0 on success, negative error number on failure. + */ +int iio_backend_data_source_get(struct iio_backend *back, unsigned int chan, + enum iio_backend_data_source *data) +{ + int ret; + + ret = iio_backend_op_call(back, data_source_get, chan, data); + if (ret) + return ret; + + if (*data >= IIO_BACKEND_DATA_SOURCE_MAX) + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(iio_backend_data_source_get, "IIO_BACKEND"); + +/** * iio_backend_set_sampling_freq - Set channel sampling rate * @back: Backend device * @chan: Channel number diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index b9f4113ae5fc..178e99b111de 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -26,6 +26,7 @@ #include <linux/sched.h> #include <linux/slab.h> #include <linux/wait.h> +#include <linux/wordpart.h> #include <linux/iio/buffer.h> #include <linux/iio/buffer_impl.h> @@ -966,8 +967,10 @@ static ssize_t iio_write_channel_info(struct device *dev, struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); int ret, fract_mult = 100000; int integer, fract = 0; + long long integer64; bool is_char = false; bool scale_db = false; + bool is_64bit = false; /* Assumes decimal - precision based on number of digits */ if (!indio_dev->info->write_raw) @@ -991,6 +994,9 @@ static ssize_t iio_write_channel_info(struct device *dev, case IIO_VAL_CHAR: is_char = true; break; + case IIO_VAL_INT_64: + is_64bit = true; + break; default: return -EINVAL; } @@ -1001,6 +1007,13 @@ static ssize_t iio_write_channel_info(struct device *dev, if (sscanf(buf, "%c", &ch) != 1) return -EINVAL; integer = ch; + } else if (is_64bit) { + ret = kstrtoll(buf, 0, &integer64); + if (ret) + return ret; + + fract = upper_32_bits(integer64); + integer = lower_32_bits(integer64); } else { ret = __iio_str_to_fixpoint(buf, fract_mult, &integer, &fract, scale_db); @@ -2144,17 +2157,19 @@ int __devm_iio_device_register(struct device *dev, struct iio_dev *indio_dev, EXPORT_SYMBOL_GPL(__devm_iio_device_register); /** - * iio_device_claim_direct_mode - Keep device in direct mode + * __iio_device_claim_direct - Keep device in direct mode * @indio_dev: the iio_dev associated with the device * * If the device is in direct mode it is guaranteed to stay - * that way until iio_device_release_direct_mode() is called. + * that way until __iio_device_release_direct() is called. * - * Use with iio_device_release_direct_mode() + * Use with __iio_device_release_direct(). * - * Returns: 0 on success, -EBUSY on failure. + * Drivers should only call iio_device_claim_direct(). + * + * Returns: true on success, false on failure. */ -int iio_device_claim_direct_mode(struct iio_dev *indio_dev) +bool __iio_device_claim_direct(struct iio_dev *indio_dev) { struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); @@ -2162,26 +2177,28 @@ int iio_device_claim_direct_mode(struct iio_dev *indio_dev) if (iio_buffer_enabled(indio_dev)) { mutex_unlock(&iio_dev_opaque->mlock); - return -EBUSY; + return false; } - return 0; + return true; } -EXPORT_SYMBOL_GPL(iio_device_claim_direct_mode); +EXPORT_SYMBOL_GPL(__iio_device_claim_direct); /** - * iio_device_release_direct_mode - releases claim on direct mode + * __iio_device_release_direct - releases claim on direct mode * @indio_dev: the iio_dev associated with the device * * Release the claim. Device is no longer guaranteed to stay * in direct mode. * - * Use with iio_device_claim_direct_mode() + * Drivers should only call iio_device_release_direct(). + * + * Use with __iio_device_claim_direct() */ -void iio_device_release_direct_mode(struct iio_dev *indio_dev) +void __iio_device_release_direct(struct iio_dev *indio_dev) { mutex_unlock(&to_iio_dev_opaque(indio_dev)->mlock); } -EXPORT_SYMBOL_GPL(iio_device_release_direct_mode); +EXPORT_SYMBOL_GPL(__iio_device_release_direct); /** * iio_device_claim_buffer_mode - Keep device in buffer mode diff --git a/drivers/iio/light/acpi-als.c b/drivers/iio/light/acpi-als.c index 2d91caf24dd0..032e6cae8b80 100644 --- a/drivers/iio/light/acpi-als.c +++ b/drivers/iio/light/acpi-als.c @@ -230,7 +230,7 @@ static int acpi_als_add(struct acpi_device *device) static const struct acpi_device_id acpi_als_device_ids[] = { {"ACPI0008", 0}, - {}, + { } }; MODULE_DEVICE_TABLE(acpi, acpi_als_device_ids); diff --git a/drivers/iio/light/adux1020.c b/drivers/iio/light/adux1020.c index 9240983a6cc4..e321f89c5340 100644 --- a/drivers/iio/light/adux1020.c +++ b/drivers/iio/light/adux1020.c @@ -820,7 +820,7 @@ static int adux1020_probe(struct i2c_client *client) static const struct i2c_device_id adux1020_id[] = { { "adux1020" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, adux1020_id); diff --git a/drivers/iio/light/al3000a.c b/drivers/iio/light/al3000a.c index e2fbb1270040..6f301c067045 100644 --- a/drivers/iio/light/al3000a.c +++ b/drivers/iio/light/al3000a.c @@ -85,12 +85,17 @@ static void al3000a_set_pwr_off(void *_data) static int al3000a_init(struct al3000a_data *data) { + struct device *dev = regmap_get_device(data->regmap); int ret; ret = al3000a_set_pwr_on(data); if (ret) return ret; + ret = devm_add_action_or_reset(dev, al3000a_set_pwr_off, data); + if (ret) + return dev_err_probe(dev, ret, "failed to add action\n"); + ret = regmap_write(data->regmap, AL3000A_REG_SYSTEM, AL3000A_CONFIG_RESET); if (ret) return ret; @@ -157,10 +162,6 @@ static int al3000a_probe(struct i2c_client *client) if (ret) return dev_err_probe(dev, ret, "failed to init ALS\n"); - ret = devm_add_action_or_reset(dev, al3000a_set_pwr_off, data); - if (ret) - return dev_err_probe(dev, ret, "failed to add action\n"); - return devm_iio_device_register(dev, indio_dev); } @@ -189,7 +190,7 @@ MODULE_DEVICE_TABLE(i2c, al3000a_id); static const struct of_device_id al3000a_of_match[] = { { .compatible = "dynaimage,al3000a" }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, al3000a_of_match); diff --git a/drivers/iio/light/al3010.c b/drivers/iio/light/al3010.c index 7cbb8b203300..0932fa2b49fa 100644 --- a/drivers/iio/light/al3010.c +++ b/drivers/iio/light/al3010.c @@ -17,13 +17,12 @@ #include <linux/bitfield.h> #include <linux/i2c.h> #include <linux/module.h> +#include <linux/regmap.h> #include <linux/mod_devicetable.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> -#define AL3010_DRV_NAME "al3010" - #define AL3010_REG_SYSTEM 0x00 #define AL3010_REG_DATA_LOW 0x0c #define AL3010_REG_CONFIG 0x10 @@ -46,8 +45,14 @@ static const int al3010_scales[][2] = { {0, 1187200}, {0, 296800}, {0, 74200}, {0, 18600} }; +static const struct regmap_config al3010_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = AL3010_REG_CONFIG, +}; + struct al3010_data { - struct i2c_client *client; + struct regmap *regmap; }; static const struct iio_chan_spec al3010_channels[] = { @@ -69,40 +74,36 @@ static const struct attribute_group al3010_attribute_group = { .attrs = al3010_attributes, }; -static int al3010_set_pwr(struct i2c_client *client, bool pwr) +static int al3010_set_pwr_on(struct al3010_data *data) { - u8 val = pwr ? AL3010_CONFIG_ENABLE : AL3010_CONFIG_DISABLE; - return i2c_smbus_write_byte_data(client, AL3010_REG_SYSTEM, val); + return regmap_write(data->regmap, AL3010_REG_SYSTEM, AL3010_CONFIG_ENABLE); } static void al3010_set_pwr_off(void *_data) { struct al3010_data *data = _data; + struct device *dev = regmap_get_device(data->regmap); + int ret; - al3010_set_pwr(data->client, false); + ret = regmap_write(data->regmap, AL3010_REG_SYSTEM, AL3010_CONFIG_DISABLE); + if (ret) + dev_err(dev, "failed to write system register\n"); } static int al3010_init(struct al3010_data *data) { + struct device *dev = regmap_get_device(data->regmap); int ret; - ret = al3010_set_pwr(data->client, true); - if (ret < 0) + ret = al3010_set_pwr_on(data); + if (ret) return ret; - ret = devm_add_action_or_reset(&data->client->dev, - al3010_set_pwr_off, - data); - if (ret < 0) + ret = devm_add_action_or_reset(dev, al3010_set_pwr_off, data); + if (ret) return ret; - - ret = i2c_smbus_write_byte_data(data->client, AL3010_REG_CONFIG, - FIELD_PREP(AL3010_GAIN_MASK, - AL3XXX_RANGE_3)); - if (ret < 0) - return ret; - - return 0; + return regmap_write(data->regmap, AL3010_REG_CONFIG, + FIELD_PREP(AL3010_GAIN_MASK, AL3XXX_RANGE_3)); } static int al3010_read_raw(struct iio_dev *indio_dev, @@ -110,7 +111,7 @@ static int al3010_read_raw(struct iio_dev *indio_dev, int *val2, long mask) { struct al3010_data *data = iio_priv(indio_dev); - int ret; + int ret, gain, raw; switch (mask) { case IIO_CHAN_INFO_RAW: @@ -119,21 +120,21 @@ static int al3010_read_raw(struct iio_dev *indio_dev, * - low byte of output is stored at AL3010_REG_DATA_LOW * - high byte of output is stored at AL3010_REG_DATA_LOW + 1 */ - ret = i2c_smbus_read_word_data(data->client, - AL3010_REG_DATA_LOW); - if (ret < 0) + ret = regmap_read(data->regmap, AL3010_REG_DATA_LOW, &raw); + if (ret) return ret; - *val = ret; + + *val = raw; + return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - ret = i2c_smbus_read_byte_data(data->client, - AL3010_REG_CONFIG); - if (ret < 0) + ret = regmap_read(data->regmap, AL3010_REG_CONFIG, &gain); + if (ret) return ret; - ret = FIELD_GET(AL3010_GAIN_MASK, ret); - *val = al3010_scales[ret][0]; - *val2 = al3010_scales[ret][1]; + gain = FIELD_GET(AL3010_GAIN_MASK, gain); + *val = al3010_scales[gain][0]; + *val2 = al3010_scales[gain][1]; return IIO_VAL_INT_PLUS_MICRO; } @@ -145,7 +146,7 @@ static int al3010_write_raw(struct iio_dev *indio_dev, int val2, long mask) { struct al3010_data *data = iio_priv(indio_dev); - int i; + unsigned int i; switch (mask) { case IIO_CHAN_INFO_SCALE: @@ -154,9 +155,8 @@ static int al3010_write_raw(struct iio_dev *indio_dev, val2 != al3010_scales[i][1]) continue; - return i2c_smbus_write_byte_data(data->client, - AL3010_REG_CONFIG, - FIELD_PREP(AL3010_GAIN_MASK, i)); + return regmap_write(data->regmap, AL3010_REG_CONFIG, + FIELD_PREP(AL3010_GAIN_MASK, i)); } break; } @@ -172,59 +172,66 @@ static const struct iio_info al3010_info = { static int al3010_probe(struct i2c_client *client) { struct al3010_data *data; + struct device *dev = &client->dev; struct iio_dev *indio_dev; int ret; - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); if (!indio_dev) return -ENOMEM; data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); - data->client = client; + data->regmap = devm_regmap_init_i2c(client, &al3010_regmap_config); + if (IS_ERR(data->regmap)) + return dev_err_probe(dev, PTR_ERR(data->regmap), + "cannot allocate regmap\n"); indio_dev->info = &al3010_info; - indio_dev->name = AL3010_DRV_NAME; + indio_dev->name = "al3010"; indio_dev->channels = al3010_channels; indio_dev->num_channels = ARRAY_SIZE(al3010_channels); indio_dev->modes = INDIO_DIRECT_MODE; ret = al3010_init(data); - if (ret < 0) { - dev_err(&client->dev, "al3010 chip init failed\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "failed to init ALS\n"); - return devm_iio_device_register(&client->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } static int al3010_suspend(struct device *dev) { - return al3010_set_pwr(to_i2c_client(dev), false); + struct al3010_data *data = iio_priv(dev_get_drvdata(dev)); + + al3010_set_pwr_off(data); + return 0; } static int al3010_resume(struct device *dev) { - return al3010_set_pwr(to_i2c_client(dev), true); + struct al3010_data *data = iio_priv(dev_get_drvdata(dev)); + + return al3010_set_pwr_on(data); } static DEFINE_SIMPLE_DEV_PM_OPS(al3010_pm_ops, al3010_suspend, al3010_resume); static const struct i2c_device_id al3010_id[] = { {"al3010", }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, al3010_id); static const struct of_device_id al3010_of_match[] = { { .compatible = "dynaimage,al3010", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, al3010_of_match); static struct i2c_driver al3010_driver = { .driver = { - .name = AL3010_DRV_NAME, + .name = "al3010", .of_match_table = al3010_of_match, .pm = pm_sleep_ptr(&al3010_pm_ops), }, diff --git a/drivers/iio/light/al3320a.c b/drivers/iio/light/al3320a.c index 497ea3fe3377..63f5a85912fc 100644 --- a/drivers/iio/light/al3320a.c +++ b/drivers/iio/light/al3320a.c @@ -15,13 +15,12 @@ #include <linux/bitfield.h> #include <linux/i2c.h> #include <linux/module.h> +#include <linux/regmap.h> #include <linux/mod_devicetable.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> -#define AL3320A_DRV_NAME "al3320a" - #define AL3320A_REG_CONFIG 0x00 #define AL3320A_REG_STATUS 0x01 #define AL3320A_REG_INT 0x02 @@ -59,8 +58,14 @@ static const int al3320a_scales[][2] = { {0, 512000}, {0, 128000}, {0, 32000}, {0, 10000} }; +static const struct regmap_config al3320a_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = AL3320A_REG_HIGH_THRESH_HIGH, +}; + struct al3320a_data { - struct i2c_client *client; + struct regmap *regmap; }; static const struct iio_chan_spec al3320a_channels[] = { @@ -82,45 +87,47 @@ static const struct attribute_group al3320a_attribute_group = { .attrs = al3320a_attributes, }; -static int al3320a_set_pwr(struct i2c_client *client, bool pwr) +static int al3320a_set_pwr_on(struct al3320a_data *data) { - u8 val = pwr ? AL3320A_CONFIG_ENABLE : AL3320A_CONFIG_DISABLE; - return i2c_smbus_write_byte_data(client, AL3320A_REG_CONFIG, val); + return regmap_write(data->regmap, AL3320A_REG_CONFIG, AL3320A_CONFIG_ENABLE); } static void al3320a_set_pwr_off(void *_data) { struct al3320a_data *data = _data; + struct device *dev = regmap_get_device(data->regmap); + int ret; - al3320a_set_pwr(data->client, false); + ret = regmap_write(data->regmap, AL3320A_REG_CONFIG, AL3320A_CONFIG_DISABLE); + if (ret) + dev_err(dev, "failed to write system register\n"); } static int al3320a_init(struct al3320a_data *data) { + struct device *dev = regmap_get_device(data->regmap); int ret; - ret = al3320a_set_pwr(data->client, true); - - if (ret < 0) + ret = al3320a_set_pwr_on(data); + if (ret) return ret; - ret = i2c_smbus_write_byte_data(data->client, AL3320A_REG_CONFIG_RANGE, - FIELD_PREP(AL3320A_GAIN_MASK, - AL3320A_RANGE_3)); - if (ret < 0) + ret = devm_add_action_or_reset(dev, al3320a_set_pwr_off, data); + if (ret) return ret; - ret = i2c_smbus_write_byte_data(data->client, AL3320A_REG_MEAN_TIME, - AL3320A_DEFAULT_MEAN_TIME); - if (ret < 0) + ret = regmap_write(data->regmap, AL3320A_REG_CONFIG_RANGE, + FIELD_PREP(AL3320A_GAIN_MASK, AL3320A_RANGE_3)); + if (ret) return ret; - ret = i2c_smbus_write_byte_data(data->client, AL3320A_REG_WAIT, - AL3320A_DEFAULT_WAIT_TIME); - if (ret < 0) + ret = regmap_write(data->regmap, AL3320A_REG_MEAN_TIME, + AL3320A_DEFAULT_MEAN_TIME); + if (ret) return ret; - return 0; + return regmap_write(data->regmap, AL3320A_REG_WAIT, + AL3320A_DEFAULT_WAIT_TIME); } static int al3320a_read_raw(struct iio_dev *indio_dev, @@ -128,7 +135,7 @@ static int al3320a_read_raw(struct iio_dev *indio_dev, int *val2, long mask) { struct al3320a_data *data = iio_priv(indio_dev); - int ret; + int ret, gain, raw; switch (mask) { case IIO_CHAN_INFO_RAW: @@ -137,21 +144,21 @@ static int al3320a_read_raw(struct iio_dev *indio_dev, * - low byte of output is stored at AL3320A_REG_DATA_LOW * - high byte of output is stored at AL3320A_REG_DATA_LOW + 1 */ - ret = i2c_smbus_read_word_data(data->client, - AL3320A_REG_DATA_LOW); - if (ret < 0) + ret = regmap_read(data->regmap, AL3320A_REG_DATA_LOW, &raw); + if (ret) return ret; - *val = ret; + + *val = raw; + return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - ret = i2c_smbus_read_byte_data(data->client, - AL3320A_REG_CONFIG_RANGE); - if (ret < 0) + ret = regmap_read(data->regmap, AL3320A_REG_CONFIG_RANGE, &gain); + if (ret) return ret; - ret = FIELD_GET(AL3320A_GAIN_MASK, ret); - *val = al3320a_scales[ret][0]; - *val2 = al3320a_scales[ret][1]; + gain = FIELD_GET(AL3320A_GAIN_MASK, gain); + *val = al3320a_scales[gain][0]; + *val2 = al3320a_scales[gain][1]; return IIO_VAL_INT_PLUS_MICRO; } @@ -163,7 +170,7 @@ static int al3320a_write_raw(struct iio_dev *indio_dev, int val2, long mask) { struct al3320a_data *data = iio_priv(indio_dev); - int i; + unsigned int i; switch (mask) { case IIO_CHAN_INFO_SCALE: @@ -172,9 +179,8 @@ static int al3320a_write_raw(struct iio_dev *indio_dev, val2 != al3320a_scales[i][1]) continue; - return i2c_smbus_write_byte_data(data->client, - AL3320A_REG_CONFIG_RANGE, - FIELD_PREP(AL3320A_GAIN_MASK, i)); + return regmap_write(data->regmap, AL3320A_REG_CONFIG_RANGE, + FIELD_PREP(AL3320A_GAIN_MASK, i)); } break; } @@ -190,46 +196,50 @@ static const struct iio_info al3320a_info = { static int al3320a_probe(struct i2c_client *client) { struct al3320a_data *data; + struct device *dev = &client->dev; struct iio_dev *indio_dev; int ret; - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); if (!indio_dev) return -ENOMEM; data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); - data->client = client; + + data->regmap = devm_regmap_init_i2c(client, &al3320a_regmap_config); + if (IS_ERR(data->regmap)) + return dev_err_probe(dev, PTR_ERR(data->regmap), + "cannot allocate regmap\n"); indio_dev->info = &al3320a_info; - indio_dev->name = AL3320A_DRV_NAME; + indio_dev->name = "al3320a"; indio_dev->channels = al3320a_channels; indio_dev->num_channels = ARRAY_SIZE(al3320a_channels); indio_dev->modes = INDIO_DIRECT_MODE; ret = al3320a_init(data); if (ret < 0) { - dev_err(&client->dev, "al3320a chip init failed\n"); + dev_err(dev, "al3320a chip init failed\n"); return ret; } - ret = devm_add_action_or_reset(&client->dev, - al3320a_set_pwr_off, - data); - if (ret < 0) - return ret; - - return devm_iio_device_register(&client->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } static int al3320a_suspend(struct device *dev) { - return al3320a_set_pwr(to_i2c_client(dev), false); + struct al3320a_data *data = iio_priv(dev_get_drvdata(dev)); + + al3320a_set_pwr_off(data); + return 0; } static int al3320a_resume(struct device *dev) { - return al3320a_set_pwr(to_i2c_client(dev), true); + struct al3320a_data *data = iio_priv(dev_get_drvdata(dev)); + + return al3320a_set_pwr_on(data); } static DEFINE_SIMPLE_DEV_PM_OPS(al3320a_pm_ops, al3320a_suspend, @@ -237,25 +247,25 @@ static DEFINE_SIMPLE_DEV_PM_OPS(al3320a_pm_ops, al3320a_suspend, static const struct i2c_device_id al3320a_id[] = { { "al3320a" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, al3320a_id); static const struct of_device_id al3320a_of_match[] = { { .compatible = "dynaimage,al3320a", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, al3320a_of_match); static const struct acpi_device_id al3320a_acpi_match[] = { {"CALS0001"}, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, al3320a_acpi_match); static struct i2c_driver al3320a_driver = { .driver = { - .name = AL3320A_DRV_NAME, + .name = "al3320a", .of_match_table = al3320a_of_match, .pm = pm_sleep_ptr(&al3320a_pm_ops), .acpi_match_table = al3320a_acpi_match, diff --git a/drivers/iio/light/apds9306.c b/drivers/iio/light/apds9306.c index 5ed7e17f49e7..e9b237de180a 100644 --- a/drivers/iio/light/apds9306.c +++ b/drivers/iio/light/apds9306.c @@ -831,11 +831,10 @@ static int apds9306_read_raw(struct iio_dev *indio_dev, * Changing device parameters during adc operation, resets * the ADC which has to avoided. */ - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = apds9306_read_data(data, val, reg); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); if (ret) return ret; diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c index d30441d33703..0003a29bf264 100644 --- a/drivers/iio/light/apds9960.c +++ b/drivers/iio/light/apds9960.c @@ -1157,7 +1157,7 @@ static const struct dev_pm_ops apds9960_pm_ops = { static const struct i2c_device_id apds9960_id[] = { { "apds9960" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, apds9960_id); diff --git a/drivers/iio/light/as73211.c b/drivers/iio/light/as73211.c index 37fffce35dd1..68f60dc3c79d 100644 --- a/drivers/iio/light/as73211.c +++ b/drivers/iio/light/as73211.c @@ -16,6 +16,7 @@ */ #include <linux/bitfield.h> +#include <linux/cleanup.h> #include <linux/completion.h> #include <linux/delay.h> #include <linux/i2c.h> @@ -418,18 +419,17 @@ static int as73211_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec cons case IIO_CHAN_INFO_RAW: { int ret; - ret = iio_device_claim_direct_mode(indio_dev); - if (ret < 0) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = as73211_req_data(data); if (ret < 0) { - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; } ret = i2c_smbus_read_word_data(data->client, chan->address); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); if (ret < 0) return ret; @@ -517,6 +517,16 @@ static int _as73211_write_raw(struct iio_dev *indio_dev, struct as73211_data *data = iio_priv(indio_dev); int ret; + /* Need to switch to config mode ... */ + if ((data->osr & AS73211_OSR_DOS_MASK) != AS73211_OSR_DOS_CONFIG) { + data->osr &= ~AS73211_OSR_DOS_MASK; + data->osr |= AS73211_OSR_DOS_CONFIG; + + ret = i2c_smbus_write_byte_data(data->client, AS73211_REG_OSR, data->osr); + if (ret < 0) + return ret; + } + switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: { int reg_bits, freq_kHz = val / HZ_PER_KHZ; /* 1024, 2048, ... */ @@ -601,28 +611,14 @@ static int as73211_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec con struct as73211_data *data = iio_priv(indio_dev); int ret; - mutex_lock(&data->mutex); - - ret = iio_device_claim_direct_mode(indio_dev); - if (ret < 0) - goto error_unlock; - - /* Need to switch to config mode ... */ - if ((data->osr & AS73211_OSR_DOS_MASK) != AS73211_OSR_DOS_CONFIG) { - data->osr &= ~AS73211_OSR_DOS_MASK; - data->osr |= AS73211_OSR_DOS_CONFIG; + guard(mutex)(&data->mutex); - ret = i2c_smbus_write_byte_data(data->client, AS73211_REG_OSR, data->osr); - if (ret < 0) - goto error_release; - } + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = _as73211_write_raw(indio_dev, chan, val, val2, mask); + iio_device_release_direct(indio_dev); -error_release: - iio_device_release_direct_mode(indio_dev); -error_unlock: - mutex_unlock(&data->mutex); return ret; } diff --git a/drivers/iio/light/bh1750.c b/drivers/iio/light/bh1750.c index 4b869fa9e5b1..764f88826fcb 100644 --- a/drivers/iio/light/bh1750.c +++ b/drivers/iio/light/bh1750.c @@ -22,12 +22,16 @@ #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> #include <linux/module.h> +#include <linux/gpio/consumer.h> #define BH1750_POWER_DOWN 0x00 #define BH1750_ONE_TIME_H_RES_MODE 0x20 /* auto-mode for BH1721 */ #define BH1750_CHANGE_INT_TIME_H_BIT 0x40 #define BH1750_CHANGE_INT_TIME_L_BIT 0x60 +/* Define the reset delay time in microseconds */ +#define BH1750_RESET_DELAY_US 10000 /* 10ms */ + enum { BH1710, BH1721, @@ -40,6 +44,7 @@ struct bh1750_data { struct mutex lock; const struct bh1750_chip_info *chip_info; u16 mtreg; + struct gpio_desc *reset_gpio; }; struct bh1750_chip_info { @@ -248,6 +253,25 @@ static int bh1750_probe(struct i2c_client *client) data->client = client; data->chip_info = &bh1750_chip_info_tbl[id->driver_data]; + /* Get reset GPIO from device tree */ + data->reset_gpio = devm_gpiod_get_optional(&client->dev, + "reset", GPIOD_OUT_HIGH); + + if (IS_ERR(data->reset_gpio)) + return dev_err_probe(&client->dev, PTR_ERR(data->reset_gpio), + "Failed to get reset GPIO\n"); + + /* Perform hardware reset if GPIO is provided */ + if (data->reset_gpio) { + /* Perform reset sequence: low-high */ + gpiod_set_value_cansleep(data->reset_gpio, 1); + fsleep(BH1750_RESET_DELAY_US); + gpiod_set_value_cansleep(data->reset_gpio, 0); + fsleep(BH1750_RESET_DELAY_US); + + dev_dbg(&client->dev, "BH1750 reset completed via GPIO\n"); + } + usec = data->chip_info->mtreg_to_usec * data->chip_info->mtreg_default; ret = bh1750_change_int_time(data, usec); if (ret < 0) diff --git a/drivers/iio/light/bh1780.c b/drivers/iio/light/bh1780.c index 475f44954f61..c7c877d2fe67 100644 --- a/drivers/iio/light/bh1780.c +++ b/drivers/iio/light/bh1780.c @@ -264,7 +264,7 @@ MODULE_DEVICE_TABLE(i2c, bh1780_id); static const struct of_device_id of_bh1780_match[] = { { .compatible = "rohm,bh1780gli", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, of_bh1780_match); diff --git a/drivers/iio/light/cm3232.c b/drivers/iio/light/cm3232.c index 5b00ad2a014e..e864d2ef036e 100644 --- a/drivers/iio/light/cm3232.c +++ b/drivers/iio/light/cm3232.c @@ -369,7 +369,7 @@ static void cm3232_remove(struct i2c_client *client) static const struct i2c_device_id cm3232_id[] = { { "cm3232" }, - {} + { } }; static int cm3232_suspend(struct device *dev) @@ -406,7 +406,7 @@ MODULE_DEVICE_TABLE(i2c, cm3232_id); static const struct of_device_id cm3232_of_match[] = { {.compatible = "capella,cm3232"}, - {} + { } }; MODULE_DEVICE_TABLE(of, cm3232_of_match); diff --git a/drivers/iio/light/cm3323.c b/drivers/iio/light/cm3323.c index 79a64e2ff812..79ad6e2209ca 100644 --- a/drivers/iio/light/cm3323.c +++ b/drivers/iio/light/cm3323.c @@ -251,13 +251,13 @@ static int cm3323_probe(struct i2c_client *client) static const struct i2c_device_id cm3323_id[] = { { "cm3323" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, cm3323_id); static const struct of_device_id cm3323_of_match[] = { { .compatible = "capella,cm3323", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, cm3323_of_match); diff --git a/drivers/iio/light/cm3605.c b/drivers/iio/light/cm3605.c index 675c0fd44db4..0c17378e27d1 100644 --- a/drivers/iio/light/cm3605.c +++ b/drivers/iio/light/cm3605.c @@ -307,7 +307,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(cm3605_dev_pm_ops, cm3605_pm_suspend, static const struct of_device_id cm3605_of_match[] = { {.compatible = "capella,cm3605"}, - { }, + { } }; MODULE_DEVICE_TABLE(of, cm3605_of_match); diff --git a/drivers/iio/light/cros_ec_light_prox.c b/drivers/iio/light/cros_ec_light_prox.c index 19e529c84e95..815806ceb5c8 100644 --- a/drivers/iio/light/cros_ec_light_prox.c +++ b/drivers/iio/light/cros_ec_light_prox.c @@ -249,7 +249,7 @@ static const struct platform_device_id cros_ec_light_prox_ids[] = { { .name = "cros-ec-light", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(platform, cros_ec_light_prox_ids); diff --git a/drivers/iio/light/gp2ap002.c b/drivers/iio/light/gp2ap002.c index d56ee217fe53..42859e5b1089 100644 --- a/drivers/iio/light/gp2ap002.c +++ b/drivers/iio/light/gp2ap002.c @@ -700,7 +700,7 @@ MODULE_DEVICE_TABLE(i2c, gp2ap002_id_table); static const struct of_device_id gp2ap002_of_match[] = { { .compatible = "sharp,gp2ap002a00f" }, { .compatible = "sharp,gp2ap002s00f" }, - { }, + { } }; MODULE_DEVICE_TABLE(of, gp2ap002_of_match); diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c index 1a352c88598e..c7df4b258e2c 100644 --- a/drivers/iio/light/gp2ap020a00f.c +++ b/drivers/iio/light/gp2ap020a00f.c @@ -1283,12 +1283,11 @@ static int gp2ap020a00f_read_raw(struct iio_dev *indio_dev, int err = -EINVAL; if (mask == IIO_CHAN_INFO_RAW) { - err = iio_device_claim_direct_mode(indio_dev); - if (err) - return err; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; err = gp2ap020a00f_read_channel(data, chan, val); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); } return err < 0 ? err : IIO_VAL_INT; } diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c index aa4c72d4849e..830e5ae7f34a 100644 --- a/drivers/iio/light/hid-sensor-als.c +++ b/drivers/iio/light/hid-sensor-als.c @@ -456,7 +456,7 @@ static const struct platform_device_id hid_als_ids[] = { /* Format: HID-SENSOR-custom_sensor_tag-usage_id_in_hex_lowercase */ .name = "HID-SENSOR-LISS-0041", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(platform, hid_als_ids); diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c index 4c65b32d34ce..efa904a70d0e 100644 --- a/drivers/iio/light/hid-sensor-prox.c +++ b/drivers/iio/light/hid-sensor-prox.c @@ -215,6 +215,9 @@ static int prox_capture_sample(struct hid_sensor_hub_device *hsdev, case 1: prox_state->human_presence[chan] = *(u8 *)raw_data * multiplier; return 0; + case 2: + prox_state->human_presence[chan] = *(u16 *)raw_data * multiplier; + return 0; case 4: prox_state->human_presence[chan] = *(u32 *)raw_data * multiplier; return 0; @@ -362,7 +365,7 @@ static const struct platform_device_id hid_prox_ids[] = { /* Format: HID-SENSOR-tag-usage_id_in_hex_lowercase */ .name = "HID-SENSOR-LISS-0226", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(platform, hid_prox_ids); diff --git a/drivers/iio/light/isl29018.c b/drivers/iio/light/isl29018.c index 201eae1c4589..1b4c18423048 100644 --- a/drivers/iio/light/isl29018.c +++ b/drivers/iio/light/isl29018.c @@ -824,7 +824,7 @@ static const struct acpi_device_id isl29018_acpi_match[] = { {"ISL29018", isl29018}, {"ISL29023", isl29023}, {"ISL29035", isl29035}, - {} + { } }; MODULE_DEVICE_TABLE(acpi, isl29018_acpi_match); @@ -832,7 +832,7 @@ static const struct i2c_device_id isl29018_id[] = { {"isl29018", isl29018}, {"isl29023", isl29023}, {"isl29035", isl29035}, - {} + { } }; MODULE_DEVICE_TABLE(i2c, isl29018_id); diff --git a/drivers/iio/light/isl29028.c b/drivers/iio/light/isl29028.c index 95bfb3ffa519..609ebf0f7313 100644 --- a/drivers/iio/light/isl29028.c +++ b/drivers/iio/light/isl29028.c @@ -680,7 +680,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(isl29028_pm_ops, isl29028_suspend, static const struct i2c_device_id isl29028_id[] = { { "isl29028" }, { "isl29030" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, isl29028_id); @@ -688,7 +688,7 @@ static const struct of_device_id isl29028_of_match[] = { { .compatible = "isl,isl29028", }, /* for backward compat., don't use */ { .compatible = "isil,isl29028", }, { .compatible = "isil,isl29030", }, - { }, + { } }; MODULE_DEVICE_TABLE(of, isl29028_of_match); diff --git a/drivers/iio/light/isl29125.c b/drivers/iio/light/isl29125.c index 326dc39e7929..6bc23b164cc5 100644 --- a/drivers/iio/light/isl29125.c +++ b/drivers/iio/light/isl29125.c @@ -131,11 +131,10 @@ static int isl29125_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = isl29125_read_data(data, chan->scan_index); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); if (ret < 0) return ret; *val = ret; diff --git a/drivers/iio/light/jsa1212.c b/drivers/iio/light/jsa1212.c index e7ba934c8e69..fa4677c28931 100644 --- a/drivers/iio/light/jsa1212.c +++ b/drivers/iio/light/jsa1212.c @@ -424,7 +424,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(jsa1212_pm_ops, jsa1212_suspend, static const struct acpi_device_id jsa1212_acpi_match[] = { {"JSA1212", 0}, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, jsa1212_acpi_match); diff --git a/drivers/iio/light/ltr390.c b/drivers/iio/light/ltr390.c index df664f360903..ee59bbb8aa09 100644 --- a/drivers/iio/light/ltr390.c +++ b/drivers/iio/light/ltr390.c @@ -717,13 +717,13 @@ static DEFINE_SIMPLE_DEV_PM_OPS(ltr390_pm_ops, ltr390_suspend, ltr390_resume); static const struct i2c_device_id ltr390_id[] = { { "ltr390" }, - { /* Sentinel */ } + { } }; MODULE_DEVICE_TABLE(i2c, ltr390_id); static const struct of_device_id ltr390_of_table[] = { { .compatible = "liteon,ltr390" }, - { /* Sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, ltr390_of_table); diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index 669da0840eba..8d8051cf6927 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -541,7 +541,7 @@ static const struct iio_chan_spec_ext_info ltr501_ext_info[] = { .shared = IIO_SEPARATE, .read = ltr501_read_near_level, }, - { /* sentinel */ } + { } }; static const struct iio_event_spec ltr501_als_event_spec[] = { @@ -646,6 +646,36 @@ static const struct iio_chan_spec ltr301_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(2), }; +static int ltr501_read_info_raw(struct ltr501_data *data, + struct iio_chan_spec const *chan, + int *val) +{ + __le16 buf[2]; + int ret; + + switch (chan->type) { + case IIO_INTENSITY: + mutex_lock(&data->lock_als); + ret = ltr501_read_als(data, buf); + mutex_unlock(&data->lock_als); + if (ret < 0) + return ret; + *val = le16_to_cpu(chan->address == LTR501_ALS_DATA1 ? + buf[0] : buf[1]); + return IIO_VAL_INT; + case IIO_PROXIMITY: + mutex_lock(&data->lock_ps); + ret = ltr501_read_ps(data); + mutex_unlock(&data->lock_ps); + if (ret < 0) + return ret; + *val = ret & LTR501_PS_DATA_MASK; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + static int ltr501_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -658,14 +688,13 @@ static int ltr501_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_PROCESSED: switch (chan->type) { case IIO_LIGHT: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; mutex_lock(&data->lock_als); ret = ltr501_read_als(data, buf); mutex_unlock(&data->lock_als); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); if (ret < 0) return ret; *val = ltr501_calculate_lux(le16_to_cpu(buf[1]), @@ -675,36 +704,12 @@ static int ltr501_read_raw(struct iio_dev *indio_dev, return -EINVAL; } case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; - switch (chan->type) { - case IIO_INTENSITY: - mutex_lock(&data->lock_als); - ret = ltr501_read_als(data, buf); - mutex_unlock(&data->lock_als); - if (ret < 0) - break; - *val = le16_to_cpu(chan->address == LTR501_ALS_DATA1 ? - buf[0] : buf[1]); - ret = IIO_VAL_INT; - break; - case IIO_PROXIMITY: - mutex_lock(&data->lock_ps); - ret = ltr501_read_ps(data); - mutex_unlock(&data->lock_ps); - if (ret < 0) - break; - *val = ret & LTR501_PS_DATA_MASK; - ret = IIO_VAL_INT; - break; - default: - ret = -EINVAL; - break; - } + ret = ltr501_read_info_raw(data, chan, val); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; case IIO_CHAN_INFO_SCALE: @@ -756,18 +761,14 @@ static int ltr501_get_gain_index(const struct ltr501_gain *gain, int size, return -1; } -static int ltr501_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, int val2, long mask) +static int __ltr501_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) { struct ltr501_data *data = iio_priv(indio_dev); int i, ret, freq_val, freq_val2; const struct ltr501_chip_info *info = data->chip_info; - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; - switch (mask) { case IIO_CHAN_INFO_SCALE: switch (chan->type) { @@ -775,53 +776,43 @@ static int ltr501_write_raw(struct iio_dev *indio_dev, i = ltr501_get_gain_index(info->als_gain, info->als_gain_tbl_size, val, val2); - if (i < 0) { - ret = -EINVAL; - break; - } + if (i < 0) + return -EINVAL; data->als_contr &= ~info->als_gain_mask; data->als_contr |= i << info->als_gain_shift; - ret = regmap_write(data->regmap, LTR501_ALS_CONTR, - data->als_contr); - break; + return regmap_write(data->regmap, LTR501_ALS_CONTR, + data->als_contr); case IIO_PROXIMITY: i = ltr501_get_gain_index(info->ps_gain, info->ps_gain_tbl_size, val, val2); - if (i < 0) { - ret = -EINVAL; - break; - } + if (i < 0) + return -EINVAL; + data->ps_contr &= ~LTR501_CONTR_PS_GAIN_MASK; data->ps_contr |= i << LTR501_CONTR_PS_GAIN_SHIFT; - ret = regmap_write(data->regmap, LTR501_PS_CONTR, - data->ps_contr); - break; + return regmap_write(data->regmap, LTR501_PS_CONTR, + data->ps_contr); default: - ret = -EINVAL; - break; + return -EINVAL; } - break; case IIO_CHAN_INFO_INT_TIME: switch (chan->type) { case IIO_INTENSITY: - if (val != 0) { - ret = -EINVAL; - break; - } + if (val != 0) + return -EINVAL; + mutex_lock(&data->lock_als); ret = ltr501_set_it_time(data, val2); mutex_unlock(&data->lock_als); - break; + return ret; default: - ret = -EINVAL; - break; + return -EINVAL; } - break; case IIO_CHAN_INFO_SAMP_FREQ: switch (chan->type) { @@ -829,50 +820,61 @@ static int ltr501_write_raw(struct iio_dev *indio_dev, ret = ltr501_als_read_samp_freq(data, &freq_val, &freq_val2); if (ret < 0) - break; + return ret; ret = ltr501_als_write_samp_freq(data, val, val2); if (ret < 0) - break; + return ret; /* update persistence count when changing frequency */ ret = ltr501_write_intr_prst(data, chan->type, 0, data->als_period); if (ret < 0) - ret = ltr501_als_write_samp_freq(data, freq_val, - freq_val2); - break; + /* Do not ovewrite error */ + ltr501_als_write_samp_freq(data, freq_val, + freq_val2); + return ret; case IIO_PROXIMITY: ret = ltr501_ps_read_samp_freq(data, &freq_val, &freq_val2); if (ret < 0) - break; + return ret; ret = ltr501_ps_write_samp_freq(data, val, val2); if (ret < 0) - break; + return ret; /* update persistence count when changing frequency */ ret = ltr501_write_intr_prst(data, chan->type, 0, data->ps_period); if (ret < 0) - ret = ltr501_ps_write_samp_freq(data, freq_val, - freq_val2); - break; + /* Do not overwrite error */ + ltr501_ps_write_samp_freq(data, freq_val, + freq_val2); + return ret; default: - ret = -EINVAL; - break; + return -EINVAL; } - break; - default: - ret = -EINVAL; - break; + return -EINVAL; } +} + +static int ltr501_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + int ret; + + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + + ret = __ltr501_write_raw(indio_dev, chan, val, val2, mask); + + iio_device_release_direct(indio_dev); - iio_device_release_direct_mode(indio_dev); return ret; } @@ -1600,7 +1602,7 @@ static const struct acpi_device_id ltr_acpi_match[] = { { "LTER0301", ltr301 }, /* https://www.catalog.update.microsoft.com/Search.aspx?q=lter0303 */ { "LTER0303", ltr303 }, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, ltr_acpi_match); @@ -1618,7 +1620,7 @@ static const struct of_device_id ltr501_of_match[] = { { .compatible = "liteon,ltr559", }, { .compatible = "liteon,ltr301", }, { .compatible = "liteon,ltr303", }, - {} + { } }; MODULE_DEVICE_TABLE(of, ltr501_of_match); diff --git a/drivers/iio/light/ltrf216a.c b/drivers/iio/light/ltrf216a.c index dbec1e7cfeb8..61f57a82b872 100644 --- a/drivers/iio/light/ltrf216a.c +++ b/drivers/iio/light/ltrf216a.c @@ -554,7 +554,7 @@ static const struct ltr_chip_info ltrf216a_chip_info = { static const struct i2c_device_id ltrf216a_id[] = { { "ltr308", .driver_data = (kernel_ulong_t)<r308_chip_info }, { "ltrf216a", .driver_data = (kernel_ulong_t)<rf216a_chip_info }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, ltrf216a_id); @@ -563,7 +563,7 @@ static const struct of_device_id ltrf216a_of_match[] = { { .compatible = "liteon,ltrf216a", .data = <rf216a_chip_info }, /* For Valve's Steamdeck device, an ACPI platform using PRP0001 */ { .compatible = "ltr,ltrf216a", .data = <rf216a_chip_info }, - {} + { } }; MODULE_DEVICE_TABLE(of, ltrf216a_of_match); diff --git a/drivers/iio/light/opt4001.c b/drivers/iio/light/opt4001.c index 6cf60151b3d8..ba4eb82d9bc2 100644 --- a/drivers/iio/light/opt4001.c +++ b/drivers/iio/light/opt4001.c @@ -448,7 +448,7 @@ MODULE_DEVICE_TABLE(i2c, opt4001_id); static const struct of_device_id opt4001_of_match[] = { { .compatible = "ti,opt4001-sot-5x3", .data = &opt4001_sot_5x3_info}, { .compatible = "ti,opt4001-picostar", .data = &opt4001_picostar_info}, - {} + { } }; MODULE_DEVICE_TABLE(of, opt4001_of_match); diff --git a/drivers/iio/light/opt4060.c b/drivers/iio/light/opt4060.c index ab55f8d2ea0c..f4085020e03e 100644 --- a/drivers/iio/light/opt4060.c +++ b/drivers/iio/light/opt4060.c @@ -311,7 +311,7 @@ any_mode_retry: * concurrently change. And we just keep trying until we get one * of the modes... */ - if (iio_device_claim_direct_mode(indio_dev)) + if (!iio_device_claim_direct(indio_dev)) goto any_mode_retry; /* * This path means that we managed to claim direct mode. In @@ -320,7 +320,8 @@ any_mode_retry: */ ret = opt4060_set_state_common(chip, continuous_sampling, continuous_irq); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); + return ret; } else { /* * This path means that we managed to claim buffer mode. In diff --git a/drivers/iio/light/pa12203001.c b/drivers/iio/light/pa12203001.c index b920bf82c102..8885852bef22 100644 --- a/drivers/iio/light/pa12203001.c +++ b/drivers/iio/light/pa12203001.c @@ -456,14 +456,14 @@ static const struct dev_pm_ops pa12203001_pm_ops = { static const struct acpi_device_id pa12203001_acpi_match[] = { { "TXCPA122", 0 }, - {} + { } }; MODULE_DEVICE_TABLE(acpi, pa12203001_acpi_match); static const struct i2c_device_id pa12203001_id[] = { { "txcpa122" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, pa12203001_id); diff --git a/drivers/iio/light/rohm-bu27034.c b/drivers/iio/light/rohm-bu27034.c index cc25596cb248..7cec5e943373 100644 --- a/drivers/iio/light/rohm-bu27034.c +++ b/drivers/iio/light/rohm-bu27034.c @@ -998,9 +998,8 @@ static int bu27034_read_raw(struct iio_dev *idev, return -EINVAL; /* Don't mess with measurement enabling while buffering */ - ret = iio_device_claim_direct_mode(idev); - if (ret) - return ret; + if (!iio_device_claim_direct(idev)) + return -EBUSY; mutex_lock(&data->mutex); /* @@ -1011,7 +1010,7 @@ static int bu27034_read_raw(struct iio_dev *idev, ret = result_get(data, chan->channel, val); mutex_unlock(&data->mutex); - iio_device_release_direct_mode(idev); + iio_device_release_direct(idev); if (ret) return ret; @@ -1050,9 +1049,8 @@ static int bu27034_write_raw(struct iio_dev *idev, struct bu27034_data *data = iio_priv(idev); int ret; - ret = iio_device_claim_direct_mode(idev); - if (ret) - return ret; + if (!iio_device_claim_direct(idev)) + return -EBUSY; switch (mask) { case IIO_CHAN_INFO_SCALE: @@ -1069,7 +1067,7 @@ static int bu27034_write_raw(struct iio_dev *idev, break; } - iio_device_release_direct_mode(idev); + iio_device_release_direct(idev); return ret; } diff --git a/drivers/iio/light/rpr0521.c b/drivers/iio/light/rpr0521.c index 2ba917c5c138..92e7552f3e39 100644 --- a/drivers/iio/light/rpr0521.c +++ b/drivers/iio/light/rpr0521.c @@ -11,6 +11,7 @@ #include <linux/module.h> #include <linux/mod_devicetable.h> +#include <linux/cleanup.h> #include <linux/init.h> #include <linux/i2c.h> #include <linux/regmap.h> @@ -704,50 +705,58 @@ static int rpr0521_write_ps_offset(struct rpr0521_data *data, int offset) return ret; } +static int rpr0521_read_info_raw(struct rpr0521_data *data, + struct iio_chan_spec const *chan, + int *val) +{ + u8 device_mask; + __le16 raw_data; + int ret; + + device_mask = rpr0521_data_reg[chan->address].device_mask; + + guard(mutex)(&data->lock); + ret = rpr0521_set_power_state(data, true, device_mask); + if (ret < 0) + return ret; + + ret = regmap_bulk_read(data->regmap, + rpr0521_data_reg[chan->address].address, + &raw_data, sizeof(raw_data)); + if (ret < 0) { + rpr0521_set_power_state(data, false, device_mask); + return ret; + } + + ret = rpr0521_set_power_state(data, false, device_mask); + if (ret < 0) + return ret; + + *val = le16_to_cpu(raw_data); + + return 0; +} + static int rpr0521_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { struct rpr0521_data *data = iio_priv(indio_dev); int ret; - int busy; - u8 device_mask; - __le16 raw_data; switch (mask) { case IIO_CHAN_INFO_RAW: if (chan->type != IIO_INTENSITY && chan->type != IIO_PROXIMITY) return -EINVAL; - busy = iio_device_claim_direct_mode(indio_dev); - if (busy) + if (!iio_device_claim_direct(indio_dev)) return -EBUSY; - device_mask = rpr0521_data_reg[chan->address].device_mask; - - mutex_lock(&data->lock); - ret = rpr0521_set_power_state(data, true, device_mask); - if (ret < 0) - goto rpr0521_read_raw_out; - - ret = regmap_bulk_read(data->regmap, - rpr0521_data_reg[chan->address].address, - &raw_data, sizeof(raw_data)); - if (ret < 0) { - rpr0521_set_power_state(data, false, device_mask); - goto rpr0521_read_raw_out; - } - - ret = rpr0521_set_power_state(data, false, device_mask); - -rpr0521_read_raw_out: - mutex_unlock(&data->lock); - iio_device_release_direct_mode(indio_dev); + ret = rpr0521_read_info_raw(data, chan, val); + iio_device_release_direct(indio_dev); if (ret < 0) return ret; - *val = le16_to_cpu(raw_data); - return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: diff --git a/drivers/iio/light/si1145.c b/drivers/iio/light/si1145.c index 66abda021696..4aa02afd853e 100644 --- a/drivers/iio/light/si1145.c +++ b/drivers/iio/light/si1145.c @@ -633,11 +633,10 @@ static int si1145_read_raw(struct iio_dev *indio_dev, case IIO_VOLTAGE: case IIO_TEMP: case IIO_UVINDEX: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = si1145_measure(indio_dev, chan); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); if (ret < 0) return ret; @@ -750,18 +749,17 @@ static int si1145_write_raw(struct iio_dev *indio_dev, return -EINVAL; } - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = si1145_param_set(data, reg1, val); if (ret < 0) { - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; } /* Set recovery period to one's complement of gain */ ret = si1145_param_set(data, reg2, (~val & 0x07) << 4); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; case IIO_CHAN_INFO_RAW: if (chan->type != IIO_CURRENT) @@ -773,19 +771,18 @@ static int si1145_write_raw(struct iio_dev *indio_dev, reg1 = SI1145_PS_LED_REG(chan->channel); shift = SI1145_PS_LED_SHIFT(chan->channel); - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = i2c_smbus_read_byte_data(data->client, reg1); if (ret < 0) { - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; } ret = i2c_smbus_write_byte_data(data->client, reg1, (ret & ~(0x0f << shift)) | ((val & 0x0f) << shift)); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; case IIO_CHAN_INFO_SAMP_FREQ: return si1145_store_samp_freq(data, val); diff --git a/drivers/iio/light/st_uvis25_core.c b/drivers/iio/light/st_uvis25_core.c index 40a810000df0..124a8f9204a9 100644 --- a/drivers/iio/light/st_uvis25_core.c +++ b/drivers/iio/light/st_uvis25_core.c @@ -117,9 +117,8 @@ static int st_uvis25_read_raw(struct iio_dev *iio_dev, { int ret; - ret = iio_device_claim_direct_mode(iio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(iio_dev)) + return -EBUSY; switch (mask) { case IIO_CHAN_INFO_PROCESSED: { @@ -144,7 +143,7 @@ static int st_uvis25_read_raw(struct iio_dev *iio_dev, break; } - iio_device_release_direct_mode(iio_dev); + iio_device_release_direct(iio_dev); return ret; } diff --git a/drivers/iio/light/st_uvis25_i2c.c b/drivers/iio/light/st_uvis25_i2c.c index f54282476d11..5d9bb4d9be63 100644 --- a/drivers/iio/light/st_uvis25_i2c.c +++ b/drivers/iio/light/st_uvis25_i2c.c @@ -41,13 +41,13 @@ static int st_uvis25_i2c_probe(struct i2c_client *client) static const struct of_device_id st_uvis25_i2c_of_match[] = { { .compatible = "st,uvis25", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, st_uvis25_i2c_of_match); static const struct i2c_device_id st_uvis25_i2c_id_table[] = { { ST_UVIS25_DEV_NAME }, - {}, + { } }; MODULE_DEVICE_TABLE(i2c, st_uvis25_i2c_id_table); diff --git a/drivers/iio/light/st_uvis25_spi.c b/drivers/iio/light/st_uvis25_spi.c index 18edc6a5a4a4..a5aad74ce73e 100644 --- a/drivers/iio/light/st_uvis25_spi.c +++ b/drivers/iio/light/st_uvis25_spi.c @@ -42,13 +42,13 @@ static int st_uvis25_spi_probe(struct spi_device *spi) static const struct of_device_id st_uvis25_spi_of_match[] = { { .compatible = "st,uvis25", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, st_uvis25_spi_of_match); static const struct spi_device_id st_uvis25_spi_id_table[] = { { ST_UVIS25_DEV_NAME }, - {}, + { } }; MODULE_DEVICE_TABLE(spi, st_uvis25_spi_id_table); diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c index b81cc44db43c..deada9ba4748 100644 --- a/drivers/iio/light/stk3310.c +++ b/drivers/iio/light/stk3310.c @@ -165,7 +165,7 @@ static const struct iio_chan_spec_ext_info stk3310_ext_info[] = { .shared = IIO_SEPARATE, .read = stk3310_read_near_level, }, - { /* sentinel */ } + { } }; static const struct iio_chan_spec stk3310_channels[] = { @@ -703,7 +703,7 @@ static const struct i2c_device_id stk3310_i2c_id[] = { { "STK3310" }, { "STK3311" }, { "STK3335" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, stk3310_i2c_id); @@ -711,7 +711,7 @@ static const struct acpi_device_id stk3310_acpi_id[] = { {"STK3013", 0}, {"STK3310", 0}, {"STK3311", 0}, - {} + { } }; MODULE_DEVICE_TABLE(acpi, stk3310_acpi_id); @@ -721,7 +721,7 @@ static const struct of_device_id stk3310_of_match[] = { { .compatible = "sensortek,stk3310", }, { .compatible = "sensortek,stk3311", }, { .compatible = "sensortek,stk3335", }, - {} + { } }; MODULE_DEVICE_TABLE(of, stk3310_of_match); diff --git a/drivers/iio/light/tcs3414.c b/drivers/iio/light/tcs3414.c index 884e43e4cda4..39268f855c77 100644 --- a/drivers/iio/light/tcs3414.c +++ b/drivers/iio/light/tcs3414.c @@ -134,16 +134,15 @@ static int tcs3414_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = tcs3414_req_data(data); if (ret < 0) { - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; } ret = i2c_smbus_read_word_data(data->client, chan->address); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); if (ret < 0) return ret; *val = ret; diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c index 2bd36a344ea5..0f8bf8503edd 100644 --- a/drivers/iio/light/tcs3472.c +++ b/drivers/iio/light/tcs3472.c @@ -148,16 +148,15 @@ static int tcs3472_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = tcs3472_req_data(data); if (ret < 0) { - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; } ret = i2c_smbus_read_word_data(data->client, chan->address); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); if (ret < 0) return ret; *val = ret; diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c index f1fe7640fce6..f2af1cd7c2d1 100644 --- a/drivers/iio/light/tsl2563.c +++ b/drivers/iio/light/tsl2563.c @@ -843,7 +843,7 @@ static const struct i2c_device_id tsl2563_id[] = { { "tsl2561", 1 }, { "tsl2562", 2 }, { "tsl2563", 3 }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, tsl2563_id); @@ -852,7 +852,7 @@ static const struct of_device_id tsl2563_of_match[] = { { .compatible = "amstaos,tsl2561" }, { .compatible = "amstaos,tsl2562" }, { .compatible = "amstaos,tsl2563" }, - {} + { } }; MODULE_DEVICE_TABLE(of, tsl2563_of_match); diff --git a/drivers/iio/light/tsl2583.c b/drivers/iio/light/tsl2583.c index 02ad11611b9c..fc3b0c4226be 100644 --- a/drivers/iio/light/tsl2583.c +++ b/drivers/iio/light/tsl2583.c @@ -922,7 +922,7 @@ static const struct i2c_device_id tsl2583_idtable[] = { { "tsl2580", 0 }, { "tsl2581", 1 }, { "tsl2583", 2 }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, tsl2583_idtable); @@ -930,7 +930,7 @@ static const struct of_device_id tsl2583_of_match[] = { { .compatible = "amstaos,tsl2580", }, { .compatible = "amstaos,tsl2581", }, { .compatible = "amstaos,tsl2583", }, - { }, + { } }; MODULE_DEVICE_TABLE(of, tsl2583_of_match); diff --git a/drivers/iio/light/tsl2591.c b/drivers/iio/light/tsl2591.c index b81ca6f73f92..08476f193a44 100644 --- a/drivers/iio/light/tsl2591.c +++ b/drivers/iio/light/tsl2591.c @@ -1204,7 +1204,7 @@ static int tsl2591_probe(struct i2c_client *client) static const struct of_device_id tsl2591_of_match[] = { { .compatible = "amstaos,tsl2591"}, - {} + { } }; MODULE_DEVICE_TABLE(of, tsl2591_of_match); diff --git a/drivers/iio/light/tsl2772.c b/drivers/iio/light/tsl2772.c index 349afdcbe30d..0b171106441a 100644 --- a/drivers/iio/light/tsl2772.c +++ b/drivers/iio/light/tsl2772.c @@ -1899,7 +1899,7 @@ static const struct i2c_device_id tsl2772_idtable[] = { { "tsl2772", tsl2772 }, { "tmd2772", tmd2772 }, { "apds9930", apds9930 }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, tsl2772_idtable); @@ -1916,7 +1916,7 @@ static const struct of_device_id tsl2772_of_match[] = { { .compatible = "amstaos,tsl2772" }, { .compatible = "amstaos,tmd2772" }, { .compatible = "avago,apds9930" }, - {} + { } }; MODULE_DEVICE_TABLE(of, tsl2772_of_match); diff --git a/drivers/iio/light/us5182d.c b/drivers/iio/light/us5182d.c index c83114aed6b2..61a0957317a1 100644 --- a/drivers/iio/light/us5182d.c +++ b/drivers/iio/light/us5182d.c @@ -949,21 +949,21 @@ static const struct dev_pm_ops us5182d_pm_ops = { static const struct acpi_device_id us5182d_acpi_match[] = { { "USD5182", 0 }, - {} + { } }; MODULE_DEVICE_TABLE(acpi, us5182d_acpi_match); static const struct i2c_device_id us5182d_id[] = { { "usd5182" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, us5182d_id); static const struct of_device_id us5182d_of_match[] = { { .compatible = "upisemi,usd5182" }, - {} + { } }; MODULE_DEVICE_TABLE(of, us5182d_of_match); diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index e19199b17f2e..90e7d4421abf 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -1084,9 +1084,8 @@ static int vcnl4010_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_SCALE: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; /* Protect against event capture. */ if (vcnl4010_is_in_periodic_mode(data)) { @@ -1096,7 +1095,7 @@ static int vcnl4010_read_raw(struct iio_dev *indio_dev, mask); } - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; case IIO_CHAN_INFO_SAMP_FREQ: switch (chan->type) { @@ -1157,9 +1156,8 @@ static int vcnl4010_write_raw(struct iio_dev *indio_dev, int ret; struct vcnl4000_data *data = iio_priv(indio_dev); - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; /* Protect against event capture. */ if (vcnl4010_is_in_periodic_mode(data)) { @@ -1183,7 +1181,7 @@ static int vcnl4010_write_raw(struct iio_dev *indio_dev, } end: - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; } @@ -1410,46 +1408,52 @@ static int vcnl4010_read_event_config(struct iio_dev *indio_dev, } } -static int vcnl4010_config_threshold(struct iio_dev *indio_dev, bool state) +static int vcnl4010_config_threshold_enable(struct vcnl4000_data *data) { - struct vcnl4000_data *data = iio_priv(indio_dev); int ret; - int icr; - int command; - if (state) { - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + /* Enable periodic measurement of proximity data. */ + ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, + VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN); + if (ret < 0) + return ret; - /* Enable periodic measurement of proximity data. */ - command = VCNL4000_SELF_TIMED_EN | VCNL4000_PROX_EN; + /* + * Enable interrupts on threshold, for proximity data by + * default. + */ + return i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, + VCNL4010_INT_THR_EN); +} - /* - * Enable interrupts on threshold, for proximity data by - * default. - */ - icr = VCNL4010_INT_THR_EN; - } else { - if (!vcnl4010_is_thr_enabled(data)) - return 0; +static int vcnl4010_config_threshold_disable(struct vcnl4000_data *data) +{ + int ret; - command = 0; - icr = 0; - } + if (!vcnl4010_is_thr_enabled(data)) + return 0; - ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, - command); + ret = i2c_smbus_write_byte_data(data->client, VCNL4000_COMMAND, 0); if (ret < 0) - goto end; + return ret; - ret = i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, icr); + return i2c_smbus_write_byte_data(data->client, VCNL4010_INT_CTRL, 0); +} -end: - if (state) - iio_device_release_direct_mode(indio_dev); +static int vcnl4010_config_threshold(struct iio_dev *indio_dev, bool state) +{ + struct vcnl4000_data *data = iio_priv(indio_dev); + int ret; - return ret; + if (state) { + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + ret = vcnl4010_config_threshold_enable(data); + iio_device_release_direct(indio_dev); + return ret; + } else { + return vcnl4010_config_threshold_disable(data); + } } static int vcnl4010_write_event_config(struct iio_dev *indio_dev, @@ -1741,7 +1745,7 @@ static const struct iio_chan_spec_ext_info vcnl4000_ext_info[] = { .shared = IIO_SEPARATE, .read = vcnl4000_read_near_level, }, - { /* sentinel */ } + { } }; static const struct iio_event_spec vcnl4000_event_spec[] = { @@ -2064,7 +2068,7 @@ static const struct of_device_id vcnl_4000_of_match[] = { .compatible = "vishay,vcnl4200", .data = (void *)VCNL4200, }, - {}, + { } }; MODULE_DEVICE_TABLE(of, vcnl_4000_of_match); diff --git a/drivers/iio/light/vcnl4035.c b/drivers/iio/light/vcnl4035.c index 67c94be02018..b2bede9d3daa 100644 --- a/drivers/iio/light/vcnl4035.c +++ b/drivers/iio/light/vcnl4035.c @@ -156,6 +156,31 @@ static int vcnl4035_set_pm_runtime_state(struct vcnl4035_data *data, bool on) return ret; } +static int vcnl4035_read_info_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val) +{ + struct vcnl4035_data *data = iio_priv(indio_dev); + int ret; + int raw_data; + unsigned int reg; + + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + + if (chan->channel) + reg = VCNL4035_ALS_DATA; + else + reg = VCNL4035_WHITE_DATA; + ret = regmap_read(data->regmap, reg, &raw_data); + iio_device_release_direct(indio_dev); + if (ret) + return ret; + + *val = raw_data; + + return IIO_VAL_INT; +} + /* * Device IT INT Time (ms) Scale (lux/step) * 000 50 0.064 @@ -175,28 +200,13 @@ static int vcnl4035_read_raw(struct iio_dev *indio_dev, { struct vcnl4035_data *data = iio_priv(indio_dev); int ret; - int raw_data; - unsigned int reg; switch (mask) { case IIO_CHAN_INFO_RAW: ret = vcnl4035_set_pm_runtime_state(data, true); if (ret < 0) return ret; - - ret = iio_device_claim_direct_mode(indio_dev); - if (!ret) { - if (chan->channel) - reg = VCNL4035_ALS_DATA; - else - reg = VCNL4035_WHITE_DATA; - ret = regmap_read(data->regmap, reg, &raw_data); - iio_device_release_direct_mode(indio_dev); - if (!ret) { - *val = raw_data; - ret = IIO_VAL_INT; - } - } + ret = vcnl4035_read_info_raw(indio_dev, chan, val); vcnl4035_set_pm_runtime_state(data, false); return ret; case IIO_CHAN_INFO_INT_TIME: diff --git a/drivers/iio/light/veml6040.c b/drivers/iio/light/veml6040.c index 216e271001a8..71a594b2ec85 100644 --- a/drivers/iio/light/veml6040.c +++ b/drivers/iio/light/veml6040.c @@ -256,13 +256,13 @@ static int veml6040_probe(struct i2c_client *client) static const struct i2c_device_id veml6040_id_table[] = { {"veml6040"}, - {} + { } }; MODULE_DEVICE_TABLE(i2c, veml6040_id_table); static const struct of_device_id veml6040_of_match[] = { {.compatible = "vishay,veml6040"}, - {} + { } }; MODULE_DEVICE_TABLE(of, veml6040_of_match); diff --git a/drivers/iio/light/veml6075.c b/drivers/iio/light/veml6075.c index 859891e8f115..edbb43407054 100644 --- a/drivers/iio/light/veml6075.c +++ b/drivers/iio/light/veml6075.c @@ -458,7 +458,7 @@ MODULE_DEVICE_TABLE(i2c, veml6075_id); static const struct of_device_id veml6075_of_match[] = { { .compatible = "vishay,veml6075" }, - {} + { } }; MODULE_DEVICE_TABLE(of, veml6075_of_match); diff --git a/drivers/iio/light/vl6180.c b/drivers/iio/light/vl6180.c index 6e2183a4243e..cc4f2e5404aa 100644 --- a/drivers/iio/light/vl6180.c +++ b/drivers/iio/light/vl6180.c @@ -745,7 +745,7 @@ static int vl6180_probe(struct i2c_client *client) static const struct of_device_id vl6180_of_match[] = { { .compatible = "st,vl6180", }, - { }, + { } }; MODULE_DEVICE_TABLE(of, vl6180_of_match); diff --git a/drivers/iio/light/zopt2201.c b/drivers/iio/light/zopt2201.c index 604be60e92ac..1e5e9bf2935f 100644 --- a/drivers/iio/light/zopt2201.c +++ b/drivers/iio/light/zopt2201.c @@ -113,11 +113,13 @@ static const struct { { 13, 3125 }, }; -static const struct { +struct zopt2201_scale { unsigned int scale, uscale; /* scale factor as integer + micro */ u8 gain; /* gain register value */ u8 res; /* resolution register value */ -} zopt2201_scale_als[] = { +}; + +static struct zopt2201_scale zopt2201_scale_als[] = { { 19, 200000, 0, 5 }, { 6, 400000, 1, 5 }, { 3, 200000, 2, 5 }, @@ -142,11 +144,7 @@ static const struct { { 0, 8333, 4, 0 }, }; -static const struct { - unsigned int scale, uscale; /* scale factor as integer + micro */ - u8 gain; /* gain register value */ - u8 res; /* resolution register value */ -} zopt2201_scale_uvb[] = { +static struct zopt2201_scale zopt2201_scale_uvb[] = { { 0, 460800, 0, 5 }, { 0, 153600, 1, 5 }, { 0, 76800, 2, 5 }, @@ -348,16 +346,17 @@ static int zopt2201_set_gain(struct zopt2201_data *data, u8 gain) return 0; } -static int zopt2201_write_scale_als_by_idx(struct zopt2201_data *data, int idx) +static int zopt2201_write_scale_by_idx(struct zopt2201_data *data, int idx, + struct zopt2201_scale *zopt2201_scale_array) { int ret; mutex_lock(&data->lock); - ret = zopt2201_set_resolution(data, zopt2201_scale_als[idx].res); + ret = zopt2201_set_resolution(data, zopt2201_scale_array[idx].res); if (ret < 0) goto unlock; - ret = zopt2201_set_gain(data, zopt2201_scale_als[idx].gain); + ret = zopt2201_set_gain(data, zopt2201_scale_array[idx].gain); unlock: mutex_unlock(&data->lock); @@ -371,29 +370,12 @@ static int zopt2201_write_scale_als(struct zopt2201_data *data, for (i = 0; i < ARRAY_SIZE(zopt2201_scale_als); i++) if (val == zopt2201_scale_als[i].scale && - val2 == zopt2201_scale_als[i].uscale) { - return zopt2201_write_scale_als_by_idx(data, i); - } + val2 == zopt2201_scale_als[i].uscale) + return zopt2201_write_scale_by_idx(data, i, zopt2201_scale_als); return -EINVAL; } -static int zopt2201_write_scale_uvb_by_idx(struct zopt2201_data *data, int idx) -{ - int ret; - - mutex_lock(&data->lock); - ret = zopt2201_set_resolution(data, zopt2201_scale_als[idx].res); - if (ret < 0) - goto unlock; - - ret = zopt2201_set_gain(data, zopt2201_scale_als[idx].gain); - -unlock: - mutex_unlock(&data->lock); - return ret; -} - static int zopt2201_write_scale_uvb(struct zopt2201_data *data, int val, int val2) { @@ -402,7 +384,7 @@ static int zopt2201_write_scale_uvb(struct zopt2201_data *data, for (i = 0; i < ARRAY_SIZE(zopt2201_scale_uvb); i++) if (val == zopt2201_scale_uvb[i].scale && val2 == zopt2201_scale_uvb[i].uscale) - return zopt2201_write_scale_uvb_by_idx(data, i); + return zopt2201_write_scale_by_idx(data, i, zopt2201_scale_uvb); return -EINVAL; } diff --git a/drivers/iio/magnetometer/af8133j.c b/drivers/iio/magnetometer/af8133j.c index c1fc339e85b4..192ba2da94e2 100644 --- a/drivers/iio/magnetometer/af8133j.c +++ b/drivers/iio/magnetometer/af8133j.c @@ -370,7 +370,8 @@ static irqreturn_t af8133j_trigger_handler(int irq, void *p) if (ret) goto out_done; - iio_push_to_buffers_with_timestamp(indio_dev, &sample, timestamp); + iio_push_to_buffers_with_ts(indio_dev, &sample, sizeof(sample), + timestamp); out_done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c index 7bc341c69697..947fe8a475f2 100644 --- a/drivers/iio/magnetometer/ak8974.c +++ b/drivers/iio/magnetometer/ak8974.c @@ -673,8 +673,8 @@ static void ak8974_fill_buffer(struct iio_dev *indio_dev) goto out_unlock; } - iio_push_to_buffers_with_timestamp(indio_dev, &ak8974->scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &ak8974->scan, sizeof(ak8974->scan), + iio_get_time_ns(indio_dev)); out_unlock: mutex_unlock(&ak8974->lock); @@ -704,7 +704,7 @@ ak8974_get_mount_matrix(const struct iio_dev *indio_dev, static const struct iio_chan_spec_ext_info ak8974_ext_info[] = { IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, ak8974_get_mount_matrix), - { }, + { } }; #define AK8974_AXIS_CHANNEL(axis, index, bits) \ @@ -1023,14 +1023,14 @@ static const struct i2c_device_id ak8974_id[] = { { "ami306" }, { "ak8974" }, { "hscdtd008a" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, ak8974_id); static const struct of_device_id ak8974_of_match[] = { { .compatible = "asahi-kasei,ak8974", }, { .compatible = "alps,hscdtd008a", }, - {} + { } }; MODULE_DEVICE_TABLE(of, ak8974_of_match); diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index ef1363126cc2..a1e92b2abffd 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -882,8 +882,8 @@ static void ak8975_fill_buffer(struct iio_dev *indio_dev) data->scan.channels[1] = clamp_t(s16, le16_to_cpu(fval[1]), -def->range, def->range); data->scan.channels[2] = clamp_t(s16, le16_to_cpu(fval[2]), -def->range, def->range); - iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), + iio_get_time_ns(indio_dev)); return; @@ -1107,7 +1107,7 @@ static const struct i2c_device_id ak8975_id[] = { {"ak09912", (kernel_ulong_t)&ak_def_array[AK09912] }, {"ak09916", (kernel_ulong_t)&ak_def_array[AK09916] }, {"ak09918", (kernel_ulong_t)&ak_def_array[AK09918] }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, ak8975_id); @@ -1122,7 +1122,7 @@ static const struct of_device_id ak8975_of_match[] = { { .compatible = "ak09912", .data = &ak_def_array[AK09912] }, { .compatible = "asahi-kasei,ak09916", .data = &ak_def_array[AK09916] }, { .compatible = "asahi-kasei,ak09918", .data = &ak_def_array[AK09918] }, - {} + { } }; MODULE_DEVICE_TABLE(of, ak8975_of_match); diff --git a/drivers/iio/magnetometer/als31300.c b/drivers/iio/magnetometer/als31300.c index 87b60c4e81fa..f72af829715f 100644 --- a/drivers/iio/magnetometer/als31300.c +++ b/drivers/iio/magnetometer/als31300.c @@ -245,8 +245,7 @@ static irqreturn_t als31300_trigger_handler(int irq, void *p) scan.channels[0] = x; scan.channels[1] = y; scan.channels[2] = z; - iio_push_to_buffers_with_timestamp(indio_dev, &scan, - pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &scan, sizeof(scan), pf->timestamp); trigger_out: iio_trigger_notify_done(indio_dev->trig); @@ -457,7 +456,7 @@ static const struct i2c_device_id als31300_id[] = { .name = "als31300-2000", .driver_data = (kernel_ulong_t)&al31300_variant_2000, }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(i2c, als31300_id); @@ -474,7 +473,7 @@ static const struct of_device_id als31300_of_match[] = { .compatible = "allegromicro,als31300-2000", .data = &al31300_variant_2000, }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, als31300_of_match); diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c index 88bb673e40d8..f9c51ceae011 100644 --- a/drivers/iio/magnetometer/bmc150_magn.c +++ b/drivers/iio/magnetometer/bmc150_magn.c @@ -678,8 +678,8 @@ static irqreturn_t bmc150_magn_trigger_handler(int irq, void *p) if (ret < 0) goto err; - iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, - pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), + pf->timestamp); err: mutex_unlock(&data->mutex); diff --git a/drivers/iio/magnetometer/bmc150_magn_i2c.c b/drivers/iio/magnetometer/bmc150_magn_i2c.c index 8cbeda924bda..b110791f688a 100644 --- a/drivers/iio/magnetometer/bmc150_magn_i2c.c +++ b/drivers/iio/magnetometer/bmc150_magn_i2c.c @@ -42,7 +42,7 @@ static const struct i2c_device_id bmc150_magn_i2c_id[] = { { "bmc150_magn" }, { "bmc156_magn" }, { "bmm150_magn" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, bmc150_magn_i2c_id); diff --git a/drivers/iio/magnetometer/bmc150_magn_spi.c b/drivers/iio/magnetometer/bmc150_magn_spi.c index 2d4b8cba32f1..896b1d280731 100644 --- a/drivers/iio/magnetometer/bmc150_magn_spi.c +++ b/drivers/iio/magnetometer/bmc150_magn_spi.c @@ -37,7 +37,7 @@ static const struct spi_device_id bmc150_magn_spi_id[] = { {"bmc150_magn", 0}, {"bmc156_magn", 0}, {"bmm150_magn", 0}, - {} + { } }; MODULE_DEVICE_TABLE(spi, bmc150_magn_spi_id); diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c index 97ddaa2a03f6..c673f9323e47 100644 --- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c +++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c @@ -563,7 +563,7 @@ static const struct platform_device_id hid_magn_3d_ids[] = { /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ .name = "HID-SENSOR-200083", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(platform, hid_magn_3d_ids); diff --git a/drivers/iio/magnetometer/hmc5843.h b/drivers/iio/magnetometer/hmc5843.h index ffd669b1ee7c..7a3faf7ffed4 100644 --- a/drivers/iio/magnetometer/hmc5843.h +++ b/drivers/iio/magnetometer/hmc5843.h @@ -34,7 +34,7 @@ enum hmc5843_ids { * @regmap: hardware access register maps * @variant: describe chip variants * @scan: buffer to pack data for passing to - * iio_push_to_buffers_with_timestamp() + * iio_push_to_buffers_with_ts() */ struct hmc5843_data { struct device *dev; diff --git a/drivers/iio/magnetometer/hmc5843_core.c b/drivers/iio/magnetometer/hmc5843_core.c index 2fc84310e2cc..fc16ebd314f7 100644 --- a/drivers/iio/magnetometer/hmc5843_core.c +++ b/drivers/iio/magnetometer/hmc5843_core.c @@ -452,8 +452,8 @@ static irqreturn_t hmc5843_trigger_handler(int irq, void *p) if (ret < 0) goto done; - iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), + iio_get_time_ns(indio_dev)); done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/magnetometer/hmc5843_i2c.c b/drivers/iio/magnetometer/hmc5843_i2c.c index 657a309e2bd5..b41709959e2b 100644 --- a/drivers/iio/magnetometer/hmc5843_i2c.c +++ b/drivers/iio/magnetometer/hmc5843_i2c.c @@ -84,7 +84,7 @@ static const struct of_device_id hmc5843_of_match[] = { { .compatible = "honeywell,hmc5883", .data = (void *)HMC5883_ID }, { .compatible = "honeywell,hmc5883l", .data = (void *)HMC5883L_ID }, { .compatible = "honeywell,hmc5983", .data = (void *)HMC5983_ID }, - {} + { } }; MODULE_DEVICE_TABLE(of, hmc5843_of_match); diff --git a/drivers/iio/magnetometer/hmc5843_spi.c b/drivers/iio/magnetometer/hmc5843_spi.c index b7fde331069d..6a55c1559b0d 100644 --- a/drivers/iio/magnetometer/hmc5843_spi.c +++ b/drivers/iio/magnetometer/hmc5843_spi.c @@ -60,7 +60,6 @@ static int hmc5843_spi_probe(struct spi_device *spi) spi->mode = SPI_MODE_3; spi->max_speed_hz = 8000000; - spi->bits_per_word = 8; ret = spi_setup(spi); if (ret) return ret; diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c index 2fe8e97f2cf8..ff09250a06e7 100644 --- a/drivers/iio/magnetometer/mag3110.c +++ b/drivers/iio/magnetometer/mag3110.c @@ -9,6 +9,7 @@ * TODO: irq, user offset, oversampling, continuous mode */ +#include <linux/cleanup.h> #include <linux/module.h> #include <linux/i2c.h> #include <linux/iio/iio.h> @@ -102,17 +103,12 @@ static int mag3110_read(struct mag3110_data *data, __be16 buf[3]) { int ret; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); ret = mag3110_request(data); - if (ret < 0) { - mutex_unlock(&data->lock); + if (ret < 0) return ret; - } - ret = i2c_smbus_read_i2c_block_data(data->client, - MAG3110_OUT_X, 3 * sizeof(__be16), (u8 *) buf); - mutex_unlock(&data->lock); - - return ret; + return i2c_smbus_read_i2c_block_data(data->client, MAG3110_OUT_X, + 3 * sizeof(__be16), (u8 *) buf); } static ssize_t mag3110_show_int_plus_micros(char *buf, @@ -231,19 +227,17 @@ static int mag3110_change_config(struct mag3110_data *data, u8 reg, u8 val) int ret; int is_active; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); is_active = mag3110_is_active(data); - if (is_active < 0) { - ret = is_active; - goto fail; - } + if (is_active < 0) + return is_active; /* config can only be changed when in standby */ if (is_active > 0) { ret = mag3110_standby(data); if (ret < 0) - goto fail; + return ret; } /* @@ -252,23 +246,52 @@ static int mag3110_change_config(struct mag3110_data *data, u8 reg, u8 val) */ ret = mag3110_wait_standby(data); if (ret < 0) - goto fail; + return ret; ret = i2c_smbus_write_byte_data(data->client, reg, val); if (ret < 0) - goto fail; + return ret; if (is_active > 0) { ret = mag3110_active(data); if (ret < 0) - goto fail; + return ret; } - ret = 0; -fail: - mutex_unlock(&data->lock); + return 0; +} - return ret; +static int __mag3110_read_info_raw(struct mag3110_data *data, + struct iio_chan_spec const *chan, + int *val) +{ + __be16 buffer[3]; + int ret; + + switch (chan->type) { + case IIO_MAGN: /* in 0.1 uT / LSB */ + ret = mag3110_read(data, buffer); + if (ret < 0) + return ret; + *val = sign_extend32(be16_to_cpu(buffer[chan->scan_index]), + chan->scan_type.realbits - 1); + return IIO_VAL_INT; + + case IIO_TEMP: { /* in 1 C / LSB */ + guard(mutex)(&data->lock); + ret = mag3110_request(data); + if (ret < 0) + return ret; + ret = i2c_smbus_read_byte_data(data->client, + MAG3110_DIE_TEMP); + if (ret < 0) + return ret; + *val = sign_extend32(ret, chan->scan_type.realbits - 1); + return IIO_VAL_INT; + } + default: + return -EINVAL; + } } static int mag3110_read_raw(struct iio_dev *indio_dev, @@ -276,46 +299,14 @@ static int mag3110_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { struct mag3110_data *data = iio_priv(indio_dev); - __be16 buffer[3]; int i, ret; switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; - - switch (chan->type) { - case IIO_MAGN: /* in 0.1 uT / LSB */ - ret = mag3110_read(data, buffer); - if (ret < 0) - goto release; - *val = sign_extend32( - be16_to_cpu(buffer[chan->scan_index]), - chan->scan_type.realbits - 1); - ret = IIO_VAL_INT; - break; - case IIO_TEMP: /* in 1 C / LSB */ - mutex_lock(&data->lock); - ret = mag3110_request(data); - if (ret < 0) { - mutex_unlock(&data->lock); - goto release; - } - ret = i2c_smbus_read_byte_data(data->client, - MAG3110_DIE_TEMP); - mutex_unlock(&data->lock); - if (ret < 0) - goto release; - *val = sign_extend32(ret, - chan->scan_type.realbits - 1); - ret = IIO_VAL_INT; - break; - default: - ret = -EINVAL; - } -release: - iio_device_release_direct_mode(indio_dev); + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + ret = __mag3110_read_info_raw(data, chan, val); + iio_device_release_direct(indio_dev); return ret; case IIO_CHAN_INFO_SCALE: @@ -346,24 +337,18 @@ release: return -EINVAL; } -static int mag3110_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, int val2, long mask) +static int __mag3110_write_raw(struct mag3110_data *data, + struct iio_chan_spec const *chan, + int val, int val2, long mask) { - struct mag3110_data *data = iio_priv(indio_dev); - int rate, ret; - - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + int rate; switch (mask) { case IIO_CHAN_INFO_SAMP_FREQ: rate = mag3110_get_samp_freq_index(data, val, val2); - if (rate < 0) { - ret = -EINVAL; - break; - } + if (rate < 0) + return -EINVAL; + data->ctrl_reg1 &= 0xff & ~MAG3110_CTRL_DR_MASK & ~MAG3110_CTRL_AC; data->ctrl_reg1 |= rate << MAG3110_CTRL_DR_SHIFT; @@ -371,22 +356,32 @@ static int mag3110_write_raw(struct iio_dev *indio_dev, if (data->sleep_val < 40) data->ctrl_reg1 |= MAG3110_CTRL_AC; - ret = mag3110_change_config(data, MAG3110_CTRL_REG1, - data->ctrl_reg1); - break; + return mag3110_change_config(data, MAG3110_CTRL_REG1, + data->ctrl_reg1); + case IIO_CHAN_INFO_CALIBBIAS: - if (val < -10000 || val > 10000) { - ret = -EINVAL; - break; - } - ret = i2c_smbus_write_word_swapped(data->client, + if (val < -10000 || val > 10000) + return -EINVAL; + + return i2c_smbus_write_word_swapped(data->client, MAG3110_OFF_X + 2 * chan->scan_index, val << 1); - break; default: - ret = -EINVAL; - break; + return -EINVAL; } - iio_device_release_direct_mode(indio_dev); +} + +static int mag3110_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct mag3110_data *data = iio_priv(indio_dev); + int ret; + + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + ret = __mag3110_write_raw(data, chan, val, val2, mask); + iio_device_release_direct(indio_dev); + return ret; } @@ -409,8 +404,8 @@ static irqreturn_t mag3110_trigger_handler(int irq, void *p) data->scan.temperature = ret; } - iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), + iio_get_time_ns(indio_dev)); done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c index dd480a4a5f98..e08a57cd6de2 100644 --- a/drivers/iio/magnetometer/mmc35240.c +++ b/drivers/iio/magnetometer/mmc35240.c @@ -556,13 +556,13 @@ MODULE_DEVICE_TABLE(of, mmc35240_of_match); static const struct acpi_device_id mmc35240_acpi_match[] = { {"MMC35240", 0}, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, mmc35240_acpi_match); static const struct i2c_device_id mmc35240_id[] = { { "mmc35240" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, mmc35240_id); diff --git a/drivers/iio/magnetometer/rm3100-core.c b/drivers/iio/magnetometer/rm3100-core.c index c99694a77a14..2b2884425746 100644 --- a/drivers/iio/magnetometer/rm3100-core.c +++ b/drivers/iio/magnetometer/rm3100-core.c @@ -399,12 +399,11 @@ static int rm3100_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret < 0) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = rm3100_read_mag(data, chan->scan_index, val); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; case IIO_CHAN_INFO_SCALE: @@ -516,8 +515,8 @@ static irqreturn_t rm3100_trigger_handler(int irq, void *p) * Always using the same buffer so that we wouldn't need to set the * paddings to 0 in case of leaking any data. */ - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, - pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, data->buffer, sizeof(data->buffer), + pf->timestamp); done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/magnetometer/rm3100-spi.c b/drivers/iio/magnetometer/rm3100-spi.c index dd6d48043740..2f60a41c07f7 100644 --- a/drivers/iio/magnetometer/rm3100-spi.c +++ b/drivers/iio/magnetometer/rm3100-spi.c @@ -32,7 +32,6 @@ static int rm3100_probe(struct spi_device *spi) spi->mode = SPI_MODE_0; /* Data rates cannot exceed 1Mbits. */ spi->max_speed_hz = 1000000; - spi->bits_per_word = 8; ret = spi_setup(spi); if (ret) return ret; diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c index 1672b274768d..ed70e782af5e 100644 --- a/drivers/iio/magnetometer/st_magn_i2c.c +++ b/drivers/iio/magnetometer/st_magn_i2c.c @@ -54,7 +54,7 @@ static const struct of_device_id st_magn_of_match[] = { .compatible = "st,lsm303c-magn", .data = LSM303C_MAGN_DEV_NAME, }, - {}, + { } }; MODULE_DEVICE_TABLE(of, st_magn_of_match); @@ -102,7 +102,7 @@ static const struct i2c_device_id st_magn_id_table[] = { { LSM9DS1_MAGN_DEV_NAME }, { IIS2MDC_MAGN_DEV_NAME }, { LSM303C_MAGN_DEV_NAME }, - {}, + { } }; MODULE_DEVICE_TABLE(i2c, st_magn_id_table); diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c index fe4d0e63133c..68816362bb95 100644 --- a/drivers/iio/magnetometer/st_magn_spi.c +++ b/drivers/iio/magnetometer/st_magn_spi.c @@ -49,7 +49,7 @@ static const struct of_device_id st_magn_of_match[] = { .compatible = "st,lsm303c-magn", .data = LSM303C_MAGN_DEV_NAME, }, - {} + { } }; MODULE_DEVICE_TABLE(of, st_magn_of_match); @@ -94,7 +94,7 @@ static const struct spi_device_id st_magn_id_table[] = { { LSM9DS1_MAGN_DEV_NAME }, { IIS2MDC_MAGN_DEV_NAME }, { LSM303C_MAGN_DEV_NAME }, - {}, + { } }; MODULE_DEVICE_TABLE(spi, st_magn_id_table); diff --git a/drivers/iio/magnetometer/tmag5273.c b/drivers/iio/magnetometer/tmag5273.c index 4187abe12784..2ca5c26f0091 100644 --- a/drivers/iio/magnetometer/tmag5273.c +++ b/drivers/iio/magnetometer/tmag5273.c @@ -712,13 +712,13 @@ static DEFINE_RUNTIME_DEV_PM_OPS(tmag5273_pm_ops, static const struct i2c_device_id tmag5273_id[] = { { "tmag5273" }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(i2c, tmag5273_id); static const struct of_device_id tmag5273_of_match[] = { { .compatible = "ti,tmag5273" }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, tmag5273_of_match); diff --git a/drivers/iio/magnetometer/yamaha-yas530.c b/drivers/iio/magnetometer/yamaha-yas530.c index 28012b20c64f..340607111d9a 100644 --- a/drivers/iio/magnetometer/yamaha-yas530.c +++ b/drivers/iio/magnetometer/yamaha-yas530.c @@ -674,8 +674,8 @@ static void yas5xx_fill_buffer(struct iio_dev *indio_dev) yas5xx->scan.channels[1] = x; yas5xx->scan.channels[2] = y; yas5xx->scan.channels[3] = z; - iio_push_to_buffers_with_timestamp(indio_dev, &yas5xx->scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &yas5xx->scan, sizeof(yas5xx->scan), + iio_get_time_ns(indio_dev)); } static irqreturn_t yas5xx_handle_trigger(int irq, void *p) @@ -1585,7 +1585,7 @@ static const struct i2c_device_id yas5xx_id[] = { {"yas532", (kernel_ulong_t)&yas5xx_chip_info_tbl[yas532] }, {"yas533", (kernel_ulong_t)&yas5xx_chip_info_tbl[yas533] }, {"yas537", (kernel_ulong_t)&yas5xx_chip_info_tbl[yas537] }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, yas5xx_id); @@ -1594,7 +1594,7 @@ static const struct of_device_id yas5xx_of_match[] = { { .compatible = "yamaha,yas532", &yas5xx_chip_info_tbl[yas532] }, { .compatible = "yamaha,yas533", &yas5xx_chip_info_tbl[yas533] }, { .compatible = "yamaha,yas537", &yas5xx_chip_info_tbl[yas537] }, - {} + { } }; MODULE_DEVICE_TABLE(of, yas5xx_of_match); diff --git a/drivers/iio/multiplexer/iio-mux.c b/drivers/iio/multiplexer/iio-mux.c index c309d991490c..b742ca9a99d1 100644 --- a/drivers/iio/multiplexer/iio-mux.c +++ b/drivers/iio/multiplexer/iio-mux.c @@ -448,7 +448,7 @@ static int mux_probe(struct platform_device *pdev) static const struct of_device_id mux_match[] = { { .compatible = "io-channel-mux" }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, mux_match); diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c index 429035b65c65..4e23a598a3fb 100644 --- a/drivers/iio/orientation/hid-sensor-incl-3d.c +++ b/drivers/iio/orientation/hid-sensor-incl-3d.c @@ -399,7 +399,7 @@ static const struct platform_device_id hid_incl_3d_ids[] = { /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ .name = "HID-SENSOR-200086", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(platform, hid_incl_3d_ids); diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c index 96f03988640c..e759f91a710a 100644 --- a/drivers/iio/orientation/hid-sensor-rotation.c +++ b/drivers/iio/orientation/hid-sensor-rotation.c @@ -19,7 +19,7 @@ struct dev_rot_state { struct hid_sensor_common common_attributes; struct hid_sensor_hub_attribute_info quaternion; struct { - s32 sampled_vals[4] __aligned(16); + s32 sampled_vals[4]; aligned_s64 timestamp; } scan; int scale_pre_decml; @@ -351,7 +351,7 @@ static const struct platform_device_id hid_dev_rot_ids[] = { /* Geomagnetic orientation(AM) sensor */ .name = "HID-SENSOR-2000c1", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(platform, hid_dev_rot_ids); diff --git a/drivers/iio/position/hid-sensor-custom-intel-hinge.c b/drivers/iio/position/hid-sensor-custom-intel-hinge.c index 423bbb8a3b38..bff7039690ac 100644 --- a/drivers/iio/position/hid-sensor-custom-intel-hinge.c +++ b/drivers/iio/position/hid-sensor-custom-intel-hinge.c @@ -358,7 +358,7 @@ static const struct platform_device_id hid_hinge_ids[] = { /* Format: HID-SENSOR-INT-usage_id_in_hex_lowercase */ .name = "HID-SENSOR-INT-020b", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(platform, hid_hinge_ids); diff --git a/drivers/iio/potentiometer/ad5272.c b/drivers/iio/potentiometer/ad5272.c index b17941e4c2f7..672b1ca3a920 100644 --- a/drivers/iio/potentiometer/ad5272.c +++ b/drivers/iio/potentiometer/ad5272.c @@ -199,7 +199,7 @@ static const struct of_device_id ad5272_dt_ids[] = { { .compatible = "adi,ad5272-100", .data = (void *)AD5272_100 }, { .compatible = "adi,ad5274-020", .data = (void *)AD5274_020 }, { .compatible = "adi,ad5274-100", .data = (void *)AD5274_100 }, - {} + { } }; MODULE_DEVICE_TABLE(of, ad5272_dt_ids); @@ -209,7 +209,7 @@ static const struct i2c_device_id ad5272_id[] = { { "ad5272-100", AD5272_100 }, { "ad5274-020", AD5274_020 }, { "ad5274-100", AD5274_100 }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, ad5272_id); diff --git a/drivers/iio/potentiometer/ds1803.c b/drivers/iio/potentiometer/ds1803.c index e0526dd0e3cb..5761f69c538a 100644 --- a/drivers/iio/potentiometer/ds1803.c +++ b/drivers/iio/potentiometer/ds1803.c @@ -231,7 +231,7 @@ static const struct of_device_id ds1803_dt_ids[] = { { .compatible = "maxim,ds1803-050", .data = &ds1803_cfg[DS1803_050] }, { .compatible = "maxim,ds1803-100", .data = &ds1803_cfg[DS1803_100] }, { .compatible = "maxim,ds3502", .data = &ds1803_cfg[DS3502] }, - {} + { } }; MODULE_DEVICE_TABLE(of, ds1803_dt_ids); @@ -240,7 +240,7 @@ static const struct i2c_device_id ds1803_id[] = { { "ds1803-050", (kernel_ulong_t)&ds1803_cfg[DS1803_050] }, { "ds1803-100", (kernel_ulong_t)&ds1803_cfg[DS1803_100] }, { "ds3502", (kernel_ulong_t)&ds1803_cfg[DS3502] }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, ds1803_id); diff --git a/drivers/iio/potentiometer/max5432.c b/drivers/iio/potentiometer/max5432.c index c8e2481dadb5..26390be79d02 100644 --- a/drivers/iio/potentiometer/max5432.c +++ b/drivers/iio/potentiometer/max5432.c @@ -114,7 +114,7 @@ static const struct of_device_id max5432_dt_ids[] = { { .compatible = "maxim,max5433", .data = (void *)MAX5432_OHM_100K }, { .compatible = "maxim,max5434", .data = (void *)MAX5432_OHM_50K }, { .compatible = "maxim,max5435", .data = (void *)MAX5432_OHM_100K }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, max5432_dt_ids); diff --git a/drivers/iio/potentiometer/max5487.c b/drivers/iio/potentiometer/max5487.c index 4838d2e72f53..3b11b991940b 100644 --- a/drivers/iio/potentiometer/max5487.c +++ b/drivers/iio/potentiometer/max5487.c @@ -137,7 +137,7 @@ static const struct acpi_device_id max5487_acpi_match[] = { { "MAX5487", 10 }, { "MAX5488", 50 }, { "MAX5489", 100 }, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, max5487_acpi_match); diff --git a/drivers/iio/potentiometer/mcp4018.c b/drivers/iio/potentiometer/mcp4018.c index 44678d372126..a88bb2231850 100644 --- a/drivers/iio/potentiometer/mcp4018.c +++ b/drivers/iio/potentiometer/mcp4018.c @@ -117,7 +117,7 @@ static const struct i2c_device_id mcp4018_id[] = { MCP4018_ID_TABLE("mcp4019-103", MCP4018_103), MCP4018_ID_TABLE("mcp4019-503", MCP4018_503), MCP4018_ID_TABLE("mcp4019-104", MCP4018_104), - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(i2c, mcp4018_id); @@ -139,7 +139,7 @@ static const struct of_device_id mcp4018_of_match[] = { MCP4018_COMPATIBLE("microchip,mcp4019-103", MCP4018_103), MCP4018_COMPATIBLE("microchip,mcp4019-503", MCP4018_503), MCP4018_COMPATIBLE("microchip,mcp4019-104", MCP4018_104), - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, mcp4018_of_match); diff --git a/drivers/iio/potentiometer/mcp41010.c b/drivers/iio/potentiometer/mcp41010.c index 2b73c7540209..f35fc4a6c55b 100644 --- a/drivers/iio/potentiometer/mcp41010.c +++ b/drivers/iio/potentiometer/mcp41010.c @@ -171,7 +171,7 @@ static const struct of_device_id mcp41010_match[] = { { .compatible = "microchip,mcp42010", .data = &mcp41010_cfg[MCP42010] }, { .compatible = "microchip,mcp42050", .data = &mcp41010_cfg[MCP42050] }, { .compatible = "microchip,mcp42100", .data = &mcp41010_cfg[MCP42100] }, - {} + { } }; MODULE_DEVICE_TABLE(of, mcp41010_match); @@ -182,7 +182,7 @@ static const struct spi_device_id mcp41010_id[] = { { "mcp42010", MCP42010 }, { "mcp42050", MCP42050 }, { "mcp42100", MCP42100 }, - {} + { } }; MODULE_DEVICE_TABLE(spi, mcp41010_id); diff --git a/drivers/iio/potentiometer/mcp4131.c b/drivers/iio/potentiometer/mcp4131.c index 7890c0993ec4..9082b559d029 100644 --- a/drivers/iio/potentiometer/mcp4131.c +++ b/drivers/iio/potentiometer/mcp4131.c @@ -403,7 +403,7 @@ static const struct of_device_id mcp4131_dt_ids[] = { .data = &mcp4131_cfg[MCP426x_503] }, { .compatible = "microchip,mcp4262-104", .data = &mcp4131_cfg[MCP426x_104] }, - {} + { } }; MODULE_DEVICE_TABLE(of, mcp4131_dt_ids); @@ -472,7 +472,7 @@ static const struct spi_device_id mcp4131_id[] = { { "mcp4262-103", MCP426x_103 }, { "mcp4262-503", MCP426x_503 }, { "mcp4262-104", MCP426x_104 }, - {} + { } }; MODULE_DEVICE_TABLE(spi, mcp4131_id); diff --git a/drivers/iio/potentiometer/mcp4531.c b/drivers/iio/potentiometer/mcp4531.c index f28880ebd758..9912e91ff7b4 100644 --- a/drivers/iio/potentiometer/mcp4531.c +++ b/drivers/iio/potentiometer/mcp4531.c @@ -276,7 +276,7 @@ static const struct i2c_device_id mcp4531_id[] = { MCP4531_ID_TABLE("mcp4662-103", MCP466x_103), MCP4531_ID_TABLE("mcp4662-503", MCP466x_503), MCP4531_ID_TABLE("mcp4662-104", MCP466x_104), - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(i2c, mcp4531_id); @@ -350,7 +350,7 @@ static const struct of_device_id mcp4531_of_match[] = { MCP4531_COMPATIBLE("microchip,mcp4662-103", MCP466x_103), MCP4531_COMPATIBLE("microchip,mcp4662-503", MCP466x_503), MCP4531_COMPATIBLE("microchip,mcp4662-104", MCP466x_104), - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(of, mcp4531_of_match); diff --git a/drivers/iio/potentiometer/tpl0102.c b/drivers/iio/potentiometer/tpl0102.c index 8923ccb0fc4f..a42b57733363 100644 --- a/drivers/iio/potentiometer/tpl0102.c +++ b/drivers/iio/potentiometer/tpl0102.c @@ -153,7 +153,7 @@ static const struct i2c_device_id tpl0102_id[] = { { "cat5140-104", CAT5140_104 }, { "tpl0102-104", TPL0102_104 }, { "tpl0401-103", TPL0401_103 }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, tpl0102_id); diff --git a/drivers/iio/potentiostat/lmp91000.c b/drivers/iio/potentiostat/lmp91000.c index c2c6b2b29867..030498d0b763 100644 --- a/drivers/iio/potentiostat/lmp91000.c +++ b/drivers/iio/potentiostat/lmp91000.c @@ -400,14 +400,14 @@ static void lmp91000_remove(struct i2c_client *client) static const struct of_device_id lmp91000_of_match[] = { { .compatible = "ti,lmp91000", }, { .compatible = "ti,lmp91002", }, - { }, + { } }; MODULE_DEVICE_TABLE(of, lmp91000_of_match); static const struct i2c_device_id lmp91000_id[] = { { "lmp91000" }, { "lmp91002" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, lmp91000_id); diff --git a/drivers/iio/pressure/abp060mg.c b/drivers/iio/pressure/abp060mg.c index 752a63c06b44..a0d956c3e254 100644 --- a/drivers/iio/pressure/abp060mg.c +++ b/drivers/iio/pressure/abp060mg.c @@ -247,7 +247,7 @@ static const struct i2c_device_id abp060mg_id_table[] = { { "abp015pd", ABP015PD }, { "abp030pd", ABP030PD }, { "abp060pd", ABP060PD }, - { /* empty */ }, + { } }; MODULE_DEVICE_TABLE(i2c, abp060mg_id_table); diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c index d44ab65c94cb..f37f20776c89 100644 --- a/drivers/iio/pressure/bmp280-core.c +++ b/drivers/iio/pressure/bmp280-core.c @@ -46,6 +46,7 @@ #include <linux/random.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> +#include <linux/types.h> #include <linux/iio/buffer.h> #include <linux/iio/iio.h> @@ -1105,9 +1106,13 @@ static irqreturn_t bmp280_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct bmp280_data *data = iio_priv(indio_dev); - u32 adc_temp, adc_press, comp_press; - s32 t_fine, comp_temp; - s32 *chans = (s32 *)data->sensor_data; + u32 adc_temp, adc_press; + s32 t_fine; + struct { + u32 comp_press; + s32 comp_temp; + aligned_s64 timestamp; + } buffer; int ret; guard(mutex)(&data->lock); @@ -1127,7 +1132,7 @@ static irqreturn_t bmp280_trigger_handler(int irq, void *p) goto out; } - comp_temp = bmp280_compensate_temp(data, adc_temp); + buffer.comp_temp = bmp280_compensate_temp(data, adc_temp); /* Pressure calculations */ adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[0])); @@ -1137,13 +1142,10 @@ static irqreturn_t bmp280_trigger_handler(int irq, void *p) } t_fine = bmp280_calc_t_fine(data, adc_temp); - comp_press = bmp280_compensate_press(data, adc_press, t_fine); - - chans[0] = comp_press; - chans[1] = comp_temp; + buffer.comp_press = bmp280_compensate_press(data, adc_press, t_fine); - iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &buffer, sizeof(buffer), + iio_get_time_ns(indio_dev)); out: iio_trigger_notify_done(indio_dev->trig); @@ -1225,11 +1227,19 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct bmp280_data *data = iio_priv(indio_dev); - u32 adc_temp, adc_press, adc_humidity, comp_press, comp_humidity; - s32 t_fine, comp_temp; - s32 *chans = (s32 *)data->sensor_data; + u32 adc_temp, adc_press, adc_humidity; + s32 t_fine; + struct { + u32 comp_press; + s32 comp_temp; + u32 comp_humidity; + aligned_s64 timestamp; + } buffer; int ret; + /* Don't leak uninitialized stack to userspace. */ + memset(&buffer, 0, sizeof(buffer)); + guard(mutex)(&data->lock); /* Burst read data registers */ @@ -1247,7 +1257,7 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p) goto out; } - comp_temp = bmp280_compensate_temp(data, adc_temp); + buffer.comp_temp = bmp280_compensate_temp(data, adc_temp); /* Pressure calculations */ adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[0])); @@ -1257,7 +1267,7 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p) } t_fine = bmp280_calc_t_fine(data, adc_temp); - comp_press = bmp280_compensate_press(data, adc_press, t_fine); + buffer.comp_press = bmp280_compensate_press(data, adc_press, t_fine); /* Humidity calculations */ adc_humidity = get_unaligned_be16(&data->buf[6]); @@ -1267,14 +1277,11 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p) goto out; } - comp_humidity = bme280_compensate_humidity(data, adc_humidity, t_fine); - - chans[0] = comp_press; - chans[1] = comp_temp; - chans[2] = comp_humidity; + buffer.comp_humidity = bme280_compensate_humidity(data, adc_humidity, + t_fine); - iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &buffer, sizeof(buffer), + iio_get_time_ns(indio_dev)); out: iio_trigger_notify_done(indio_dev->trig); @@ -1899,9 +1906,13 @@ static irqreturn_t bmp380_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct bmp280_data *data = iio_priv(indio_dev); - u32 adc_temp, adc_press, comp_press; - s32 t_fine, comp_temp; - s32 *chans = (s32 *)data->sensor_data; + u32 adc_temp, adc_press; + s32 t_fine; + struct { + u32 comp_press; + s32 comp_temp; + aligned_s64 timestamp; + } buffer; int ret; guard(mutex)(&data->lock); @@ -1921,7 +1932,7 @@ static irqreturn_t bmp380_trigger_handler(int irq, void *p) goto out; } - comp_temp = bmp380_compensate_temp(data, adc_temp); + buffer.comp_temp = bmp380_compensate_temp(data, adc_temp); /* Pressure calculations */ adc_press = get_unaligned_le24(&data->buf[0]); @@ -1931,13 +1942,10 @@ static irqreturn_t bmp380_trigger_handler(int irq, void *p) } t_fine = bmp380_calc_t_fine(data, adc_temp); - comp_press = bmp380_compensate_press(data, adc_press, t_fine); + buffer.comp_press = bmp380_compensate_press(data, adc_press, t_fine); - chans[0] = comp_press; - chans[1] = comp_temp; - - iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &buffer, sizeof(buffer), + iio_get_time_ns(indio_dev)); out: iio_trigger_notify_done(indio_dev->trig); @@ -2608,7 +2616,12 @@ static irqreturn_t bmp580_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct bmp280_data *data = iio_priv(indio_dev); - int ret, offset; + struct { + __le32 comp_temp; + __le32 comp_press; + aligned_s64 timestamp; + } buffer; + int ret; guard(mutex)(&data->lock); @@ -2620,18 +2633,14 @@ static irqreturn_t bmp580_trigger_handler(int irq, void *p) goto out; } - offset = 0; - /* Pressure calculations */ - memcpy(&data->sensor_data[offset], &data->buf[3], 3); - - offset += sizeof(s32); + memcpy(&buffer.comp_press, &data->buf[3], 3); /* Temperature calculations */ - memcpy(&data->sensor_data[offset], &data->buf[0], 3); + memcpy(&buffer.comp_temp, &data->buf[0], 3); - iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &buffer, sizeof(buffer), + iio_get_time_ns(indio_dev)); out: iio_trigger_notify_done(indio_dev->trig); @@ -2952,25 +2961,26 @@ static irqreturn_t bmp180_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct bmp280_data *data = iio_priv(indio_dev); - int ret, comp_temp, comp_press; - s32 *chans = (s32 *)data->sensor_data; + struct { + u32 comp_press; + s32 comp_temp; + aligned_s64 timestamp; + } buffer; + int ret; guard(mutex)(&data->lock); - ret = bmp180_read_temp(data, &comp_temp); + ret = bmp180_read_temp(data, &buffer.comp_temp); if (ret) goto out; - ret = bmp180_read_press(data, &comp_press); + ret = bmp180_read_press(data, &buffer.comp_press); if (ret) goto out; - chans[0] = comp_press; - chans[1] = comp_temp; - - iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &buffer, sizeof(buffer), + iio_get_time_ns(indio_dev)); out: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/pressure/bmp280-i2c.c b/drivers/iio/pressure/bmp280-i2c.c index 868e1b2ec711..8e459b6c97ff 100644 --- a/drivers/iio/pressure/bmp280-i2c.c +++ b/drivers/iio/pressure/bmp280-i2c.c @@ -33,7 +33,7 @@ static const struct of_device_id bmp280_of_i2c_match[] = { { .compatible = "bosch,bme280", .data = &bme280_chip_info }, { .compatible = "bosch,bmp380", .data = &bmp380_chip_info }, { .compatible = "bosch,bmp580", .data = &bmp580_chip_info }, - { }, + { } }; MODULE_DEVICE_TABLE(of, bmp280_of_i2c_match); @@ -44,7 +44,7 @@ static const struct i2c_device_id bmp280_i2c_id[] = { {"bme280", (kernel_ulong_t)&bme280_chip_info }, {"bmp380", (kernel_ulong_t)&bmp380_chip_info }, {"bmp580", (kernel_ulong_t)&bmp580_chip_info }, - { }, + { } }; MODULE_DEVICE_TABLE(i2c, bmp280_i2c_id); diff --git a/drivers/iio/pressure/bmp280-spi.c b/drivers/iio/pressure/bmp280-spi.c index 0e6e27892f99..3b90384f17d7 100644 --- a/drivers/iio/pressure/bmp280-spi.c +++ b/drivers/iio/pressure/bmp280-spi.c @@ -81,14 +81,6 @@ static int bmp280_spi_probe(struct spi_device *spi) const struct bmp280_chip_info *chip_info; struct regmap_bus const *bmp_regmap_bus; struct regmap *regmap; - int ret; - - spi->bits_per_word = 8; - ret = spi_setup(spi); - if (ret < 0) { - dev_err(&spi->dev, "spi_setup failed!\n"); - return ret; - } chip_info = spi_get_device_match_data(spi); @@ -121,7 +113,7 @@ static const struct of_device_id bmp280_of_spi_match[] = { { .compatible = "bosch,bme280", .data = &bme280_chip_info }, { .compatible = "bosch,bmp380", .data = &bmp380_chip_info }, { .compatible = "bosch,bmp580", .data = &bmp580_chip_info }, - { }, + { } }; MODULE_DEVICE_TABLE(of, bmp280_of_spi_match); diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h index 5b2ee1d0ee46..25bb9c743a05 100644 --- a/drivers/iio/pressure/bmp280.h +++ b/drivers/iio/pressure/bmp280.h @@ -349,7 +349,6 @@ BMP280_NUM_TEMP_BYTES + \ BME280_NUM_HUMIDITY_BYTES) -#define BME280_NUM_MAX_CHANNELS 3 /* Core exported structs */ static const char *const bmp280_supply_names[] = { @@ -452,13 +451,6 @@ struct bmp280_data { */ int sampling_freq; - /* - * Data to push to userspace triggered buffer. Up to 3 channels and - * s64 timestamp, aligned. - */ - u8 sensor_data[ALIGN(sizeof(s32) * BME280_NUM_MAX_CHANNELS, sizeof(s64)) - + sizeof(s64)] __aligned(sizeof(s64)); - /* Value to hold the current operation mode of the device */ enum bmp280_op_mode op_mode; diff --git a/drivers/iio/pressure/cros_ec_baro.c b/drivers/iio/pressure/cros_ec_baro.c index 2649c2f89e89..c6b950c596c1 100644 --- a/drivers/iio/pressure/cros_ec_baro.c +++ b/drivers/iio/pressure/cros_ec_baro.c @@ -192,7 +192,7 @@ static const struct platform_device_id cros_ec_baro_ids[] = { { .name = "cros-ec-baro", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(platform, cros_ec_baro_ids); diff --git a/drivers/iio/pressure/dlhl60d.c b/drivers/iio/pressure/dlhl60d.c index e99e97ea6300..48afe5c94000 100644 --- a/drivers/iio/pressure/dlhl60d.c +++ b/drivers/iio/pressure/dlhl60d.c @@ -147,12 +147,11 @@ static int dlh_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = dlh_read_direct(st, &pressure, &temperature); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); if (ret) return ret; @@ -344,14 +343,14 @@ static int dlh_probe(struct i2c_client *client) static const struct of_device_id dlh_of_match[] = { { .compatible = "asc,dlhl60d" }, { .compatible = "asc,dlhl60g" }, - {} + { } }; MODULE_DEVICE_TABLE(of, dlh_of_match); static const struct i2c_device_id dlh_id[] = { { "dlhl60d", dlhl60d }, { "dlhl60g", dlhl60g }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, dlh_id); diff --git a/drivers/iio/pressure/dps310.c b/drivers/iio/pressure/dps310.c index c6f44f0f4d2e..8edaa4d10a70 100644 --- a/drivers/iio/pressure/dps310.c +++ b/drivers/iio/pressure/dps310.c @@ -888,13 +888,13 @@ static int dps310_probe(struct i2c_client *client) static const struct i2c_device_id dps310_id[] = { { DPS310_DEV_NAME }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, dps310_id); static const struct acpi_device_id dps310_acpi_match[] = { { "IFX3100" }, - {} + { } }; MODULE_DEVICE_TABLE(acpi, dps310_acpi_match); diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c index f7273d30c5f0..5f1d6abda3e4 100644 --- a/drivers/iio/pressure/hid-sensor-press.c +++ b/drivers/iio/pressure/hid-sensor-press.c @@ -176,8 +176,9 @@ static int press_proc_event(struct hid_sensor_hub_device *hsdev, if (!press_state->timestamp) press_state->timestamp = iio_get_time_ns(indio_dev); - iio_push_to_buffers_with_timestamp( - indio_dev, &press_state->scan, press_state->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &press_state->scan, + sizeof(press_state->scan), + press_state->timestamp); } return 0; @@ -339,7 +340,7 @@ static const struct platform_device_id hid_press_ids[] = { /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ .name = "HID-SENSOR-200031", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(platform, hid_press_ids); diff --git a/drivers/iio/pressure/hp03.c b/drivers/iio/pressure/hp03.c index 6f7a16787143..cbb4aaf45e2c 100644 --- a/drivers/iio/pressure/hp03.c +++ b/drivers/iio/pressure/hp03.c @@ -273,7 +273,7 @@ MODULE_DEVICE_TABLE(i2c, hp03_id); static const struct of_device_id hp03_of_match[] = { { .compatible = "hoperf,hp03" }, - { }, + { } }; MODULE_DEVICE_TABLE(of, hp03_of_match); diff --git a/drivers/iio/pressure/hp206c.c b/drivers/iio/pressure/hp206c.c index 442740941933..abe10ccb6770 100644 --- a/drivers/iio/pressure/hp206c.c +++ b/drivers/iio/pressure/hp206c.c @@ -396,13 +396,13 @@ static int hp206c_probe(struct i2c_client *client) static const struct i2c_device_id hp206c_id[] = { {"hp206c"}, - {} + { } }; MODULE_DEVICE_TABLE(i2c, hp206c_id); static const struct acpi_device_id hp206c_acpi_match[] = { {"HOP206C", 0}, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, hp206c_acpi_match); diff --git a/drivers/iio/pressure/hsc030pa.c b/drivers/iio/pressure/hsc030pa.c index 168245818cfe..2d00c0656259 100644 --- a/drivers/iio/pressure/hsc030pa.c +++ b/drivers/iio/pressure/hsc030pa.c @@ -314,8 +314,8 @@ static irqreturn_t hsc_trigger_handler(int irq, void *private) memcpy(&data->scan.chan[0], &data->buffer[0], 2); memcpy(&data->scan.chan[1], &data->buffer[2], 2); - iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), + iio_get_time_ns(indio_dev)); error: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/pressure/hsc030pa_i2c.c b/drivers/iio/pressure/hsc030pa_i2c.c index 7f2398aa8155..a34ef4653f34 100644 --- a/drivers/iio/pressure/hsc030pa_i2c.c +++ b/drivers/iio/pressure/hsc030pa_i2c.c @@ -48,13 +48,13 @@ static int hsc_i2c_probe(struct i2c_client *client) static const struct of_device_id hsc_i2c_match[] = { { .compatible = "honeywell,hsc030pa" }, - {} + { } }; MODULE_DEVICE_TABLE(of, hsc_i2c_match); static const struct i2c_device_id hsc_i2c_id[] = { { "hsc030pa" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, hsc_i2c_id); diff --git a/drivers/iio/pressure/hsc030pa_spi.c b/drivers/iio/pressure/hsc030pa_spi.c index 60768726e9ad..5d331b3b6da8 100644 --- a/drivers/iio/pressure/hsc030pa_spi.c +++ b/drivers/iio/pressure/hsc030pa_spi.c @@ -35,13 +35,13 @@ static int hsc_spi_probe(struct spi_device *spi) static const struct of_device_id hsc_spi_match[] = { { .compatible = "honeywell,hsc030pa" }, - {} + { } }; MODULE_DEVICE_TABLE(of, hsc_spi_match); static const struct spi_device_id hsc_spi_id[] = { { "hsc030pa" }, - {} + { } }; MODULE_DEVICE_TABLE(spi, hsc_spi_id); diff --git a/drivers/iio/pressure/icp10100.c b/drivers/iio/pressure/icp10100.c index 3e0bf5d31ad7..1951c1cc84cf 100644 --- a/drivers/iio/pressure/icp10100.c +++ b/drivers/iio/pressure/icp10100.c @@ -343,9 +343,8 @@ static int icp10100_read_raw_measures(struct iio_dev *indio_dev, uint32_t pressure_mPa; int ret; - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = icp10100_get_measures(st, &raw_pressure, &raw_temp); if (ret) @@ -370,7 +369,7 @@ static int icp10100_read_raw_measures(struct iio_dev *indio_dev, } error_release: - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; } @@ -439,7 +438,6 @@ static int icp10100_write_raw(struct iio_dev *indio_dev, { struct icp10100_state *st = iio_priv(indio_dev); unsigned int mode; - int ret; switch (mask) { case IIO_CHAN_INFO_OVERSAMPLING_RATIO: @@ -449,13 +447,12 @@ static int icp10100_write_raw(struct iio_dev *indio_dev, mode = ilog2(val); if (mode >= ICP10100_MODE_NB) return -EINVAL; - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; mutex_lock(&st->lock); st->mode = mode; mutex_unlock(&st->lock); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return 0; default: return -EINVAL; diff --git a/drivers/iio/pressure/mpl115_spi.c b/drivers/iio/pressure/mpl115_spi.c index 888cfa666238..4e1d24beff94 100644 --- a/drivers/iio/pressure/mpl115_spi.c +++ b/drivers/iio/pressure/mpl115_spi.c @@ -85,7 +85,7 @@ static int mpl115_spi_probe(struct spi_device *spi) static const struct spi_device_id mpl115_spi_ids[] = { { "mpl115", 0 }, - {} + { } }; MODULE_DEVICE_TABLE(spi, mpl115_spi_ids); diff --git a/drivers/iio/pressure/mpl3115.c b/drivers/iio/pressure/mpl3115.c index 71ded2eee060..d6715997f137 100644 --- a/drivers/iio/pressure/mpl3115.c +++ b/drivers/iio/pressure/mpl3115.c @@ -69,6 +69,52 @@ static int mpl3115_request(struct mpl3115_data *data) return 0; } +static int mpl3115_read_info_raw(struct mpl3115_data *data, + struct iio_chan_spec const *chan, int *val) +{ + int ret; + + switch (chan->type) { + case IIO_PRESSURE: { /* in 0.25 pascal / LSB */ + __be32 tmp = 0; + + guard(mutex)(&data->lock); + ret = mpl3115_request(data); + if (ret < 0) + return ret; + + ret = i2c_smbus_read_i2c_block_data(data->client, + MPL3115_OUT_PRESS, + 3, (u8 *) &tmp); + if (ret < 0) + return ret; + + *val = be32_to_cpu(tmp) >> chan->scan_type.shift; + return IIO_VAL_INT; + } + case IIO_TEMP: { /* in 0.0625 celsius / LSB */ + __be16 tmp; + + guard(mutex)(&data->lock); + ret = mpl3115_request(data); + if (ret < 0) + return ret; + + ret = i2c_smbus_read_i2c_block_data(data->client, + MPL3115_OUT_TEMP, + 2, (u8 *) &tmp); + if (ret < 0) + return ret; + + *val = sign_extend32(be16_to_cpu(tmp) >> chan->scan_type.shift, + chan->scan_type.realbits - 1); + return IIO_VAL_INT; + } + default: + return -EINVAL; + } +} + static int mpl3115_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -78,54 +124,11 @@ static int mpl3115_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; - - switch (chan->type) { - case IIO_PRESSURE: { /* in 0.25 pascal / LSB */ - __be32 tmp = 0; - - mutex_lock(&data->lock); - ret = mpl3115_request(data); - if (ret < 0) { - mutex_unlock(&data->lock); - break; - } - ret = i2c_smbus_read_i2c_block_data(data->client, - MPL3115_OUT_PRESS, 3, (u8 *) &tmp); - mutex_unlock(&data->lock); - if (ret < 0) - break; - *val = be32_to_cpu(tmp) >> chan->scan_type.shift; - ret = IIO_VAL_INT; - break; - } - case IIO_TEMP: { /* in 0.0625 celsius / LSB */ - __be16 tmp; - - mutex_lock(&data->lock); - ret = mpl3115_request(data); - if (ret < 0) { - mutex_unlock(&data->lock); - break; - } - ret = i2c_smbus_read_i2c_block_data(data->client, - MPL3115_OUT_TEMP, 2, (u8 *) &tmp); - mutex_unlock(&data->lock); - if (ret < 0) - break; - *val = sign_extend32(be16_to_cpu(tmp) >> chan->scan_type.shift, - chan->scan_type.realbits - 1); - ret = IIO_VAL_INT; - break; - } - default: - ret = -EINVAL; - break; - } + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; - iio_device_release_direct_mode(indio_dev); + ret = mpl3115_read_info_raw(data, chan, val); + iio_device_release_direct(indio_dev); return ret; case IIO_CHAN_INFO_SCALE: @@ -188,8 +191,8 @@ static irqreturn_t mpl3115_trigger_handler(int irq, void *p) } mutex_unlock(&data->lock); - iio_push_to_buffers_with_timestamp(indio_dev, buffer, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, buffer, sizeof(buffer), + iio_get_time_ns(indio_dev)); done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/pressure/mprls0025pa_i2c.c b/drivers/iio/pressure/mprls0025pa_i2c.c index 48b23a4256ce..1a48f8d43d71 100644 --- a/drivers/iio/pressure/mprls0025pa_i2c.c +++ b/drivers/iio/pressure/mprls0025pa_i2c.c @@ -74,13 +74,13 @@ static int mpr_i2c_probe(struct i2c_client *client) static const struct of_device_id mpr_i2c_match[] = { { .compatible = "honeywell,mprls0025pa" }, - {} + { } }; MODULE_DEVICE_TABLE(of, mpr_i2c_match); static const struct i2c_device_id mpr_i2c_id[] = { { "mprls0025pa" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, mpr_i2c_id); diff --git a/drivers/iio/pressure/mprls0025pa_spi.c b/drivers/iio/pressure/mprls0025pa_spi.c index 09f724c76d70..d04102f8a4a0 100644 --- a/drivers/iio/pressure/mprls0025pa_spi.c +++ b/drivers/iio/pressure/mprls0025pa_spi.c @@ -66,13 +66,13 @@ static int mpr_spi_probe(struct spi_device *spi) static const struct of_device_id mpr_spi_match[] = { { .compatible = "honeywell,mprls0025pa" }, - {} + { } }; MODULE_DEVICE_TABLE(of, mpr_spi_match); static const struct spi_device_id mpr_spi_id[] = { { "mprls0025pa" }, - {} + { } }; MODULE_DEVICE_TABLE(spi, mpr_spi_id); diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c index 00c077b2a2a4..bdac27bd5a5d 100644 --- a/drivers/iio/pressure/ms5611_core.c +++ b/drivers/iio/pressure/ms5611_core.c @@ -308,7 +308,6 @@ static int ms5611_write_raw(struct iio_dev *indio_dev, { struct ms5611_state *st = iio_priv(indio_dev); const struct ms5611_osr *osr = NULL; - int ret; if (mask != IIO_CHAN_INFO_OVERSAMPLING_RATIO) return -EINVAL; @@ -322,9 +321,8 @@ static int ms5611_write_raw(struct iio_dev *indio_dev, if (!osr) return -EINVAL; - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; mutex_lock(&st->lock); @@ -334,7 +332,7 @@ static int ms5611_write_raw(struct iio_dev *indio_dev, st->pressure_osr = osr; mutex_unlock(&st->lock); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return 0; } diff --git a/drivers/iio/pressure/ms5611_spi.c b/drivers/iio/pressure/ms5611_spi.c index b5a91e885793..25c7bd2d8fdf 100644 --- a/drivers/iio/pressure/ms5611_spi.c +++ b/drivers/iio/pressure/ms5611_spi.c @@ -92,7 +92,6 @@ static int ms5611_spi_probe(struct spi_device *spi) spi->mode = SPI_MODE_0; spi->max_speed_hz = min(spi->max_speed_hz, 20000000U); - spi->bits_per_word = 8; ret = spi_setup(spi); if (ret < 0) return ret; diff --git a/drivers/iio/pressure/ms5637.c b/drivers/iio/pressure/ms5637.c index a1767a17fdce..59705a666979 100644 --- a/drivers/iio/pressure/ms5637.c +++ b/drivers/iio/pressure/ms5637.c @@ -219,7 +219,7 @@ static const struct i2c_device_id ms5637_id[] = { {"ms5805", (kernel_ulong_t)&ms5805_data }, {"ms5837", (kernel_ulong_t)&ms5837_data }, {"ms8607-temppressure", (kernel_ulong_t)&ms8607_data }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, ms5637_id); @@ -229,7 +229,7 @@ static const struct of_device_id ms5637_of_match[] = { { .compatible = "meas,ms5805", .data = &ms5805_data }, { .compatible = "meas,ms5837", .data = &ms5837_data }, { .compatible = "meas,ms8607-temppressure", .data = &ms8607_data }, - { }, + { } }; MODULE_DEVICE_TABLE(of, ms5637_of_match); diff --git a/drivers/iio/pressure/rohm-bm1390.c b/drivers/iio/pressure/rohm-bm1390.c index 9c1197f0e742..dac27fd359ad 100644 --- a/drivers/iio/pressure/rohm-bm1390.c +++ b/drivers/iio/pressure/rohm-bm1390.c @@ -319,12 +319,11 @@ static int bm1390_read_raw(struct iio_dev *idev, return -EINVAL; case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(idev); - if (ret) - return ret; + if (!iio_device_claim_direct(idev)) + return -EBUSY; ret = bm1390_read_data(data, chan, val, val2); - iio_device_release_direct_mode(idev); + iio_device_release_direct(idev); if (ret) return ret; @@ -653,7 +652,8 @@ static irqreturn_t bm1390_trigger_handler(int irq, void *p) } } - iio_push_to_buffers_with_timestamp(idev, &data->buf, data->timestamp); + iio_push_to_buffers_with_ts(idev, &data->buf, sizeof(data->buf), + data->timestamp); iio_trigger_notify_done(idev->trig); return IRQ_HANDLED; @@ -883,13 +883,13 @@ static int bm1390_probe(struct i2c_client *i2c) static const struct of_device_id bm1390_of_match[] = { { .compatible = "rohm,bm1390glv-z" }, - {} + { } }; MODULE_DEVICE_TABLE(of, bm1390_of_match); static const struct i2c_device_id bm1390_id[] = { { "bm1390glv-z", }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, bm1390_id); diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c index b7b66ddc3a73..0f50bac1fb4d 100644 --- a/drivers/iio/pressure/st_pressure_i2c.c +++ b/drivers/iio/pressure/st_pressure_i2c.c @@ -50,13 +50,13 @@ static const struct of_device_id st_press_of_match[] = { .compatible = "st,lps22df", .data = LPS22DF_PRESS_DEV_NAME, }, - {}, + { } }; MODULE_DEVICE_TABLE(of, st_press_of_match); static const struct acpi_device_id st_press_acpi_match[] = { {"SNO9210", LPS22HB}, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, st_press_acpi_match); @@ -69,7 +69,7 @@ static const struct i2c_device_id st_press_id_table[] = { { LPS35HW_PRESS_DEV_NAME, LPS35HW }, { LPS22HH_PRESS_DEV_NAME, LPS22HH }, { LPS22DF_PRESS_DEV_NAME, LPS22DF }, - {}, + { } }; MODULE_DEVICE_TABLE(i2c, st_press_id_table); diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c index 1a4bd1a0f787..39827e6841ca 100644 --- a/drivers/iio/pressure/st_pressure_spi.c +++ b/drivers/iio/pressure/st_pressure_spi.c @@ -55,7 +55,7 @@ static const struct of_device_id st_press_of_match[] = { .compatible = "st,lps22df", .data = LPS22DF_PRESS_DEV_NAME, }, - {}, + { } }; MODULE_DEVICE_TABLE(of, st_press_of_match); @@ -106,7 +106,7 @@ static const struct spi_device_id st_press_id_table[] = { { "lps25h-press", }, { "lps331ap-press" }, { "lps22hb-press" }, - {}, + { } }; MODULE_DEVICE_TABLE(spi, st_press_id_table); diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c index 9db1c94dfc18..1640aa3717ed 100644 --- a/drivers/iio/pressure/zpa2326.c +++ b/drivers/iio/pressure/zpa2326.c @@ -582,7 +582,7 @@ static int zpa2326_fill_sample_buffer(struct iio_dev *indio_dev, struct { u32 pressure; u16 temperature; - u64 timestamp; + aligned_s64 timestamp; } sample; int err; @@ -618,8 +618,8 @@ static int zpa2326_fill_sample_buffer(struct iio_dev *indio_dev, */ zpa2326_dbg(indio_dev, "filling raw samples buffer"); - iio_push_to_buffers_with_timestamp(indio_dev, &sample, - private->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &sample, sizeof(sample), + private->timestamp); return 0; } @@ -1062,9 +1062,8 @@ static int zpa2326_sample_oneshot(struct iio_dev *indio_dev, int ret; struct zpa2326_private *priv; - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = zpa2326_resume(indio_dev); if (ret < 0) @@ -1120,7 +1119,7 @@ static int zpa2326_sample_oneshot(struct iio_dev *indio_dev, suspend: zpa2326_suspend(indio_dev); release: - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; } @@ -1438,7 +1437,6 @@ static int zpa2326_set_frequency(struct iio_dev *indio_dev, int hz) { struct zpa2326_private *priv = iio_priv(indio_dev); int freq; - int err; /* Check if requested frequency is supported. */ for (freq = 0; freq < ARRAY_SIZE(zpa2326_sampling_frequencies); freq++) @@ -1448,13 +1446,12 @@ static int zpa2326_set_frequency(struct iio_dev *indio_dev, int hz) return -EINVAL; /* Don't allow changing frequency if buffered sampling is ongoing. */ - err = iio_device_claim_direct_mode(indio_dev); - if (err) - return err; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; priv->frequency = &zpa2326_sampling_frequencies[freq]; - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return 0; } diff --git a/drivers/iio/pressure/zpa2326_spi.c b/drivers/iio/pressure/zpa2326_spi.c index c678f5b96266..af756e2b0f31 100644 --- a/drivers/iio/pressure/zpa2326_spi.c +++ b/drivers/iio/pressure/zpa2326_spi.c @@ -47,7 +47,6 @@ static int zpa2326_probe_spi(struct spi_device *spi) */ spi->mode = SPI_MODE_3; spi->max_speed_hz = min(spi->max_speed_hz, 1000000U); - spi->bits_per_word = 8; err = spi_setup(spi); if (err < 0) return err; @@ -63,7 +62,7 @@ static void zpa2326_remove_spi(struct spi_device *spi) static const struct spi_device_id zpa2326_spi_ids[] = { { "zpa2326", 0 }, - { }, + { } }; MODULE_DEVICE_TABLE(spi, zpa2326_spi_ids); diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c index 9d3caf2bef18..f1018b14aecf 100644 --- a/drivers/iio/proximity/as3935.c +++ b/drivers/iio/proximity/as3935.c @@ -231,8 +231,8 @@ static irqreturn_t as3935_trigger_handler(int irq, void *private) goto err_read; st->scan.chan = val & AS3935_DATA_MASK; - iio_push_to_buffers_with_timestamp(indio_dev, &st->scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &st->scan, sizeof(st->scan), + iio_get_time_ns(indio_dev)); err_read: iio_trigger_notify_done(indio_dev->trig); @@ -444,13 +444,13 @@ static int as3935_probe(struct spi_device *spi) static const struct of_device_id as3935_of_match[] = { { .compatible = "ams,as3935", }, - { /* sentinel */ }, + { } }; MODULE_DEVICE_TABLE(of, as3935_of_match); static const struct spi_device_id as3935_id[] = { {"as3935", 0}, - {}, + { } }; MODULE_DEVICE_TABLE(spi, as3935_id); diff --git a/drivers/iio/proximity/cros_ec_mkbp_proximity.c b/drivers/iio/proximity/cros_ec_mkbp_proximity.c index 667369be0555..1f9de7066ebf 100644 --- a/drivers/iio/proximity/cros_ec_mkbp_proximity.c +++ b/drivers/iio/proximity/cros_ec_mkbp_proximity.c @@ -59,16 +59,11 @@ static int cros_ec_mkbp_proximity_parse_state(const void *data) static int cros_ec_mkbp_proximity_query(struct cros_ec_device *ec_dev, int *state) { - struct { - struct cros_ec_command msg; - union { - struct ec_params_mkbp_info params; - u32 switches; - }; - } __packed buf = { }; - struct ec_params_mkbp_info *params = &buf.params; - struct cros_ec_command *msg = &buf.msg; - u32 *switches = &buf.switches; + DEFINE_RAW_FLEX(struct cros_ec_command, buf, data, + MAX(sizeof(u32), sizeof(struct ec_params_mkbp_info))); + struct ec_params_mkbp_info *params = (struct ec_params_mkbp_info *)buf->data; + struct cros_ec_command *msg = buf; + u32 *switches = (u32 *)buf->data; size_t insize = sizeof(*switches); int ret; @@ -250,7 +245,7 @@ static void cros_ec_mkbp_proximity_remove(struct platform_device *pdev) static const struct of_device_id cros_ec_mkbp_proximity_of_match[] = { { .compatible = "google,cros-ec-mkbp-proximity" }, - {} + { } }; MODULE_DEVICE_TABLE(of, cros_ec_mkbp_proximity_of_match); diff --git a/drivers/iio/proximity/hx9023s.c b/drivers/iio/proximity/hx9023s.c index 5aa8e5a22f32..33781c314728 100644 --- a/drivers/iio/proximity/hx9023s.c +++ b/drivers/iio/proximity/hx9023s.c @@ -701,12 +701,11 @@ static int hx9023s_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = hx9023s_get_proximity(data, chan, val); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; case IIO_CHAN_INFO_SAMP_FREQ: return hx9023s_get_samp_freq(data, val, val2); @@ -954,8 +953,8 @@ static irqreturn_t hx9023s_trigger_handler(int irq, void *private) data->buffer.channels[i++] = cpu_to_le16(data->ch_data[index].diff); } - iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer, - pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &data->buffer, + sizeof(data->buffer), pf->timestamp); out: iio_trigger_notify_done(indio_dev->trig); @@ -1191,13 +1190,13 @@ static DEFINE_SIMPLE_DEV_PM_OPS(hx9023s_pm_ops, hx9023s_suspend, static const struct of_device_id hx9023s_of_match[] = { { .compatible = "tyhx,hx9023s" }, - {} + { } }; MODULE_DEVICE_TABLE(of, hx9023s_of_match); static const struct i2c_device_id hx9023s_id[] = { { "hx9023s" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, hx9023s_id); diff --git a/drivers/iio/proximity/irsd200.c b/drivers/iio/proximity/irsd200.c index b0ffd3574013..0d30b91dbcbc 100644 --- a/drivers/iio/proximity/irsd200.c +++ b/drivers/iio/proximity/irsd200.c @@ -760,15 +760,19 @@ static irqreturn_t irsd200_trigger_handler(int irq, void *pollf) { struct iio_dev *indio_dev = ((struct iio_poll_func *)pollf)->indio_dev; struct irsd200_data *data = iio_priv(indio_dev); - s64 buf[2] = {}; + struct { + s16 channel; + aligned_s64 ts; + } scan; int ret; - ret = irsd200_read_data(data, (s16 *)buf); + memset(&scan, 0, sizeof(scan)); + ret = irsd200_read_data(data, &scan.channel); if (ret) goto end; - iio_push_to_buffers_with_timestamp(indio_dev, buf, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &scan, sizeof(scan), + iio_get_time_ns(indio_dev)); end: iio_trigger_notify_done(indio_dev->trig); @@ -941,7 +945,7 @@ static const struct of_device_id irsd200_of_match[] = { { .compatible = "murata,irsd200", }, - {} + { } }; MODULE_DEVICE_TABLE(of, irsd200_of_match); diff --git a/drivers/iio/proximity/isl29501.c b/drivers/iio/proximity/isl29501.c index dc66ca9bba6b..d1510fe24050 100644 --- a/drivers/iio/proximity/isl29501.c +++ b/drivers/iio/proximity/isl29501.c @@ -481,7 +481,7 @@ static const struct iio_chan_spec_ext_info isl29501_ext_info[] = { _ISL29501_EXT_INFO("calib_phase_temp_b", REG_CALIB_PHASE_TEMP_B), _ISL29501_EXT_INFO("calib_phase_light_a", REG_CALIB_PHASE_LIGHT_A), _ISL29501_EXT_INFO("calib_phase_light_b", REG_CALIB_PHASE_LIGHT_B), - { }, + { } }; #define ISL29501_DISTANCE_SCAN_INDEX 0 @@ -990,7 +990,7 @@ static int isl29501_probe(struct i2c_client *client) static const struct i2c_device_id isl29501_id[] = { { "isl29501" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, isl29501_id); diff --git a/drivers/iio/proximity/mb1232.c b/drivers/iio/proximity/mb1232.c index cfc75d001f20..01783486bc7d 100644 --- a/drivers/iio/proximity/mb1232.c +++ b/drivers/iio/proximity/mb1232.c @@ -125,8 +125,8 @@ static irqreturn_t mb1232_trigger_handler(int irq, void *p) if (data->scan.distance < 0) goto err; - iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, - pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), + pf->timestamp); err: iio_trigger_notify_done(indio_dev->trig); @@ -239,7 +239,7 @@ static const struct of_device_id of_mb1232_match[] = { { .compatible = "maxbotix,mb1242", }, { .compatible = "maxbotix,mb7040", }, { .compatible = "maxbotix,mb7137", }, - {}, + { } }; MODULE_DEVICE_TABLE(of, of_mb1232_match); diff --git a/drivers/iio/proximity/ping.c b/drivers/iio/proximity/ping.c index 2ad69b150902..c5b4e1378b7d 100644 --- a/drivers/iio/proximity/ping.c +++ b/drivers/iio/proximity/ping.c @@ -268,7 +268,7 @@ static const struct iio_chan_spec ping_chan_spec[] = { static const struct of_device_id of_ping_match[] = { { .compatible = "parallax,ping", .data = &pa_ping_cfg }, { .compatible = "parallax,laserping", .data = &pa_laser_ping_cfg }, - {}, + { } }; MODULE_DEVICE_TABLE(of, of_ping_match); diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c index f3d054b06b4c..1deaf70e92ce 100644 --- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c +++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c @@ -208,7 +208,7 @@ static int lidar_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_RAW: { u16 reg; - if (iio_device_claim_direct_mode(indio_dev)) + if (!iio_device_claim_direct(indio_dev)) return -EBUSY; ret = lidar_get_measurement(data, ®); @@ -216,7 +216,7 @@ static int lidar_read_raw(struct iio_dev *indio_dev, *val = reg; ret = IIO_VAL_INT; } - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); break; } case IIO_CHAN_INFO_SCALE: @@ -238,8 +238,9 @@ static irqreturn_t lidar_trigger_handler(int irq, void *private) ret = lidar_get_measurement(data, &data->scan.chan); if (!ret) { - iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, + sizeof(data->scan), + iio_get_time_ns(indio_dev)); } else if (ret != -EINVAL) { dev_err(&data->client->dev, "cannot read LIDAR measurement"); } diff --git a/drivers/iio/proximity/srf04.c b/drivers/iio/proximity/srf04.c index 71ad29e441b2..b059bac1078b 100644 --- a/drivers/iio/proximity/srf04.c +++ b/drivers/iio/proximity/srf04.c @@ -240,7 +240,7 @@ static const struct of_device_id of_srf04_match[] = { { .compatible = "maxbotix,mb1020", .data = &mb_lv_cfg }, { .compatible = "maxbotix,mb1030", .data = &mb_lv_cfg }, { .compatible = "maxbotix,mb1040", .data = &mb_lv_cfg }, - {}, + { } }; MODULE_DEVICE_TABLE(of, of_srf04_match); diff --git a/drivers/iio/proximity/srf08.c b/drivers/iio/proximity/srf08.c index 86cab113ef3d..6e32fdfd161b 100644 --- a/drivers/iio/proximity/srf08.c +++ b/drivers/iio/proximity/srf08.c @@ -191,8 +191,8 @@ static irqreturn_t srf08_trigger_handler(int irq, void *p) mutex_lock(&data->lock); data->scan.chan = sensor_data; - iio_push_to_buffers_with_timestamp(indio_dev, - &data->scan, pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), + pf->timestamp); mutex_unlock(&data->lock); err: @@ -531,7 +531,7 @@ static const struct of_device_id of_srf08_match[] = { { .compatible = "devantech,srf02", (void *)SRF02 }, { .compatible = "devantech,srf08", (void *)SRF08 }, { .compatible = "devantech,srf10", (void *)SRF10 }, - {}, + { } }; MODULE_DEVICE_TABLE(of, of_srf08_match); diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c index b60707eba39d..fb02eac78ed4 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -995,21 +995,21 @@ static const struct sx931x_info sx9311_info = { static const struct acpi_device_id sx9310_acpi_match[] = { { "STH9310", (kernel_ulong_t)&sx9310_info }, { "STH9311", (kernel_ulong_t)&sx9311_info }, - {} + { } }; MODULE_DEVICE_TABLE(acpi, sx9310_acpi_match); static const struct of_device_id sx9310_of_match[] = { { .compatible = "semtech,sx9310", &sx9310_info }, { .compatible = "semtech,sx9311", &sx9311_info }, - {} + { } }; MODULE_DEVICE_TABLE(of, sx9310_of_match); static const struct i2c_device_id sx9310_id[] = { { "sx9310", (kernel_ulong_t)&sx9310_info }, { "sx9311", (kernel_ulong_t)&sx9311_info }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, sx9310_id); diff --git a/drivers/iio/proximity/sx9324.c b/drivers/iio/proximity/sx9324.c index 73d972416c01..c7b2d03c23bc 100644 --- a/drivers/iio/proximity/sx9324.c +++ b/drivers/iio/proximity/sx9324.c @@ -202,7 +202,7 @@ static const struct iio_chan_spec_ext_info sx9324_channel_ext_info[] = { .shared = IIO_SEPARATE, .read = sx9324_phase_configuration_show, }, - {} + { } }; #define SX9324_CHANNEL(idx) \ diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c index c4e94d0fb163..8913da59dc73 100644 --- a/drivers/iio/proximity/sx9500.c +++ b/drivers/iio/proximity/sx9500.c @@ -387,11 +387,10 @@ static int sx9500_read_raw(struct iio_dev *indio_dev, case IIO_PROXIMITY: switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = sx9500_read_proximity(data, chan, val); - iio_device_release_direct_mode(indio_dev); + iio_device_release_direct(indio_dev); return ret; case IIO_CHAN_INFO_SAMP_FREQ: return sx9500_read_samp_freq(data, val, val2); @@ -866,7 +865,7 @@ static const struct acpi_gpio_mapping acpi_sx9500_gpios[] = { * GPIO to be output only. Ask the GPIO core to ignore this limit. */ { "interrupt-gpios", &interrupt_gpios, 1, ACPI_GPIO_QUIRK_NO_IO_RESTRICTION }, - { }, + { } }; static void sx9500_gpio_probe(struct i2c_client *client, @@ -1031,7 +1030,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(sx9500_pm_ops, sx9500_suspend, sx9500_resume); static const struct acpi_device_id sx9500_acpi_match[] = { {"SSX9500", 0}, {"SASX9500", 0}, - { }, + { } }; MODULE_DEVICE_TABLE(acpi, sx9500_acpi_match); diff --git a/drivers/iio/proximity/sx_common.c b/drivers/iio/proximity/sx_common.c index f70198a1f0d1..59b35e40739b 100644 --- a/drivers/iio/proximity/sx_common.c +++ b/drivers/iio/proximity/sx_common.c @@ -379,8 +379,8 @@ static irqreturn_t sx_common_trigger_handler(int irq, void *private) data->buffer.channels[i++] = val; } - iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer, - pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &data->buffer, + sizeof(data->buffer), pf->timestamp); out: mutex_unlock(&data->mutex); diff --git a/drivers/iio/proximity/vcnl3020.c b/drivers/iio/proximity/vcnl3020.c index bb6c9cc88b35..31e77d9e0c90 100644 --- a/drivers/iio/proximity/vcnl3020.c +++ b/drivers/iio/proximity/vcnl3020.c @@ -653,7 +653,7 @@ static const struct of_device_id vcnl3020_of_match[] = { { .compatible = "vishay,vcnl3020", }, - {} + { } }; MODULE_DEVICE_TABLE(of, vcnl3020_of_match); diff --git a/drivers/iio/proximity/vl53l0x-i2c.c b/drivers/iio/proximity/vl53l0x-i2c.c index 87d10faaff9b..ef4aa7b2835e 100644 --- a/drivers/iio/proximity/vl53l0x-i2c.c +++ b/drivers/iio/proximity/vl53l0x-i2c.c @@ -94,8 +94,8 @@ static irqreturn_t vl53l0x_trigger_handler(int irq, void *priv) return -EREMOTEIO; data->scan.chan = get_unaligned_be16(&buffer[10]); - iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), + iio_get_time_ns(indio_dev)); iio_trigger_notify_done(indio_dev->trig); vl53l0x_clear_irq(data); diff --git a/drivers/iio/resolver/ad2s1200.c b/drivers/iio/resolver/ad2s1200.c index 9d95241bdf8f..0bc84f12cb34 100644 --- a/drivers/iio/resolver/ad2s1200.c +++ b/drivers/iio/resolver/ad2s1200.c @@ -186,7 +186,7 @@ MODULE_DEVICE_TABLE(of, ad2s1200_of_match); static const struct spi_device_id ad2s1200_id[] = { { "ad2s1200" }, { "ad2s1205" }, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad2s1200_id); diff --git a/drivers/iio/resolver/ad2s1210.c b/drivers/iio/resolver/ad2s1210.c index ab860cedecd1..9b028c8bb1db 100644 --- a/drivers/iio/resolver/ad2s1210.c +++ b/drivers/iio/resolver/ad2s1210.c @@ -1340,7 +1340,8 @@ static irqreturn_t ad2s1210_trigger_handler(int irq, void *p) } ad2s1210_push_events(indio_dev, st->sample.fault, pf->timestamp); - iio_push_to_buffers_with_timestamp(indio_dev, &st->scan, pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &st->scan, sizeof(st->scan), + pf->timestamp); error_ret: iio_trigger_notify_done(indio_dev->trig); @@ -1597,7 +1598,7 @@ MODULE_DEVICE_TABLE(of, ad2s1210_of_match); static const struct spi_device_id ad2s1210_id[] = { { "ad2s1210" }, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad2s1210_id); diff --git a/drivers/iio/resolver/ad2s90.c b/drivers/iio/resolver/ad2s90.c index be6836e55376..18f1c905eeac 100644 --- a/drivers/iio/resolver/ad2s90.c +++ b/drivers/iio/resolver/ad2s90.c @@ -105,13 +105,13 @@ static int ad2s90_probe(struct spi_device *spi) static const struct of_device_id ad2s90_of_match[] = { { .compatible = "adi,ad2s90", }, - {} + { } }; MODULE_DEVICE_TABLE(of, ad2s90_of_match); static const struct spi_device_id ad2s90_id[] = { { "ad2s90" }, - {} + { } }; MODULE_DEVICE_TABLE(spi, ad2s90_id); diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c index 692520e1c497..9f628a8e5cfb 100644 --- a/drivers/iio/temperature/hid-sensor-temperature.c +++ b/drivers/iio/temperature/hid-sensor-temperature.c @@ -131,8 +131,9 @@ static int temperature_proc_event(struct hid_sensor_hub_device *hsdev, struct temperature_state *temp_st = iio_priv(indio_dev); if (atomic_read(&temp_st->common_attributes.data_ready)) - iio_push_to_buffers_with_timestamp(indio_dev, &temp_st->scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &temp_st->scan, + sizeof(temp_st->scan), + iio_get_time_ns(indio_dev)); return 0; } @@ -272,7 +273,7 @@ static const struct platform_device_id hid_temperature_ids[] = { /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ .name = "HID-SENSOR-200033", }, - { /* sentinel */ } + { } }; MODULE_DEVICE_TABLE(platform, hid_temperature_ids); diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c index f8ea2219ab48..7dd40d69cce6 100644 --- a/drivers/iio/temperature/ltc2983.c +++ b/drivers/iio/temperature/ltc2983.c @@ -1664,7 +1664,7 @@ static const struct spi_device_id ltc2983_id_table[] = { { "ltc2984", (kernel_ulong_t)<c2984_chip_info_data }, { "ltc2986", (kernel_ulong_t)<c2986_chip_info_data }, { "ltm2985", (kernel_ulong_t)<m2985_chip_info_data }, - {}, + { } }; MODULE_DEVICE_TABLE(spi, ltc2983_id_table); @@ -1673,7 +1673,7 @@ static const struct of_device_id ltc2983_of_match[] = { { .compatible = "adi,ltc2984", .data = <c2984_chip_info_data }, { .compatible = "adi,ltc2986", .data = <c2986_chip_info_data }, { .compatible = "adi,ltm2985", .data = <m2985_chip_info_data }, - {}, + { } }; MODULE_DEVICE_TABLE(of, ltc2983_of_match); diff --git a/drivers/iio/temperature/maxim_thermocouple.c b/drivers/iio/temperature/maxim_thermocouple.c index 555a61e2f3fd..cae8e84821d7 100644 --- a/drivers/iio/temperature/maxim_thermocouple.c +++ b/drivers/iio/temperature/maxim_thermocouple.c @@ -9,7 +9,6 @@ #include <linux/init.h> #include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/mutex.h> #include <linux/err.h> #include <linux/spi/spi.h> #include <linux/iio/iio.h> @@ -169,8 +168,9 @@ static irqreturn_t maxim_thermocouple_trigger_handler(int irq, void *private) ret = spi_read(data->spi, data->buffer, data->chip->read_size); if (!ret) { - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, data->buffer, + sizeof(data->buffer), + iio_get_time_ns(indio_dev)); } iio_trigger_notify_done(indio_dev->trig); @@ -183,40 +183,35 @@ static int maxim_thermocouple_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { struct maxim_thermocouple_data *data = iio_priv(indio_dev); - int ret = -EINVAL; + int ret; switch (mask) { case IIO_CHAN_INFO_RAW: - ret = iio_device_claim_direct_mode(indio_dev); - if (ret) - return ret; + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; ret = maxim_thermocouple_read(data, chan, val); - iio_device_release_direct_mode(indio_dev); - - if (!ret) - return IIO_VAL_INT; + iio_device_release_direct(indio_dev); + if (ret) + return ret; - break; + return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: switch (chan->channel2) { case IIO_MOD_TEMP_AMBIENT: *val = 62; *val2 = 500000; /* 1000 * 0.0625 */ - ret = IIO_VAL_INT_PLUS_MICRO; - break; + return IIO_VAL_INT_PLUS_MICRO; default: *val = 250; /* 1000 * 0.25 */ - ret = IIO_VAL_INT; + return IIO_VAL_INT; } - break; case IIO_CHAN_INFO_THERMOCOUPLE_TYPE: *val = data->tc_type; - ret = IIO_VAL_CHAR; - break; + return IIO_VAL_CHAR; + default: + return -EINVAL; } - - return ret; } static const struct iio_info maxim_thermocouple_info = { @@ -271,7 +266,7 @@ static const struct spi_device_id maxim_thermocouple_id[] = { {"max31855t", MAX31855T}, {"max31855e", MAX31855E}, {"max31855r", MAX31855R}, - {}, + { } }; MODULE_DEVICE_TABLE(spi, maxim_thermocouple_id); diff --git a/drivers/iio/temperature/mcp9600.c b/drivers/iio/temperature/mcp9600.c index c2447860adfd..6e9108d5cf75 100644 --- a/drivers/iio/temperature/mcp9600.c +++ b/drivers/iio/temperature/mcp9600.c @@ -449,13 +449,13 @@ static int mcp9600_probe(struct i2c_client *client) static const struct i2c_device_id mcp9600_id[] = { { "mcp9600" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, mcp9600_id); static const struct of_device_id mcp9600_of_match[] = { { .compatible = "microchip,mcp9600" }, - {} + { } }; MODULE_DEVICE_TABLE(of, mcp9600_of_match); diff --git a/drivers/iio/temperature/tmp006.c b/drivers/iio/temperature/tmp006.c index b5c94b7492f5..29bff9d8859d 100644 --- a/drivers/iio/temperature/tmp006.c +++ b/drivers/iio/temperature/tmp006.c @@ -269,8 +269,8 @@ static irqreturn_t tmp006_trigger_handler(int irq, void *p) goto err; scan.channels[1] = ret; - iio_push_to_buffers_with_timestamp(indio_dev, &scan, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_ts(indio_dev, &scan, sizeof(scan), + iio_get_time_ns(indio_dev)); err: iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; diff --git a/drivers/iio/temperature/tmp007.c b/drivers/iio/temperature/tmp007.c index fd4d389ce1df..043283b02c4d 100644 --- a/drivers/iio/temperature/tmp007.c +++ b/drivers/iio/temperature/tmp007.c @@ -558,7 +558,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(tmp007_pm_ops, tmp007_suspend, tmp007_resume); static const struct of_device_id tmp007_of_match[] = { { .compatible = "ti,tmp007", }, - { }, + { } }; MODULE_DEVICE_TABLE(of, tmp007_of_match); diff --git a/drivers/iio/temperature/tsys01.c b/drivers/iio/temperature/tsys01.c index cfaa16f46a3f..334bba6fdae6 100644 --- a/drivers/iio/temperature/tsys01.c +++ b/drivers/iio/temperature/tsys01.c @@ -207,13 +207,13 @@ static int tsys01_i2c_probe(struct i2c_client *client) static const struct i2c_device_id tsys01_id[] = { { "tsys01" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, tsys01_id); static const struct of_device_id tsys01_of_match[] = { { .compatible = "meas,tsys01", }, - { }, + { } }; MODULE_DEVICE_TABLE(of, tsys01_of_match); diff --git a/drivers/iio/temperature/tsys02d.c b/drivers/iio/temperature/tsys02d.c index ef34b3c58f26..0cad27205667 100644 --- a/drivers/iio/temperature/tsys02d.c +++ b/drivers/iio/temperature/tsys02d.c @@ -169,7 +169,7 @@ static int tsys02d_probe(struct i2c_client *client) static const struct i2c_device_id tsys02d_id[] = { { "tsys02d" }, - {} + { } }; MODULE_DEVICE_TABLE(i2c, tsys02d_id); diff --git a/drivers/iio/test/iio-test-format.c b/drivers/iio/test/iio-test-format.c index fc67e6b73df7..872dd8582003 100644 --- a/drivers/iio/test/iio-test-format.c +++ b/drivers/iio/test/iio-test-format.c @@ -257,7 +257,7 @@ static struct kunit_case iio_format_test_cases[] = { KUNIT_CASE(iio_test_iio_format_value_fractional_log2), KUNIT_CASE(iio_test_iio_format_value_multiple), KUNIT_CASE(iio_test_iio_format_value_integer_64), - {} + { } }; static struct kunit_suite iio_format_test_suite = { diff --git a/drivers/iio/test/iio-test-gts.c b/drivers/iio/test/iio-test-gts.c index 1eceec9d477f..11250bc905c9 100644 --- a/drivers/iio/test/iio-test-gts.c +++ b/drivers/iio/test/iio-test-gts.c @@ -499,7 +499,7 @@ static struct kunit_case iio_gts_test_cases[] = { KUNIT_CASE(test_iio_find_closest_gain_low), KUNIT_CASE(test_iio_gts_total_gain_to_scale), KUNIT_CASE(test_iio_gts_avail_test), - {} + { } }; static struct kunit_suite iio_gts_test_suite = { diff --git a/drivers/iio/test/iio-test-rescale.c b/drivers/iio/test/iio-test-rescale.c index bbc6a2e1c2c1..ac6942cf1e44 100644 --- a/drivers/iio/test/iio-test-rescale.c +++ b/drivers/iio/test/iio-test-rescale.c @@ -704,7 +704,7 @@ static void iio_rescale_test_offset(struct kunit *test) static struct kunit_case iio_rescale_test_cases[] = { KUNIT_CASE_PARAM(iio_rescale_test_scale, iio_rescale_scale_gen_params), KUNIT_CASE_PARAM(iio_rescale_test_offset, iio_rescale_offset_gen_params), - {} + { } }; static struct kunit_suite iio_rescale_test_suite = { diff --git a/drivers/iio/trigger/stm32-lptimer-trigger.c b/drivers/iio/trigger/stm32-lptimer-trigger.c index f1e18913236a..2505ace440b4 100644 --- a/drivers/iio/trigger/stm32-lptimer-trigger.c +++ b/drivers/iio/trigger/stm32-lptimer-trigger.c @@ -16,16 +16,43 @@ #include <linux/platform_device.h> #include <linux/property.h> -/* List Low-Power Timer triggers */ -static const char * const stm32_lptim_triggers[] = { - LPTIM1_OUT, - LPTIM2_OUT, - LPTIM3_OUT, +/* Maximum triggers + one trailing null entry to indicate the end of array */ +#define MAX_TRIGGERS 3 + +struct stm32_lptim_cfg { + const char * const (*triggers)[MAX_TRIGGERS]; + unsigned int nb_triggers; +}; + +/* List Low-Power Timer triggers for H7, MP13, MP15 */ +static const char * const stm32_lptim_triggers[][MAX_TRIGGERS] = { + { LPTIM1_OUT,}, + { LPTIM2_OUT,}, + { LPTIM3_OUT,}, +}; + +/* List Low-Power Timer triggers for STM32MP25 */ +static const char * const stm32mp25_lptim_triggers[][MAX_TRIGGERS] = { + { LPTIM1_CH1, LPTIM1_CH2, }, + { LPTIM2_CH1, LPTIM2_CH2, }, + { LPTIM3_CH1,}, + { LPTIM4_CH1,}, + { LPTIM5_OUT,}, +}; + +static const struct stm32_lptim_cfg stm32mp15_lptim_cfg = { + .triggers = stm32_lptim_triggers, + .nb_triggers = ARRAY_SIZE(stm32_lptim_triggers), +}; + +static const struct stm32_lptim_cfg stm32mp25_lptim_cfg = { + .triggers = stm32mp25_lptim_triggers, + .nb_triggers = ARRAY_SIZE(stm32mp25_lptim_triggers), }; struct stm32_lptim_trigger { struct device *dev; - const char *trg; + const char * const *triggers; }; static int stm32_lptim_validate_device(struct iio_trigger *trig, @@ -56,22 +83,33 @@ EXPORT_SYMBOL(is_stm32_lptim_trigger); static int stm32_lptim_setup_trig(struct stm32_lptim_trigger *priv) { - struct iio_trigger *trig; + const char * const *cur = priv->triggers; + int ret; - trig = devm_iio_trigger_alloc(priv->dev, "%s", priv->trg); - if (!trig) - return -ENOMEM; + while (cur && *cur) { + struct iio_trigger *trig; - trig->dev.parent = priv->dev->parent; - trig->ops = &stm32_lptim_trigger_ops; - iio_trigger_set_drvdata(trig, priv); + trig = devm_iio_trigger_alloc(priv->dev, "%s", *cur); + if (!trig) + return -ENOMEM; - return devm_iio_trigger_register(priv->dev, trig); + trig->dev.parent = priv->dev->parent; + trig->ops = &stm32_lptim_trigger_ops; + iio_trigger_set_drvdata(trig, priv); + + ret = devm_iio_trigger_register(priv->dev, trig); + if (ret) + return ret; + cur++; + } + + return 0; } static int stm32_lptim_trigger_probe(struct platform_device *pdev) { struct stm32_lptim_trigger *priv; + struct stm32_lptim_cfg const *lptim_cfg; u32 index; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); @@ -81,18 +119,21 @@ static int stm32_lptim_trigger_probe(struct platform_device *pdev) if (device_property_read_u32(&pdev->dev, "reg", &index)) return -EINVAL; - if (index >= ARRAY_SIZE(stm32_lptim_triggers)) + lptim_cfg = device_get_match_data(&pdev->dev); + + if (index >= lptim_cfg->nb_triggers) return -EINVAL; priv->dev = &pdev->dev; - priv->trg = stm32_lptim_triggers[index]; + priv->triggers = lptim_cfg->triggers[index]; return stm32_lptim_setup_trig(priv); } static const struct of_device_id stm32_lptim_trig_of_match[] = { - { .compatible = "st,stm32-lptimer-trigger", }, - {}, + { .compatible = "st,stm32-lptimer-trigger", .data = &stm32mp15_lptim_cfg }, + { .compatible = "st,stm32mp25-lptimer-trigger", .data = &stm32mp25_lptim_cfg}, + { } }; MODULE_DEVICE_TABLE(of, stm32_lptim_trig_of_match); diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c index e41cb741253b..925b864facca 100644 --- a/drivers/iio/trigger/stm32-timer-trigger.c +++ b/drivers/iio/trigger/stm32-timer-trigger.c @@ -711,7 +711,7 @@ static const struct iio_chan_spec_ext_info stm32_trigger_count_info[] = { IIO_ENUM_AVAILABLE("enable_mode", IIO_SHARED_BY_TYPE, &stm32_enable_mode_enum), IIO_ENUM("trigger_mode", IIO_SEPARATE, &stm32_trigger_mode_enum), IIO_ENUM_AVAILABLE("trigger_mode", IIO_SHARED_BY_TYPE, &stm32_trigger_mode_enum), - {} + { } }; static const struct iio_chan_spec stm32_trigger_channel = { @@ -921,7 +921,7 @@ static const struct of_device_id stm32_trig_of_match[] = { .compatible = "st,stm32mp25-timer-trigger", .data = (void *)&stm32mp25_timer_trg_cfg, }, - { /* end node */ }, + { } }; MODULE_DEVICE_TABLE(of, stm32_trig_of_match); |