diff options
Diffstat (limited to 'drivers/iio/accel')
| -rw-r--r-- | drivers/iio/accel/Kconfig | 7 | ||||
| -rw-r--r-- | drivers/iio/accel/adis16201.c | 133 | ||||
| -rw-r--r-- | drivers/iio/accel/adxl313_spi.c | 2 | ||||
| -rw-r--r-- | drivers/iio/accel/adxl367.c | 59 | ||||
| -rw-r--r-- | drivers/iio/accel/adxl372_spi.c | 2 | ||||
| -rw-r--r-- | drivers/iio/accel/adxl380.c | 7 | ||||
| -rw-r--r-- | drivers/iio/accel/adxl380_spi.c | 2 | ||||
| -rw-r--r-- | drivers/iio/accel/bma220_spi.c | 3 | ||||
| -rw-r--r-- | drivers/iio/accel/bma400_core.c | 2 | ||||
| -rw-r--r-- | drivers/iio/accel/kionix-kx022a.c | 22 | ||||
| -rw-r--r-- | drivers/iio/accel/kionix-kx022a.h | 2 | ||||
| -rw-r--r-- | drivers/iio/accel/kxcjk-1013.c | 1 | ||||
| -rw-r--r-- | drivers/iio/accel/mma8452.c | 145 | ||||
| -rw-r--r-- | drivers/iio/accel/mma9551.c | 1 | ||||
| -rw-r--r-- | drivers/iio/accel/mma9553.c | 1 | ||||
| -rw-r--r-- | drivers/iio/accel/sca3000.c | 2 |
16 files changed, 250 insertions, 141 deletions
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 4094299e2ed8..141ac984247c 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -7,13 +7,14 @@ menu "Accelerometers" config ADIS16201 - tristate "Analog Devices ADIS16201 Dual-Axis Digital Inclinometer and Accelerometer" + tristate "ADIS16201 Digital Inclinometer and similar" depends on SPI select IIO_ADIS_LIB select IIO_ADIS_LIB_BUFFER if IIO_BUFFER help - Say Y here to build support for Analog Devices adis16201 dual-axis - digital inclinometer and accelerometer. + Say Y here to build support for Analog Devices Digital Inclinometers: + - ADIS16201 + - ADIS16203 To compile this driver as a module, say M here: the module will be called adis16201. diff --git a/drivers/iio/accel/adis16201.c b/drivers/iio/accel/adis16201.c index ba0f97944c6d..6d5a7b696112 100644 --- a/drivers/iio/accel/adis16201.c +++ b/drivers/iio/accel/adis16201.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * ADIS16201 Dual-Axis Digital Inclinometer and Accelerometer + * ADIS16201 Digital Inclinometer and similar * * Copyright 2010 Analog Devices Inc. */ @@ -63,6 +63,7 @@ #define ADIS16201_DIAG_STAT_REG 0x3C #define ADIS16201_DIAG_STAT_ALARM2 BIT(9) #define ADIS16201_DIAG_STAT_ALARM1 BIT(8) +#define ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT 5 #define ADIS16201_DIAG_STAT_SPI_FAIL_BIT 3 #define ADIS16201_DIAG_STAT_FLASH_UPT_FAIL_BIT 2 /* Power supply above 3.625 V */ @@ -87,6 +88,21 @@ enum adis16201_scan { ADIS16201_SCAN_TEMP, }; +struct adis16201_chip_info { + const char *name; + const struct iio_chan_spec *arr_channels; + const struct adis_data *data; + unsigned int incli_scale_val2; + unsigned int read_bits_incli; + unsigned int num_channels; + u16 write_mask_incli; +}; + +struct adis16201_state { + struct adis adis; + const struct adis16201_chip_info *info; +}; + static const u8 adis16201_addresses[] = { [ADIS16201_SCAN_ACC_X] = ADIS16201_XACCL_OFFS_REG, [ADIS16201_SCAN_ACC_Y] = ADIS16201_YACCL_OFFS_REG, @@ -99,7 +115,7 @@ static int adis16201_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { - struct adis *st = iio_priv(indio_dev); + struct adis16201_state *st = iio_priv(indio_dev); int ret; int bits; u8 addr; @@ -137,7 +153,7 @@ static int adis16201_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_NANO; case IIO_INCLI: *val = 0; - *val2 = 100000; + *val2 = st->info->incli_scale_val2; return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; @@ -157,13 +173,13 @@ static int adis16201_read_raw(struct iio_dev *indio_dev, bits = 12; break; case IIO_INCLI: - bits = 9; + bits = st->info->read_bits_incli; break; default: return -EINVAL; } addr = adis16201_addresses[chan->scan_index]; - ret = adis_read_reg_16(st, addr, &val16); + ret = adis_read_reg_16(&st->adis, addr, &val16); if (ret) return ret; @@ -180,41 +196,49 @@ static int adis16201_write_raw(struct iio_dev *indio_dev, int val2, long mask) { - struct adis *st = iio_priv(indio_dev); - int m; + struct adis16201_state *st = iio_priv(indio_dev); if (mask != IIO_CHAN_INFO_CALIBBIAS) return -EINVAL; switch (chan->type) { case IIO_ACCEL: - m = GENMASK(11, 0); + val &= GENMASK(11, 0); break; case IIO_INCLI: - m = GENMASK(8, 0); + val &= st->info->write_mask_incli; break; default: return -EINVAL; } - return adis_write_reg_16(st, adis16201_addresses[chan->scan_index], - val & m); + return adis_write_reg_16(&st->adis, adis16201_addresses[chan->scan_index], + val); } static const struct iio_chan_spec adis16201_channels[] = { - ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT_REG, ADIS16201_SCAN_SUPPLY, 0, - 12), - ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT_REG, ADIS16201_SCAN_TEMP, 0, 12), ADIS_ACCEL_CHAN(X, ADIS16201_XACCL_OUT_REG, ADIS16201_SCAN_ACC_X, BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), ADIS_ACCEL_CHAN(Y, ADIS16201_YACCL_OUT_REG, ADIS16201_SCAN_ACC_Y, BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), - ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC_REG, ADIS16201_SCAN_AUX_ADC, 0, 12), ADIS_INCLI_CHAN(X, ADIS16201_XINCL_OUT_REG, ADIS16201_SCAN_INCLI_X, BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 12), ADIS_INCLI_CHAN(Y, ADIS16201_YINCL_OUT_REG, ADIS16201_SCAN_INCLI_Y, BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 12), - IIO_CHAN_SOFT_TIMESTAMP(7) + ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT_REG, ADIS16201_SCAN_SUPPLY, 0, + 12), + ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC_REG, ADIS16201_SCAN_AUX_ADC, 0, 12), + ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT_REG, ADIS16201_SCAN_TEMP, 0, 12), + IIO_CHAN_SOFT_TIMESTAMP(7), +}; + +static const struct iio_chan_spec adis16203_channels[] = { + ADIS_INCLI_CHAN(X, ADIS16201_XINCL_OUT_REG, ADIS16201_SCAN_INCLI_X, + BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), + ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT_REG, ADIS16201_SCAN_SUPPLY, 0, 12), + ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC_REG, ADIS16201_SCAN_AUX_ADC, 0, 12), + ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT_REG, ADIS16201_SCAN_TEMP, 0, 12), + IIO_CHAN_SOFT_TIMESTAMP(7), }; static const struct iio_info adis16201_info = { @@ -224,6 +248,7 @@ static const struct iio_info adis16201_info = { }; static const char * const adis16201_status_error_msgs[] = { + [ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT] = "Self test failure", [ADIS16201_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure", [ADIS16201_DIAG_STAT_FLASH_UPT_FAIL_BIT] = "Flash update failed", [ADIS16201_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V", @@ -254,10 +279,49 @@ static const struct adis_data adis16201_data = { BIT(ADIS16201_DIAG_STAT_POWER_LOW_BIT), }; +static const struct adis_data adis16203_data = { + .read_delay = 20, + .msc_ctrl_reg = ADIS16201_MSC_CTRL_REG, + .glob_cmd_reg = ADIS16201_GLOB_CMD_REG, + .diag_stat_reg = ADIS16201_DIAG_STAT_REG, + + .self_test_mask = ADIS16201_MSC_CTRL_SELF_TEST_EN, + .self_test_reg = ADIS16201_MSC_CTRL_REG, + .self_test_no_autoclear = true, + .timeouts = &adis16201_timeouts, + + .status_error_msgs = adis16201_status_error_msgs, + .status_error_mask = BIT(ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT) | + BIT(ADIS16201_DIAG_STAT_SPI_FAIL_BIT) | + BIT(ADIS16201_DIAG_STAT_FLASH_UPT_FAIL_BIT) | + BIT(ADIS16201_DIAG_STAT_POWER_HIGH_BIT) | + BIT(ADIS16201_DIAG_STAT_POWER_LOW_BIT), +}; + +static const struct adis16201_chip_info adis16201_chip_data = { + .arr_channels = adis16201_channels, + .incli_scale_val2 = 100000, + .write_mask_incli = GENMASK(8, 0), + .read_bits_incli = 9, + .num_channels = ARRAY_SIZE(adis16201_channels), + .name = "adis16201", + .data = &adis16201_data, +}; + +static const struct adis16201_chip_info adis16203_chip_data = { + .arr_channels = adis16203_channels, + .incli_scale_val2 = 25000, + .write_mask_incli = GENMASK(13, 0), + .read_bits_incli = 14, + .num_channels = ARRAY_SIZE(adis16203_channels), + .name = "adis16203", + .data = &adis16203_data, +}; + static int adis16201_probe(struct spi_device *spi) { struct iio_dev *indio_dev; - struct adis *st; + struct adis16201_state *st; int ret; indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); @@ -266,38 +330,57 @@ static int adis16201_probe(struct spi_device *spi) st = iio_priv(indio_dev); - indio_dev->name = spi->dev.driver->name; + st->info = spi_get_device_match_data(spi); + if (!st->info) + return -ENODATA; + + indio_dev->name = st->info->name; indio_dev->info = &adis16201_info; - indio_dev->channels = adis16201_channels; - indio_dev->num_channels = ARRAY_SIZE(adis16201_channels); + indio_dev->channels = st->info->arr_channels; + indio_dev->num_channels = st->info->num_channels; indio_dev->modes = INDIO_DIRECT_MODE; - ret = adis_init(st, indio_dev, spi, &adis16201_data); + ret = adis_init(&st->adis, indio_dev, spi, st->info->data); if (ret) return ret; - ret = devm_adis_setup_buffer_and_trigger(st, indio_dev, NULL); + ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL); if (ret) return ret; - ret = __adis_initial_startup(st); + ret = __adis_initial_startup(&st->adis); if (ret) return ret; return devm_iio_device_register(&spi->dev, indio_dev); } +static const struct of_device_id adis16201_of_match[] = { + { .compatible = "adi,adis16201", .data = &adis16201_chip_data }, + { .compatible = "adi,adis16203", .data = &adis16203_chip_data }, + { } +}; +MODULE_DEVICE_TABLE(of, adis16201_of_match); + +static const struct spi_device_id adis16201_ids[] = { + { .name = "adis16201", .driver_data = (kernel_ulong_t)&adis16201_chip_data }, + { .name = "adis16203", .driver_data = (kernel_ulong_t)&adis16203_chip_data }, + { } +}; +MODULE_DEVICE_TABLE(spi, adis16201_ids); + static struct spi_driver adis16201_driver = { .driver = { .name = "adis16201", + .of_match_table = adis16201_of_match, }, .probe = adis16201_probe, + .id_table = adis16201_ids, }; module_spi_driver(adis16201_driver); MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_DESCRIPTION("Analog Devices ADIS16201 Dual-Axis Digital Inclinometer and Accelerometer"); +MODULE_DESCRIPTION("Analog Devices ADIS16201 Inclinometer and similar"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:adis16201"); MODULE_IMPORT_NS("IIO_ADISLIB"); diff --git a/drivers/iio/accel/adxl313_spi.c b/drivers/iio/accel/adxl313_spi.c index a61295de104f..0f0da44461f7 100644 --- a/drivers/iio/accel/adxl313_spi.c +++ b/drivers/iio/accel/adxl313_spi.c @@ -79,6 +79,8 @@ static int adxl313_spi_probe(struct spi_device *spi) return ret; chip_data = spi_get_device_match_data(spi); + if (!chip_data) + return -ENODATA; regmap = devm_regmap_init_spi(spi, &adxl31x_spi_regmap_config[chip_data->type]); diff --git a/drivers/iio/accel/adxl367.c b/drivers/iio/accel/adxl367.c index 4ff1c7a0988b..026db73057c5 100644 --- a/drivers/iio/accel/adxl367.c +++ b/drivers/iio/accel/adxl367.c @@ -13,6 +13,7 @@ #include <linux/iio/sysfs.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/property.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/unaligned.h> @@ -81,6 +82,7 @@ #define ADXL367_SAMPLES_L_MASK GENMASK(7, 0) #define ADXL367_REG_INT1_MAP 0x2A +#define ADXL367_REG_INT2_MAP 0x2B #define ADXL367_INT_INACT_MASK BIT(5) #define ADXL367_INT_ACT_MASK BIT(4) #define ADXL367_INT_FIFO_WATERMARK_MASK BIT(2) @@ -168,6 +170,8 @@ struct adxl367_state { enum adxl367_odr odr; enum adxl367_range range; + u8 int_map_reg; + unsigned int act_threshold; unsigned int act_time_ms; unsigned int inact_threshold; @@ -366,8 +370,7 @@ static int adxl367_set_act_interrupt_en(struct adxl367_state *st, { unsigned int mask = adxl367_act_int_mask_tbl[act]; - return regmap_update_bits(st->regmap, ADXL367_REG_INT1_MAP, - mask, en ? mask : 0); + return regmap_assign_bits(st->regmap, st->int_map_reg, mask, en); } static int adxl367_get_act_interrupt_en(struct adxl367_state *st, @@ -378,7 +381,7 @@ static int adxl367_get_act_interrupt_en(struct adxl367_state *st, unsigned int val; int ret; - ret = regmap_read(st->regmap, ADXL367_REG_INT1_MAP, &val); + ret = regmap_read(st->regmap, st->int_map_reg, &val); if (ret) return ret; @@ -401,9 +404,8 @@ static int adxl367_set_act_en(struct adxl367_state *st, static int adxl367_set_fifo_watermark_interrupt_en(struct adxl367_state *st, bool en) { - return regmap_update_bits(st->regmap, ADXL367_REG_INT1_MAP, - ADXL367_INT_FIFO_WATERMARK_MASK, - en ? ADXL367_INT_FIFO_WATERMARK_MASK : 0); + return regmap_assign_bits(st->regmap, st->int_map_reg, + ADXL367_INT_FIFO_WATERMARK_MASK, en); } static int adxl367_get_fifo_mode(struct adxl367_state *st, @@ -631,8 +633,7 @@ static int adxl367_set_odr(struct iio_dev *indio_dev, enum adxl367_odr odr) static int adxl367_set_temp_adc_en(struct adxl367_state *st, unsigned int reg, bool en) { - return regmap_update_bits(st->regmap, reg, ADXL367_ADC_EN_MASK, - en ? ADXL367_ADC_EN_MASK : 0); + return regmap_assign_bits(st->regmap, reg, ADXL367_ADC_EN_MASK, en); } static int adxl367_set_temp_adc_reg_en(struct adxl367_state *st, @@ -787,6 +788,13 @@ static bool adxl367_push_fifo_data(struct iio_dev *indio_dev, u8 status, if (!FIELD_GET(ADXL367_STATUS_FIFO_FULL_MASK, status)) return false; + if (fifo_entries > ADXL367_FIFO_SIZE) { + dev_err_ratelimited(st->dev, + "FIFO entry count %u exceeds FIFO size %u\n", + fifo_entries, ADXL367_FIFO_SIZE); + return true; + } + fifo_entries -= fifo_entries % st->fifo_set_size; ret = st->ops->read_fifo(st->context, st->fifo_buf, fifo_entries); @@ -1426,6 +1434,36 @@ static int adxl367_setup(struct adxl367_state *st) return adxl367_set_measure_en(st, true); } +static int adxl367_set_int_map_reg(struct adxl367_state *st, int irq) +{ + int ret; + + /* + * Route the mappings to whichever of INT1/INT2 is named in the + * interrupt-names property. -EINVAL (property absent) and -ENODATA + * (name not listed) are not errors; anything else is. + */ + ret = fwnode_irq_get_byname(dev_fwnode(st->dev), "INT1"); + if (ret > 0) { + st->int_map_reg = ADXL367_REG_INT1_MAP; + return ret; + } + if (ret != -ENODATA && ret != -EINVAL) + return ret; + + ret = fwnode_irq_get_byname(dev_fwnode(st->dev), "INT2"); + if (ret > 0) { + st->int_map_reg = ADXL367_REG_INT2_MAP; + return ret; + } + if (ret != -ENODATA && ret != -EINVAL) + return ret; + + /* No INT1/INT2 named: default to INT1 and the bus interrupt. */ + st->int_map_reg = ADXL367_REG_INT1_MAP; + return irq; +} + int adxl367_probe(struct device *dev, const struct adxl367_ops *ops, void *context, struct regmap *regmap, int irq) { @@ -1455,6 +1493,11 @@ int adxl367_probe(struct device *dev, const struct adxl367_ops *ops, indio_dev->info = &adxl367_info; indio_dev->modes = INDIO_DIRECT_MODE; + ret = adxl367_set_int_map_reg(st, irq); + if (ret < 0) + return dev_err_probe(st->dev, ret, "Failed to get interrupt\n"); + irq = ret; + ret = devm_regulator_bulk_get_enable(st->dev, ARRAY_SIZE(regulator_names), regulator_names); diff --git a/drivers/iio/accel/adxl372_spi.c b/drivers/iio/accel/adxl372_spi.c index 128e148c4e96..d54544d6df6f 100644 --- a/drivers/iio/accel/adxl372_spi.c +++ b/drivers/iio/accel/adxl372_spi.c @@ -25,6 +25,8 @@ static int adxl372_spi_probe(struct spi_device *spi) struct regmap *regmap; chip_info = spi_get_device_match_data(spi); + if (!chip_info) + return -ENODATA; regmap = devm_regmap_init_spi(spi, &adxl372_spi_regmap_config); if (IS_ERR(regmap)) diff --git a/drivers/iio/accel/adxl380.c b/drivers/iio/accel/adxl380.c index 7dca5523091f..8518ee23e114 100644 --- a/drivers/iio/accel/adxl380.c +++ b/drivers/iio/accel/adxl380.c @@ -966,6 +966,13 @@ static irqreturn_t adxl380_irq_handler(int irq, void *p) if (ret) return IRQ_HANDLED; + if (fifo_entries > ADXL380_FIFO_SAMPLES) { + dev_err_ratelimited(st->dev, + "FIFO entry count %u exceeds FIFO size %lu\n", + fifo_entries, ADXL380_FIFO_SAMPLES); + return IRQ_HANDLED; + } + fifo_entries = rounddown(fifo_entries, st->fifo_set_size); ret = regmap_noinc_read(st->regmap, ADXL380_FIFO_DATA, &st->fifo_buf, sizeof(*st->fifo_buf) * fifo_entries); diff --git a/drivers/iio/accel/adxl380_spi.c b/drivers/iio/accel/adxl380_spi.c index ae8467f4e6c0..8ffb3a8690a6 100644 --- a/drivers/iio/accel/adxl380_spi.c +++ b/drivers/iio/accel/adxl380_spi.c @@ -25,6 +25,8 @@ static int adxl380_spi_probe(struct spi_device *spi) struct regmap *regmap; chip_data = spi_get_device_match_data(spi); + if (!chip_data) + return -ENODATA; regmap = devm_regmap_init_spi(spi, &adxl380_spi_regmap_config); if (IS_ERR(regmap)) diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c index d6c1087cc3c0..d7a95289df48 100644 --- a/drivers/iio/accel/bma220_spi.c +++ b/drivers/iio/accel/bma220_spi.c @@ -28,12 +28,13 @@ static const struct spi_device_id bma220_spi_id[] = { { .name = "bma220" }, { } }; +MODULE_DEVICE_TABLE(spi, bma220_spi_id); static const struct acpi_device_id bma220_acpi_id[] = { { "BMA0220", 0 }, { } }; -MODULE_DEVICE_TABLE(spi, bma220_spi_id); +MODULE_DEVICE_TABLE(acpi, bma220_acpi_id); static const struct of_device_id bma220_of_spi_match[] = { { .compatible = "bosch,bma220" }, diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c index 7e3cff4cca91..6bc64ca87f4b 100644 --- a/drivers/iio/accel/bma400_core.c +++ b/drivers/iio/accel/bma400_core.c @@ -6,8 +6,6 @@ * * TODO: * - Support for power management - * - Support events and interrupts - * - Create channel for step count * - Create channel for sensor time */ diff --git a/drivers/iio/accel/kionix-kx022a.c b/drivers/iio/accel/kionix-kx022a.c index 9ff70a373141..add89512af79 100644 --- a/drivers/iio/accel/kionix-kx022a.c +++ b/drivers/iio/accel/kionix-kx022a.c @@ -301,11 +301,10 @@ struct kx022a_data { __le16 *fifo_buffer; /* 3 x 16bit accel data + timestamp */ - __le16 buffer[8] __aligned(IIO_DMA_MINALIGN); struct { __le16 channels[3]; aligned_s64 ts; - } scan; + } scan __aligned(IIO_DMA_MINALIGN); }; static const struct iio_mount_matrix * @@ -611,14 +610,15 @@ static int kx022a_get_axis(struct kx022a_data *data, struct iio_chan_spec const *chan, int *val) { + __le16 *buf = &data->scan.channels[0]; int ret; - ret = regmap_bulk_read(data->regmap, chan->address, &data->buffer[0], - sizeof(__le16)); + ret = regmap_bulk_read(data->regmap, chan->address, + buf, sizeof(*buf)); if (ret) return ret; - *val = (s16)le16_to_cpu(data->buffer[0]); + *val = (s16)le16_to_cpup(buf); return IIO_VAL_INT; } @@ -809,7 +809,7 @@ static int __kx022a_fifo_flush(struct iio_dev *idev, unsigned int samples, * the timestamps. If we are ran from IRQ, then the * IRQF_ONESHOT has us covered - but if we are ran by the * user-space read we need to disable the IRQ to be on a safe - * side. We do this usng synchronous disable so that if the + * side. We do this using synchronous disable so that if the * IRQ thread is being ran on other CPU we wait for it to be * finished. */ @@ -864,7 +864,8 @@ static int __kx022a_fifo_flush(struct iio_dev *idev, unsigned int samples, for_each_set_bit(bit, idev->active_scan_mask, AXIS_MAX) chs[bit] = sam[bit]; - iio_push_to_buffers_with_timestamp(idev, &data->scan, tstamp); + iio_push_to_buffers_with_ts(idev, &data->scan, + sizeof(data->scan), tstamp); tstamp += sample_period; } @@ -1047,12 +1048,13 @@ static irqreturn_t kx022a_trigger_handler(int irq, void *p) struct kx022a_data *data = iio_priv(idev); int ret; - ret = regmap_bulk_read(data->regmap, data->chip_info->xout_l, data->buffer, - KX022A_FIFO_SAMPLES_SIZE_BYTES); + ret = regmap_bulk_read(data->regmap, data->chip_info->xout_l, + data->scan.channels, KX022A_FIFO_SAMPLES_SIZE_BYTES); if (ret < 0) goto err_read; - iio_push_to_buffers_with_timestamp(idev, data->buffer, data->timestamp); + iio_push_to_buffers_with_ts(idev, &data->scan, sizeof(data->scan), + data->timestamp); err_read: iio_trigger_notify_done(idev->trig); diff --git a/drivers/iio/accel/kionix-kx022a.h b/drivers/iio/accel/kionix-kx022a.h index 0ed54f584223..a2d122c1e234 100644 --- a/drivers/iio/accel/kionix-kx022a.h +++ b/drivers/iio/accel/kionix-kx022a.h @@ -65,7 +65,7 @@ #define KX022A_MASK_IEN BIT(5) #define KX022A_MASK_IPOL BIT(4) #define KX022A_IPOL_LOW 0 -#define KX022A_IPOL_HIGH KX022A_MASK_IPOL1 +#define KX022A_IPOL_HIGH KX022A_MASK_IPOL #define KX022A_MASK_ITYP BIT(3) #define KX022A_ITYP_PULSE KX022A_MASK_ITYP #define KX022A_ITYP_LEVEL 0 diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index 8994c9e8e048..b3d753bd9476 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -1547,6 +1547,7 @@ static void kxcjk1013_remove(struct i2c_client *client) iio_device_unregister(indio_dev); + pm_runtime_dont_use_autosuspend(&client->dev); pm_runtime_disable(&client->dev); pm_runtime_set_suspended(&client->dev); diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 7d683686dd9d..fe62a903f0e2 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -18,6 +18,8 @@ * TODO: orientation events */ +#include <linux/array_size.h> +#include <linux/cleanup.h> #include <linux/delay.h> #include <linux/i2c.h> #include <linux/module.h> @@ -110,8 +112,7 @@ struct mma8452_data { u8 data_cfg; const struct mma_chip_info *chip_info; int sleep_val; - struct regulator *vdd_reg; - struct regulator *vddio_reg; + struct regulator_bulk_data regs[2]; /* Ensure correct alignment of time stamp when present */ struct { @@ -222,15 +223,15 @@ static int mma8452_drdy(struct mma8452_data *data) static int mma8452_set_runtime_pm_state(struct i2c_client *client, bool on) { #ifdef CONFIG_PM + struct device *dev = &client->dev; int ret; if (on) - ret = pm_runtime_resume_and_get(&client->dev); + ret = pm_runtime_resume_and_get(dev); else - ret = pm_runtime_put_autosuspend(&client->dev); + ret = pm_runtime_put_autosuspend(dev); if (ret < 0) { - dev_err(&client->dev, - "failed to change power state to %d\n", on); + dev_err(dev, "failed to change power state to %d\n", on); return ret; } @@ -495,14 +496,14 @@ static int mma8452_read_raw(struct iio_dev *indio_dev, int i, ret; switch (mask) { - case IIO_CHAN_INFO_RAW: - if (!iio_device_claim_direct(indio_dev)) + case IIO_CHAN_INFO_RAW: { + IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim); + if (IIO_DEV_ACQUIRE_FAILED(claim)) return -EBUSY; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); + ret = mma8452_read(data, buffer); - mutex_unlock(&data->lock); - iio_device_release_direct(indio_dev); if (ret < 0) return ret; @@ -511,6 +512,7 @@ static int mma8452_read_raw(struct iio_dev *indio_dev, chan->scan_type.realbits - 1); return IIO_VAL_INT; + } case IIO_CHAN_INFO_SCALE: i = data->data_cfg & MMA8452_DATA_CFG_FS_MASK; *val = data->chip_info->mma_scales[i][0]; @@ -599,36 +601,30 @@ static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val) int ret; int is_active; - mutex_lock(&data->lock); + guard(mutex)(&data->lock); is_active = mma8452_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 = mma8452_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 = mma8452_active(data); if (ret < 0) - goto fail; + return ret; } - ret = 0; -fail: - mutex_unlock(&data->lock); - - return ret; + return 0; } static int mma8452_set_power_mode(struct mma8452_data *data, u8 mode) @@ -777,14 +773,11 @@ static int mma8452_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)) + IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim); + if (IIO_DEV_ACQUIRE_FAILED(claim)) return -EBUSY; - ret = __mma8452_write_raw(indio_dev, chan, val, val2, mask); - iio_device_release_direct(indio_dev); - return ret; + return __mma8452_write_raw(indio_dev, chan, val, val2, mask); } static int mma8452_get_event_regs(struct mma8452_data *data, @@ -1552,7 +1545,7 @@ static int mma8452_probe(struct i2c_client *client) 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; @@ -1562,32 +1555,21 @@ static int mma8452_probe(struct i2c_client *client) data->chip_info = i2c_get_match_data(client); if (!data->chip_info) - return dev_err_probe(&client->dev, -ENODEV, - "unknown device model\n"); + return dev_err_probe(dev, -ENODEV, "unknown device model\n"); - ret = iio_read_mount_matrix(&client->dev, &data->orientation); + ret = iio_read_mount_matrix(dev, &data->orientation); if (ret) return ret; - data->vdd_reg = devm_regulator_get(&client->dev, "vdd"); - if (IS_ERR(data->vdd_reg)) - return dev_err_probe(&client->dev, PTR_ERR(data->vdd_reg), - "failed to get VDD regulator!\n"); - - data->vddio_reg = devm_regulator_get(&client->dev, "vddio"); - if (IS_ERR(data->vddio_reg)) - return dev_err_probe(&client->dev, PTR_ERR(data->vddio_reg), - "failed to get VDDIO regulator!\n"); - - ret = regulator_enable(data->vdd_reg); + data->regs[0].supply = "vdd"; + data->regs[1].supply = "vddio"; + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->regs), data->regs); if (ret) - return dev_err_probe(dev, ret, "failed to enable VDD regulator!\n"); + return dev_err_probe(dev, ret, "failed to get regulators\n"); - ret = regulator_enable(data->vddio_reg); - if (ret) { - dev_err_probe(dev, ret, "failed to enable VDDIO regulator!\n"); - goto disable_regulator_vdd; - } + ret = regulator_bulk_enable(ARRAY_SIZE(data->regs), data->regs); + if (ret) + return dev_err_probe(dev, ret, "failed to enable regulators\n"); ret = i2c_smbus_read_byte_data(client, MMA8452_WHO_AM_I); if (ret < 0) @@ -1608,7 +1590,7 @@ static int mma8452_probe(struct i2c_client *client) goto disable_regulators; } - dev_info(&client->dev, "registering %s accelerometer; ID 0x%x\n", + dev_info(dev, "registering %s accelerometer; ID 0x%x\n", data->chip_info->name, data->chip_info->chip_id); i2c_set_clientdata(client, indio_dev); @@ -1641,10 +1623,10 @@ static int mma8452_probe(struct i2c_client *client) if (client->irq) { int irq2; - irq2 = fwnode_irq_get_byname(dev_fwnode(&client->dev), "INT2"); + irq2 = fwnode_irq_get_byname(dev_fwnode(dev), "INT2"); if (irq2 == client->irq) { - dev_dbg(&client->dev, "using interrupt line INT2\n"); + dev_dbg(dev, "using interrupt line INT2\n"); } else { ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG5, @@ -1652,7 +1634,7 @@ static int mma8452_probe(struct i2c_client *client) if (ret < 0) goto disable_regulators; - dev_dbg(&client->dev, "using interrupt line INT1\n"); + dev_dbg(dev, "using interrupt line INT1\n"); } ret = i2c_smbus_write_byte_data(client, @@ -1689,14 +1671,13 @@ static int mma8452_probe(struct i2c_client *client) goto buffer_cleanup; } - ret = pm_runtime_set_active(&client->dev); + ret = pm_runtime_set_active(dev); if (ret < 0) goto free_irq; - pm_runtime_enable(&client->dev); - pm_runtime_set_autosuspend_delay(&client->dev, - MMA8452_AUTO_SUSPEND_DELAY_MS); - pm_runtime_use_autosuspend(&client->dev); + pm_runtime_enable(dev); + pm_runtime_set_autosuspend_delay(dev, MMA8452_AUTO_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(dev); ret = iio_device_register(indio_dev); if (ret < 0) @@ -1722,10 +1703,7 @@ trigger_cleanup: mma8452_trigger_cleanup(indio_dev); disable_regulators: - regulator_disable(data->vddio_reg); - -disable_regulator_vdd: - regulator_disable(data->vdd_reg); + regulator_bulk_disable(ARRAY_SIZE(data->regs), data->regs); return ret; } @@ -1734,11 +1712,12 @@ static void mma8452_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); struct mma8452_data *data = iio_priv(indio_dev); + struct device *dev = &client->dev; iio_device_unregister(indio_dev); - pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); if (client->irq) free_irq(client->irq, indio_dev); @@ -1747,8 +1726,7 @@ static void mma8452_remove(struct i2c_client *client) mma8452_trigger_cleanup(indio_dev); mma8452_standby(iio_priv(indio_dev)); - regulator_disable(data->vddio_reg); - regulator_disable(data->vdd_reg); + regulator_bulk_disable(ARRAY_SIZE(data->regs), data->regs); } #ifdef CONFIG_PM @@ -1758,23 +1736,16 @@ static int mma8452_runtime_suspend(struct device *dev) struct mma8452_data *data = iio_priv(indio_dev); int ret; - mutex_lock(&data->lock); - ret = mma8452_standby(data); - mutex_unlock(&data->lock); + scoped_guard(mutex, &data->lock) + ret = mma8452_standby(data); if (ret < 0) { - dev_err(&data->client->dev, "powering off device failed\n"); + dev_err(dev, "powering off device failed\n"); return -EAGAIN; } - ret = regulator_disable(data->vddio_reg); - if (ret) { - dev_err(dev, "failed to disable VDDIO regulator\n"); - return ret; - } - - ret = regulator_disable(data->vdd_reg); + ret = regulator_bulk_disable(ARRAY_SIZE(data->regs), data->regs); if (ret) { - dev_err(dev, "failed to disable VDD regulator\n"); + dev_err(dev, "failed to disable regulators\n"); return ret; } @@ -1787,16 +1758,9 @@ static int mma8452_runtime_resume(struct device *dev) struct mma8452_data *data = iio_priv(indio_dev); int ret, sleep_val; - ret = regulator_enable(data->vdd_reg); - if (ret) { - dev_err(dev, "failed to enable VDD regulator\n"); - return ret; - } - - ret = regulator_enable(data->vddio_reg); + ret = regulator_bulk_enable(ARRAY_SIZE(data->regs), data->regs); if (ret) { - dev_err(dev, "failed to enable VDDIO regulator\n"); - regulator_disable(data->vdd_reg); + dev_err(dev, "failed to enable regulators\n"); return ret; } @@ -1814,8 +1778,7 @@ static int mma8452_runtime_resume(struct device *dev) return 0; runtime_resume_failed: - regulator_disable(data->vddio_reg); - regulator_disable(data->vdd_reg); + regulator_bulk_disable(ARRAY_SIZE(data->regs), data->regs); return ret; } diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c index 7e01427fd9c4..182f488edab1 100644 --- a/drivers/iio/accel/mma9551.c +++ b/drivers/iio/accel/mma9551.c @@ -500,6 +500,7 @@ static void mma9551_remove(struct i2c_client *client) iio_device_unregister(indio_dev); + pm_runtime_dont_use_autosuspend(&client->dev); pm_runtime_disable(&client->dev); pm_runtime_set_suspended(&client->dev); diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c index 8e7aaac89d47..5a36d415a837 100644 --- a/drivers/iio/accel/mma9553.c +++ b/drivers/iio/accel/mma9553.c @@ -1136,6 +1136,7 @@ static void mma9553_remove(struct i2c_client *client) iio_device_unregister(indio_dev); + pm_runtime_dont_use_autosuspend(&client->dev); pm_runtime_disable(&client->dev); pm_runtime_set_suspended(&client->dev); diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c index 8f1ac1d3305e..acd0890c78a5 100644 --- a/drivers/iio/accel/sca3000.c +++ b/drivers/iio/accel/sca3000.c @@ -1462,6 +1462,8 @@ static int sca3000_probe(struct spi_device *spi) st->us = spi; mutex_init(&st->lock); st->info = spi_get_device_match_data(spi); + if (!st->info) + return -ENODATA; indio_dev->name = st->info->name; indio_dev->info = &sca3000_info; |
