From 4ffa22fd22a7cbde1a1394b2707ea73593dc0fda Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Thu, 23 Jul 2020 09:29:43 +0300 Subject: iio: add IIO_MOD_O2 modifier Add modifier IIO_MOD_O2 for O2 concentration reporting Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/iio') diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 606d5e61c575..59003dc44e60 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -133,6 +133,7 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_PM10] = "pm10", [IIO_MOD_ETHANOL] = "ethanol", [IIO_MOD_H2] = "h2", + [IIO_MOD_O2] = "o2", }; /* relies on pairs of these shared then separate */ -- cgit v1.2.3 From 6da3a6ce281fa7a51e1e3af0fa6d9e52bd9bf11a Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Thu, 23 Jul 2020 09:29:44 +0300 Subject: iio: chemical: atlas-ezo-sensor: add support for O2 sensor Add support for the Atlas EZO O2 chemical sensor which required some refactoring of the driver and parsing of i2c transfer. Sensor data is converted by the scaling value from percent to IIO_CONCENTRATION. Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- drivers/iio/chemical/atlas-ezo-sensor.c | 73 ++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 19 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/chemical/atlas-ezo-sensor.c b/drivers/iio/chemical/atlas-ezo-sensor.c index 8b72bb012363..60a0c752fbc5 100644 --- a/drivers/iio/chemical/atlas-ezo-sensor.c +++ b/drivers/iio/chemical/atlas-ezo-sensor.c @@ -16,10 +16,11 @@ #include #define ATLAS_EZO_DRV_NAME "atlas-ezo-sensor" -#define ATLAS_CO2_INT_TIME_IN_MS 950 +#define ATLAS_INT_TIME_IN_MS 950 enum { ATLAS_CO2_EZO, + ATLAS_O2_EZO, }; struct atlas_ezo_device { @@ -38,31 +39,53 @@ struct atlas_ezo_data { u8 buffer[8]; }; +#define ATLAS_CONCENTRATION_CHANNEL(_modifier) \ + { \ + .type = IIO_CONCENTRATION, \ + .modified = 1,\ + .channel2 = _modifier, \ + .info_mask_separate = \ + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index = 0, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 32, \ + .storagebits = 32, \ + .endianness = IIO_CPU, \ + }, \ + } + static const struct iio_chan_spec atlas_co2_ezo_channels[] = { - { - .type = IIO_CONCENTRATION, - .modified = 1, - .channel2 = IIO_MOD_CO2, - .info_mask_separate = - BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), - .scan_index = 0, - .scan_type = { - .sign = 'u', - .realbits = 32, - .storagebits = 32, - .endianness = IIO_CPU, - }, - }, + ATLAS_CONCENTRATION_CHANNEL(IIO_MOD_CO2), +}; + +static const struct iio_chan_spec atlas_o2_ezo_channels[] = { + ATLAS_CONCENTRATION_CHANNEL(IIO_MOD_O2), }; static struct atlas_ezo_device atlas_ezo_devices[] = { [ATLAS_CO2_EZO] = { .channels = atlas_co2_ezo_channels, .num_channels = 1, - .delay = ATLAS_CO2_INT_TIME_IN_MS, + .delay = ATLAS_INT_TIME_IN_MS, }, + [ATLAS_O2_EZO] = { + .channels = atlas_o2_ezo_channels, + .num_channels = 1, + .delay = ATLAS_INT_TIME_IN_MS, + } }; +static void atlas_ezo_sanitize(char *buf) +{ + char *ptr = strchr(buf, '.'); + + if (!ptr) + return; + + memmove(ptr, ptr + 1, strlen(ptr)); +} + static int atlas_ezo_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -96,6 +119,9 @@ static int atlas_ezo_read_raw(struct iio_dev *indio_dev, return -EBUSY; } + /* removing floating point for fixed number representation */ + atlas_ezo_sanitize(data->buffer + 2); + ret = kstrtol(data->buffer + 1, 10, &tmp); *val = tmp; @@ -105,9 +131,16 @@ static int atlas_ezo_read_raw(struct iio_dev *indio_dev, return ret ? ret : IIO_VAL_INT; } case IIO_CHAN_INFO_SCALE: - *val = 0; - *val2 = 100; /* 0.0001 */ - return IIO_VAL_INT_PLUS_MICRO; + switch (chan->channel2) { + case IIO_MOD_CO2: + *val = 0; + *val2 = 100; /* 0.0001 */ + return IIO_VAL_INT_PLUS_MICRO; + case IIO_MOD_O2: + *val = 100; + return IIO_VAL_INT; + } + return -EINVAL; } return 0; @@ -119,12 +152,14 @@ static const struct iio_info atlas_info = { static const struct i2c_device_id atlas_ezo_id[] = { { "atlas-co2-ezo", ATLAS_CO2_EZO }, + { "atlas-o2-ezo", ATLAS_O2_EZO }, {} }; MODULE_DEVICE_TABLE(i2c, atlas_ezo_id); static const struct of_device_id atlas_ezo_dt_ids[] = { { .compatible = "atlas,co2-ezo", .data = (void *)ATLAS_CO2_EZO, }, + { .compatible = "atlas,o2-ezo", .data = (void *)ATLAS_O2_EZO, }, {} }; MODULE_DEVICE_TABLE(of, atlas_ezo_dt_ids); -- cgit v1.2.3 From a507801275559a4c89b4a7ebbba983104ee2bd06 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Wed, 22 Jul 2020 10:22:01 +0300 Subject: iio: frequency: ad9523: convert rest of driver to device managed functions The driver pretty much uses device managed functions. The only left-over is the iio_device_register() function, which also requires an action-or-reset hook to disable the regulator on the remove and error path. Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/frequency/ad9523.c | 60 ++++++++++++++---------------------------- 1 file changed, 20 insertions(+), 40 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c index 334e1d779d6d..bdb0bc3b12dd 100644 --- a/drivers/iio/frequency/ad9523.c +++ b/drivers/iio/frequency/ad9523.c @@ -969,6 +969,13 @@ static int ad9523_setup(struct iio_dev *indio_dev) return 0; } +static void ad9523_reg_disable(void *data) +{ + struct regulator *reg = data; + + regulator_disable(reg); +} + static int ad9523_probe(struct spi_device *spi) { struct ad9523_platform_data *pdata = spi->dev.platform_data; @@ -994,21 +1001,22 @@ static int ad9523_probe(struct spi_device *spi) ret = regulator_enable(st->reg); if (ret) return ret; + + ret = devm_add_action_or_reset(&spi->dev, ad9523_reg_disable, + st->reg); + if (ret) + return ret; } st->pwrdown_gpio = devm_gpiod_get_optional(&spi->dev, "powerdown", GPIOD_OUT_HIGH); - if (IS_ERR(st->pwrdown_gpio)) { - ret = PTR_ERR(st->pwrdown_gpio); - goto error_disable_reg; - } + if (IS_ERR(st->pwrdown_gpio)) + return PTR_ERR(st->pwrdown_gpio); st->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset", GPIOD_OUT_LOW); - if (IS_ERR(st->reset_gpio)) { - ret = PTR_ERR(st->reset_gpio); - goto error_disable_reg; - } + if (IS_ERR(st->reset_gpio)) + return PTR_ERR(st->reset_gpio); if (st->reset_gpio) { udelay(1); @@ -1017,10 +1025,8 @@ static int ad9523_probe(struct spi_device *spi) st->sync_gpio = devm_gpiod_get_optional(&spi->dev, "sync", GPIOD_OUT_HIGH); - if (IS_ERR(st->sync_gpio)) { - ret = PTR_ERR(st->sync_gpio); - goto error_disable_reg; - } + if (IS_ERR(st->sync_gpio)) + return PTR_ERR(st->sync_gpio); spi_set_drvdata(spi, indio_dev); st->spi = spi; @@ -1035,34 +1041,9 @@ static int ad9523_probe(struct spi_device *spi) ret = ad9523_setup(indio_dev); if (ret < 0) - goto error_disable_reg; - - ret = iio_device_register(indio_dev); - if (ret) - goto error_disable_reg; - - dev_info(&spi->dev, "probed %s\n", indio_dev->name); - - return 0; - -error_disable_reg: - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); - - return ret; -} - -static int ad9523_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct ad9523_state *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - - if (!IS_ERR(st->reg)) - regulator_disable(st->reg); + return ret; - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static const struct spi_device_id ad9523_id[] = { @@ -1076,7 +1057,6 @@ static struct spi_driver ad9523_driver = { .name = "ad9523", }, .probe = ad9523_probe, - .remove = ad9523_remove, .id_table = ad9523_id, }; module_spi_driver(ad9523_driver); -- cgit v1.2.3 From 9b3b3b284ad550ca6cd5049e84728d4939148b9d Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Wed, 22 Jul 2020 10:25:46 +0300 Subject: iio: adxl372_spi: change indentation for of_table The change is mostly stylistic. The table should be indented with tabs instead of spaces. Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/accel/adxl372_spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/accel/adxl372_spi.c b/drivers/iio/accel/adxl372_spi.c index 3ef7e3a4804e..1f1352fee99a 100644 --- a/drivers/iio/accel/adxl372_spi.c +++ b/drivers/iio/accel/adxl372_spi.c @@ -40,8 +40,8 @@ static const struct spi_device_id adxl372_spi_id[] = { MODULE_DEVICE_TABLE(spi, adxl372_spi_id); static const struct of_device_id adxl372_of_match[] = { - { .compatible = "adi,adxl372" }, - { }, + { .compatible = "adi,adxl372" }, + { } }; MODULE_DEVICE_TABLE(of, adxl372_of_match); -- cgit v1.2.3 From 5579db2cd5dd4032407114287dd0f97e07478e99 Mon Sep 17 00:00:00 2001 From: Stefan Popa Date: Wed, 22 Jul 2020 10:30:03 +0300 Subject: iio: adxl372_i2c: Add OF device ID table The driver does not have a struct of_device_id table, but supported devices are registered via Device Trees. This patch adds OF device ID table. Signed-off-by: Stefan Popa Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/accel/adxl372_i2c.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/iio') diff --git a/drivers/iio/accel/adxl372_i2c.c b/drivers/iio/accel/adxl372_i2c.c index e1affe480c77..9a07ab3d151a 100644 --- a/drivers/iio/accel/adxl372_i2c.c +++ b/drivers/iio/accel/adxl372_i2c.c @@ -6,6 +6,7 @@ */ #include +#include #include #include @@ -46,9 +47,16 @@ static const struct i2c_device_id adxl372_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, adxl372_i2c_id); +static const struct of_device_id adxl372_of_match[] = { + { .compatible = "adi,adxl372" }, + { } +}; +MODULE_DEVICE_TABLE(of, adxl372_of_match); + static struct i2c_driver adxl372_i2c_driver = { .driver = { .name = "adxl372_i2c", + .of_match_table = adxl372_of_match, }, .probe = adxl372_i2c_probe, .id_table = adxl372_i2c_id, -- cgit v1.2.3 From 6f762972b2a766d9d03fc05de8d0880e90b98df1 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 20 Jul 2020 16:52:37 +0300 Subject: iio: Kconfig: ad8366: add entry for HMC1119 chip The change is mostly cosmetic. When looking into the menuconfig help of the ad8366 driver, the HMC1119 chip should also show up (since the driver supports it). Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/amplifiers/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/iio') diff --git a/drivers/iio/amplifiers/Kconfig b/drivers/iio/amplifiers/Kconfig index 9b02c9a2bc8a..5eb1357a9c78 100644 --- a/drivers/iio/amplifiers/Kconfig +++ b/drivers/iio/amplifiers/Kconfig @@ -18,6 +18,7 @@ config AD8366 AD8366 Dual-Digital Variable Gain Amplifier (VGA) ADA4961 BiCMOS RF Digital Gain Amplifier (DGA) ADL5240 Digitally controlled variable gain amplifier (VGA) + HMC1119 0.25 dB LSB, 7-Bit, Silicon Digital Attenuator To compile this driver as a module, choose M here: the module will be called ad8366. -- cgit v1.2.3 From 4d55cb8e78df3d6bb40ff4abf02bb15d1145846c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 20 Jul 2020 16:51:33 +0300 Subject: iio: trigger: make stub functions static inline Make sure that the trigger function stubs are all static inline. Otherwise we might see compiler warnings about declared but unused functions. Fixes 77712e5fbe2e4: ("Staging: iio: Staticise non-exported functions") Signed-off-by: Lars-Peter Clausen Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/iio_core_trigger.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/iio_core_trigger.h b/drivers/iio/iio_core_trigger.h index 9d1a92cc6480..374816bc3e73 100644 --- a/drivers/iio/iio_core_trigger.h +++ b/drivers/iio/iio_core_trigger.h @@ -30,7 +30,7 @@ int iio_trigger_detach_poll_func(struct iio_trigger *trig, * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers * @indio_dev: iio_dev associated with the device that will consume the trigger **/ -static int iio_device_register_trigger_consumer(struct iio_dev *indio_dev) +static inline int iio_device_register_trigger_consumer(struct iio_dev *indio_dev) { return 0; } @@ -39,7 +39,7 @@ static int iio_device_register_trigger_consumer(struct iio_dev *indio_dev) * iio_device_unregister_trigger_consumer() - reverse the registration process * @indio_dev: iio_dev associated with the device that consumed the trigger **/ -static void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev) +static inline void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev) { } -- cgit v1.2.3 From 2c8920fff1457a41912e8d3e3b9eafb582656440 Mon Sep 17 00:00:00 2001 From: Nishant Malpani Date: Sun, 26 Jul 2020 19:40:16 +0530 Subject: iio: gyro: Add driver support for ADXRS290 ADXRS290 is a high performance MEMS pitch and roll (dual-axis in-plane) angular rate sensor (gyroscope) designed for use in stabilization applications. It also features an internal temperature sensor and programmable high-pass and low-pass filters. Add support for ADXRS290 in direct-access mode for now. Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADXRS290.pdf Reviewed-by: Andy Shevchenko Signed-off-by: Nishant Malpani Signed-off-by: Jonathan Cameron --- MAINTAINERS | 6 + drivers/iio/gyro/Kconfig | 10 + drivers/iio/gyro/Makefile | 1 + drivers/iio/gyro/adxrs290.c | 444 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 461 insertions(+) create mode 100644 drivers/iio/gyro/adxrs290.c (limited to 'drivers/iio') diff --git a/MAINTAINERS b/MAINTAINERS index 0edac88f4a84..e4389d830329 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1108,6 +1108,12 @@ L: linux-media@vger.kernel.org S: Maintained F: drivers/media/i2c/adv7842* +ANALOG DEVICES INC ADXRS290 DRIVER +M: Nishant Malpani +L: linux-iio@vger.kernel.org +S: Supported +F: drivers/iio/gyro/adxrs290.c + ANALOG DEVICES INC ASOC CODEC DRIVERS M: Lars-Peter Clausen M: Nuno Sá diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig index 6daeddf37f60..024a34139875 100644 --- a/drivers/iio/gyro/Kconfig +++ b/drivers/iio/gyro/Kconfig @@ -41,6 +41,16 @@ config ADIS16260 This driver can also be built as a module. If so, the module will be called adis16260. +config ADXRS290 + tristate "Analog Devices ADXRS290 Dual-Axis MEMS Gyroscope SPI driver" + depends on SPI + help + Say yes here to build support for Analog Devices ADXRS290 programmable + digital output gyroscope. + + This driver can also be built as a module. If so, the module will be + called adxrs290. + config ADXRS450 tristate "Analog Devices ADXRS450/3 Digital Output Gyroscope SPI driver" depends on SPI diff --git a/drivers/iio/gyro/Makefile b/drivers/iio/gyro/Makefile index 45cbd5dc644e..0319b397dc3f 100644 --- a/drivers/iio/gyro/Makefile +++ b/drivers/iio/gyro/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_ADIS16080) += adis16080.o obj-$(CONFIG_ADIS16130) += adis16130.o obj-$(CONFIG_ADIS16136) += adis16136.o obj-$(CONFIG_ADIS16260) += adis16260.o +obj-$(CONFIG_ADXRS290) += adxrs290.o obj-$(CONFIG_ADXRS450) += adxrs450.o obj-$(CONFIG_BMG160) += bmg160_core.o obj-$(CONFIG_BMG160_I2C) += bmg160_i2c.o diff --git a/drivers/iio/gyro/adxrs290.c b/drivers/iio/gyro/adxrs290.c new file mode 100644 index 000000000000..38bab4e3eee9 --- /dev/null +++ b/drivers/iio/gyro/adxrs290.c @@ -0,0 +1,444 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * ADXRS290 SPI Gyroscope Driver + * + * Copyright (C) 2020 Nishant Malpani + * Copyright (C) 2020 Analog Devices, Inc. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define ADXRS290_ADI_ID 0xAD +#define ADXRS290_MEMS_ID 0x1D +#define ADXRS290_DEV_ID 0x92 + +#define ADXRS290_REG_ADI_ID 0x00 +#define ADXRS290_REG_MEMS_ID 0x01 +#define ADXRS290_REG_DEV_ID 0x02 +#define ADXRS290_REG_REV_ID 0x03 +#define ADXRS290_REG_SN0 0x04 /* Serial Number Registers, 4 bytes */ +#define ADXRS290_REG_DATAX0 0x08 /* Roll Rate o/p Data Regs, 2 bytes */ +#define ADXRS290_REG_DATAY0 0x0A /* Pitch Rate o/p Data Regs, 2 bytes */ +#define ADXRS290_REG_TEMP0 0x0C +#define ADXRS290_REG_POWER_CTL 0x10 +#define ADXRS290_REG_FILTER 0x11 +#define ADXRS290_REG_DATA_RDY 0x12 + +#define ADXRS290_READ BIT(7) +#define ADXRS290_TSM BIT(0) +#define ADXRS290_MEASUREMENT BIT(1) +#define ADXRS290_SYNC GENMASK(1, 0) +#define ADXRS290_LPF_MASK GENMASK(2, 0) +#define ADXRS290_LPF(x) FIELD_PREP(ADXRS290_LPF_MASK, x) +#define ADXRS290_HPF_MASK GENMASK(7, 4) +#define ADXRS290_HPF(x) FIELD_PREP(ADXRS290_HPF_MASK, x) + +#define ADXRS290_READ_REG(reg) (ADXRS290_READ | (reg)) + +#define ADXRS290_MAX_TRANSITION_TIME_MS 100 + +enum adxrs290_mode { + ADXRS290_MODE_STANDBY, + ADXRS290_MODE_MEASUREMENT, +}; + +struct adxrs290_state { + struct spi_device *spi; + /* Serialize reads and their subsequent processing */ + struct mutex lock; + enum adxrs290_mode mode; + unsigned int lpf_3db_freq_idx; + unsigned int hpf_3db_freq_idx; +}; + +/* + * Available cut-off frequencies of the low pass filter in Hz. + * The integer part and fractional part are represented separately. + */ +static const int adxrs290_lpf_3db_freq_hz_table[][2] = { + [0] = {480, 0}, + [1] = {320, 0}, + [2] = {160, 0}, + [3] = {80, 0}, + [4] = {56, 600000}, + [5] = {40, 0}, + [6] = {28, 300000}, + [7] = {20, 0}, +}; + +/* + * Available cut-off frequencies of the high pass filter in Hz. + * The integer part and fractional part are represented separately. + */ +static const int adxrs290_hpf_3db_freq_hz_table[][2] = { + [0] = {0, 0}, + [1] = {0, 11000}, + [2] = {0, 22000}, + [3] = {0, 44000}, + [4] = {0, 87000}, + [5] = {0, 175000}, + [6] = {0, 350000}, + [7] = {0, 700000}, + [8] = {1, 400000}, + [9] = {2, 800000}, + [10] = {11, 300000}, +}; + +static int adxrs290_get_rate_data(struct iio_dev *indio_dev, const u8 cmd, int *val) +{ + struct adxrs290_state *st = iio_priv(indio_dev); + int ret = 0; + int temp; + + mutex_lock(&st->lock); + temp = spi_w8r16(st->spi, cmd); + if (temp < 0) { + ret = temp; + goto err_unlock; + } + + *val = temp; + +err_unlock: + mutex_unlock(&st->lock); + return ret; +} + +static int adxrs290_get_temp_data(struct iio_dev *indio_dev, int *val) +{ + const u8 cmd = ADXRS290_READ_REG(ADXRS290_REG_TEMP0); + struct adxrs290_state *st = iio_priv(indio_dev); + int ret = 0; + int temp; + + mutex_lock(&st->lock); + temp = spi_w8r16(st->spi, cmd); + if (temp < 0) { + ret = temp; + goto err_unlock; + } + + /* extract lower 12 bits temperature reading */ + *val = temp & 0x0FFF; + +err_unlock: + mutex_unlock(&st->lock); + return ret; +} + +static int adxrs290_get_3db_freq(struct iio_dev *indio_dev, u8 *val, u8 *val2) +{ + const u8 cmd = ADXRS290_READ_REG(ADXRS290_REG_FILTER); + struct adxrs290_state *st = iio_priv(indio_dev); + int ret = 0; + short temp; + + mutex_lock(&st->lock); + temp = spi_w8r8(st->spi, cmd); + if (temp < 0) { + ret = temp; + goto err_unlock; + } + + *val = FIELD_GET(ADXRS290_LPF_MASK, temp); + *val2 = FIELD_GET(ADXRS290_HPF_MASK, temp); + +err_unlock: + mutex_unlock(&st->lock); + return ret; +} + +static int adxrs290_spi_write_reg(struct spi_device *spi, const u8 reg, + const u8 val) +{ + u8 buf[2]; + + buf[0] = reg; + buf[1] = val; + + return spi_write_then_read(spi, buf, ARRAY_SIZE(buf), NULL, 0); +} + +static int adxrs290_find_match(const int (*freq_tbl)[2], const int n, + const int val, const int val2) +{ + int i; + + for (i = 0; i < n; i++) { + if (freq_tbl[i][0] == val && freq_tbl[i][1] == val2) + return i; + } + + return -EINVAL; +} + +static int adxrs290_set_filter_freq(struct iio_dev *indio_dev, + const unsigned int lpf_idx, + const unsigned int hpf_idx) +{ + struct adxrs290_state *st = iio_priv(indio_dev); + u8 val; + + val = ADXRS290_HPF(hpf_idx) | ADXRS290_LPF(lpf_idx); + + return adxrs290_spi_write_reg(st->spi, ADXRS290_REG_FILTER, val); +} + +static int adxrs290_initial_setup(struct iio_dev *indio_dev) +{ + struct adxrs290_state *st = iio_priv(indio_dev); + + st->mode = ADXRS290_MODE_MEASUREMENT; + + return adxrs290_spi_write_reg(st->spi, + ADXRS290_REG_POWER_CTL, + ADXRS290_MEASUREMENT | ADXRS290_TSM); +} + +static int adxrs290_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + struct adxrs290_state *st = iio_priv(indio_dev); + unsigned int t; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_ANGL_VEL: + ret = adxrs290_get_rate_data(indio_dev, + ADXRS290_READ_REG(chan->address), + val); + if (ret < 0) + return ret; + + return IIO_VAL_INT; + case IIO_TEMP: + ret = adxrs290_get_temp_data(indio_dev, val); + if (ret < 0) + return ret; + + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ANGL_VEL: + /* 1 LSB = 0.005 degrees/sec */ + *val = 0; + *val2 = 87266; + return IIO_VAL_INT_PLUS_NANO; + case IIO_TEMP: + /* 1 LSB = 0.1 degrees Celsius */ + *val = 100; + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + switch (chan->type) { + case IIO_ANGL_VEL: + t = st->lpf_3db_freq_idx; + *val = adxrs290_lpf_3db_freq_hz_table[t][0]; + *val2 = adxrs290_lpf_3db_freq_hz_table[t][1]; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: + switch (chan->type) { + case IIO_ANGL_VEL: + t = st->hpf_3db_freq_idx; + *val = adxrs290_hpf_3db_freq_hz_table[t][0]; + *val2 = adxrs290_hpf_3db_freq_hz_table[t][1]; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + } + + return -EINVAL; +} + +static int adxrs290_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct adxrs290_state *st = iio_priv(indio_dev); + int lpf_idx, hpf_idx; + + switch (mask) { + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + lpf_idx = adxrs290_find_match(adxrs290_lpf_3db_freq_hz_table, + ARRAY_SIZE(adxrs290_lpf_3db_freq_hz_table), + val, val2); + if (lpf_idx < 0) + return -EINVAL; + /* caching the updated state of the low-pass filter */ + st->lpf_3db_freq_idx = lpf_idx; + /* retrieving the current state of the high-pass filter */ + hpf_idx = st->hpf_3db_freq_idx; + return adxrs290_set_filter_freq(indio_dev, lpf_idx, hpf_idx); + case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: + hpf_idx = adxrs290_find_match(adxrs290_hpf_3db_freq_hz_table, + ARRAY_SIZE(adxrs290_hpf_3db_freq_hz_table), + val, val2); + if (hpf_idx < 0) + return -EINVAL; + /* caching the updated state of the high-pass filter */ + st->hpf_3db_freq_idx = hpf_idx; + /* retrieving the current state of the low-pass filter */ + lpf_idx = st->lpf_3db_freq_idx; + return adxrs290_set_filter_freq(indio_dev, lpf_idx, hpf_idx); + } + + return -EINVAL; +} + +static int adxrs290_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + *vals = (const int *)adxrs290_lpf_3db_freq_hz_table; + *type = IIO_VAL_INT_PLUS_MICRO; + /* Values are stored in a 2D matrix */ + *length = ARRAY_SIZE(adxrs290_lpf_3db_freq_hz_table) * 2; + + return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: + *vals = (const int *)adxrs290_hpf_3db_freq_hz_table; + *type = IIO_VAL_INT_PLUS_MICRO; + /* Values are stored in a 2D matrix */ + *length = ARRAY_SIZE(adxrs290_hpf_3db_freq_hz_table) * 2; + + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + +#define ADXRS290_ANGL_VEL_CHANNEL(reg, axis) { \ + .type = IIO_ANGL_VEL, \ + .address = reg, \ + .modified = 1, \ + .channel2 = IIO_MOD_##axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \ + BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \ + .info_mask_shared_by_type_available = \ + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \ + BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \ +} + +static const struct iio_chan_spec adxrs290_channels[] = { + ADXRS290_ANGL_VEL_CHANNEL(ADXRS290_REG_DATAX0, X), + ADXRS290_ANGL_VEL_CHANNEL(ADXRS290_REG_DATAY0, Y), + { + .type = IIO_TEMP, + .address = ADXRS290_REG_TEMP0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + }, +}; + +static const struct iio_info adxrs290_info = { + .read_raw = &adxrs290_read_raw, + .write_raw = &adxrs290_write_raw, + .read_avail = &adxrs290_read_avail, +}; + +static int adxrs290_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct adxrs290_state *st; + u8 val, val2; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st = iio_priv(indio_dev); + st->spi = spi; + + indio_dev->name = "adxrs290"; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = adxrs290_channels; + indio_dev->num_channels = ARRAY_SIZE(adxrs290_channels); + indio_dev->info = &adxrs290_info; + + val = spi_w8r8(spi, ADXRS290_READ_REG(ADXRS290_REG_ADI_ID)); + if (val != ADXRS290_ADI_ID) { + dev_err(&spi->dev, "Wrong ADI ID 0x%02x\n", val); + return -ENODEV; + } + + val = spi_w8r8(spi, ADXRS290_READ_REG(ADXRS290_REG_MEMS_ID)); + if (val != ADXRS290_MEMS_ID) { + dev_err(&spi->dev, "Wrong MEMS ID 0x%02x\n", val); + return -ENODEV; + } + + val = spi_w8r8(spi, ADXRS290_READ_REG(ADXRS290_REG_DEV_ID)); + if (val != ADXRS290_DEV_ID) { + dev_err(&spi->dev, "Wrong DEV ID 0x%02x\n", val); + return -ENODEV; + } + + /* default mode the gyroscope starts in */ + st->mode = ADXRS290_MODE_STANDBY; + + /* switch to measurement mode and switch on the temperature sensor */ + ret = adxrs290_initial_setup(indio_dev); + if (ret < 0) + return ret; + + /* max transition time to measurement mode */ + msleep(ADXRS290_MAX_TRANSITION_TIME_MS); + + ret = adxrs290_get_3db_freq(indio_dev, &val, &val2); + if (ret < 0) + return ret; + + st->lpf_3db_freq_idx = val; + st->hpf_3db_freq_idx = val2; + + return devm_iio_device_register(&spi->dev, indio_dev); +} + +static const struct of_device_id adxrs290_of_match[] = { + { .compatible = "adi,adxrs290" }, + { } +}; +MODULE_DEVICE_TABLE(of, adxrs290_of_match); + +static struct spi_driver adxrs290_driver = { + .driver = { + .name = "adxrs290", + .of_match_table = adxrs290_of_match, + }, + .probe = adxrs290_probe, +}; +module_spi_driver(adxrs290_driver); + +MODULE_AUTHOR("Nishant Malpani "); +MODULE_DESCRIPTION("Analog Devices ADXRS290 Gyroscope SPI driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 403e5586b52e466893ce3a7b7f3a3ecdc4c82d3e Mon Sep 17 00:00:00 2001 From: Christian Eggers Date: Wed, 5 Aug 2020 07:57:44 +0200 Subject: iio: light: as73211: New driver Support for AMS AS73211 JENCOLOR(R) Digital XYZ Sensor. This driver has no built-in trigger. In order for making triggered measurements, an external (software) trigger driver like iio-trig-hrtimer or iio-trig-sysfs is required. The sensor supports single and continuous measurement modes. The latter is not used by design as this would require tight timing synchronization between hardware and driver without much benefit. Datasheet: https://ams.com/documents/20143/36005/AS73211_DS000556_3-01.pdf Signed-off-by: Christian Eggers Reviewed-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- MAINTAINERS | 7 + drivers/iio/light/Kconfig | 15 + drivers/iio/light/Makefile | 1 + drivers/iio/light/as73211.c | 801 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 824 insertions(+) create mode 100644 drivers/iio/light/as73211.c (limited to 'drivers/iio') diff --git a/MAINTAINERS b/MAINTAINERS index 39bf100972e9..2e9d0ccd66a1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -943,6 +943,13 @@ S: Supported F: arch/arm64/boot/dts/amd/amd-seattle-xgbe*.dtsi F: drivers/net/ethernet/amd/xgbe/ +AMS AS73211 DRIVER +M: Christian Eggers +L: linux-iio@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/iio/light/ams,as73211.yaml +F: drivers/iio/light/as73211.c + ANALOG DEVICES INC AD5686 DRIVER M: Michael Hennerich L: linux-pm@vger.kernel.org diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 182bd18c4bb2..cade6dc0305b 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -86,6 +86,21 @@ config APDS9960 To compile this driver as a module, choose M here: the module will be called apds9960 +config AS73211 + tristate "AMS AS73211 XYZ color sensor" + depends on I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + If you say yes here you get support for the AMS AS73211 + JENCOLOR(R) Digital XYZ Sensor. + + For triggered measurements, you will need an additional trigger driver + like IIO_HRTIMER_TRIGGER or IIO_SYSFS_TRIGGER. + + This driver can also be built as a module. If so, the module + will be called as73211. + config BH1750 tristate "ROHM BH1750 ambient light sensor" depends on I2C diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index d1c8aa30b9a8..ea376deaca54 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_AL3010) += al3010.o obj-$(CONFIG_AL3320A) += al3320a.o obj-$(CONFIG_APDS9300) += apds9300.o obj-$(CONFIG_APDS9960) += apds9960.o +obj-$(CONFIG_AS73211) += as73211.o obj-$(CONFIG_BH1750) += bh1750.o obj-$(CONFIG_BH1780) += bh1780.o obj-$(CONFIG_CM32181) += cm32181.o diff --git a/drivers/iio/light/as73211.c b/drivers/iio/light/as73211.c new file mode 100644 index 000000000000..b1178dfc1f65 --- /dev/null +++ b/drivers/iio/light/as73211.c @@ -0,0 +1,801 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Support for AMS AS73211 JENCOLOR(R) Digital XYZ Sensor + * + * Author: Christian Eggers + * + * Copyright (c) 2020 ARRI Lighting + * + * Color light sensor with 16-bit channels for x, y, z and temperature); + * 7-bit I2C slave address 0x74 .. 0x77. + * + * Datasheet: https://ams.com/documents/20143/36005/AS73211_DS000556_3-01.pdf + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HZ_PER_KHZ 1000 + +#define AS73211_DRV_NAME "as73211" + +/* AS73211 configuration registers */ +#define AS73211_REG_OSR 0x0 +#define AS73211_REG_AGEN 0x2 +#define AS73211_REG_CREG1 0x6 +#define AS73211_REG_CREG2 0x7 +#define AS73211_REG_CREG3 0x8 + +/* AS73211 output register bank */ +#define AS73211_OUT_OSR_STATUS 0 +#define AS73211_OUT_TEMP 1 +#define AS73211_OUT_MRES1 2 +#define AS73211_OUT_MRES2 3 +#define AS73211_OUT_MRES3 4 + +#define AS73211_OSR_SS BIT(7) +#define AS73211_OSR_PD BIT(6) +#define AS73211_OSR_SW_RES BIT(3) +#define AS73211_OSR_DOS_MASK GENMASK(2, 0) +#define AS73211_OSR_DOS_CONFIG FIELD_PREP(AS73211_OSR_DOS_MASK, 0x2) +#define AS73211_OSR_DOS_MEASURE FIELD_PREP(AS73211_OSR_DOS_MASK, 0x3) + +#define AS73211_AGEN_DEVID_MASK GENMASK(7, 4) +#define AS73211_AGEN_DEVID(x) FIELD_PREP(AS73211_AGEN_DEVID_MASK, (x)) +#define AS73211_AGEN_MUT_MASK GENMASK(3, 0) +#define AS73211_AGEN_MUT(x) FIELD_PREP(AS73211_AGEN_MUT_MASK, (x)) + +#define AS73211_CREG1_GAIN_MASK GENMASK(7, 4) +#define AS73211_CREG1_GAIN_1 11 +#define AS73211_CREG1_TIME_MASK GENMASK(3, 0) + +#define AS73211_CREG3_CCLK_MASK GENMASK(1, 0) + +#define AS73211_OSR_STATUS_OUTCONVOF BIT(15) +#define AS73211_OSR_STATUS_MRESOF BIT(14) +#define AS73211_OSR_STATUS_ADCOF BIT(13) +#define AS73211_OSR_STATUS_LDATA BIT(12) +#define AS73211_OSR_STATUS_NDATA BIT(11) +#define AS73211_OSR_STATUS_NOTREADY BIT(10) + +#define AS73211_SAMPLE_FREQ_BASE 1024000 + +#define AS73211_SAMPLE_TIME_NUM 15 +#define AS73211_SAMPLE_TIME_MAX_MS BIT(AS73211_SAMPLE_TIME_NUM - 1) + +/* Available sample frequencies are 1.024MHz multiplied by powers of two. */ +static const int as73211_samp_freq_avail[] = { + AS73211_SAMPLE_FREQ_BASE * 1, + AS73211_SAMPLE_FREQ_BASE * 2, + AS73211_SAMPLE_FREQ_BASE * 4, + AS73211_SAMPLE_FREQ_BASE * 8, +}; + +static const int as73211_hardwaregain_avail[] = { + 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, +}; + +/** + * struct as73211_data - Instance data for one AS73211 + * @client: I2C client. + * @osr: Cached Operational State Register. + * @creg1: Cached Configuration Register 1. + * @creg2: Cached Configuration Register 2. + * @creg3: Cached Configuration Register 3. + * @mutex: Keeps cached registers in sync with the device. + * @completion: Completion to wait for interrupt. + * @int_time_avail: Available integration times (depend on sampling frequency). + */ +struct as73211_data { + struct i2c_client *client; + u8 osr; + u8 creg1; + u8 creg2; + u8 creg3; + struct mutex mutex; + struct completion completion; + int int_time_avail[AS73211_SAMPLE_TIME_NUM * 2]; +}; + +#define AS73211_COLOR_CHANNEL(_color, _si, _addr) { \ + .type = IIO_INTENSITY, \ + .modified = 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_type = \ + BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ + BIT(IIO_CHAN_INFO_HARDWAREGAIN) | \ + BIT(IIO_CHAN_INFO_INT_TIME), \ + .info_mask_shared_by_type_available = \ + BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ + BIT(IIO_CHAN_INFO_HARDWAREGAIN) | \ + BIT(IIO_CHAN_INFO_INT_TIME), \ + .channel2 = IIO_MOD_##_color, \ + .address = _addr, \ + .scan_index = _si, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_LE, \ + }, \ +} + +#define AS73211_OFFSET_TEMP_INT (-66) +#define AS73211_OFFSET_TEMP_MICRO 900000 +#define AS73211_SCALE_TEMP_INT 0 +#define AS73211_SCALE_TEMP_MICRO 50000 + +#define AS73211_SCALE_X 277071108 /* nW/m^2 */ +#define AS73211_SCALE_Y 298384270 /* nW/m^2 */ +#define AS73211_SCALE_Z 160241927 /* nW/m^2 */ + +/* Channel order MUST match devices result register order */ +#define AS73211_SCAN_INDEX_TEMP 0 +#define AS73211_SCAN_INDEX_X 1 +#define AS73211_SCAN_INDEX_Y 2 +#define AS73211_SCAN_INDEX_Z 3 +#define AS73211_SCAN_INDEX_TS 4 + +#define AS73211_SCAN_MASK_COLOR ( \ + BIT(AS73211_SCAN_INDEX_X) | \ + BIT(AS73211_SCAN_INDEX_Y) | \ + BIT(AS73211_SCAN_INDEX_Z)) + +#define AS73211_SCAN_MASK_ALL ( \ + BIT(AS73211_SCAN_INDEX_TEMP) | \ + AS73211_SCAN_MASK_COLOR) + +static const struct iio_chan_spec as73211_channels[] = { + { + .type = IIO_TEMP, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_OFFSET) | + BIT(IIO_CHAN_INFO_SCALE), + .address = AS73211_OUT_TEMP, + .scan_index = AS73211_SCAN_INDEX_TEMP, + .scan_type = { + .sign = 'u', + .realbits = 16, + .storagebits = 16, + .endianness = IIO_LE, + } + }, + AS73211_COLOR_CHANNEL(X, AS73211_SCAN_INDEX_X, AS73211_OUT_MRES1), + AS73211_COLOR_CHANNEL(Y, AS73211_SCAN_INDEX_Y, AS73211_OUT_MRES2), + AS73211_COLOR_CHANNEL(Z, AS73211_SCAN_INDEX_Z, AS73211_OUT_MRES3), + IIO_CHAN_SOFT_TIMESTAMP(AS73211_SCAN_INDEX_TS), +}; + +static unsigned int as73211_integration_time_1024cyc(struct as73211_data *data) +{ + /* + * Return integration time in units of 1024 clock cycles. Integration time + * in CREG1 is in powers of 2 (x 1024 cycles). + */ + return BIT(FIELD_GET(AS73211_CREG1_TIME_MASK, data->creg1)); +} + +static unsigned int as73211_integration_time_us(struct as73211_data *data, + unsigned int integration_time_1024cyc) +{ + /* + * f_samp is configured in CREG3 in powers of 2 (x 1.024 MHz) + * t_cycl is configured in CREG1 in powers of 2 (x 1024 cycles) + * t_int_us = 1 / (f_samp) * t_cycl * US_PER_SEC + * = 1 / (2^CREG3_CCLK * 1,024,000) * 2^CREG1_CYCLES * 1,024 * US_PER_SEC + * = 2^(-CREG3_CCLK) * 2^CREG1_CYCLES * 1,000 + * In order to get rid of negative exponents, we extend the "fraction" + * by 2^3 (CREG3_CCLK,max = 3) + * t_int_us = 2^(3-CREG3_CCLK) * 2^CREG1_CYCLES * 125 + */ + return BIT(3 - FIELD_GET(AS73211_CREG3_CCLK_MASK, data->creg3)) * + integration_time_1024cyc * 125; +} + +static void as73211_integration_time_calc_avail(struct as73211_data *data) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(data->int_time_avail) / 2; i++) { + unsigned int time_us = as73211_integration_time_us(data, BIT(i)); + + data->int_time_avail[i * 2 + 0] = time_us / USEC_PER_SEC; + data->int_time_avail[i * 2 + 1] = time_us % USEC_PER_SEC; + } +} + +static unsigned int as73211_gain(struct as73211_data *data) +{ + /* gain can be calculated from CREG1 as 2^(11 - CREG1_GAIN) */ + return BIT(AS73211_CREG1_GAIN_1 - FIELD_GET(AS73211_CREG1_GAIN_MASK, data->creg1)); +} + +/* must be called with as73211_data::mutex held. */ +static int as73211_req_data(struct as73211_data *data) +{ + unsigned int time_us = as73211_integration_time_us(data, + as73211_integration_time_1024cyc(data)); + struct device *dev = &data->client->dev; + union i2c_smbus_data smbus_data; + u16 osr_status; + int ret; + + if (data->client->irq) + reinit_completion(&data->completion); + + /* + * During measurement, there should be no traffic on the i2c bus as the + * electrical noise would disturb the measurement process. + */ + i2c_lock_bus(data->client->adapter, I2C_LOCK_SEGMENT); + + data->osr &= ~AS73211_OSR_DOS_MASK; + data->osr |= AS73211_OSR_DOS_MEASURE | AS73211_OSR_SS; + + smbus_data.byte = data->osr; + ret = __i2c_smbus_xfer(data->client->adapter, data->client->addr, + data->client->flags, I2C_SMBUS_WRITE, + AS73211_REG_OSR, I2C_SMBUS_BYTE_DATA, &smbus_data); + if (ret < 0) { + i2c_unlock_bus(data->client->adapter, I2C_LOCK_SEGMENT); + return ret; + } + + /* + * Reset AS73211_OSR_SS (is self clearing) in order to avoid unintentional + * triggering of further measurements later. + */ + data->osr &= ~AS73211_OSR_SS; + + /* + * Add some extra margin for the timeout. sensor timing is not as precise + * as our one ... + */ + time_us += time_us / 8; + if (data->client->irq) { + ret = wait_for_completion_timeout(&data->completion, usecs_to_jiffies(time_us)); + if (!ret) { + dev_err(dev, "timeout waiting for READY IRQ\n"); + i2c_unlock_bus(data->client->adapter, I2C_LOCK_SEGMENT); + return -ETIMEDOUT; + } + } else { + /* Wait integration time */ + usleep_range(time_us, 2 * time_us); + } + + i2c_unlock_bus(data->client->adapter, I2C_LOCK_SEGMENT); + + ret = i2c_smbus_read_word_data(data->client, AS73211_OUT_OSR_STATUS); + if (ret < 0) + return ret; + + osr_status = ret; + if (osr_status != (AS73211_OSR_DOS_MEASURE | AS73211_OSR_STATUS_NDATA)) { + if (osr_status & AS73211_OSR_SS) { + dev_err(dev, "%s() Measurement has not stopped\n", __func__); + return -ETIME; + } + if (osr_status & AS73211_OSR_STATUS_NOTREADY) { + dev_err(dev, "%s() Data is not ready\n", __func__); + return -ENODATA; + } + if (!(osr_status & AS73211_OSR_STATUS_NDATA)) { + dev_err(dev, "%s() No new data available\n", __func__); + return -ENODATA; + } + if (osr_status & AS73211_OSR_STATUS_LDATA) { + dev_err(dev, "%s() Result buffer overrun\n", __func__); + return -ENOBUFS; + } + if (osr_status & AS73211_OSR_STATUS_ADCOF) { + dev_err(dev, "%s() ADC overflow\n", __func__); + return -EOVERFLOW; + } + if (osr_status & AS73211_OSR_STATUS_MRESOF) { + dev_err(dev, "%s() Measurement result overflow\n", __func__); + return -EOVERFLOW; + } + if (osr_status & AS73211_OSR_STATUS_OUTCONVOF) { + dev_err(dev, "%s() Timer overflow\n", __func__); + return -EOVERFLOW; + } + dev_err(dev, "%s() Unexpected status value\n", __func__); + return -EIO; + } + + return 0; +} + +static int as73211_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct as73211_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: { + int ret; + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret < 0) + return ret; + + ret = as73211_req_data(data); + if (ret < 0) { + iio_device_release_direct_mode(indio_dev); + return ret; + } + + ret = i2c_smbus_read_word_data(data->client, chan->address); + iio_device_release_direct_mode(indio_dev); + if (ret < 0) + return ret; + + *val = ret; + return IIO_VAL_INT; + } + case IIO_CHAN_INFO_OFFSET: + *val = AS73211_OFFSET_TEMP_INT; + *val2 = AS73211_OFFSET_TEMP_MICRO; + return IIO_VAL_INT_PLUS_MICRO; + + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_TEMP: + *val = AS73211_SCALE_TEMP_INT; + *val2 = AS73211_SCALE_TEMP_MICRO; + return IIO_VAL_INT_PLUS_MICRO; + + case IIO_INTENSITY: { + unsigned int scale; + + switch (chan->channel2) { + case IIO_MOD_X: + scale = AS73211_SCALE_X; + break; + case IIO_MOD_Y: + scale = AS73211_SCALE_Y; + break; + case IIO_MOD_Z: + scale = AS73211_SCALE_Z; + break; + default: + return -EINVAL; + } + scale /= as73211_gain(data); + scale /= as73211_integration_time_1024cyc(data); + *val = scale; + return IIO_VAL_INT; + + default: + return -EINVAL; + }} + + case IIO_CHAN_INFO_SAMP_FREQ: + /* f_samp is configured in CREG3 in powers of 2 (x 1.024 MHz) */ + *val = BIT(FIELD_GET(AS73211_CREG3_CCLK_MASK, data->creg3)) * + AS73211_SAMPLE_FREQ_BASE; + return IIO_VAL_INT; + + case IIO_CHAN_INFO_HARDWAREGAIN: + *val = as73211_gain(data); + return IIO_VAL_INT; + + case IIO_CHAN_INFO_INT_TIME: { + unsigned int time_us; + + mutex_lock(&data->mutex); + time_us = as73211_integration_time_us(data, as73211_integration_time_1024cyc(data)); + mutex_unlock(&data->mutex); + *val = time_us / USEC_PER_SEC; + *val2 = time_us % USEC_PER_SEC; + return IIO_VAL_INT_PLUS_MICRO; + + default: + return -EINVAL; + }} +} + +static int as73211_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, long mask) +{ + struct as73211_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + *length = ARRAY_SIZE(as73211_samp_freq_avail); + *vals = as73211_samp_freq_avail; + *type = IIO_VAL_INT; + return IIO_AVAIL_LIST; + + case IIO_CHAN_INFO_HARDWAREGAIN: + *length = ARRAY_SIZE(as73211_hardwaregain_avail); + *vals = as73211_hardwaregain_avail; + *type = IIO_VAL_INT; + return IIO_AVAIL_LIST; + + case IIO_CHAN_INFO_INT_TIME: + *length = ARRAY_SIZE(data->int_time_avail); + *vals = data->int_time_avail; + *type = IIO_VAL_INT_PLUS_MICRO; + return IIO_AVAIL_LIST; + + default: + return -EINVAL; + } +} + +static int _as73211_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan __always_unused, + int val, int val2, long mask) +{ + struct as73211_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: { + int reg_bits, freq_kHz = val / HZ_PER_KHZ; /* 1024, 2048, ... */ + + /* val must be 1024 * 2^x */ + if (val < 0 || (freq_kHz * HZ_PER_KHZ) != val || + !is_power_of_2(freq_kHz) || val2) + return -EINVAL; + + /* f_samp is configured in CREG3 in powers of 2 (x 1.024 MHz (=2^10)) */ + reg_bits = ilog2(freq_kHz) - 10; + if (!FIELD_FIT(AS73211_CREG3_CCLK_MASK, reg_bits)) + return -EINVAL; + + data->creg3 &= ~AS73211_CREG3_CCLK_MASK; + data->creg3 |= FIELD_PREP(AS73211_CREG3_CCLK_MASK, reg_bits); + as73211_integration_time_calc_avail(data); + + ret = i2c_smbus_write_byte_data(data->client, AS73211_REG_CREG3, data->creg3); + if (ret < 0) + return ret; + + return 0; + } + case IIO_CHAN_INFO_HARDWAREGAIN: { + unsigned int reg_bits; + + if (val < 0 || !is_power_of_2(val) || val2) + return -EINVAL; + + /* gain can be calculated from CREG1 as 2^(11 - CREG1_GAIN) */ + reg_bits = AS73211_CREG1_GAIN_1 - ilog2(val); + if (!FIELD_FIT(AS73211_CREG1_GAIN_MASK, reg_bits)) + return -EINVAL; + + data->creg1 &= ~AS73211_CREG1_GAIN_MASK; + data->creg1 |= FIELD_PREP(AS73211_CREG1_GAIN_MASK, reg_bits); + + ret = i2c_smbus_write_byte_data(data->client, AS73211_REG_CREG1, data->creg1); + if (ret < 0) + return ret; + + return 0; + } + case IIO_CHAN_INFO_INT_TIME: { + int val_us = val * USEC_PER_SEC + val2; + int time_ms; + int reg_bits; + + /* f_samp is configured in CREG3 in powers of 2 (x 1.024 MHz) */ + int f_samp_1_024mhz = BIT(FIELD_GET(AS73211_CREG3_CCLK_MASK, data->creg3)); + + /* + * time_ms = time_us * US_PER_MS * f_samp_1_024mhz / MHZ_PER_HZ + * = time_us * f_samp_1_024mhz / 1000 + */ + time_ms = (val_us * f_samp_1_024mhz) / 1000; /* 1 ms, 2 ms, ... (power of two) */ + if (time_ms < 0 || !is_power_of_2(time_ms) || time_ms > AS73211_SAMPLE_TIME_MAX_MS) + return -EINVAL; + + reg_bits = ilog2(time_ms); + if (!FIELD_FIT(AS73211_CREG1_TIME_MASK, reg_bits)) + return -EINVAL; /* not possible due to previous tests */ + + data->creg1 &= ~AS73211_CREG1_TIME_MASK; + data->creg1 |= FIELD_PREP(AS73211_CREG1_TIME_MASK, reg_bits); + + ret = i2c_smbus_write_byte_data(data->client, AS73211_REG_CREG1, data->creg1); + if (ret < 0) + return ret; + + return 0; + + default: + return -EINVAL; + }} +} + +static int as73211_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + 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; + + ret = i2c_smbus_write_byte_data(data->client, AS73211_REG_OSR, data->osr); + if (ret < 0) + goto error_release; + } + + ret = _as73211_write_raw(indio_dev, chan, val, val2, mask); + +error_release: + iio_device_release_direct_mode(indio_dev); +error_unlock: + mutex_unlock(&data->mutex); + return ret; +} + +static irqreturn_t as73211_ready_handler(int irq __always_unused, void *priv) +{ + struct as73211_data *data = iio_priv(priv); + + complete(&data->completion); + + return IRQ_HANDLED; +} + +static irqreturn_t as73211_trigger_handler(int irq __always_unused, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct as73211_data *data = iio_priv(indio_dev); + struct { + __le16 chan[4]; + s64 ts __aligned(8); + } scan; + int data_result, ret; + + mutex_lock(&data->mutex); + + data_result = as73211_req_data(data); + if (data_result < 0 && data_result != -EOVERFLOW) + goto done; /* don't push any data for errors other than EOVERFLOW */ + + if (*indio_dev->active_scan_mask == AS73211_SCAN_MASK_ALL) { + /* Optimization for reading all (color + temperature) channels */ + u8 addr = as73211_channels[0].address; + struct i2c_msg msgs[] = { + { + .addr = data->client->addr, + .flags = 0, + .len = 1, + .buf = &addr, + }, + { + .addr = data->client->addr, + .flags = I2C_M_RD, + .len = sizeof(scan.chan), + .buf = (u8 *)&scan.chan, + }, + }; + + ret = i2c_transfer(data->client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret < 0) + goto done; + } else { + /* Optimization for reading only color channels */ + + /* AS73211 starts reading at address 2 */ + ret = i2c_master_recv(data->client, + (char *)&scan.chan[1], 3 * sizeof(scan.chan[1])); + if (ret < 0) + goto done; + } + + if (data_result) { + /* + * Saturate all channels (in case of overflows). Temperature channel + * is not affected by overflows. + */ + scan.chan[1] = cpu_to_le16(U16_MAX); + scan.chan[2] = cpu_to_le16(U16_MAX); + scan.chan[3] = cpu_to_le16(U16_MAX); + } + + iio_push_to_buffers_with_timestamp(indio_dev, &scan, iio_get_time_ns(indio_dev)); + +done: + mutex_unlock(&data->mutex); + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static const struct iio_info as73211_info = { + .read_raw = as73211_read_raw, + .read_avail = as73211_read_avail, + .write_raw = as73211_write_raw, +}; + +static int as73211_power(struct iio_dev *indio_dev, bool state) +{ + struct as73211_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->mutex); + + if (state) + data->osr &= ~AS73211_OSR_PD; + else + data->osr |= AS73211_OSR_PD; + + ret = i2c_smbus_write_byte_data(data->client, AS73211_REG_OSR, data->osr); + + mutex_unlock(&data->mutex); + + if (ret < 0) + return ret; + + return 0; +} + +static void as73211_power_disable(void *data) +{ + struct iio_dev *indio_dev = data; + + as73211_power(indio_dev, false); +} + +static int as73211_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct as73211_data *data; + struct iio_dev *indio_dev; + int ret; + + 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; + + mutex_init(&data->mutex); + init_completion(&data->completion); + + indio_dev->info = &as73211_info; + indio_dev->name = AS73211_DRV_NAME; + indio_dev->channels = as73211_channels; + indio_dev->num_channels = ARRAY_SIZE(as73211_channels); + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = i2c_smbus_read_byte_data(data->client, AS73211_REG_OSR); + if (ret < 0) + return ret; + data->osr = ret; + + /* reset device */ + data->osr |= AS73211_OSR_SW_RES; + ret = i2c_smbus_write_byte_data(data->client, AS73211_REG_OSR, data->osr); + if (ret < 0) + return ret; + + ret = i2c_smbus_read_byte_data(data->client, AS73211_REG_OSR); + if (ret < 0) + return ret; + data->osr = ret; + + /* + * Reading AGEN is only possible after reset (AGEN is not available if + * device is in measurement mode). + */ + ret = i2c_smbus_read_byte_data(data->client, AS73211_REG_AGEN); + if (ret < 0) + return ret; + + /* At the time of writing this driver, only DEVID 2 and MUT 1 are known. */ + if ((ret & AS73211_AGEN_DEVID_MASK) != AS73211_AGEN_DEVID(2) || + (ret & AS73211_AGEN_MUT_MASK) != AS73211_AGEN_MUT(1)) + return -ENODEV; + + ret = i2c_smbus_read_byte_data(data->client, AS73211_REG_CREG1); + if (ret < 0) + return ret; + data->creg1 = ret; + + ret = i2c_smbus_read_byte_data(data->client, AS73211_REG_CREG2); + if (ret < 0) + return ret; + data->creg2 = ret; + + ret = i2c_smbus_read_byte_data(data->client, AS73211_REG_CREG3); + if (ret < 0) + return ret; + data->creg3 = ret; + as73211_integration_time_calc_avail(data); + + ret = as73211_power(indio_dev, true); + if (ret < 0) + return ret; + + ret = devm_add_action_or_reset(dev, as73211_power_disable, indio_dev); + if (ret) + return ret; + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, as73211_trigger_handler, NULL); + if (ret) + return ret; + + if (client->irq) { + ret = devm_request_threaded_irq(&client->dev, client->irq, + NULL, + as73211_ready_handler, + IRQF_ONESHOT, + client->name, indio_dev); + if (ret) + return ret; + } + + return devm_iio_device_register(dev, indio_dev); +} + +static int __maybe_unused as73211_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + + return as73211_power(indio_dev, false); +} + +static int __maybe_unused as73211_resume(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + + return as73211_power(indio_dev, true); +} + +static SIMPLE_DEV_PM_OPS(as73211_pm_ops, as73211_suspend, as73211_resume); + +static const struct of_device_id as73211_of_match[] = { + { .compatible = "ams,as73211" }, + { } +}; +MODULE_DEVICE_TABLE(of, as73211_of_match); + +static const struct i2c_device_id as73211_id[] = { + { "as73211", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as73211_id); + +static struct i2c_driver as73211_driver = { + .driver = { + .name = AS73211_DRV_NAME, + .of_match_table = as73211_of_match, + .pm = &as73211_pm_ops, + }, + .probe_new = as73211_probe, + .id_table = as73211_id, +}; +module_i2c_driver(as73211_driver); + +MODULE_AUTHOR("Christian Eggers "); +MODULE_DESCRIPTION("AS73211 XYZ True Color Sensor driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From d9f753f3e9edc0b4c0acdbe2708746242f7c7a79 Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:02 -0600 Subject: iio: sx9310: Update macros declarations Follows spec sheet for macro declarations. Signed-off-by: Daniel Campello Reviewed-by: Stephen Boyd Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9310.c | 146 +++++++++++++++++++---------------------- 1 file changed, 68 insertions(+), 78 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c index dc2e11b43431..c02a9e8b7a7a 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -33,45 +34,44 @@ #define SX9310_REG_IRQ_SRC 0x00 #define SX9310_REG_STAT0 0x01 #define SX9310_REG_STAT1 0x02 +#define SX9310_REG_STAT1_COMPSTAT_MASK GENMASK(3, 0) #define SX9310_REG_IRQ_MSK 0x03 #define SX9310_CONVDONE_IRQ BIT(3) #define SX9310_FAR_IRQ BIT(5) #define SX9310_CLOSE_IRQ BIT(6) -#define SX9310_EVENT_IRQ (SX9310_FAR_IRQ | \ - SX9310_CLOSE_IRQ) #define SX9310_REG_IRQ_FUNC 0x04 #define SX9310_REG_PROX_CTRL0 0x10 -#define SX9310_REG_PROX_CTRL0_PROXSTAT2 0x10 -#define SX9310_REG_PROX_CTRL0_EN_MASK 0x0F +#define SX9310_REG_PROX_CTRL0_SENSOREN_MASK GENMASK(3, 0) +#define SX9310_REG_PROX_CTRL0_SCANPERIOD_MASK GENMASK(7, 4) +#define SX9310_REG_PROX_CTRL0_SCANPERIOD_15MS 0x01 #define SX9310_REG_PROX_CTRL1 0x11 #define SX9310_REG_PROX_CTRL2 0x12 -#define SX9310_REG_PROX_CTRL2_COMBMODE_ALL 0x80 -#define SX9310_REG_PROX_CTRL2_SHIELDEN_DYNAMIC 0x04 +#define SX9310_REG_PROX_CTRL2_COMBMODE_CS1_CS2 (0x02 << 6) +#define SX9310_REG_PROX_CTRL2_SHIELDEN_DYNAMIC (0x01 << 2) #define SX9310_REG_PROX_CTRL3 0x13 -#define SX9310_REG_PROX_CTRL3_GAIN0_X8 0x0c +#define SX9310_REG_PROX_CTRL3_GAIN0_X8 (0x03 << 2) #define SX9310_REG_PROX_CTRL3_GAIN12_X4 0x02 #define SX9310_REG_PROX_CTRL4 0x14 #define SX9310_REG_PROX_CTRL4_RESOLUTION_FINEST 0x07 #define SX9310_REG_PROX_CTRL5 0x15 -#define SX9310_REG_PROX_CTRL5_RANGE_SMALL 0xc0 -#define SX9310_REG_PROX_CTRL5_STARTUPSENS_CS1 0x04 +#define SX9310_REG_PROX_CTRL5_RANGE_SMALL (0x03 << 6) +#define SX9310_REG_PROX_CTRL5_STARTUPSENS_CS1 (0x01 << 2) #define SX9310_REG_PROX_CTRL5_RAWFILT_1P25 0x02 #define SX9310_REG_PROX_CTRL6 0x16 -#define SX9310_REG_PROX_CTRL6_COMP_COMMON 0x20 +#define SX9310_REG_PROX_CTRL6_AVGTHRESH_DEFAULT 0x20 #define SX9310_REG_PROX_CTRL7 0x17 -#define SX9310_REG_PROX_CTRL7_AVGNEGFILT_2 0x08 +#define SX9310_REG_PROX_CTRL7_AVGNEGFILT_2 (0x01 << 3) #define SX9310_REG_PROX_CTRL7_AVGPOSFILT_512 0x05 #define SX9310_REG_PROX_CTRL8 0x18 #define SX9310_REG_PROX_CTRL9 0x19 -#define SX9310_REG_PROX_CTRL8_9_PTHRESH12_28 0x40 -#define SX9310_REG_PROX_CTRL8_9_PTHRESH_96 0x88 +#define SX9310_REG_PROX_CTRL8_9_PTHRESH_28 (0x08 << 3) +#define SX9310_REG_PROX_CTRL8_9_PTHRESH_96 (0x11 << 3) #define SX9310_REG_PROX_CTRL8_9_BODYTHRESH_900 0x03 #define SX9310_REG_PROX_CTRL8_9_BODYTHRESH_1500 0x05 #define SX9310_REG_PROX_CTRL10 0x1a -#define SX9310_REG_PROX_CTRL10_HYST_6PCT 0x10 -#define SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_8 0x12 -#define SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_8 0x03 +#define SX9310_REG_PROX_CTRL10_HYST_6PCT (0x01 << 4) +#define SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_2 0x01 #define SX9310_REG_PROX_CTRL11 0x1b #define SX9310_REG_PROX_CTRL12 0x1c #define SX9310_REG_PROX_CTRL13 0x1d @@ -82,8 +82,8 @@ #define SX9310_REG_PROX_CTRL18 0x22 #define SX9310_REG_PROX_CTRL19 0x23 #define SX9310_REG_SAR_CTRL0 0x2a -#define SX9310_REG_SAR_CTRL0_SARDEB_4_SAMPLES 0x40 -#define SX9310_REG_SAR_CTRL0_SARHYST_8 0x10 +#define SX9310_REG_SAR_CTRL0_SARDEB_4_SAMPLES (0x02 << 5) +#define SX9310_REG_SAR_CTRL0_SARHYST_8 (0x02 << 3) #define SX9310_REG_SAR_CTRL1 0x2b /* Each increment of the slope register is 0.0078125. */ #define SX9310_REG_SAR_CTRL1_SLOPE(_hnslope) (_hnslope / 78125) @@ -107,7 +107,7 @@ #define SX9310_REG_SAR_MSB 0x39 #define SX9310_REG_SAR_LSB 0x3a -#define SX9310_REG_I2CADDR 0x40 +#define SX9310_REG_I2C_ADDR 0x40 #define SX9310_REG_PAUSE 0x41 #define SX9310_REG_WHOAMI 0x42 #define SX9310_WHOAMI_VALUE 0x01 @@ -116,14 +116,9 @@ #define SX9310_REG_RESET 0x7f #define SX9310_SOFT_RESET 0xde -#define SX9310_SCAN_PERIOD_MASK GENMASK(7, 4) -#define SX9310_SCAN_PERIOD_SHIFT 4 - -#define SX9310_COMPSTAT_MASK GENMASK(3, 0) /* 4 hardware channels, as defined in STAT0: COMB, CS2, CS1 and CS0. */ #define SX9310_NUM_CHANNELS 4 -#define SX9310_CHAN_ENABLED_MASK GENMASK(3, 0) struct sx9310_data { /* Serialize access to registers and channel configuration */ @@ -251,7 +246,7 @@ static const struct regmap_range sx9310_readable_reg_ranges[] = { regmap_reg_range(SX9310_REG_PROX_CTRL0, SX9310_REG_PROX_CTRL19), regmap_reg_range(SX9310_REG_SAR_CTRL0, SX9310_REG_SAR_CTRL2), regmap_reg_range(SX9310_REG_SENSOR_SEL, SX9310_REG_SAR_LSB), - regmap_reg_range(SX9310_REG_I2CADDR, SX9310_REG_WHOAMI), + regmap_reg_range(SX9310_REG_I2C_ADDR, SX9310_REG_WHOAMI), regmap_reg_range(SX9310_REG_RESET, SX9310_REG_RESET), }; @@ -292,7 +287,7 @@ static int sx9310_update_chan_en(struct sx9310_data *data, if ((data->chan_read | data->chan_event) != (chan_read | chan_event)) { ret = regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL0, - SX9310_CHAN_ENABLED_MASK, + SX9310_REG_PROX_CTRL0_SENSOREN_MASK, chan_read | chan_event); if (ret) return ret; @@ -361,7 +356,7 @@ static int sx9310_wait_for_sample(struct sx9310_data *data) if (ret < 0) return ret; - val = (val & SX9310_SCAN_PERIOD_MASK) >> SX9310_SCAN_PERIOD_SHIFT; + val = FIELD_GET(SX9310_REG_PROX_CTRL0_SCANPERIOD_MASK, val); msleep(sx9310_scan_period_table[val]); @@ -435,7 +430,7 @@ static int sx9310_read_samp_freq(struct sx9310_data *data, int *val, int *val2) if (ret < 0) return ret; - regval = (regval & SX9310_SCAN_PERIOD_MASK) >> SX9310_SCAN_PERIOD_SHIFT; + regval = FIELD_GET(SX9310_REG_PROX_CTRL0_SCANPERIOD_MASK, regval); *val = sx9310_samp_freq_table[regval].val; *val2 = sx9310_samp_freq_table[regval].val2; @@ -482,9 +477,10 @@ static int sx9310_set_samp_freq(struct sx9310_data *data, int val, int val2) mutex_lock(&data->mutex); - ret = regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL0, - SX9310_SCAN_PERIOD_MASK, - i << SX9310_SCAN_PERIOD_SHIFT); + ret = regmap_update_bits( + data->regmap, SX9310_REG_PROX_CTRL0, + SX9310_REG_PROX_CTRL0_SCANPERIOD_MASK, + FIELD_PREP(SX9310_REG_PROX_CTRL0_SCANPERIOD_MASK, i)); mutex_unlock(&data->mutex); @@ -572,7 +568,7 @@ static irqreturn_t sx9310_irq_thread_handler(int irq, void *private) goto out; } - if (val & SX9310_EVENT_IRQ) + if (val & (SX9310_FAR_IRQ | SX9310_CLOSE_IRQ)) sx9310_push_events(indio_dev); if (val & SX9310_CONVDONE_IRQ) @@ -600,6 +596,7 @@ static int sx9310_write_event_config(struct iio_dev *indio_dev, enum iio_event_direction dir, int state) { struct sx9310_data *data = iio_priv(indio_dev); + unsigned int eventirq = SX9310_FAR_IRQ | SX9310_CLOSE_IRQ; int ret; /* If the state hasn't changed, there's nothing to do. */ @@ -612,7 +609,7 @@ static int sx9310_write_event_config(struct iio_dev *indio_dev, if (ret < 0) goto out_unlock; if (!(data->chan_event & ~BIT(chan->channel))) { - ret = sx9310_enable_irq(data, SX9310_EVENT_IRQ); + ret = sx9310_enable_irq(data, eventirq); if (ret < 0) sx9310_put_event_channel(data, chan->channel); } @@ -621,7 +618,7 @@ static int sx9310_write_event_config(struct iio_dev *indio_dev, if (ret < 0) goto out_unlock; if (!data->chan_event) { - ret = sx9310_disable_irq(data, SX9310_EVENT_IRQ); + ret = sx9310_disable_irq(data, eventirq); if (ret < 0) sx9310_get_event_channel(data, chan->channel); } @@ -744,53 +741,46 @@ struct sx9310_reg_default { u8 def; }; -#define SX_INIT(_reg, _def) \ - { \ - .reg = SX9310_REG_##_reg, \ - .def = _def, \ - } - static const struct sx9310_reg_default sx9310_default_regs[] = { - SX_INIT(IRQ_MSK, 0x00), - SX_INIT(IRQ_FUNC, 0x00), + { SX9310_REG_IRQ_MSK, 0x00 }, + { SX9310_REG_IRQ_FUNC, 0x00 }, /* * The lower 4 bits should not be set as it enable sensors measurements. * Turning the detection on before the configuration values are set to * good values can cause the device to return erroneous readings. */ - SX_INIT(PROX_CTRL0, SX9310_REG_PROX_CTRL0_PROXSTAT2), - SX_INIT(PROX_CTRL1, 0x00), - SX_INIT(PROX_CTRL2, SX9310_REG_PROX_CTRL2_COMBMODE_ALL | - SX9310_REG_PROX_CTRL2_SHIELDEN_DYNAMIC), - SX_INIT(PROX_CTRL3, SX9310_REG_PROX_CTRL3_GAIN0_X8 | - SX9310_REG_PROX_CTRL3_GAIN12_X4), - SX_INIT(PROX_CTRL4, SX9310_REG_PROX_CTRL4_RESOLUTION_FINEST), - SX_INIT(PROX_CTRL5, SX9310_REG_PROX_CTRL5_RANGE_SMALL | - SX9310_REG_PROX_CTRL5_STARTUPSENS_CS1 | - SX9310_REG_PROX_CTRL5_RAWFILT_1P25), - SX_INIT(PROX_CTRL6, SX9310_REG_PROX_CTRL6_COMP_COMMON), - SX_INIT(PROX_CTRL7, SX9310_REG_PROX_CTRL7_AVGNEGFILT_2 | - SX9310_REG_PROX_CTRL7_AVGPOSFILT_512), - SX_INIT(PROX_CTRL8, SX9310_REG_PROX_CTRL8_9_PTHRESH_96 | - SX9310_REG_PROX_CTRL8_9_BODYTHRESH_1500), - SX_INIT(PROX_CTRL9, SX9310_REG_PROX_CTRL8_9_PTHRESH12_28 | - SX9310_REG_PROX_CTRL8_9_BODYTHRESH_900), - SX_INIT(PROX_CTRL10, SX9310_REG_PROX_CTRL10_HYST_6PCT | - SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_8 | - SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_8), - SX_INIT(PROX_CTRL11, 0x00), - SX_INIT(PROX_CTRL12, 0x00), - SX_INIT(PROX_CTRL13, 0x00), - SX_INIT(PROX_CTRL14, 0x00), - SX_INIT(PROX_CTRL15, 0x00), - SX_INIT(PROX_CTRL16, 0x00), - SX_INIT(PROX_CTRL17, 0x00), - SX_INIT(PROX_CTRL18, 0x00), - SX_INIT(PROX_CTRL19, 0x00), - SX_INIT(SAR_CTRL0, SX9310_REG_SAR_CTRL0_SARDEB_4_SAMPLES | - SX9310_REG_SAR_CTRL0_SARHYST_8), - SX_INIT(SAR_CTRL1, SX9310_REG_SAR_CTRL1_SLOPE(10781250)), - SX_INIT(SAR_CTRL2, SX9310_REG_SAR_CTRL2_SAROFFSET_DEFAULT), + { SX9310_REG_PROX_CTRL0, SX9310_REG_PROX_CTRL0_SCANPERIOD_15MS }, + { SX9310_REG_PROX_CTRL1, 0x00 }, + { SX9310_REG_PROX_CTRL2, SX9310_REG_PROX_CTRL2_COMBMODE_CS1_CS2 | + SX9310_REG_PROX_CTRL2_SHIELDEN_DYNAMIC }, + { SX9310_REG_PROX_CTRL3, SX9310_REG_PROX_CTRL3_GAIN0_X8 | + SX9310_REG_PROX_CTRL3_GAIN12_X4 }, + { SX9310_REG_PROX_CTRL4, SX9310_REG_PROX_CTRL4_RESOLUTION_FINEST }, + { SX9310_REG_PROX_CTRL5, SX9310_REG_PROX_CTRL5_RANGE_SMALL | + SX9310_REG_PROX_CTRL5_STARTUPSENS_CS1 | + SX9310_REG_PROX_CTRL5_RAWFILT_1P25 }, + { SX9310_REG_PROX_CTRL6, SX9310_REG_PROX_CTRL6_AVGTHRESH_DEFAULT }, + { SX9310_REG_PROX_CTRL7, SX9310_REG_PROX_CTRL7_AVGNEGFILT_2 | + SX9310_REG_PROX_CTRL7_AVGPOSFILT_512 }, + { SX9310_REG_PROX_CTRL8, SX9310_REG_PROX_CTRL8_9_PTHRESH_96 | + SX9310_REG_PROX_CTRL8_9_BODYTHRESH_1500 }, + { SX9310_REG_PROX_CTRL9, SX9310_REG_PROX_CTRL8_9_PTHRESH_28 | + SX9310_REG_PROX_CTRL8_9_BODYTHRESH_900 }, + { SX9310_REG_PROX_CTRL10, SX9310_REG_PROX_CTRL10_HYST_6PCT | + SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_2 }, + { SX9310_REG_PROX_CTRL11, 0x00 }, + { SX9310_REG_PROX_CTRL12, 0x00 }, + { SX9310_REG_PROX_CTRL13, 0x00 }, + { SX9310_REG_PROX_CTRL14, 0x00 }, + { SX9310_REG_PROX_CTRL15, 0x00 }, + { SX9310_REG_PROX_CTRL16, 0x00 }, + { SX9310_REG_PROX_CTRL17, 0x00 }, + { SX9310_REG_PROX_CTRL18, 0x00 }, + { SX9310_REG_PROX_CTRL19, 0x00 }, + { SX9310_REG_SAR_CTRL0, SX9310_REG_SAR_CTRL0_SARDEB_4_SAMPLES | + SX9310_REG_SAR_CTRL0_SARHYST_8 }, + { SX9310_REG_SAR_CTRL1, SX9310_REG_SAR_CTRL1_SLOPE(10781250) }, + { SX9310_REG_SAR_CTRL2, SX9310_REG_SAR_CTRL2_SAROFFSET_DEFAULT }, }; /* Activate all channels and perform an initial compensation. */ @@ -807,7 +797,7 @@ static int sx9310_init_compensation(struct iio_dev *indio_dev) /* run the compensation phase on all channels */ ret = regmap_write(data->regmap, SX9310_REG_PROX_CTRL0, - ctrl0 | SX9310_REG_PROX_CTRL0_EN_MASK); + ctrl0 | SX9310_REG_PROX_CTRL0_SENSOREN_MASK); if (ret < 0) return ret; @@ -816,7 +806,7 @@ static int sx9310_init_compensation(struct iio_dev *indio_dev) ret = regmap_read(data->regmap, SX9310_REG_STAT1, &val); if (ret < 0) goto out; - if (!(val & SX9310_COMPSTAT_MASK)) + if (!(val & SX9310_REG_STAT1_COMPSTAT_MASK)) break; } @@ -989,7 +979,7 @@ static int __maybe_unused sx9310_suspend(struct device *dev) if (ret) goto out; - ctrl0 = data->suspend_ctrl0 & ~SX9310_REG_PROX_CTRL0_EN_MASK; + ctrl0 = data->suspend_ctrl0 & ~SX9310_REG_PROX_CTRL0_SENSOREN_MASK; ret = regmap_write(data->regmap, SX9310_REG_PROX_CTRL0, ctrl0); if (ret) goto out; -- cgit v1.2.3 From 364e853ceec92cafe2c0d7fe7cc1d89891903234 Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:03 -0600 Subject: iio: sx9310: Fix irq handling Fixes enable/disable irq handling at various points. The driver needs to only enable/disable irqs if there is an actual irq handler installed. Signed-off-by: Daniel Campello Reviewed-by: Stephen Boyd Reviewed-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9310.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c index c02a9e8b7a7a..4ad8194c70a9 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -323,11 +323,15 @@ static int sx9310_put_event_channel(struct sx9310_data *data, int channel) static int sx9310_enable_irq(struct sx9310_data *data, unsigned int irq) { + if (!data->client->irq) + return 0; return regmap_update_bits(data->regmap, SX9310_REG_IRQ_MSK, irq, irq); } static int sx9310_disable_irq(struct sx9310_data *data, unsigned int irq) { + if (!data->client->irq) + return 0; return regmap_update_bits(data->regmap, SX9310_REG_IRQ_MSK, irq, 0); } @@ -381,7 +385,7 @@ static int sx9310_read_proximity(struct sx9310_data *data, mutex_unlock(&data->mutex); - if (data->client->irq > 0) { + if (data->client->irq) { ret = wait_for_completion_interruptible(&data->completion); reinit_completion(&data->completion); } else { @@ -1007,10 +1011,11 @@ static int __maybe_unused sx9310_resume(struct device *dev) out: mutex_unlock(&data->mutex); + if (ret) + return ret; enable_irq(data->client->irq); - - return ret; + return 0; } static const struct dev_pm_ops sx9310_pm_ops = { -- cgit v1.2.3 From ef5bdbab3511a6df31a0f660a7bc1e2494d72f61 Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:04 -0600 Subject: iio: sx9310: Remove acpi and of table macros Avoids unused warnings due to acpi/of table macros. Reported-by: kbuild test robot Signed-off-by: Daniel Campello Reviewed-by: Andy Shevchenko Reviewed-by: Stephen Boyd Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9310.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c index 4ad8194c70a9..da32564bcc2a 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -16,8 +16,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -1046,8 +1046,8 @@ MODULE_DEVICE_TABLE(i2c, sx9310_id); static struct i2c_driver sx9310_driver = { .driver = { .name = "sx9310", - .acpi_match_table = ACPI_PTR(sx9310_acpi_match), - .of_match_table = of_match_ptr(sx9310_of_match), + .acpi_match_table = sx9310_acpi_match, + .of_match_table = sx9310_of_match, .pm = &sx9310_pm_ops, }, .probe = sx9310_probe, -- cgit v1.2.3 From 9b2cac94698794c49b993db0646c37c2188dcfae Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:05 -0600 Subject: iio: sx9310: Change from .probe to .probe_new Uses .probe_new in place of .probe. Also uses device_get_match_data() for whoami matching. Signed-off-by: Daniel Campello Reviewed-by: Andy Shevchenko Reviewed-by: Stephen Boyd Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9310.c | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c index da32564bcc2a..b94dec3e48ae 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -139,7 +139,7 @@ struct sx9310_data { struct completion completion; unsigned int chan_read, chan_event; int channel_users[SX9310_NUM_CHANNELS]; - int whoami; + unsigned int whoami; }; static const struct iio_event_spec sx9310_events[] = { @@ -856,24 +856,15 @@ static int sx9310_init_device(struct iio_dev *indio_dev) static int sx9310_set_indio_dev_name(struct device *dev, struct iio_dev *indio_dev, - const struct i2c_device_id *id, int whoami) + unsigned int whoami) { - const struct acpi_device_id *acpi_id; - - /* id will be NULL when enumerated via ACPI */ - if (id) { - if (id->driver_data != whoami) - dev_err(dev, "WHOAMI does not match i2c_device_id: %s", - id->name); - } else if (ACPI_HANDLE(dev)) { - acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev); - if (!acpi_id) - return -ENODEV; - if (acpi_id->driver_data != whoami) - dev_err(dev, "WHOAMI does not match acpi_device_id: %s", - acpi_id->id); - } else + unsigned int long ddata; + + ddata = (uintptr_t)device_get_match_data(dev); + if (ddata != whoami) { + dev_err(dev, "WHOAMI does not match device data: %u\n", whoami); return -ENODEV; + } switch (whoami) { case SX9310_WHOAMI_VALUE: @@ -883,15 +874,14 @@ static int sx9310_set_indio_dev_name(struct device *dev, indio_dev->name = "sx9311"; break; default: - dev_err(dev, "unexpected WHOAMI response: %u", whoami); + dev_err(dev, "unexpected WHOAMI response: %u\n", whoami); return -ENODEV; } return 0; } -static int sx9310_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int sx9310_probe(struct i2c_client *client) { int ret; struct iio_dev *indio_dev; @@ -917,8 +907,7 @@ static int sx9310_probe(struct i2c_client *client, return ret; } - ret = sx9310_set_indio_dev_name(&client->dev, indio_dev, id, - data->whoami); + ret = sx9310_set_indio_dev_name(&client->dev, indio_dev, data->whoami); if (ret < 0) return ret; @@ -1030,8 +1019,8 @@ static const struct acpi_device_id sx9310_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, sx9310_acpi_match); static const struct of_device_id sx9310_of_match[] = { - { .compatible = "semtech,sx9310" }, - { .compatible = "semtech,sx9311" }, + { .compatible = "semtech,sx9310", (void *)SX9310_WHOAMI_VALUE }, + { .compatible = "semtech,sx9311", (void *)SX9311_WHOAMI_VALUE }, {}, }; MODULE_DEVICE_TABLE(of, sx9310_of_match); @@ -1050,7 +1039,7 @@ static struct i2c_driver sx9310_driver = { .of_match_table = sx9310_of_match, .pm = &sx9310_pm_ops, }, - .probe = sx9310_probe, + .probe_new = sx9310_probe, .id_table = sx9310_id, }; module_i2c_driver(sx9310_driver); -- cgit v1.2.3 From 01b9cb0dea76c70b3696cdff79c2e8f5772a6356 Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:06 -0600 Subject: iio: sx9310: Fixes various memory handling Makes use __aligned(8) to ensure that the timestamp is correctly aligned when we call io_push_to_buffers_with_timestamp(). Also makes use of sizeof() for regmap_bulk_read instead of static value. Signed-off-by: Daniel Campello Reviewed-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9310.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c index b94dec3e48ae..b56003ce3ca0 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -132,8 +132,11 @@ struct sx9310_data { */ bool prox_stat[SX9310_NUM_CHANNELS]; bool trigger_enabled; - __be16 buffer[SX9310_NUM_CHANNELS + - 4]; /* 64-bit data + 64-bit timestamp */ + /* Ensure correct alignment of timestamp when present. */ + struct { + __be16 channels[SX9310_NUM_CHANNELS]; + s64 ts __aligned(8); + } buffer; /* Remember enabled channels and sample rate during suspend. */ unsigned int suspend_ctrl0; struct completion completion; @@ -344,7 +347,7 @@ static int sx9310_read_prox_data(struct sx9310_data *data, if (ret < 0) return ret; - return regmap_bulk_read(data->regmap, chan->address, val, 2); + return regmap_bulk_read(data->regmap, chan->address, val, sizeof(*val)); } /* @@ -694,10 +697,10 @@ static irqreturn_t sx9310_trigger_handler(int irq, void *private) if (ret < 0) goto out; - data->buffer[i++] = val; + data->buffer.channels[i++] = val; } - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer, pf->timestamp); out: -- cgit v1.2.3 From 68aa360a77c6d6695cb68ed34a5413e2b2b80fa6 Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:07 -0600 Subject: iio: sx9310: Use long instead of int for channel bitmaps Uses for_each_set_bit() macro to loop over channel bitmaps. Signed-off-by: Daniel Campello Reviewed-by: Andy Shevchenko Reviewed-by: Stephen Boyd Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9310.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c index b56003ce3ca0..a9deed262dbd 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -119,6 +119,7 @@ /* 4 hardware channels, as defined in STAT0: COMB, CS2, CS1 and CS0. */ #define SX9310_NUM_CHANNELS 4 +static_assert(SX9310_NUM_CHANNELS < BITS_PER_LONG); struct sx9310_data { /* Serialize access to registers and channel configuration */ @@ -130,7 +131,7 @@ struct sx9310_data { * Last reading of the proximity status for each channel. * We only send an event to user space when this changes. */ - bool prox_stat[SX9310_NUM_CHANNELS]; + unsigned long chan_prox_stat; bool trigger_enabled; /* Ensure correct alignment of timestamp when present. */ struct { @@ -140,7 +141,8 @@ struct sx9310_data { /* Remember enabled channels and sample rate during suspend. */ unsigned int suspend_ctrl0; struct completion completion; - unsigned int chan_read, chan_event; + unsigned long chan_read; + unsigned long chan_event; int channel_users[SX9310_NUM_CHANNELS]; unsigned int whoami; }; @@ -283,15 +285,16 @@ static const struct regmap_config sx9310_regmap_config = { }; static int sx9310_update_chan_en(struct sx9310_data *data, - unsigned int chan_read, - unsigned int chan_event) + unsigned long chan_read, + unsigned long chan_event) { int ret; + unsigned long channels = chan_read | chan_event; - if ((data->chan_read | data->chan_event) != (chan_read | chan_event)) { + if ((data->chan_read | data->chan_event) != channels) { ret = regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL0, SX9310_REG_PROX_CTRL0_SENSOREN_MASK, - chan_read | chan_event); + channels); if (ret) return ret; } @@ -532,6 +535,7 @@ static void sx9310_push_events(struct iio_dev *indio_dev) unsigned int val, chan; struct sx9310_data *data = iio_priv(indio_dev); s64 timestamp = iio_get_time_ns(indio_dev); + unsigned long prox_changed; /* Read proximity state on all channels */ ret = regmap_read(data->regmap, SX9310_REG_STAT0, &val); @@ -540,24 +544,23 @@ static void sx9310_push_events(struct iio_dev *indio_dev) return; } - for (chan = 0; chan < SX9310_NUM_CHANNELS; chan++) { + /* + * Only iterate over channels with changes on proximity status that have + * events enabled. + */ + prox_changed = (data->chan_prox_stat ^ val) & data->chan_event; + + for_each_set_bit(chan, &prox_changed, SX9310_NUM_CHANNELS) { int dir; u64 ev; - bool new_prox = val & BIT(chan); - - if (!(data->chan_event & BIT(chan))) - continue; - if (new_prox == data->prox_stat[chan]) - /* No change on this channel. */ - continue; - dir = new_prox ? IIO_EV_DIR_FALLING : IIO_EV_DIR_RISING; + dir = (val & BIT(chan)) ? IIO_EV_DIR_FALLING : IIO_EV_DIR_RISING; ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, chan, IIO_EV_TYPE_THRESH, dir); iio_push_event(indio_dev, ev, timestamp); - data->prox_stat[chan] = new_prox; } + data->chan_prox_stat = val; } static irqreturn_t sx9310_irq_thread_handler(int irq, void *private) @@ -714,13 +717,13 @@ out: static int sx9310_buffer_preenable(struct iio_dev *indio_dev) { struct sx9310_data *data = iio_priv(indio_dev); - unsigned int channels = 0; + unsigned long channels = 0; int bit, ret; mutex_lock(&data->mutex); for_each_set_bit(bit, indio_dev->active_scan_mask, indio_dev->masklength) - channels |= BIT(indio_dev->channels[bit].channel); + __set_bit(indio_dev->channels[bit].channel, &channels); ret = sx9310_update_chan_en(data, channels, data->chan_event); mutex_unlock(&data->mutex); -- cgit v1.2.3 From dc46198f27ff72efce2c2fa8ef4ee52fa80c06ec Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:08 -0600 Subject: iio: sx9310: Use regmap_read_poll_timeout() for compensation Simplify compensation stage by using regmap_read_poll_timeout(). Signed-off-by: Daniel Campello Reviewed-by: Andy Shevchenko Reviewed-by: Stephen Boyd Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9310.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c index a9deed262dbd..dd04aaf66d31 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -797,7 +797,7 @@ static const struct sx9310_reg_default sx9310_default_regs[] = { static int sx9310_init_compensation(struct iio_dev *indio_dev) { struct sx9310_data *data = iio_priv(indio_dev); - int i, ret; + int ret; unsigned int val; unsigned int ctrl0; @@ -811,22 +811,17 @@ static int sx9310_init_compensation(struct iio_dev *indio_dev) if (ret < 0) return ret; - for (i = 100; i >= 0; i--) { - msleep(20); - ret = regmap_read(data->regmap, SX9310_REG_STAT1, &val); - if (ret < 0) - goto out; - if (!(val & SX9310_REG_STAT1_COMPSTAT_MASK)) - break; - } - - if (i < 0) { - dev_err(&data->client->dev, - "initial compensation timed out: 0x%02x", val); - ret = -ETIMEDOUT; + ret = regmap_read_poll_timeout(data->regmap, SX9310_REG_STAT1, val, + !(val & SX9310_REG_STAT1_COMPSTAT_MASK), + 20000, 2000000); + if (ret) { + if (ret == -ETIMEDOUT) + dev_err(&data->client->dev, + "initial compensation timed out: 0x%02x\n", + val); + return ret; } -out: regmap_write(data->regmap, SX9310_REG_PROX_CTRL0, ctrl0); return ret; } -- cgit v1.2.3 From 124cbc339cabde29a0a4d2b9c51c5068884145b0 Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:09 -0600 Subject: iio: sx9310: Update copyright Fixes wrong copyright year. Signed-off-by: Daniel Campello Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9310.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c index dd04aaf66d31..419f47a2fbd5 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -6,8 +6,8 @@ * Based on SX9500 driver and Semtech driver using the input framework * . - * Reworked April 2019 by Evan Green - * and January 2020 by Daniel Campello + * Reworked in April 2019 by Evan Green + * and in January 2020 by Daniel Campello . */ #include -- cgit v1.2.3 From a917af2ab8573a92b1434f9b45add3438edcbcb2 Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:10 -0600 Subject: iio: sx9310: Simplify error return handling Checks for non-zero return values to signal error conditions. Signed-off-by: Daniel Campello Reviewed-by: Andy Shevchenko Reviewed-by: Stephen Boyd Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9310.c | 56 +++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c index 419f47a2fbd5..55269c2064c0 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -347,7 +347,7 @@ static int sx9310_read_prox_data(struct sx9310_data *data, int ret; ret = regmap_write(data->regmap, SX9310_REG_SENSOR_SEL, chan->channel); - if (ret < 0) + if (ret) return ret; return regmap_bulk_read(data->regmap, chan->address, val, sizeof(*val)); @@ -363,7 +363,7 @@ static int sx9310_wait_for_sample(struct sx9310_data *data) unsigned int val; ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL0, &val); - if (ret < 0) + if (ret) return ret; val = FIELD_GET(SX9310_REG_PROX_CTRL0_SCANPERIOD_MASK, val); @@ -376,17 +376,17 @@ static int sx9310_wait_for_sample(struct sx9310_data *data) static int sx9310_read_proximity(struct sx9310_data *data, const struct iio_chan_spec *chan, int *val) { - int ret = 0; + int ret; __be16 rawval; mutex_lock(&data->mutex); ret = sx9310_get_read_channel(data, chan->channel); - if (ret < 0) + if (ret) goto out; ret = sx9310_enable_irq(data, SX9310_CONVDONE_IRQ); - if (ret < 0) + if (ret) goto out_put_channel; mutex_unlock(&data->mutex); @@ -400,22 +400,22 @@ static int sx9310_read_proximity(struct sx9310_data *data, mutex_lock(&data->mutex); - if (ret < 0) + if (ret) goto out_disable_irq; ret = sx9310_read_prox_data(data, chan, &rawval); - if (ret < 0) + if (ret) goto out_disable_irq; *val = sign_extend32(be16_to_cpu(rawval), (chan->address == SX9310_REG_DIFF_MSB ? 11 : 15)); ret = sx9310_disable_irq(data, SX9310_CONVDONE_IRQ); - if (ret < 0) + if (ret) goto out_put_channel; ret = sx9310_put_read_channel(data, chan->channel); - if (ret < 0) + if (ret) goto out; mutex_unlock(&data->mutex); @@ -437,7 +437,7 @@ static int sx9310_read_samp_freq(struct sx9310_data *data, int *val, int *val2) unsigned int regval; int ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL0, ®val); - if (ret < 0) + if (ret) return ret; regval = FIELD_GET(SX9310_REG_PROX_CTRL0_SCANPERIOD_MASK, regval); @@ -539,7 +539,7 @@ static void sx9310_push_events(struct iio_dev *indio_dev) /* Read proximity state on all channels */ ret = regmap_read(data->regmap, SX9310_REG_STAT0, &val); - if (ret < 0) { + if (ret) { dev_err(&data->client->dev, "i2c transfer error in irq\n"); return; } @@ -573,7 +573,7 @@ static irqreturn_t sx9310_irq_thread_handler(int irq, void *private) mutex_lock(&data->mutex); ret = regmap_read(data->regmap, SX9310_REG_IRQ_SRC, &val); - if (ret < 0) { + if (ret) { dev_err(&data->client->dev, "i2c transfer error in irq\n"); goto out; } @@ -616,20 +616,20 @@ static int sx9310_write_event_config(struct iio_dev *indio_dev, mutex_lock(&data->mutex); if (state) { ret = sx9310_get_event_channel(data, chan->channel); - if (ret < 0) + if (ret) goto out_unlock; if (!(data->chan_event & ~BIT(chan->channel))) { ret = sx9310_enable_irq(data, eventirq); - if (ret < 0) + if (ret) sx9310_put_event_channel(data, chan->channel); } } else { ret = sx9310_put_event_channel(data, chan->channel); - if (ret < 0) + if (ret) goto out_unlock; if (!data->chan_event) { ret = sx9310_disable_irq(data, eventirq); - if (ret < 0) + if (ret) sx9310_get_event_channel(data, chan->channel); } } @@ -668,7 +668,7 @@ static int sx9310_set_trigger_state(struct iio_trigger *trig, bool state) ret = sx9310_enable_irq(data, SX9310_CONVDONE_IRQ); else if (!data->chan_read) ret = sx9310_disable_irq(data, SX9310_CONVDONE_IRQ); - if (ret < 0) + if (ret) goto out; data->trigger_enabled = state; @@ -697,7 +697,7 @@ static irqreturn_t sx9310_trigger_handler(int irq, void *private) indio_dev->masklength) { ret = sx9310_read_prox_data(data, &indio_dev->channels[bit], &val); - if (ret < 0) + if (ret) goto out; data->buffer.channels[i++] = val; @@ -802,13 +802,13 @@ static int sx9310_init_compensation(struct iio_dev *indio_dev) unsigned int ctrl0; ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL0, &ctrl0); - if (ret < 0) + if (ret) return ret; /* run the compensation phase on all channels */ ret = regmap_write(data->regmap, SX9310_REG_PROX_CTRL0, ctrl0 | SX9310_REG_PROX_CTRL0_SENSOREN_MASK); - if (ret < 0) + if (ret) return ret; ret = regmap_read_poll_timeout(data->regmap, SX9310_REG_STAT1, val, @@ -834,21 +834,21 @@ static int sx9310_init_device(struct iio_dev *indio_dev) unsigned int i, val; ret = regmap_write(data->regmap, SX9310_REG_RESET, SX9310_SOFT_RESET); - if (ret < 0) + if (ret) return ret; usleep_range(1000, 2000); /* power-up time is ~1ms. */ /* Clear reset interrupt state by reading SX9310_REG_IRQ_SRC. */ ret = regmap_read(data->regmap, SX9310_REG_IRQ_SRC, &val); - if (ret < 0) + if (ret) return ret; /* Program some sane defaults. */ for (i = 0; i < ARRAY_SIZE(sx9310_default_regs); i++) { initval = &sx9310_default_regs[i]; ret = regmap_write(data->regmap, initval->reg, initval->def); - if (ret < 0) + if (ret) return ret; } @@ -902,14 +902,14 @@ static int sx9310_probe(struct i2c_client *client) return PTR_ERR(data->regmap); ret = regmap_read(data->regmap, SX9310_REG_WHOAMI, &data->whoami); - if (ret < 0) { + if (ret) { dev_err(&client->dev, "error in reading WHOAMI register: %d", ret); return ret; } ret = sx9310_set_indio_dev_name(&client->dev, indio_dev, data->whoami); - if (ret < 0) + if (ret) return ret; ACPI_COMPANION_SET(&indio_dev->dev, ACPI_COMPANION(&client->dev)); @@ -920,7 +920,7 @@ static int sx9310_probe(struct i2c_client *client) i2c_set_clientdata(client, indio_dev); ret = sx9310_init_device(indio_dev); - if (ret < 0) + if (ret) return ret; if (client->irq) { @@ -929,7 +929,7 @@ static int sx9310_probe(struct i2c_client *client) sx9310_irq_thread_handler, IRQF_TRIGGER_LOW | IRQF_ONESHOT, "sx9310_event", indio_dev); - if (ret < 0) + if (ret) return ret; data->trig = @@ -951,7 +951,7 @@ static int sx9310_probe(struct i2c_client *client) iio_pollfunc_store_time, sx9310_trigger_handler, &sx9310_buffer_setup_ops); - if (ret < 0) + if (ret) return ret; return devm_iio_device_register(&client->dev, indio_dev); -- cgit v1.2.3 From e943bba88ed58080fe23eecbfc0da3fa2839a390 Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:11 -0600 Subject: iio: sx9310: Use variable to hold &client->dev Improves readability by storing &client->dev in a local variable. Signed-off-by: Daniel Campello Reviewed-by: Andy Shevchenko Reviewed-by: Stephen Boyd Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9310.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c index 55269c2064c0..1650da9b4f10 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -885,11 +885,12 @@ static int sx9310_set_indio_dev_name(struct device *dev, static int sx9310_probe(struct i2c_client *client) { int ret; + struct device *dev = &client->dev; struct iio_dev *indio_dev; struct sx9310_data *data; - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); - if (indio_dev == NULL) + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) return -ENOMEM; data = iio_priv(indio_dev); @@ -903,16 +904,15 @@ static int sx9310_probe(struct i2c_client *client) ret = regmap_read(data->regmap, SX9310_REG_WHOAMI, &data->whoami); if (ret) { - dev_err(&client->dev, "error in reading WHOAMI register: %d", - ret); + dev_err(dev, "error in reading WHOAMI register: %d", ret); return ret; } - ret = sx9310_set_indio_dev_name(&client->dev, indio_dev, data->whoami); + ret = sx9310_set_indio_dev_name(dev, indio_dev, data->whoami); if (ret) return ret; - ACPI_COMPANION_SET(&indio_dev->dev, ACPI_COMPANION(&client->dev)); + ACPI_COMPANION_SET(&indio_dev->dev, ACPI_COMPANION(dev)); indio_dev->channels = sx9310_channels; indio_dev->num_channels = ARRAY_SIZE(sx9310_channels); indio_dev->info = &sx9310_info; @@ -924,7 +924,7 @@ static int sx9310_probe(struct i2c_client *client) return ret; if (client->irq) { - ret = devm_request_threaded_irq(&client->dev, client->irq, + ret = devm_request_threaded_irq(dev, client->irq, sx9310_irq_handler, sx9310_irq_thread_handler, IRQF_TRIGGER_LOW | IRQF_ONESHOT, @@ -932,29 +932,29 @@ static int sx9310_probe(struct i2c_client *client) if (ret) return ret; - data->trig = - devm_iio_trigger_alloc(&client->dev, "%s-dev%d", - indio_dev->name, indio_dev->id); + data->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", + indio_dev->name, + indio_dev->id); if (!data->trig) return -ENOMEM; - data->trig->dev.parent = &client->dev; + data->trig->dev.parent = dev; data->trig->ops = &sx9310_trigger_ops; iio_trigger_set_drvdata(data->trig, indio_dev); - ret = devm_iio_trigger_register(&client->dev, data->trig); + ret = devm_iio_trigger_register(dev, data->trig); if (ret) return ret; } - ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, iio_pollfunc_store_time, sx9310_trigger_handler, &sx9310_buffer_setup_ops); if (ret) return ret; - return devm_iio_device_register(&client->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } static int __maybe_unused sx9310_suspend(struct device *dev) -- cgit v1.2.3 From de479073fa1eb7031b4f85429102e002521a0a95 Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:12 -0600 Subject: iio: sx9310: Miscellaneous format fixes Miscellaneous format fixes throughout the whole file. Signed-off-by: Daniel Campello Reviewed-by: Andy Shevchenko Reviewed-by: Stephen Boyd Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9310.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c index 1650da9b4f10..51974477cd4d 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -91,28 +91,21 @@ #define SX9310_REG_SAR_CTRL2_SAROFFSET_DEFAULT 0x3c #define SX9310_REG_SENSOR_SEL 0x30 - #define SX9310_REG_USE_MSB 0x31 #define SX9310_REG_USE_LSB 0x32 - #define SX9310_REG_AVG_MSB 0x33 #define SX9310_REG_AVG_LSB 0x34 - #define SX9310_REG_DIFF_MSB 0x35 #define SX9310_REG_DIFF_LSB 0x36 - #define SX9310_REG_OFFSET_MSB 0x37 #define SX9310_REG_OFFSET_LSB 0x38 - #define SX9310_REG_SAR_MSB 0x39 #define SX9310_REG_SAR_LSB 0x3a - #define SX9310_REG_I2C_ADDR 0x40 #define SX9310_REG_PAUSE 0x41 #define SX9310_REG_WHOAMI 0x42 #define SX9310_WHOAMI_VALUE 0x01 #define SX9311_WHOAMI_VALUE 0x02 - #define SX9310_REG_RESET 0x7f #define SX9310_SOFT_RESET 0xde @@ -408,7 +401,7 @@ static int sx9310_read_proximity(struct sx9310_data *data, goto out_disable_irq; *val = sign_extend32(be16_to_cpu(rawval), - (chan->address == SX9310_REG_DIFF_MSB ? 11 : 15)); + chan->address == SX9310_REG_DIFF_MSB ? 11 : 15); ret = sx9310_disable_irq(data, SX9310_CONVDONE_IRQ); if (ret) @@ -435,8 +428,9 @@ out: static int sx9310_read_samp_freq(struct sx9310_data *data, int *val, int *val2) { unsigned int regval; - int ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL0, ®val); + int ret; + ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL0, ®val); if (ret) return ret; @@ -521,10 +515,9 @@ static irqreturn_t sx9310_irq_handler(int irq, void *private) iio_trigger_poll(data->trig); /* - * Even if no event is enabled, we need to wake the thread to - * clear the interrupt state by reading SX9310_REG_IRQ_SRC. It - * is not possible to do that here because regmap_read takes a - * mutex. + * Even if no event is enabled, we need to wake the thread to clear the + * interrupt state by reading SX9310_REG_IRQ_SRC. + * It is not possible to do that here because regmap_read takes a mutex. */ return IRQ_WAKE_THREAD; } @@ -641,7 +634,7 @@ out_unlock: static struct attribute *sx9310_attributes[] = { &iio_dev_attr_sampling_frequency_available.dev_attr.attr, - NULL, + NULL }; static const struct attribute_group sx9310_attribute_group = { @@ -969,7 +962,6 @@ static int __maybe_unused sx9310_suspend(struct device *dev) mutex_lock(&data->mutex); ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL0, &data->suspend_ctrl0); - if (ret) goto out; @@ -1015,21 +1007,21 @@ static const struct dev_pm_ops sx9310_pm_ops = { static const struct acpi_device_id sx9310_acpi_match[] = { { "STH9310", SX9310_WHOAMI_VALUE }, { "STH9311", SX9311_WHOAMI_VALUE }, - {}, + {} }; MODULE_DEVICE_TABLE(acpi, sx9310_acpi_match); static const struct of_device_id sx9310_of_match[] = { { .compatible = "semtech,sx9310", (void *)SX9310_WHOAMI_VALUE }, { .compatible = "semtech,sx9311", (void *)SX9311_WHOAMI_VALUE }, - {}, + {} }; MODULE_DEVICE_TABLE(of, sx9310_of_match); static const struct i2c_device_id sx9310_id[] = { { "sx9310", SX9310_WHOAMI_VALUE }, { "sx9311", SX9311_WHOAMI_VALUE }, - {}, + {} }; MODULE_DEVICE_TABLE(i2c, sx9310_id); -- cgit v1.2.3 From 2756db5e90ac4b881d5926bdeef75e84a128aa8d Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 3 Aug 2020 17:58:13 -0600 Subject: iio: sx9310: Drop channel_users[] This struct member isn't used. Drop it. Fixes: 72ad02b15d63 ("iio: Add SEMTECH SX9310/9311 sensor driver") Signed-off-by: Stephen Boyd Reviewed-by: Douglas Anderson Reviewed-by: Daniel Campello Signed-off-by: Daniel Campello Reviewed-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9310.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c index 51974477cd4d..6697299ce665 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -136,7 +136,6 @@ struct sx9310_data { struct completion completion; unsigned long chan_read; unsigned long chan_event; - int channel_users[SX9310_NUM_CHANNELS]; unsigned int whoami; }; -- cgit v1.2.3 From f86ff7480c3efc7398b366b6d16158768c878d36 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 3 Aug 2020 17:58:14 -0600 Subject: iio: sx9310: Enable vdd and svdd regulators at probe Enable the main power supply (vdd) and digital IO power supply (svdd) during probe so that the i2c communication and device works properly on boards that aggressively power gate these supplies. Signed-off-by: Stephen Boyd Reviewed-by: Douglas Anderson Signed-off-by: Daniel Campello Reviewed-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9310.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers/iio') diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c index 6697299ce665..018184667672 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -120,6 +121,7 @@ struct sx9310_data { struct i2c_client *client; struct iio_trigger *trig; struct regmap *regmap; + struct regulator_bulk_data supplies[2]; /* * Last reading of the proximity status for each channel. * We only send an event to user space when this changes. @@ -874,6 +876,13 @@ static int sx9310_set_indio_dev_name(struct device *dev, return 0; } +static void sx9310_regulator_disable(void *_data) +{ + struct sx9310_data *data = _data; + + regulator_bulk_disable(ARRAY_SIZE(data->supplies), data->supplies); +} + static int sx9310_probe(struct i2c_client *client) { int ret; @@ -887,6 +896,8 @@ static int sx9310_probe(struct i2c_client *client) data = iio_priv(indio_dev); data->client = client; + data->supplies[0].supply = "vdd"; + data->supplies[1].supply = "svdd"; mutex_init(&data->mutex); init_completion(&data->completion); @@ -894,6 +905,21 @@ static int sx9310_probe(struct i2c_client *client) if (IS_ERR(data->regmap)) return PTR_ERR(data->regmap); + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->supplies), + data->supplies); + if (ret) + return ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(data->supplies), data->supplies); + if (ret) + return ret; + /* Must wait for Tpor time after initial power up */ + usleep_range(1000, 1100); + + ret = devm_add_action_or_reset(dev, sx9310_regulator_disable, data); + if (ret) + return ret; + ret = regmap_read(data->regmap, SX9310_REG_WHOAMI, &data->whoami); if (ret) { dev_err(dev, "error in reading WHOAMI register: %d", ret); -- cgit v1.2.3 From fe184be8c3528f848f66d51340d42afc92209f0a Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 3 Aug 2020 17:58:15 -0600 Subject: iio: sx9310: Use irq trigger flags from firmware We shouldn't need to set default irq trigger flags here as the firmware should have properly indicated the trigger type, i.e. level low, in the DT or ACPI tables. Signed-off-by: Stephen Boyd Signed-off-by: Daniel Campello Reviewed-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9310.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c index 018184667672..9d72d08ab9e7 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -945,7 +945,7 @@ static int sx9310_probe(struct i2c_client *client) ret = devm_request_threaded_irq(dev, client->irq, sx9310_irq_handler, sx9310_irq_thread_handler, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, + IRQF_ONESHOT, "sx9310_event", indio_dev); if (ret) return ret; -- cgit v1.2.3 From 0115a63c999363b9558376b61c4037813d9063db Mon Sep 17 00:00:00 2001 From: Eugene Zaikonnikov Date: Fri, 7 Aug 2020 16:17:55 +0200 Subject: iio: humidity: Add TI HDC20x0 support Add driver support for HDC2010/2080 series devices and sysfs documentation for their heater element. HDC2010 is an integrated high-accuracy humidity and temperature sensor with very low power consumption. The device includes a resistive heating element. The temperature range is -40C to 125C with 0.2C accuracy. Humidity measurement is 0 to 100% with 2% RH accuracy. Signed-off-by: Eugene Zaikonnikov Signed-off-by: Jonathan Cameron --- .../ABI/testing/sysfs-bus-iio-humidity-hdc2010 | 9 + drivers/iio/humidity/Kconfig | 10 + drivers/iio/humidity/Makefile | 1 + drivers/iio/humidity/hdc2010.c | 353 +++++++++++++++++++++ 4 files changed, 373 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-humidity-hdc2010 create mode 100644 drivers/iio/humidity/hdc2010.c (limited to 'drivers/iio') diff --git a/Documentation/ABI/testing/sysfs-bus-iio-humidity-hdc2010 b/Documentation/ABI/testing/sysfs-bus-iio-humidity-hdc2010 new file mode 100644 index 000000000000..5b78af5f341d --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-humidity-hdc2010 @@ -0,0 +1,9 @@ +What: /sys/bus/iio/devices/iio:deviceX/out_current_heater_raw +What: /sys/bus/iio/devices/iio:deviceX/out_current_heater_raw_available +KernelVersion: 5.3.8 +Contact: linux-iio@vger.kernel.org +Description: + Controls the heater device within the humidity sensor to get + rid of excess condensation. + + Valid control values are 0 = OFF, and 1 = ON. diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig index 6c5507a6cd74..6549fcf6db69 100644 --- a/drivers/iio/humidity/Kconfig +++ b/drivers/iio/humidity/Kconfig @@ -38,6 +38,16 @@ config HDC100X To compile this driver as a module, choose M here: the module will be called hdc100x. +config HDC2010 + tristate "TI HDC2010 relative humidity and temperature sensor" + depends on I2C + help + Say yes here to build support for the Texas Instruments + HDC2010 and HDC2080 relative humidity and temperature sensors. + + To compile this driver as a module, choose M here: the module + will be called hdc2010. + config HID_SENSOR_HUMIDITY tristate "HID Environmental humidity sensor" depends on HID_SENSOR_HUB diff --git a/drivers/iio/humidity/Makefile b/drivers/iio/humidity/Makefile index ae4204995017..f19ff3de97c5 100644 --- a/drivers/iio/humidity/Makefile +++ b/drivers/iio/humidity/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_AM2315) += am2315.o obj-$(CONFIG_DHT11) += dht11.o obj-$(CONFIG_HDC100X) += hdc100x.o +obj-$(CONFIG_HDC2010) += hdc2010.o obj-$(CONFIG_HID_SENSOR_HUMIDITY) += hid-sensor-humidity.o hts221-y := hts221_core.o \ diff --git a/drivers/iio/humidity/hdc2010.c b/drivers/iio/humidity/hdc2010.c new file mode 100644 index 000000000000..744cb0f535b3 --- /dev/null +++ b/drivers/iio/humidity/hdc2010.c @@ -0,0 +1,353 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * hdc2010.c - Support for the TI HDC2010 and HDC2080 + * temperature + relative humidity sensors + * + * Copyright (C) 2020 Norphonic AS + * Author: Eugene Zaikonnikov + * + * Datasheet: https://www.ti.com/product/HDC2010/datasheet + * Datasheet: https://www.ti.com/product/HDC2080/datasheet + */ + +#include +#include +#include +#include + +#include +#include + +#define HDC2010_REG_TEMP_LOW 0x00 +#define HDC2010_REG_TEMP_HIGH 0x01 +#define HDC2010_REG_HUMIDITY_LOW 0x02 +#define HDC2010_REG_HUMIDITY_HIGH 0x03 +#define HDC2010_REG_INTERRUPT_DRDY 0x04 +#define HDC2010_REG_TEMP_MAX 0x05 +#define HDC2010_REG_HUMIDITY_MAX 0x06 +#define HDC2010_REG_INTERRUPT_EN 0x07 +#define HDC2010_REG_TEMP_OFFSET_ADJ 0x08 +#define HDC2010_REG_HUMIDITY_OFFSET_ADJ 0x09 +#define HDC2010_REG_TEMP_THR_L 0x0a +#define HDC2010_REG_TEMP_THR_H 0x0b +#define HDC2010_REG_RH_THR_L 0x0c +#define HDC2010_REG_RH_THR_H 0x0d +#define HDC2010_REG_RESET_DRDY_INT_CONF 0x0e +#define HDC2010_REG_MEASUREMENT_CONF 0x0f + +#define HDC2010_MEAS_CONF GENMASK(2, 1) +#define HDC2010_MEAS_TRIG BIT(0) +#define HDC2010_HEATER_EN BIT(3) +#define HDC2010_AMM GENMASK(6, 4) + +struct hdc2010_data { + struct i2c_client *client; + struct mutex lock; + u8 measurement_config; + u8 interrupt_config; + u8 drdy_config; +}; + +enum hdc2010_addr_groups { + HDC2010_GROUP_TEMP = 0, + HDC2010_GROUP_HUMIDITY, +}; + +struct hdc2010_reg_record { + unsigned long primary; + unsigned long peak; +}; + +static const struct hdc2010_reg_record hdc2010_reg_translation[] = { + [HDC2010_GROUP_TEMP] = { + .primary = HDC2010_REG_TEMP_LOW, + .peak = HDC2010_REG_TEMP_MAX, + }, + [HDC2010_GROUP_HUMIDITY] = { + .primary = HDC2010_REG_HUMIDITY_LOW, + .peak = HDC2010_REG_HUMIDITY_MAX, + }, +}; + +static IIO_CONST_ATTR(out_current_heater_raw_available, "0 1"); + +static struct attribute *hdc2010_attributes[] = { + &iio_const_attr_out_current_heater_raw_available.dev_attr.attr, + NULL +}; + +static const struct attribute_group hdc2010_attribute_group = { + .attrs = hdc2010_attributes, +}; + +static const struct iio_chan_spec hdc2010_channels[] = { + { + .type = IIO_TEMP, + .address = HDC2010_GROUP_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_PEAK) | + BIT(IIO_CHAN_INFO_OFFSET) | + BIT(IIO_CHAN_INFO_SCALE), + }, + { + .type = IIO_HUMIDITYRELATIVE, + .address = HDC2010_GROUP_HUMIDITY, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_PEAK) | + BIT(IIO_CHAN_INFO_SCALE), + }, + { + .type = IIO_CURRENT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .extend_name = "heater", + .output = 1, + }, +}; + +static int hdc2010_update_drdy_config(struct hdc2010_data *data, + char mask, char val) +{ + u8 tmp = (~mask & data->drdy_config) | val; + int ret; + + ret = i2c_smbus_write_byte_data(data->client, + HDC2010_REG_RESET_DRDY_INT_CONF, tmp); + if (ret) + return ret; + + data->drdy_config = tmp; + + return 0; +} + +static int hdc2010_get_prim_measurement_word(struct hdc2010_data *data, + struct iio_chan_spec const *chan) +{ + struct i2c_client *client = data->client; + s32 ret; + + ret = i2c_smbus_read_word_data(client, + hdc2010_reg_translation[chan->address].primary); + + if (ret < 0) + dev_err(&client->dev, "Could not read sensor measurement word\n"); + + return ret; +} + +static int hdc2010_get_peak_measurement_byte(struct hdc2010_data *data, + struct iio_chan_spec const *chan) +{ + struct i2c_client *client = data->client; + s32 ret; + + ret = i2c_smbus_read_byte_data(client, + hdc2010_reg_translation[chan->address].peak); + + if (ret < 0) + dev_err(&client->dev, "Could not read sensor measurement byte\n"); + + return ret; +} + +static int hdc2010_get_heater_status(struct hdc2010_data *data) +{ + return !!(data->drdy_config & HDC2010_HEATER_EN); +} + +static int hdc2010_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + struct hdc2010_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: { + int ret; + + if (chan->type == IIO_CURRENT) { + *val = hdc2010_get_heater_status(data); + return IIO_VAL_INT; + } + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + mutex_lock(&data->lock); + ret = hdc2010_get_prim_measurement_word(data, chan); + mutex_unlock(&data->lock); + iio_device_release_direct_mode(indio_dev); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + } + case IIO_CHAN_INFO_PEAK: { + int ret; + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + mutex_lock(&data->lock); + ret = hdc2010_get_peak_measurement_byte(data, chan); + mutex_unlock(&data->lock); + iio_device_release_direct_mode(indio_dev); + if (ret < 0) + return ret; + /* Scaling up the value so we can use same offset as RAW */ + *val = ret * 256; + return IIO_VAL_INT; + } + case IIO_CHAN_INFO_SCALE: + *val2 = 65536; + if (chan->type == IIO_TEMP) + *val = 165000; + else + *val = 100000; + return IIO_VAL_FRACTIONAL; + case IIO_CHAN_INFO_OFFSET: + *val = -15887; + *val2 = 515151; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +} + +static int hdc2010_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct hdc2010_data *data = iio_priv(indio_dev); + int new, ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (chan->type != IIO_CURRENT || val2 != 0) + return -EINVAL; + + switch (val) { + case 1: + new = HDC2010_HEATER_EN; + break; + case 0: + new = 0; + break; + default: + return -EINVAL; + } + + mutex_lock(&data->lock); + ret = hdc2010_update_drdy_config(data, HDC2010_HEATER_EN, new); + mutex_unlock(&data->lock); + return ret; + default: + return -EINVAL; + } +} + +static const struct iio_info hdc2010_info = { + .read_raw = hdc2010_read_raw, + .write_raw = hdc2010_write_raw, + .attrs = &hdc2010_attribute_group, +}; + +static int hdc2010_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct iio_dev *indio_dev; + struct hdc2010_data *data; + u8 tmp; + int ret; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C)) + return -EOPNOTSUPP; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + mutex_init(&data->lock); + + indio_dev->dev.parent = &client->dev; + /* + * As DEVICE ID register does not differentiate between + * HDC2010 and HDC2080, we have the name hardcoded + */ + indio_dev->name = "hdc2010"; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &hdc2010_info; + + indio_dev->channels = hdc2010_channels; + indio_dev->num_channels = ARRAY_SIZE(hdc2010_channels); + + /* Enable Automatic Measurement Mode at 5Hz */ + ret = hdc2010_update_drdy_config(data, HDC2010_AMM, HDC2010_AMM); + if (ret) + return ret; + + /* + * We enable both temp and humidity measurement. + * However the measurement won't start even in AMM until triggered. + */ + tmp = (data->measurement_config & ~HDC2010_MEAS_CONF) | + HDC2010_MEAS_TRIG; + + ret = i2c_smbus_write_byte_data(client, HDC2010_REG_MEASUREMENT_CONF, tmp); + if (ret) { + dev_warn(&client->dev, "Unable to set up measurement\n"); + if (hdc2010_update_drdy_config(data, HDC2010_AMM, 0)) + dev_warn(&client->dev, "Unable to restore default AMM\n"); + return ret; + }; + + data->measurement_config = tmp; + + return iio_device_register(indio_dev); +} + +static int hdc2010_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct hdc2010_data *data = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + /* Disable Automatic Measurement Mode */ + if (hdc2010_update_drdy_config(data, HDC2010_AMM, 0)) + dev_warn(&client->dev, "Unable to restore default AMM\n"); + + return 0; +} + +static const struct i2c_device_id hdc2010_id[] = { + { "hdc2010" }, + { "hdc2080" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, hdc2010_id); + +static const struct of_device_id hdc2010_dt_ids[] = { + { .compatible = "ti,hdc2010" }, + { .compatible = "ti,hdc2080" }, + { } +}; +MODULE_DEVICE_TABLE(of, hdc2010_dt_ids); + +static struct i2c_driver hdc2010_driver = { + .driver = { + .name = "hdc2010", + .of_match_table = hdc2010_dt_ids, + }, + .probe = hdc2010_probe, + .remove = hdc2010_remove, + .id_table = hdc2010_id, +}; +module_i2c_driver(hdc2010_driver); + +MODULE_AUTHOR("Eugene Zaikonnikov "); +MODULE_DESCRIPTION("TI HDC2010 humidity and temperature sensor driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 5dfb88af3d5204e581985056ccfb601d47252996 Mon Sep 17 00:00:00 2001 From: Vincent Whitchurch Date: Tue, 4 Aug 2020 11:31:38 +0200 Subject: iio: dac: dac5571: Support powerdown for multi-channel The driver currently only allows channel 0 to be powered down but the multi-channel variants of the hardware allow each channel to be powered down separately and with separate power down modes. Add support for this. Signed-off-by: Vincent Whitchurch Acked-by: Sean Nyekjaer Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ti-dac5571.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/dac/ti-dac5571.c b/drivers/iio/dac/ti-dac5571.c index 00fc7db8eb65..d303b19814e7 100644 --- a/drivers/iio/dac/ti-dac5571.c +++ b/drivers/iio/dac/ti-dac5571.c @@ -47,8 +47,8 @@ struct dac5571_data { struct mutex lock; struct regulator *vref; u16 val[4]; - bool powerdown; - u8 powerdown_mode; + bool powerdown[4]; + u8 powerdown_mode[4]; struct dac5571_spec const *spec; int (*dac5571_cmd)(struct dac5571_data *data, int channel, u16 val); int (*dac5571_pwrdwn)(struct dac5571_data *data, int channel, u8 pwrdwn); @@ -125,7 +125,7 @@ static int dac5571_get_powerdown_mode(struct iio_dev *indio_dev, { struct dac5571_data *data = iio_priv(indio_dev); - return data->powerdown_mode; + return data->powerdown_mode[chan->channel]; } static int dac5571_set_powerdown_mode(struct iio_dev *indio_dev, @@ -135,17 +135,17 @@ static int dac5571_set_powerdown_mode(struct iio_dev *indio_dev, struct dac5571_data *data = iio_priv(indio_dev); int ret = 0; - if (data->powerdown_mode == mode) + if (data->powerdown_mode[chan->channel] == mode) return 0; mutex_lock(&data->lock); - if (data->powerdown) { + if (data->powerdown[chan->channel]) { ret = data->dac5571_pwrdwn(data, chan->channel, DAC5571_POWERDOWN(mode)); if (ret) goto out; } - data->powerdown_mode = mode; + data->powerdown_mode[chan->channel] = mode; out: mutex_unlock(&data->lock); @@ -167,7 +167,7 @@ static ssize_t dac5571_read_powerdown(struct iio_dev *indio_dev, { struct dac5571_data *data = iio_priv(indio_dev); - return sprintf(buf, "%d\n", data->powerdown); + return sprintf(buf, "%d\n", data->powerdown[chan->channel]); } static ssize_t dac5571_write_powerdown(struct iio_dev *indio_dev, @@ -183,19 +183,20 @@ static ssize_t dac5571_write_powerdown(struct iio_dev *indio_dev, if (ret) return ret; - if (data->powerdown == powerdown) + if (data->powerdown[chan->channel] == powerdown) return len; mutex_lock(&data->lock); if (powerdown) ret = data->dac5571_pwrdwn(data, chan->channel, - DAC5571_POWERDOWN(data->powerdown_mode)); + DAC5571_POWERDOWN(data->powerdown_mode[chan->channel])); else - ret = data->dac5571_cmd(data, chan->channel, data->val[0]); + ret = data->dac5571_cmd(data, chan->channel, + data->val[chan->channel]); if (ret) goto out; - data->powerdown = powerdown; + data->powerdown[chan->channel] = powerdown; out: mutex_unlock(&data->lock); @@ -209,9 +210,9 @@ static const struct iio_chan_spec_ext_info dac5571_ext_info[] = { .name = "powerdown", .read = dac5571_read_powerdown, .write = dac5571_write_powerdown, - .shared = IIO_SHARED_BY_TYPE, + .shared = IIO_SEPARATE, }, - IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE, &dac5571_powerdown_mode), + IIO_ENUM("powerdown_mode", IIO_SEPARATE, &dac5571_powerdown_mode), IIO_ENUM_AVAILABLE("powerdown_mode", &dac5571_powerdown_mode), {}, }; @@ -276,7 +277,7 @@ static int dac5571_write_raw(struct iio_dev *indio_dev, if (val >= (1 << data->spec->resolution) || val < 0) return -EINVAL; - if (data->powerdown) + if (data->powerdown[chan->channel]) return -EBUSY; mutex_lock(&data->lock); -- cgit v1.2.3 From 245d56d75ea6860c583fbd54382ad82bbd405910 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Tue, 21 Jul 2020 18:14:44 +0100 Subject: iio:adc:bcm_iproc: Drop of_match_ptr protection and switch to mod_devicetable.h This driver cannot be instantiated from ACPI due to it's use of syscon_regmap_lookup_by_phandle() but in the interests of clearing this anti pattern out of IIO, let us switch to an explicit check in Kconfig and remove the protections on the of_match_table The switch of header is because we only use of_device_id in here and that is defined in mod_devicetable.h not of.h. Signed-off-by: Jonathan Cameron Cc: Raveendra Padasalagi Reviewed-by: Andy Shevchenko --- drivers/iio/adc/Kconfig | 2 +- drivers/iio/adc/bcm_iproc_adc.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 66d9cc073157..f495d01a79b9 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -340,7 +340,7 @@ config AXP288_ADC config BCM_IPROC_ADC tristate "Broadcom IPROC ADC driver" - depends on ARCH_BCM_IPROC || COMPILE_TEST + depends on (ARCH_BCM_IPROC && OF) || COMPILE_TEST depends on MFD_SYSCON default ARCH_BCM_CYGNUS help diff --git a/drivers/iio/adc/bcm_iproc_adc.c b/drivers/iio/adc/bcm_iproc_adc.c index 936da32faa9d..44e1e53ada72 100644 --- a/drivers/iio/adc/bcm_iproc_adc.c +++ b/drivers/iio/adc/bcm_iproc_adc.c @@ -4,7 +4,7 @@ */ #include -#include +#include #include #include #include @@ -617,7 +617,7 @@ static struct platform_driver iproc_adc_driver = { .remove = iproc_adc_remove, .driver = { .name = "iproc-static-adc", - .of_match_table = of_match_ptr(iproc_adc_of_match), + .of_match_table = iproc_adc_of_match, }, }; module_platform_driver(iproc_adc_driver); -- cgit v1.2.3 From ad5bd081c62be386e8f0fc360e452c6e9e3005a1 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Tue, 21 Jul 2020 18:14:43 +0100 Subject: iio:adc:ti-adc128s052: drop of_match_ptr protection There is no real advantage in having these protections and for parts that do not have an explicit ACPI ID, it prevents the use of PRP0001. I'm trying to clear this out of IIO in general to avoid copying in new drivers. Include mod_devicetable.h as we are using of_device_id in here so including that header is best practice. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Angelo Compagnucci --- drivers/iio/adc/ti-adc128s052.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/ti-adc128s052.c b/drivers/iio/adc/ti-adc128s052.c index e86f55ce093f..3143f35a6509 100644 --- a/drivers/iio/adc/ti-adc128s052.c +++ b/drivers/iio/adc/ti-adc128s052.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -220,7 +221,7 @@ MODULE_DEVICE_TABLE(acpi, adc128_acpi_match); static struct spi_driver adc128_driver = { .driver = { .name = "adc128s052", - .of_match_table = of_match_ptr(adc128_of_match), + .of_match_table = adc128_of_match, .acpi_match_table = ACPI_PTR(adc128_acpi_match), }, .probe = adc128_probe, -- cgit v1.2.3 From 0a4596f5bd5ae3d234803353b14deef26663722e Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Tue, 21 Jul 2020 18:14:42 +0100 Subject: iio:adc:ti-adc108s102: Drop CONFIG_OF and of_match_ptr protections I'm trying to clean this (now) anti-pattern out of IIO to avoid cut and paste into new drivers. Also add an include of mod_devicetable.h as the driver directly uses struct of_device_id which is defined in there. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Jan Kiszka --- drivers/iio/adc/ti-adc108s102.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/ti-adc108s102.c b/drivers/iio/adc/ti-adc108s102.c index 9b9b27415c93..183b2245e89b 100644 --- a/drivers/iio/adc/ti-adc108s102.c +++ b/drivers/iio/adc/ti-adc108s102.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -299,13 +300,11 @@ static int adc108s102_remove(struct spi_device *spi) return 0; } -#ifdef CONFIG_OF static const struct of_device_id adc108s102_of_match[] = { { .compatible = "ti,adc108s102" }, { } }; MODULE_DEVICE_TABLE(of, adc108s102_of_match); -#endif #ifdef CONFIG_ACPI static const struct acpi_device_id adc108s102_acpi_ids[] = { @@ -324,7 +323,7 @@ MODULE_DEVICE_TABLE(spi, adc108s102_id); static struct spi_driver adc108s102_driver = { .driver = { .name = "adc108s102", - .of_match_table = of_match_ptr(adc108s102_of_match), + .of_match_table = adc108s102_of_match, .acpi_match_table = ACPI_PTR(adc108s102_acpi_ids), }, .probe = adc108s102_probe, -- cgit v1.2.3 From c458b7ca3fd0c9671caf38630e6f6a006d90e113 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Tue, 21 Jul 2020 18:14:41 +0100 Subject: iio:adc:ti-adc081c: Drop ACPI ids that seem very unlikely to be official. We have no known users of these in the wild. it seems very unlikely these are real IDs having the form ADCXXXX as that ID is owned by Achnor Datacomm not TI. Suggested-by: Andy Shevchenko Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko --- drivers/iio/adc/ti-adc081c.c | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c index 9426f70a8005..8bc04cfae465 100644 --- a/drivers/iio/adc/ti-adc081c.c +++ b/drivers/iio/adc/ti-adc081c.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -153,17 +152,7 @@ static int adc081c_probe(struct i2c_client *client, if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) return -EOPNOTSUPP; - if (ACPI_COMPANION(&client->dev)) { - const struct acpi_device_id *ad_id; - - ad_id = acpi_match_device(client->dev.driver->acpi_match_table, - &client->dev); - if (!ad_id) - return -ENODEV; - model = &adcxx1c_models[ad_id->driver_data]; - } else { - model = &adcxx1c_models[id->driver_data]; - } + model = &adcxx1c_models[id->driver_data]; iio = devm_iio_device_alloc(&client->dev, sizeof(*adc)); if (!iio) @@ -238,21 +227,10 @@ static const struct of_device_id adc081c_of_match[] = { }; MODULE_DEVICE_TABLE(of, adc081c_of_match); -#ifdef CONFIG_ACPI -static const struct acpi_device_id adc081c_acpi_match[] = { - { "ADC081C", ADC081C }, - { "ADC101C", ADC101C }, - { "ADC121C", ADC121C }, - { } -}; -MODULE_DEVICE_TABLE(acpi, adc081c_acpi_match); -#endif - static struct i2c_driver adc081c_driver = { .driver = { .name = "adc081c", .of_match_table = adc081c_of_match, - .acpi_match_table = ACPI_PTR(adc081c_acpi_match), }, .probe = adc081c_probe, .remove = adc081c_remove, -- cgit v1.2.3 From ea3e611b29b201612a0e9fcb32727f80d66bc053 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Fri, 14 Aug 2020 06:49:41 -0700 Subject: iio: health: max30102: update author's email Update email to author's current employer Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- drivers/iio/health/max30102.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c index 9b47d9472a4f..bb504e993f19 100644 --- a/drivers/iio/health/max30102.c +++ b/drivers/iio/health/max30102.c @@ -2,7 +2,7 @@ /* * max30102.c - Support for MAX30102 heart rate and pulse oximeter sensor * - * Copyright (C) 2017 Matt Ranostay + * Copyright (C) 2017 Matt Ranostay * * Support for MAX30105 optical particle sensor * Copyright (C) 2017 Peter Meerwald-Stadler @@ -632,6 +632,6 @@ static struct i2c_driver max30102_driver = { }; module_i2c_driver(max30102_driver); -MODULE_AUTHOR("Matt Ranostay "); +MODULE_AUTHOR("Matt Ranostay "); MODULE_DESCRIPTION("MAX30102 heart rate/pulse oximeter and MAX30105 particle sensor driver"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 81f434f01722c8f95c59fc24c5e09f508a07a0ca Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 9 Aug 2020 15:13:05 +0100 Subject: iio:adc:axp20x: Convert from OF to generic fw / device properties Whilst fairly unlikely anyone will ever use this driver with anything other than DT, we are trying to move IIO over to the generic interfaces where easy to do so. In this case this involved moving to generic check on presence of fwnode, generic device_get_match_data() and dropping the of_match_ptr protection. Also relevant header changes to have property.h and mod_devicetable.h only. Also drop the casting away of a const in favour of retaining the const throughout. Signed-off-by: Jonathan Cameron Cc: Quentin Schulz Reviewed-by: Andy Shevchenko --- drivers/iio/adc/axp20x_adc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/axp20x_adc.c b/drivers/iio/adc/axp20x_adc.c index 798ff2d89691..3e0c0233b431 100644 --- a/drivers/iio/adc/axp20x_adc.c +++ b/drivers/iio/adc/axp20x_adc.c @@ -9,10 +9,10 @@ #include #include #include -#include -#include +#include #include #include +#include #include #include @@ -67,7 +67,7 @@ struct axp_data; struct axp20x_adc_iio { struct regmap *regmap; - struct axp_data *data; + const struct axp_data *data; }; enum axp20x_adc_channel_v { @@ -670,15 +670,15 @@ static int axp20x_probe(struct platform_device *pdev) info->regmap = axp20x_dev->regmap; indio_dev->modes = INDIO_DIRECT_MODE; - if (!pdev->dev.of_node) { + if (!dev_fwnode(&pdev->dev)) { const struct platform_device_id *id; id = platform_get_device_id(pdev); - info->data = (struct axp_data *)id->driver_data; + info->data = (const struct axp_data *)id->driver_data; } else { struct device *dev = &pdev->dev; - info->data = (struct axp_data *)of_device_get_match_data(dev); + info->data = device_get_match_data(dev); } indio_dev->name = platform_get_device_id(pdev)->name; @@ -742,7 +742,7 @@ static int axp20x_remove(struct platform_device *pdev) static struct platform_driver axp20x_adc_driver = { .driver = { .name = "axp20x-adc", - .of_match_table = of_match_ptr(axp20x_adc_of_match), + .of_match_table = axp20x_adc_of_match, }, .id_table = axp20x_adc_id_match, .probe = axp20x_probe, -- cgit v1.2.3 From 59713492b7866e031e0c66e25f4f034c96f1be5a Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Tue, 26 May 2020 23:02:21 +0200 Subject: iio: dac: ad5686: Constify static struct iio_chan_spec These are never modified and can be made const to allow the compiler to put it in read-only memory. Before: text data bss dec hex filename 6642 12608 64 19314 4b72 drivers/iio/dac/ad5686.o After: text data bss dec hex filename 16946 2304 64 19314 4b72 drivers/iio/dac/ad5686.o Signed-off-by: Rikard Falkeborn Acked-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5686.c | 8 ++++---- drivers/iio/dac/ad5686.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c index 56cf9344d187..148d9541f517 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c @@ -206,12 +206,12 @@ static const struct iio_chan_spec_ext_info ad5686_ext_info[] = { } #define DECLARE_AD5693_CHANNELS(name, bits, _shift) \ -static struct iio_chan_spec name[] = { \ +static const struct iio_chan_spec name[] = { \ AD5868_CHANNEL(0, 0, bits, _shift), \ } #define DECLARE_AD5686_CHANNELS(name, bits, _shift) \ -static struct iio_chan_spec name[] = { \ +static const struct iio_chan_spec name[] = { \ AD5868_CHANNEL(0, 1, bits, _shift), \ AD5868_CHANNEL(1, 2, bits, _shift), \ AD5868_CHANNEL(2, 4, bits, _shift), \ @@ -219,7 +219,7 @@ static struct iio_chan_spec name[] = { \ } #define DECLARE_AD5676_CHANNELS(name, bits, _shift) \ -static struct iio_chan_spec name[] = { \ +static const struct iio_chan_spec name[] = { \ AD5868_CHANNEL(0, 0, bits, _shift), \ AD5868_CHANNEL(1, 1, bits, _shift), \ AD5868_CHANNEL(2, 2, bits, _shift), \ @@ -231,7 +231,7 @@ static struct iio_chan_spec name[] = { \ } #define DECLARE_AD5679_CHANNELS(name, bits, _shift) \ -static struct iio_chan_spec name[] = { \ +static const struct iio_chan_spec name[] = { \ AD5868_CHANNEL(0, 0, bits, _shift), \ AD5868_CHANNEL(1, 1, bits, _shift), \ AD5868_CHANNEL(2, 2, bits, _shift), \ diff --git a/drivers/iio/dac/ad5686.h b/drivers/iio/dac/ad5686.h index 52009b5eef88..a15f2970577e 100644 --- a/drivers/iio/dac/ad5686.h +++ b/drivers/iio/dac/ad5686.h @@ -104,7 +104,7 @@ typedef int (*ad5686_read_func)(struct ad5686_state *st, u8 addr); struct ad5686_chip_info { u16 int_vref_mv; unsigned int num_channels; - struct iio_chan_spec *channels; + const struct iio_chan_spec *channels; enum ad5686_regmap_type regmap_type; }; -- cgit v1.2.3 From f6712ed711236159e99ed48221ba41c931721503 Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Thu, 20 Aug 2020 11:01:26 +0800 Subject: iio: adc: adi-axi-adc: Use kobj_to_dev() instead of container_of() Use kobj_to_dev() instead of container_of() Signed-off-by: Tian Tao Acked-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/adc/adi-axi-adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c index 86b6b65916ee..9109da2d2e15 100644 --- a/drivers/iio/adc/adi-axi-adc.c +++ b/drivers/iio/adc/adi-axi-adc.c @@ -276,7 +276,7 @@ static struct attribute *adi_axi_adc_attributes[] = { static umode_t axi_adc_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct adi_axi_adc_state *st = iio_priv(indio_dev); struct adi_axi_adc_conv *conv = &st->client->conv; -- cgit v1.2.3 From dc3ebfcaa51ff9ffa417f23e47c4e1aa01bc501d Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Mon, 17 Aug 2020 03:50:52 +0300 Subject: iio: chemical: atlas-ezo-sensor: add humidity sensor support Add support for atlas,hum-ezo / humidity sensor which with scaling provides respective data in millipercent Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- drivers/iio/chemical/atlas-ezo-sensor.c | 37 ++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/chemical/atlas-ezo-sensor.c b/drivers/iio/chemical/atlas-ezo-sensor.c index 60a0c752fbc5..b1bacfe3c3ce 100644 --- a/drivers/iio/chemical/atlas-ezo-sensor.c +++ b/drivers/iio/chemical/atlas-ezo-sensor.c @@ -17,10 +17,12 @@ #define ATLAS_EZO_DRV_NAME "atlas-ezo-sensor" #define ATLAS_INT_TIME_IN_MS 950 +#define ATLAS_INT_HUM_TIME_IN_MS 350 enum { ATLAS_CO2_EZO, ATLAS_O2_EZO, + ATLAS_HUM_EZO, }; struct atlas_ezo_device { @@ -63,6 +65,21 @@ static const struct iio_chan_spec atlas_o2_ezo_channels[] = { ATLAS_CONCENTRATION_CHANNEL(IIO_MOD_O2), }; +static const struct iio_chan_spec atlas_hum_ezo_channels[] = { + { + .type = IIO_HUMIDITYRELATIVE, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 0, + .scan_type = { + .sign = 'u', + .realbits = 32, + .storagebits = 32, + .endianness = IIO_CPU, + }, + }, +}; + static struct atlas_ezo_device atlas_ezo_devices[] = { [ATLAS_CO2_EZO] = { .channels = atlas_co2_ezo_channels, @@ -73,7 +90,12 @@ static struct atlas_ezo_device atlas_ezo_devices[] = { .channels = atlas_o2_ezo_channels, .num_channels = 1, .delay = ATLAS_INT_TIME_IN_MS, - } + }, + [ATLAS_HUM_EZO] = { + .channels = atlas_hum_ezo_channels, + .num_channels = 1, + .delay = ATLAS_INT_HUM_TIME_IN_MS, + }, }; static void atlas_ezo_sanitize(char *buf) @@ -131,6 +153,17 @@ static int atlas_ezo_read_raw(struct iio_dev *indio_dev, return ret ? ret : IIO_VAL_INT; } case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_HUMIDITYRELATIVE: + *val = 10; + return IIO_VAL_INT; + case IIO_CONCENTRATION: + break; + default: + return -EINVAL; + } + + /* IIO_CONCENTRATION modifiers */ switch (chan->channel2) { case IIO_MOD_CO2: *val = 0; @@ -153,6 +186,7 @@ static const struct iio_info atlas_info = { static const struct i2c_device_id atlas_ezo_id[] = { { "atlas-co2-ezo", ATLAS_CO2_EZO }, { "atlas-o2-ezo", ATLAS_O2_EZO }, + { "atlas-hum-ezo", ATLAS_HUM_EZO }, {} }; MODULE_DEVICE_TABLE(i2c, atlas_ezo_id); @@ -160,6 +194,7 @@ MODULE_DEVICE_TABLE(i2c, atlas_ezo_id); static const struct of_device_id atlas_ezo_dt_ids[] = { { .compatible = "atlas,co2-ezo", .data = (void *)ATLAS_CO2_EZO, }, { .compatible = "atlas,o2-ezo", .data = (void *)ATLAS_O2_EZO, }, + { .compatible = "atlas,hum-ezo", .data = (void *)ATLAS_HUM_EZO, }, {} }; MODULE_DEVICE_TABLE(of, atlas_ezo_dt_ids); -- cgit v1.2.3 From 3bdb1255e6b0a49e83412ad0d15eb2b2f7f63482 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:09 +0200 Subject: iio: accel: bma180: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and also it prints the error value. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200829064726.26268-1-krzk@kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bma180.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index 5b7a467c7b27..448faed001fd 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -1000,19 +1000,15 @@ static int bma180_probe(struct i2c_client *client, return ret; data->vdd_supply = devm_regulator_get(dev, "vdd"); - if (IS_ERR(data->vdd_supply)) { - if (PTR_ERR(data->vdd_supply) != -EPROBE_DEFER) - dev_err(dev, "Failed to get vdd regulator %d\n", - (int)PTR_ERR(data->vdd_supply)); - return PTR_ERR(data->vdd_supply); - } + if (IS_ERR(data->vdd_supply)) + return dev_err_probe(dev, PTR_ERR(data->vdd_supply), + "Failed to get vdd regulator\n"); + data->vddio_supply = devm_regulator_get(dev, "vddio"); - if (IS_ERR(data->vddio_supply)) { - if (PTR_ERR(data->vddio_supply) != -EPROBE_DEFER) - dev_err(dev, "Failed to get vddio regulator %d\n", - (int)PTR_ERR(data->vddio_supply)); - return PTR_ERR(data->vddio_supply); - } + if (IS_ERR(data->vddio_supply)) + return dev_err_probe(dev, PTR_ERR(data->vddio_supply), + "Failed to get vddio regulator\n"); + /* Typical voltage 2.4V these are min and max */ ret = regulator_set_voltage(data->vdd_supply, 1620000, 3600000); if (ret) -- cgit v1.2.3 From c8b9a02361d99364faddbf1193b85d476f35cfd3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:10 +0200 Subject: iio: accel: mma8452: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and also it prints the error value. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200829064726.26268-2-krzk@kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma8452.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index ba27f8673131..9b5f23b3a5fb 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -1538,22 +1538,14 @@ static int mma8452_probe(struct i2c_client *client, data->chip_info = match->data; data->vdd_reg = devm_regulator_get(&client->dev, "vdd"); - if (IS_ERR(data->vdd_reg)) { - if (PTR_ERR(data->vdd_reg) == -EPROBE_DEFER) - return -EPROBE_DEFER; - - dev_err(&client->dev, "failed to get VDD regulator!\n"); - return PTR_ERR(data->vdd_reg); - } + 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)) { - if (PTR_ERR(data->vddio_reg) == -EPROBE_DEFER) - return -EPROBE_DEFER; - - dev_err(&client->dev, "failed to get VDDIO regulator!\n"); - return PTR_ERR(data->vddio_reg); - } + 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); if (ret) { -- cgit v1.2.3 From 55dc295200e60fd4a334098dd4c036eff9e9ead3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:11 +0200 Subject: iio: adc: envelope-detector: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and also it prints the error value. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Andy Shevchenko Acked-by: Peter Rosin Link: https://lore.kernel.org/r/20200829064726.26268-3-krzk@kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/adc/envelope-detector.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/envelope-detector.c b/drivers/iio/adc/envelope-detector.c index 2a4fd3bb64cf..d73eac36153f 100644 --- a/drivers/iio/adc/envelope-detector.c +++ b/drivers/iio/adc/envelope-detector.c @@ -348,11 +348,9 @@ static int envelope_detector_probe(struct platform_device *pdev) indio_dev->num_channels = 1; env->dac = devm_iio_channel_get(dev, "dac"); - if (IS_ERR(env->dac)) { - if (PTR_ERR(env->dac) != -EPROBE_DEFER) - dev_err(dev, "failed to get dac input channel\n"); - return PTR_ERR(env->dac); - } + if (IS_ERR(env->dac)) + return dev_err_probe(dev, PTR_ERR(env->dac), + "failed to get dac input channel\n"); env->comp_irq = platform_get_irq_byname(pdev, "comp"); if (env->comp_irq < 0) @@ -360,11 +358,9 @@ static int envelope_detector_probe(struct platform_device *pdev) ret = devm_request_irq(dev, env->comp_irq, envelope_detector_comp_isr, 0, "envelope-detector", env); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to request interrupt\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "failed to request interrupt\n"); + env->comp_irq_trigger = irq_get_trigger_type(env->comp_irq); if (env->comp_irq_trigger & IRQF_TRIGGER_RISING) env->comp_irq_trigger_inv |= IRQF_TRIGGER_FALLING; -- cgit v1.2.3 From 1030b5bc68ae572467122bfe7aa48b118e942c52 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:12 +0200 Subject: iio: adc: exynos_adc: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and also it prints the error value. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200829064726.26268-4-krzk@kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/adc/exynos_adc.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c index 7d23b6c33284..20477b249f2a 100644 --- a/drivers/iio/adc/exynos_adc.c +++ b/drivers/iio/adc/exynos_adc.c @@ -844,13 +844,9 @@ static int exynos_adc_probe(struct platform_device *pdev) } info->vdd = devm_regulator_get(&pdev->dev, "vdd"); - if (IS_ERR(info->vdd)) { - if (PTR_ERR(info->vdd) != -EPROBE_DEFER) - dev_err(&pdev->dev, - "failed getting regulator, err = %ld\n", - PTR_ERR(info->vdd)); - return PTR_ERR(info->vdd); - } + if (IS_ERR(info->vdd)) + return dev_err_probe(&pdev->dev, PTR_ERR(info->vdd), + "failed getting regulator"); ret = regulator_enable(info->vdd); if (ret) -- cgit v1.2.3 From 291cb0b37af611503ccacff752ac0fc920b0a21b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:13 +0200 Subject: iio: adc: ltc2497: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and also it prints the error value. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200829064726.26268-5-krzk@kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ltc2497-core.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/ltc2497-core.c b/drivers/iio/adc/ltc2497-core.c index 9b8fd9c32364..2a485c8a1940 100644 --- a/drivers/iio/adc/ltc2497-core.c +++ b/drivers/iio/adc/ltc2497-core.c @@ -180,13 +180,9 @@ int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev) return ret; ddata->ref = devm_regulator_get(dev, "vref"); - if (IS_ERR(ddata->ref)) { - if (PTR_ERR(ddata->ref) != -EPROBE_DEFER) - dev_err(dev, "Failed to get vref regulator: %pe\n", - ddata->ref); - - return PTR_ERR(ddata->ref); - } + if (IS_ERR(ddata->ref)) + return dev_err_probe(dev, PTR_ERR(ddata->ref), + "Failed to get vref regulator\n"); ret = regulator_enable(ddata->ref); if (ret < 0) { -- cgit v1.2.3 From a3e584fab675b833e9923a0f5e76031b027525d9 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:14 +0200 Subject: iio: adc: meson_saradc: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and also it prints the error value. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Andy Shevchenko Acked-by: Martin Blumenstingl Link: https://lore.kernel.org/r/20200829064726.26268-6-krzk@kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/adc/meson_saradc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index 93c2252c0b89..a9d06e8a576a 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -719,11 +719,8 @@ static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev) if (ret == -ENODEV) return 0; - if (ret != -EPROBE_DEFER) - dev_err(indio_dev->dev.parent, - "failed to get temperature_calib cell\n"); - - return ret; + return dev_err_probe(indio_dev->dev.parent, ret, + "failed to get temperature_calib cell\n"); } priv->tsc_regmap = -- cgit v1.2.3 From 6d2710ce2c45122eea4ccdb4cee1fd56e6702cea Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:15 +0200 Subject: iio: adc: rcar-gyroadc: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and also it prints the error value. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200829064726.26268-7-krzk@kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/adc/rcar-gyroadc.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/rcar-gyroadc.c b/drivers/iio/adc/rcar-gyroadc.c index d2c1419e72a0..dcaefc108ff6 100644 --- a/drivers/iio/adc/rcar-gyroadc.c +++ b/drivers/iio/adc/rcar-gyroadc.c @@ -495,12 +495,9 @@ static int rcar_gyroadc_probe(struct platform_device *pdev) return PTR_ERR(priv->regs); priv->clk = devm_clk_get(dev, "fck"); - if (IS_ERR(priv->clk)) { - ret = PTR_ERR(priv->clk); - if (ret != -EPROBE_DEFER) - dev_err(dev, "Failed to get IF clock (ret=%i)\n", ret); - return ret; - } + if (IS_ERR(priv->clk)) + return dev_err_probe(dev, PTR_ERR(priv->clk), + "Failed to get IF clock\n"); ret = rcar_gyroadc_parse_subdevs(indio_dev); if (ret) -- cgit v1.2.3 From ce30eeb613cbde817ae3c041505a3181cccb9d35 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:16 +0200 Subject: iio: adc: stm32: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and also it prints the error value. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200829064726.26268-8-krzk@kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stm32-adc-core.c | 75 +++++++++++++------------------------- drivers/iio/adc/stm32-adc.c | 10 ++--- drivers/iio/adc/stm32-dfsdm-adc.c | 10 ++--- drivers/iio/adc/stm32-dfsdm-core.c | 9 ++--- drivers/iio/dac/stm32-dac-core.c | 5 +-- 5 files changed, 35 insertions(+), 74 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c index 0e2068ec068b..3f27b4817a42 100644 --- a/drivers/iio/adc/stm32-adc-core.c +++ b/drivers/iio/adc/stm32-adc-core.c @@ -582,11 +582,9 @@ static int stm32_adc_core_switches_probe(struct device *dev, priv->syscfg = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); if (IS_ERR(priv->syscfg)) { ret = PTR_ERR(priv->syscfg); - if (ret != -ENODEV) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "Can't probe syscfg: %d\n", ret); - return ret; - } + if (ret != -ENODEV) + return dev_err_probe(dev, ret, "Can't probe syscfg\n"); + priv->syscfg = NULL; } @@ -596,12 +594,9 @@ static int stm32_adc_core_switches_probe(struct device *dev, priv->booster = devm_regulator_get_optional(dev, "booster"); if (IS_ERR(priv->booster)) { ret = PTR_ERR(priv->booster); - if (ret != -ENODEV) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "can't get booster %d\n", - ret); - return ret; - } + if (ret != -ENODEV) + dev_err_probe(dev, ret, "can't get booster\n"); + priv->booster = NULL; } } @@ -612,11 +607,9 @@ static int stm32_adc_core_switches_probe(struct device *dev, priv->vdd = devm_regulator_get_optional(dev, "vdd"); if (IS_ERR(priv->vdd)) { ret = PTR_ERR(priv->vdd); - if (ret != -ENODEV) { - if (ret != -EPROBE_DEFER) - dev_err(dev, "can't get vdd %d\n", ret); - return ret; - } + if (ret != -ENODEV) + return dev_err_probe(dev, ret, "can't get vdd\n"); + priv->vdd = NULL; } } @@ -669,42 +662,24 @@ static int stm32_adc_probe(struct platform_device *pdev) priv->common.phys_base = res->start; priv->vdda = devm_regulator_get(&pdev->dev, "vdda"); - if (IS_ERR(priv->vdda)) { - ret = PTR_ERR(priv->vdda); - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "vdda get failed, %d\n", ret); - return ret; - } + if (IS_ERR(priv->vdda)) + return dev_err_probe(&pdev->dev, PTR_ERR(priv->vdda), + "vdda get failed\n"); priv->vref = devm_regulator_get(&pdev->dev, "vref"); - if (IS_ERR(priv->vref)) { - ret = PTR_ERR(priv->vref); - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "vref get failed, %d\n", ret); - return ret; - } - - priv->aclk = devm_clk_get(&pdev->dev, "adc"); - if (IS_ERR(priv->aclk)) { - ret = PTR_ERR(priv->aclk); - if (ret != -ENOENT) { - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "Can't get 'adc' clock\n"); - return ret; - } - priv->aclk = NULL; - } - - priv->bclk = devm_clk_get(&pdev->dev, "bus"); - if (IS_ERR(priv->bclk)) { - ret = PTR_ERR(priv->bclk); - if (ret != -ENOENT) { - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "Can't get 'bus' clock\n"); - return ret; - } - priv->bclk = NULL; - } + if (IS_ERR(priv->vref)) + return dev_err_probe(&pdev->dev, PTR_ERR(priv->vref), + "vref get failed\n"); + + priv->aclk = devm_clk_get_optional(&pdev->dev, "adc"); + if (IS_ERR(priv->aclk)) + return dev_err_probe(&pdev->dev, PTR_ERR(priv->aclk), + "Can't get 'adc' clock\n"); + + priv->bclk = devm_clk_get_optional(&pdev->dev, "bus"); + if (IS_ERR(priv->bclk)) + return dev_err_probe(&pdev->dev, PTR_ERR(priv->bclk), + "Can't get 'bus' clock\n"); ret = stm32_adc_core_switches_probe(dev, priv); if (ret) diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index 3eb9ebe8372f..b3f31f147347 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -1805,13 +1805,9 @@ static int stm32_adc_dma_request(struct device *dev, struct iio_dev *indio_dev) adc->dma_chan = dma_request_chan(dev, "rx"); if (IS_ERR(adc->dma_chan)) { ret = PTR_ERR(adc->dma_chan); - if (ret != -ENODEV) { - if (ret != -EPROBE_DEFER) - dev_err(dev, - "DMA channel request failed with %d\n", - ret); - return ret; - } + if (ret != -ENODEV) + return dev_err_probe(dev, ret, + "DMA channel request failed with\n"); /* DMA is optional: fall back to IRQ mode */ adc->dma_chan = NULL; diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index 5e10fb4f3704..c7e0109315f8 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -1473,13 +1473,9 @@ static int stm32_dfsdm_adc_init(struct device *dev, struct iio_dev *indio_dev) /* Optionally request DMA */ ret = stm32_dfsdm_dma_request(dev, indio_dev); if (ret) { - if (ret != -ENODEV) { - if (ret != -EPROBE_DEFER) - dev_err(dev, - "DMA channel request failed with %d\n", - ret); - return ret; - } + if (ret != -ENODEV) + return dev_err_probe(dev, ret, + "DMA channel request failed with\n"); dev_dbg(dev, "No DMA support\n"); return 0; diff --git a/drivers/iio/adc/stm32-dfsdm-core.c b/drivers/iio/adc/stm32-dfsdm-core.c index 26e2011c5868..0b8bea88b011 100644 --- a/drivers/iio/adc/stm32-dfsdm-core.c +++ b/drivers/iio/adc/stm32-dfsdm-core.c @@ -243,12 +243,9 @@ static int stm32_dfsdm_parse_of(struct platform_device *pdev, * on use case. */ priv->clk = devm_clk_get(&pdev->dev, "dfsdm"); - if (IS_ERR(priv->clk)) { - ret = PTR_ERR(priv->clk); - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "Failed to get clock (%d)\n", ret); - return ret; - } + if (IS_ERR(priv->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(priv->clk), + "Failed to get clock\n"); priv->aclk = devm_clk_get(&pdev->dev, "audio"); if (IS_ERR(priv->aclk)) diff --git a/drivers/iio/dac/stm32-dac-core.c b/drivers/iio/dac/stm32-dac-core.c index 7e5809ba0dee..906436780347 100644 --- a/drivers/iio/dac/stm32-dac-core.c +++ b/drivers/iio/dac/stm32-dac-core.c @@ -150,10 +150,7 @@ static int stm32_dac_probe(struct platform_device *pdev) rst = devm_reset_control_get_optional_exclusive(dev, NULL); if (rst) { if (IS_ERR(rst)) { - ret = PTR_ERR(rst); - if (ret != -EPROBE_DEFER) - dev_err(dev, "reset get failed, %d\n", ret); - + ret = dev_err_probe(dev, PTR_ERR(rst), "reset get failed\n"); goto err_hw_stop; } -- cgit v1.2.3 From bfa96be8a49c1548b7d1311022262676d7fc6f30 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:17 +0200 Subject: iio: afe: iio-rescale: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and also it prints the error value. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Andy Shevchenko Acked-by: Peter Rosin Link: https://lore.kernel.org/r/20200829064726.26268-9-krzk@kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/afe/iio-rescale.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c index 69c0f277ada0..e42ea2b1707d 100644 --- a/drivers/iio/afe/iio-rescale.c +++ b/drivers/iio/afe/iio-rescale.c @@ -276,11 +276,9 @@ static int rescale_probe(struct platform_device *pdev) int ret; source = devm_iio_channel_get(dev, NULL); - if (IS_ERR(source)) { - if (PTR_ERR(source) != -EPROBE_DEFER) - dev_err(dev, "failed to get source channel\n"); - return PTR_ERR(source); - } + if (IS_ERR(source)) + return dev_err_probe(dev, PTR_ERR(source), + "failed to get source channel\n"); sizeof_ext_info = iio_get_channel_ext_info_count(source); if (sizeof_ext_info) { -- cgit v1.2.3 From 8facae29c468bd4ac1cabb440cdbac47ac9ac9e1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:18 +0200 Subject: iio: amplifiers: hmc425a: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and also it prints the error value. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200829064726.26268-10-krzk@kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/amplifiers/hmc425a.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/amplifiers/hmc425a.c b/drivers/iio/amplifiers/hmc425a.c index 582708924e4f..9efa692151f0 100644 --- a/drivers/iio/amplifiers/hmc425a.c +++ b/drivers/iio/amplifiers/hmc425a.c @@ -201,12 +201,9 @@ static int hmc425a_probe(struct platform_device *pdev) st->gain = st->chip_info->default_gain; st->gpios = devm_gpiod_get_array(&pdev->dev, "ctrl", GPIOD_OUT_LOW); - if (IS_ERR(st->gpios)) { - ret = PTR_ERR(st->gpios); - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "failed to get gpios\n"); - return ret; - } + if (IS_ERR(st->gpios)) + return dev_err_probe(&pdev->dev, PTR_ERR(st->gpios), + "failed to get gpios\n"); if (st->gpios->ndescs != st->chip_info->num_gpios) { dev_err(&pdev->dev, "%d GPIOs needed to operate\n", -- cgit v1.2.3 From ed1759093cacbe359597fce1ca0f2831ccb96deb Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:19 +0200 Subject: iio: chemical: scd30: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and also it prints the error value. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Andy Shevchenko Acked-by: Tomasz Duszynski Link: https://lore.kernel.org/r/20200829064726.26268-11-krzk@kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/chemical/scd30_core.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/chemical/scd30_core.c b/drivers/iio/chemical/scd30_core.c index eac76972f83e..4d0d798c7cd3 100644 --- a/drivers/iio/chemical/scd30_core.c +++ b/drivers/iio/chemical/scd30_core.c @@ -705,13 +705,8 @@ int scd30_probe(struct device *dev, int irq, const char *name, void *priv, indio_dev->available_scan_masks = scd30_scan_masks; state->vdd = devm_regulator_get(dev, "vdd"); - if (IS_ERR(state->vdd)) { - if (PTR_ERR(state->vdd) == -EPROBE_DEFER) - return -EPROBE_DEFER; - - dev_err(dev, "failed to get regulator\n"); - return PTR_ERR(state->vdd); - } + if (IS_ERR(state->vdd)) + return dev_err_probe(dev, PTR_ERR(state->vdd), "failed to get regulator\n"); ret = regulator_enable(state->vdd); if (ret) -- cgit v1.2.3 From a567abf66ec8346ff5e7ad2ed5192136d6c838e7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:20 +0200 Subject: iio: dac: dpot-dac: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and also it prints the error value. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Andy Shevchenko Acked-by: Peter Rosin Link: https://lore.kernel.org/r/20200829064726.26268-12-krzk@kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/dac/dpot-dac.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/dac/dpot-dac.c b/drivers/iio/dac/dpot-dac.c index b3835fb6b862..d2431d734905 100644 --- a/drivers/iio/dac/dpot-dac.c +++ b/drivers/iio/dac/dpot-dac.c @@ -183,18 +183,14 @@ static int dpot_dac_probe(struct platform_device *pdev) indio_dev->num_channels = 1; dac->vref = devm_regulator_get(dev, "vref"); - if (IS_ERR(dac->vref)) { - if (PTR_ERR(dac->vref) != -EPROBE_DEFER) - dev_err(&pdev->dev, "failed to get vref regulator\n"); - return PTR_ERR(dac->vref); - } + if (IS_ERR(dac->vref)) + return dev_err_probe(&pdev->dev, PTR_ERR(dac->vref), + "failed to get vref regulator\n"); dac->dpot = devm_iio_channel_get(dev, "dpot"); - if (IS_ERR(dac->dpot)) { - if (PTR_ERR(dac->dpot) != -EPROBE_DEFER) - dev_err(dev, "failed to get dpot input channel\n"); - return PTR_ERR(dac->dpot); - } + if (IS_ERR(dac->dpot)) + return dev_err_probe(&pdev->dev, PTR_ERR(dac->dpot), + "failed to get dpot input channel\n"); ret = iio_get_channel_type(dac->dpot, &type); if (ret < 0) -- cgit v1.2.3 From 75e13a76bf2af7ad890038e9de7235c42a3e5fa6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:21 +0200 Subject: iio: imu: inv_mpu6050: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and also it prints the error value. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Andy Shevchenko Reviewed-by: Jean-Baptiste Maneyrol Link: https://lore.kernel.org/r/20200829064726.26268-13-krzk@kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 3fee3947f772..18a1898e3e34 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -1475,22 +1475,14 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, } st->vdd_supply = devm_regulator_get(dev, "vdd"); - if (IS_ERR(st->vdd_supply)) { - if (PTR_ERR(st->vdd_supply) != -EPROBE_DEFER) - dev_err(dev, "Failed to get vdd regulator %d\n", - (int)PTR_ERR(st->vdd_supply)); - - return PTR_ERR(st->vdd_supply); - } + if (IS_ERR(st->vdd_supply)) + return dev_err_probe(dev, PTR_ERR(st->vdd_supply), + "Failed to get vdd regulator\n"); st->vddio_supply = devm_regulator_get(dev, "vddio"); - if (IS_ERR(st->vddio_supply)) { - if (PTR_ERR(st->vddio_supply) != -EPROBE_DEFER) - dev_err(dev, "Failed to get vddio regulator %d\n", - (int)PTR_ERR(st->vddio_supply)); - - return PTR_ERR(st->vddio_supply); - } + if (IS_ERR(st->vddio_supply)) + return dev_err_probe(dev, PTR_ERR(st->vddio_supply), + "Failed to get vddio regulator\n"); result = regulator_enable(st->vdd_supply); if (result) { -- cgit v1.2.3 From 17b7d92324f93066592f52d9b39777a67fa7187b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:22 +0200 Subject: iio: light: isl29018: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and also it prints the error value. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200829064726.26268-14-krzk@kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/light/isl29018.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/light/isl29018.c b/drivers/iio/light/isl29018.c index ac8ad0f32689..2689867467a8 100644 --- a/drivers/iio/light/isl29018.c +++ b/drivers/iio/light/isl29018.c @@ -746,12 +746,9 @@ static int isl29018_probe(struct i2c_client *client, chip->suspended = false; chip->vcc_reg = devm_regulator_get(&client->dev, "vcc"); - if (IS_ERR(chip->vcc_reg)) { - err = PTR_ERR(chip->vcc_reg); - if (err != -EPROBE_DEFER) - dev_err(&client->dev, "failed to get VCC regulator!\n"); - return err; - } + if (IS_ERR(chip->vcc_reg)) + return dev_err_probe(&client->dev, PTR_ERR(chip->vcc_reg), + "failed to get VCC regulator!\n"); err = regulator_enable(chip->vcc_reg); if (err) { -- cgit v1.2.3 From eb17f3ed864a29d695e9c5cafd2eea9ee934cdd9 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:23 +0200 Subject: iio: light: tsl2772: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and also it prints the error value. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200829064726.26268-15-krzk@kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/light/tsl2772.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/light/tsl2772.c b/drivers/iio/light/tsl2772.c index 735399405417..d79205361dfa 100644 --- a/drivers/iio/light/tsl2772.c +++ b/drivers/iio/light/tsl2772.c @@ -1776,14 +1776,8 @@ static int tsl2772_probe(struct i2c_client *clientp, ret = devm_regulator_bulk_get(&clientp->dev, ARRAY_SIZE(chip->supplies), chip->supplies); - if (ret < 0) { - if (ret != -EPROBE_DEFER) - dev_err(&clientp->dev, - "Failed to get regulators: %d\n", - ret); - - return ret; - } + if (ret < 0) + return dev_err_probe(&clientp->dev, ret, "Failed to get regulators\n"); ret = regulator_bulk_enable(ARRAY_SIZE(chip->supplies), chip->supplies); if (ret < 0) { -- cgit v1.2.3 From 5d2180ce1485863ef2ace9a06fb57f857575142e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:24 +0200 Subject: iio: magnetometer: ak8974: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and also it prints the error value. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Andy Shevchenko Acked-by: Linus Walleij Link: https://lore.kernel.org/r/20200829064726.26268-16-krzk@kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/ak8974.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c index 6a8ae145f0c0..7cd9768fbcb2 100644 --- a/drivers/iio/magnetometer/ak8974.c +++ b/drivers/iio/magnetometer/ak8974.c @@ -843,15 +843,8 @@ static int ak8974_probe(struct i2c_client *i2c, ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(ak8974->regs), ak8974->regs); - if (ret < 0) { - if (ret != -EPROBE_DEFER) - dev_err(&i2c->dev, "cannot get regulators: %d\n", ret); - else - dev_dbg(&i2c->dev, - "regulators unavailable, deferring probe\n"); - - return ret; - } + if (ret < 0) + return dev_err_probe(&i2c->dev, ret, "cannot get regulators\n"); ret = regulator_bulk_enable(ARRAY_SIZE(ak8974->regs), ak8974->regs); if (ret < 0) { -- cgit v1.2.3 From 0d81951dad5a0807277d2751ba2b4f98818b049d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:25 +0200 Subject: iio: magnetometer: mag3110: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and also it prints the error value. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200829064726.26268-17-krzk@kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/mag3110.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c index 4d305a21c379..838b13c8bb3d 100644 --- a/drivers/iio/magnetometer/mag3110.c +++ b/drivers/iio/magnetometer/mag3110.c @@ -476,22 +476,14 @@ static int mag3110_probe(struct i2c_client *client, data = iio_priv(indio_dev); data->vdd_reg = devm_regulator_get(&client->dev, "vdd"); - if (IS_ERR(data->vdd_reg)) { - if (PTR_ERR(data->vdd_reg) == -EPROBE_DEFER) - return -EPROBE_DEFER; - - dev_err(&client->dev, "failed to get VDD regulator!\n"); - return PTR_ERR(data->vdd_reg); - } + 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)) { - if (PTR_ERR(data->vddio_reg) == -EPROBE_DEFER) - return -EPROBE_DEFER; - - dev_err(&client->dev, "failed to get VDDIO regulator!\n"); - return PTR_ERR(data->vddio_reg); - } + 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); if (ret) { -- cgit v1.2.3 From c10eb9b22cf2f268f1ac78bf1ded7efaf9583940 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:26 +0200 Subject: iio: multiplexer: iio-mux: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and also it prints the error value. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Andy Shevchenko Acked-by: Peter Rosin Link: https://lore.kernel.org/r/20200829064726.26268-18-krzk@kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/multiplexer/iio-mux.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/multiplexer/iio-mux.c b/drivers/iio/multiplexer/iio-mux.c index 6910218fdb00..d54ae5cbe51b 100644 --- a/drivers/iio/multiplexer/iio-mux.c +++ b/drivers/iio/multiplexer/iio-mux.c @@ -354,11 +354,9 @@ static int mux_probe(struct platform_device *pdev) return -ENODEV; parent = devm_iio_channel_get(dev, "parent"); - if (IS_ERR(parent)) { - if (PTR_ERR(parent) != -EPROBE_DEFER) - dev_err(dev, "failed to get parent channel\n"); - return PTR_ERR(parent); - } + if (IS_ERR(parent)) + return dev_err_probe(dev, PTR_ERR(parent), + "failed to get parent channel\n"); sizeof_ext_info = iio_get_channel_ext_info_count(parent); if (sizeof_ext_info) { -- cgit v1.2.3 From 7e604a3d212ca006802f485f7bac9712a5ddd805 Mon Sep 17 00:00:00 2001 From: Nishant Malpani Date: Tue, 25 Aug 2020 18:15:52 +0530 Subject: iio: gyro: adxrs290: Insert missing mutex initialization call Insert a missing mutex_init() call during the probe that initializes the driver's local lock to unlocked state. Fixes: 2c8920fff145 ("iio: gyro: Add driver support for ADXRS290") Signed-off-by: Nishant Malpani Link: https://lore.kernel.org/r/20200825124552.11155-1-nish.malpani25@gmail.com Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/adxrs290.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/iio') diff --git a/drivers/iio/gyro/adxrs290.c b/drivers/iio/gyro/adxrs290.c index 38bab4e3eee9..ff989536d2fb 100644 --- a/drivers/iio/gyro/adxrs290.c +++ b/drivers/iio/gyro/adxrs290.c @@ -385,6 +385,8 @@ static int adxrs290_probe(struct spi_device *spi) indio_dev->num_channels = ARRAY_SIZE(adxrs290_channels); indio_dev->info = &adxrs290_info; + mutex_init(&st->lock); + val = spi_w8r8(spi, ADXRS290_READ_REG(ADXRS290_REG_ADI_ID)); if (val != ADXRS290_ADI_ID) { dev_err(&spi->dev, "Wrong ADI ID 0x%02x\n", val); -- cgit v1.2.3 From b99095e53a1c01ff8de0928058792711efc00f3c Mon Sep 17 00:00:00 2001 From: Crt Mori Date: Tue, 18 Aug 2020 23:37:33 +0200 Subject: iio:temperature:mlx90632: Reduce number of equal calulcations TAdut4 was calculated each iteration although it did not change. In light of near future additions of the Extended range DSP calculations, this function refactoring will help reduce unrelated changes in that series as well as reduce the number of new functions needed. Signed-off-by: Crt Mori Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200818213737.140613-2-cmo@melexis.com Signed-off-by: Jonathan Cameron --- drivers/iio/temperature/mlx90632.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/temperature/mlx90632.c b/drivers/iio/temperature/mlx90632.c index 51b812bcff2e..c3de10ba5b1e 100644 --- a/drivers/iio/temperature/mlx90632.c +++ b/drivers/iio/temperature/mlx90632.c @@ -374,11 +374,11 @@ static s32 mlx90632_calc_temp_ambient(s16 ambient_new_raw, s16 ambient_old_raw, } static s32 mlx90632_calc_temp_object_iteration(s32 prev_object_temp, s64 object, - s64 TAdut, s32 Fa, s32 Fb, + s64 TAdut, s64 TAdut4, s32 Fa, s32 Fb, s32 Ga, s16 Ha, s16 Hb, u16 emissivity) { - s64 calcedKsTO, calcedKsTA, ir_Alpha, TAdut4, Alpha_corr; + s64 calcedKsTO, calcedKsTA, ir_Alpha, Alpha_corr; s64 Ha_customer, Hb_customer; Ha_customer = ((s64)Ha * 1000000LL) >> 14ULL; @@ -393,30 +393,35 @@ static s32 mlx90632_calc_temp_object_iteration(s32 prev_object_temp, s64 object, Alpha_corr = emissivity * div64_s64(Alpha_corr, 100000LL); Alpha_corr = div64_s64(Alpha_corr, 1000LL); ir_Alpha = div64_s64((s64)object * 10000000LL, Alpha_corr); - TAdut4 = (div64_s64(TAdut, 10000LL) + 27315) * - (div64_s64(TAdut, 10000LL) + 27315) * - (div64_s64(TAdut, 10000LL) + 27315) * - (div64_s64(TAdut, 10000LL) + 27315); return (int_sqrt64(int_sqrt64(ir_Alpha * 1000000000000LL + TAdut4)) - 27315 - Hb_customer) * 10; } +static s64 mlx90632_calc_ta4(s64 TAdut, s64 scale) +{ + return (div64_s64(TAdut, scale) + 27315) * + (div64_s64(TAdut, scale) + 27315) * + (div64_s64(TAdut, scale) + 27315) * + (div64_s64(TAdut, scale) + 27315); +} + static s32 mlx90632_calc_temp_object(s64 object, s64 ambient, s32 Ea, s32 Eb, s32 Fa, s32 Fb, s32 Ga, s16 Ha, s16 Hb, u16 tmp_emi) { - s64 kTA, kTA0, TAdut; + s64 kTA, kTA0, TAdut, TAdut4; s64 temp = 25000; s8 i; kTA = (Ea * 1000LL) >> 16LL; kTA0 = (Eb * 1000LL) >> 8LL; TAdut = div64_s64(((ambient - kTA0) * 1000000LL), kTA) + 25 * 1000000LL; + TAdut4 = mlx90632_calc_ta4(TAdut, 10000LL); /* Iterations of calculation as described in datasheet */ for (i = 0; i < 5; ++i) { - temp = mlx90632_calc_temp_object_iteration(temp, object, TAdut, + temp = mlx90632_calc_temp_object_iteration(temp, object, TAdut, TAdut4, Fa, Fb, Ga, Ha, Hb, tmp_emi); } -- cgit v1.2.3 From 856437dbb85b918c7ed167dea929f1a11aa20cb4 Mon Sep 17 00:00:00 2001 From: Crt Mori Date: Tue, 18 Aug 2020 23:37:34 +0200 Subject: iio:temperature:mlx90632: Add kerneldoc to the internal struct Document internal/private struct for mlx90632 device. Signed-off-by: Crt Mori Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200818213737.140613-3-cmo@melexis.com Signed-off-by: Jonathan Cameron --- drivers/iio/temperature/mlx90632.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/temperature/mlx90632.c b/drivers/iio/temperature/mlx90632.c index c3de10ba5b1e..ce75f5a3486b 100644 --- a/drivers/iio/temperature/mlx90632.c +++ b/drivers/iio/temperature/mlx90632.c @@ -89,9 +89,16 @@ #define MLX90632_MAX_MEAS_NUM 31 /**< Maximum measurements in list */ #define MLX90632_SLEEP_DELAY_MS 3000 /**< Autosleep delay */ +/** + * struct mlx90632_data - private data for the MLX90632 device + * @client: I2C client of the device + * @lock: Internal mutex for multiple reads for single measurement + * @regmap: Regmap of the device + * @emissivity: Object emissivity from 0 to 1000 where 1000 = 1. + */ struct mlx90632_data { struct i2c_client *client; - struct mutex lock; /* Multiple reads for single measurement */ + struct mutex lock; struct regmap *regmap; u16 emissivity; }; -- cgit v1.2.3 From 037697dd264dd35a1f0ee13a3e8e3adb23f46075 Mon Sep 17 00:00:00 2001 From: Crt Mori Date: Tue, 18 Aug 2020 23:37:35 +0200 Subject: iio:temperature:mlx90632: Convert polling while loop to regmap Reduce number of lines and improve readability to convert polling while loops to regmap_read_poll_timeout. Signed-off-by: Crt Mori Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200818213737.140613-4-cmo@melexis.com Signed-off-by: Jonathan Cameron --- drivers/iio/temperature/mlx90632.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/temperature/mlx90632.c b/drivers/iio/temperature/mlx90632.c index ce75f5a3486b..d782634c107f 100644 --- a/drivers/iio/temperature/mlx90632.c +++ b/drivers/iio/temperature/mlx90632.c @@ -180,25 +180,19 @@ static s32 mlx90632_pwr_continuous(struct regmap *regmap) */ static int mlx90632_perform_measurement(struct mlx90632_data *data) { - int ret, tries = 100; unsigned int reg_status; + int ret; ret = regmap_update_bits(data->regmap, MLX90632_REG_STATUS, MLX90632_STAT_DATA_RDY, 0); if (ret < 0) return ret; - while (tries-- > 0) { - ret = regmap_read(data->regmap, MLX90632_REG_STATUS, - ®_status); - if (ret < 0) - return ret; - if (reg_status & MLX90632_STAT_DATA_RDY) - break; - usleep_range(10000, 11000); - } + ret = regmap_read_poll_timeout(data->regmap, MLX90632_REG_STATUS, reg_status, + !(reg_status & MLX90632_STAT_DATA_RDY), 10000, + 100 * 10000); - if (tries < 0) { + if (ret < 0) { dev_err(&data->client->dev, "data not ready"); return -ETIMEDOUT; } -- cgit v1.2.3 From e02472f74a8120cd5a0be0e7d48c9d95d4cde6a0 Mon Sep 17 00:00:00 2001 From: Crt Mori Date: Tue, 18 Aug 2020 23:37:36 +0200 Subject: iio:temperature:mlx90632: Adding extended calibration option For some time the market wants medical grade accuracy in medical range, while still retaining the declared accuracy outside of the medical range within the same sensor. That is why we created extended calibration which is automatically switched to when object temperature is too high. This patch also introduces the object_ambient_temperature variable which is needed for more accurate calculation of the object infra-red footprint as sensor's ambient temperature might be totally different than what the ambient temperature is at object and that is why we can have some more errors which can be eliminated. Currently this temperature is fixed at 25, but the interface to adjust it by user (with external sensor or just IR measurement of the other object which acts as ambient), will be introduced in another commit. Signed-off-by: Crt Mori Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200818213737.140613-5-cmo@melexis.com Signed-off-by: Jonathan Cameron --- drivers/iio/temperature/mlx90632.c | 218 ++++++++++++++++++++++++++++++++++++- 1 file changed, 216 insertions(+), 2 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/temperature/mlx90632.c b/drivers/iio/temperature/mlx90632.c index d782634c107f..94bca2b2866a 100644 --- a/drivers/iio/temperature/mlx90632.c +++ b/drivers/iio/temperature/mlx90632.c @@ -10,7 +10,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -58,6 +60,8 @@ /* Control register address - volatile */ #define MLX90632_REG_CONTROL 0x3001 /* Control Register address */ #define MLX90632_CFG_PWR_MASK GENMASK(2, 1) /* PowerMode Mask */ +#define MLX90632_CFG_MTYP_MASK GENMASK(8, 4) /* Meas select Mask */ + /* PowerModes statuses */ #define MLX90632_PWR_STATUS(ctrl_val) (ctrl_val << 1) #define MLX90632_PWR_STATUS_HALT MLX90632_PWR_STATUS(0) /* hold */ @@ -65,6 +69,18 @@ #define MLX90632_PWR_STATUS_STEP MLX90632_PWR_STATUS(2) /* step */ #define MLX90632_PWR_STATUS_CONTINUOUS MLX90632_PWR_STATUS(3) /* continuous*/ +/* Measurement types */ +#define MLX90632_MTYP_MEDICAL 0 +#define MLX90632_MTYP_EXTENDED 17 + +/* Measurement type select*/ +#define MLX90632_MTYP_STATUS(ctrl_val) (ctrl_val << 4) +#define MLX90632_MTYP_STATUS_MEDICAL MLX90632_MTYP_STATUS(MLX90632_MTYP_MEDICAL) +#define MLX90632_MTYP_STATUS_EXTENDED MLX90632_MTYP_STATUS(MLX90632_MTYP_EXTENDED) + +/* I2C command register - volatile */ +#define MLX90632_REG_I2C_CMD 0x3005 /* I2C command Register address */ + /* Device status register - volatile */ #define MLX90632_REG_STATUS 0x3fff /* Device status register */ #define MLX90632_STAT_BUSY BIT(10) /* Device busy indicator */ @@ -78,9 +94,21 @@ #define MLX90632_RAM_2(meas_num) (MLX90632_ADDR_RAM + 3 * meas_num + 1) #define MLX90632_RAM_3(meas_num) (MLX90632_ADDR_RAM + 3 * meas_num + 2) +/* Name important RAM_MEAS channels */ +#define MLX90632_RAM_DSP5_EXTENDED_AMBIENT_1 MLX90632_RAM_3(17) +#define MLX90632_RAM_DSP5_EXTENDED_AMBIENT_2 MLX90632_RAM_3(18) +#define MLX90632_RAM_DSP5_EXTENDED_OBJECT_1 MLX90632_RAM_1(17) +#define MLX90632_RAM_DSP5_EXTENDED_OBJECT_2 MLX90632_RAM_2(17) +#define MLX90632_RAM_DSP5_EXTENDED_OBJECT_3 MLX90632_RAM_1(18) +#define MLX90632_RAM_DSP5_EXTENDED_OBJECT_4 MLX90632_RAM_2(18) +#define MLX90632_RAM_DSP5_EXTENDED_OBJECT_5 MLX90632_RAM_1(19) +#define MLX90632_RAM_DSP5_EXTENDED_OBJECT_6 MLX90632_RAM_2(19) + /* Magic constants */ #define MLX90632_ID_MEDICAL 0x0105 /* EEPROM DSPv5 Medical device id */ #define MLX90632_ID_CONSUMER 0x0205 /* EEPROM DSPv5 Consumer device id */ +#define MLX90632_ID_EXTENDED 0x0505 /* EEPROM DSPv5 Extended range device id */ +#define MLX90632_ID_MASK GENMASK(14, 0) /* DSP version and device ID in EE_VERSION */ #define MLX90632_DSP_VERSION 5 /* DSP version */ #define MLX90632_DSP_MASK GENMASK(7, 0) /* DSP version in EE_VERSION */ #define MLX90632_RESET_CMD 0x0006 /* Reset sensor (address or global) */ @@ -88,6 +116,7 @@ #define MLX90632_REF_3 12LL /**< ResCtrlRef value of Channel 3 */ #define MLX90632_MAX_MEAS_NUM 31 /**< Maximum measurements in list */ #define MLX90632_SLEEP_DELAY_MS 3000 /**< Autosleep delay */ +#define MLX90632_EXTENDED_LIMIT 27000 /* Extended mode raw value limit */ /** * struct mlx90632_data - private data for the MLX90632 device @@ -95,16 +124,23 @@ * @lock: Internal mutex for multiple reads for single measurement * @regmap: Regmap of the device * @emissivity: Object emissivity from 0 to 1000 where 1000 = 1. + * @mtyp: Measurement type physical sensor configuration for extended range + * calculations + * @object_ambient_temperature: Ambient temperature at object (might differ of + * the ambient temperature of sensor. */ struct mlx90632_data { struct i2c_client *client; struct mutex lock; struct regmap *regmap; u16 emissivity; + u8 mtyp; + u32 object_ambient_temperature; }; static const struct regmap_range mlx90632_volatile_reg_range[] = { regmap_reg_range(MLX90632_REG_I2C_ADDR, MLX90632_REG_CONTROL), + regmap_reg_range(MLX90632_REG_I2C_CMD, MLX90632_REG_I2C_CMD), regmap_reg_range(MLX90632_REG_STATUS, MLX90632_REG_STATUS), regmap_reg_range(MLX90632_RAM_1(0), MLX90632_RAM_3(MLX90632_MAX_MEAS_NUM)), @@ -120,6 +156,7 @@ static const struct regmap_range mlx90632_read_reg_range[] = { regmap_reg_range(MLX90632_EE_CTRL, MLX90632_EE_I2C_ADDR), regmap_reg_range(MLX90632_EE_Ha, MLX90632_EE_Hb), regmap_reg_range(MLX90632_REG_I2C_ADDR, MLX90632_REG_CONTROL), + regmap_reg_range(MLX90632_REG_I2C_CMD, MLX90632_REG_I2C_CMD), regmap_reg_range(MLX90632_REG_STATUS, MLX90632_REG_STATUS), regmap_reg_range(MLX90632_RAM_1(0), MLX90632_RAM_3(MLX90632_MAX_MEAS_NUM)), @@ -200,6 +237,26 @@ static int mlx90632_perform_measurement(struct mlx90632_data *data) return (reg_status & MLX90632_STAT_CYCLE_POS) >> 2; } +static int mlx90632_set_meas_type(struct regmap *regmap, u8 type) +{ + int ret; + + if ((type != MLX90632_MTYP_MEDICAL) && (type != MLX90632_MTYP_EXTENDED)) + return -EINVAL; + + ret = regmap_write(regmap, MLX90632_REG_I2C_CMD, MLX90632_RESET_CMD); + if (ret < 0) + return ret; + + ret = regmap_write_bits(regmap, MLX90632_REG_CONTROL, + (MLX90632_CFG_MTYP_MASK | MLX90632_CFG_PWR_MASK), + (MLX90632_MTYP_STATUS(type) | MLX90632_PWR_STATUS_HALT)); + if (ret < 0) + return ret; + + return mlx90632_pwr_continuous(regmap); +} + static int mlx90632_channel_new_select(int perform_ret, uint8_t *channel_new, uint8_t *channel_old) { @@ -301,6 +358,97 @@ read_unlock: return ret; } +static int mlx90632_read_ambient_raw_extended(struct regmap *regmap, + s16 *ambient_new_raw, s16 *ambient_old_raw) +{ + unsigned int read_tmp; + int ret; + + ret = regmap_read(regmap, MLX90632_RAM_DSP5_EXTENDED_AMBIENT_1, &read_tmp); + if (ret < 0) + return ret; + *ambient_new_raw = (s16)read_tmp; + + ret = regmap_read(regmap, MLX90632_RAM_DSP5_EXTENDED_AMBIENT_2, &read_tmp); + if (ret < 0) + return ret; + *ambient_old_raw = (s16)read_tmp; + + return 0; +} + +static int mlx90632_read_object_raw_extended(struct regmap *regmap, s16 *object_new_raw) +{ + unsigned int read_tmp; + s32 read; + int ret; + + ret = regmap_read(regmap, MLX90632_RAM_DSP5_EXTENDED_OBJECT_1, &read_tmp); + if (ret < 0) + return ret; + read = (s16)read_tmp; + + ret = regmap_read(regmap, MLX90632_RAM_DSP5_EXTENDED_OBJECT_2, &read_tmp); + if (ret < 0) + return ret; + read = read - (s16)read_tmp; + + ret = regmap_read(regmap, MLX90632_RAM_DSP5_EXTENDED_OBJECT_3, &read_tmp); + if (ret < 0) + return ret; + read = read - (s16)read_tmp; + + ret = regmap_read(regmap, MLX90632_RAM_DSP5_EXTENDED_OBJECT_4, &read_tmp); + if (ret < 0) + return ret; + read = (read + (s16)read_tmp) / 2; + + ret = regmap_read(regmap, MLX90632_RAM_DSP5_EXTENDED_OBJECT_5, &read_tmp); + if (ret < 0) + return ret; + read = read + (s16)read_tmp; + + ret = regmap_read(regmap, MLX90632_RAM_DSP5_EXTENDED_OBJECT_6, &read_tmp); + if (ret < 0) + return ret; + read = read + (s16)read_tmp; + + if (read > S16_MAX || read < S16_MIN) + return -ERANGE; + + *object_new_raw = read; + + return 0; +} + +static int mlx90632_read_all_channel_extended(struct mlx90632_data *data, s16 *object_new_raw, + s16 *ambient_new_raw, s16 *ambient_old_raw) +{ + s32 ret, meas; + + mutex_lock(&data->lock); + ret = mlx90632_set_meas_type(data->regmap, MLX90632_MTYP_EXTENDED); + if (ret < 0) + goto read_unlock; + + ret = read_poll_timeout(mlx90632_perform_measurement, meas, meas == 19, + 50000, 800000, false, data); + if (ret != 0) + goto read_unlock; + + ret = mlx90632_read_object_raw_extended(data->regmap, object_new_raw); + if (ret < 0) + goto read_unlock; + + ret = mlx90632_read_ambient_raw_extended(data->regmap, ambient_new_raw, ambient_old_raw); + +read_unlock: + (void) mlx90632_set_meas_type(data->regmap, MLX90632_MTYP_MEDICAL); + + mutex_unlock(&data->lock); + return ret; +} + static int mlx90632_read_ee_register(struct regmap *regmap, u16 reg_lsb, s32 *reg_value) { @@ -355,9 +503,23 @@ static s64 mlx90632_preprocess_temp_obj(s16 object_new_raw, s16 object_old_raw, return div64_s64((tmp << 19ULL), 1000LL); } +static s64 mlx90632_preprocess_temp_obj_extended(s16 object_new_raw, s16 ambient_new_raw, + s16 ambient_old_raw, s16 Ka) +{ + s64 VR_IR, kKa, tmp; + + kKa = ((s64)Ka * 1000LL) >> 10ULL; + VR_IR = (s64)ambient_old_raw * 1000000LL + + kKa * div64_s64((s64)ambient_new_raw * 1000LL, + MLX90632_REF_3); + tmp = div64_s64( + div64_s64((s64) object_new_raw * 1000000000000LL, MLX90632_REF_12), + VR_IR); + return div64_s64(tmp << 19ULL, 1000LL); +} + static s32 mlx90632_calc_temp_ambient(s16 ambient_new_raw, s16 ambient_old_raw, - s32 P_T, s32 P_R, s32 P_G, s32 P_O, - s16 Gb) + s32 P_T, s32 P_R, s32 P_G, s32 P_O, s16 Gb) { s64 Asub, Bsub, Ablock, Bblock, Cblock, AMB, sum; @@ -429,6 +591,31 @@ static s32 mlx90632_calc_temp_object(s64 object, s64 ambient, s32 Ea, s32 Eb, return temp; } +static s32 mlx90632_calc_temp_object_extended(s64 object, s64 ambient, s64 reflected, + s32 Ea, s32 Eb, s32 Fa, s32 Fb, s32 Ga, + s16 Ha, s16 Hb, u16 tmp_emi) +{ + s64 kTA, kTA0, TAdut, TAdut4, Tr4, TaTr4; + s64 temp = 25000; + s8 i; + + kTA = (Ea * 1000LL) >> 16LL; + kTA0 = (Eb * 1000LL) >> 8LL; + TAdut = div64_s64((ambient - kTA0) * 1000000LL, kTA) + 25 * 1000000LL; + Tr4 = mlx90632_calc_ta4(reflected, 10); + TAdut4 = mlx90632_calc_ta4(TAdut, 10000LL); + TaTr4 = Tr4 - div64_s64(Tr4 - TAdut4, tmp_emi) * 1000; + + /* Iterations of calculation as described in datasheet */ + for (i = 0; i < 5; ++i) { + temp = mlx90632_calc_temp_object_iteration(temp, object, TAdut, TaTr4, + Fa / 2, Fb, Ga, Ha, Hb, + tmp_emi); + } + + return temp; +} + static int mlx90632_calc_object_dsp105(struct mlx90632_data *data, int *val) { s32 ret; @@ -476,6 +663,26 @@ static int mlx90632_calc_object_dsp105(struct mlx90632_data *data, int *val) if (ret < 0) return ret; + if (object_new_raw > MLX90632_EXTENDED_LIMIT && + data->mtyp == MLX90632_MTYP_EXTENDED) { + ret = mlx90632_read_all_channel_extended(data, &object_new_raw, + &ambient_new_raw, &ambient_old_raw); + if (ret < 0) + return ret; + + /* Use extended mode calculations */ + ambient = mlx90632_preprocess_temp_amb(ambient_new_raw, + ambient_old_raw, Gb); + object = mlx90632_preprocess_temp_obj_extended(object_new_raw, + ambient_new_raw, + ambient_old_raw, Ka); + *val = mlx90632_calc_temp_object_extended(object, ambient, + data->object_ambient_temperature, + Ea, Eb, Fa, Fb, Ga, + Ha, Hb, data->emissivity); + return 0; + } + ambient = mlx90632_preprocess_temp_amb(ambient_new_raw, ambient_old_raw, Gb); object = mlx90632_preprocess_temp_obj(object_new_raw, @@ -649,6 +856,7 @@ static int mlx90632_probe(struct i2c_client *client, i2c_set_clientdata(client, indio_dev); mlx90632->client = client; mlx90632->regmap = regmap; + mlx90632->mtyp = MLX90632_MTYP_MEDICAL; mutex_init(&mlx90632->lock); indio_dev->name = id->name; @@ -668,12 +876,17 @@ static int mlx90632_probe(struct i2c_client *client, dev_err(&client->dev, "read of version failed: %d\n", ret); return ret; } + read = read & MLX90632_ID_MASK; if (read == MLX90632_ID_MEDICAL) { dev_dbg(&client->dev, "Detected Medical EEPROM calibration %x\n", read); } else if (read == MLX90632_ID_CONSUMER) { dev_dbg(&client->dev, "Detected Consumer EEPROM calibration %x\n", read); + } else if (read == MLX90632_ID_EXTENDED) { + dev_dbg(&client->dev, + "Detected Extended range EEPROM calibration %x\n", read); + mlx90632->mtyp = MLX90632_MTYP_EXTENDED; } else if ((read & MLX90632_DSP_MASK) == MLX90632_DSP_VERSION) { dev_dbg(&client->dev, "Detected Unknown EEPROM calibration %x\n", read); @@ -685,6 +898,7 @@ static int mlx90632_probe(struct i2c_client *client, } mlx90632->emissivity = 1000; + mlx90632->object_ambient_temperature = 25000; /* 25 degrees milliCelsius */ pm_runtime_disable(&client->dev); ret = pm_runtime_set_active(&client->dev); -- cgit v1.2.3 From 50677d2882e1844763f455b314fa2225d9da5e56 Mon Sep 17 00:00:00 2001 From: Crt Mori Date: Tue, 18 Aug 2020 23:37:37 +0200 Subject: iio:temperature:mlx90632: Some stylefixing leftovers There is some inconsistency and whitespace cleanup performed in this patch. It was done on top of my other patches, but I can rebase to head of the togreg branch if it would go in sooner. Signed-off-by: Crt Mori Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200818213737.140613-6-cmo@melexis.com Signed-off-by: Jonathan Cameron --- drivers/iio/temperature/mlx90632.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/temperature/mlx90632.c b/drivers/iio/temperature/mlx90632.c index 94bca2b2866a..472a7fb20615 100644 --- a/drivers/iio/temperature/mlx90632.c +++ b/drivers/iio/temperature/mlx90632.c @@ -112,10 +112,10 @@ #define MLX90632_DSP_VERSION 5 /* DSP version */ #define MLX90632_DSP_MASK GENMASK(7, 0) /* DSP version in EE_VERSION */ #define MLX90632_RESET_CMD 0x0006 /* Reset sensor (address or global) */ -#define MLX90632_REF_12 12LL /**< ResCtrlRef value of Ch 1 or Ch 2 */ -#define MLX90632_REF_3 12LL /**< ResCtrlRef value of Channel 3 */ -#define MLX90632_MAX_MEAS_NUM 31 /**< Maximum measurements in list */ -#define MLX90632_SLEEP_DELAY_MS 3000 /**< Autosleep delay */ +#define MLX90632_REF_12 12LL /* ResCtrlRef value of Ch 1 or Ch 2 */ +#define MLX90632_REF_3 12LL /* ResCtrlRef value of Channel 3 */ +#define MLX90632_MAX_MEAS_NUM 31 /* Maximum measurements in list */ +#define MLX90632_SLEEP_DELAY_MS 3000 /* Autosleep delay */ #define MLX90632_EXTENDED_LIMIT 27000 /* Extended mode raw value limit */ /** @@ -889,7 +889,7 @@ static int mlx90632_probe(struct i2c_client *client, mlx90632->mtyp = MLX90632_MTYP_EXTENDED; } else if ((read & MLX90632_DSP_MASK) == MLX90632_DSP_VERSION) { dev_dbg(&client->dev, - "Detected Unknown EEPROM calibration %x\n", read); + "Detected Unknown EEPROM calibration %x\n", read); } else { dev_err(&client->dev, "Wrong DSP version %x (expected %x)\n", -- cgit v1.2.3 From b0fc6783d4ae58f796fb183c40dbc7fa3199d51d Mon Sep 17 00:00:00 2001 From: Stefan Popa Date: Mon, 10 Aug 2020 12:32:56 +0300 Subject: iio: accel: adxl372: Add support for FIFO peak mode By default, if all three channels (x, y, z) are enabled, sample sets of concurrent 3-axis data is stored in the FIFO. This patch adds the option to configure the FIFO to store peak acceleration (x, y and z) of every over-threshold event. When pushing to iio buffer we push only enabled axis data. Currently the driver configures adxl372 to work in loop mode. The inactivity and activity timings decide how fast the chip will loop through the awake and waiting states and the thresholds on x,y,z axis decide when activity or inactivity will be detected. This patch adds standard events sysfs entries for the inactivity and activity timings: thresh_falling_period/thresh_rising_period and for the in_accel_x_thresh_falling/rising_value. Signed-off-by: Stefan Popa Signed-off-by: Alexandru Tachici Link: https://lore.kernel.org/r/20200810093257.65929-2-alexandru.tachici@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/accel/adxl372.c | 311 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 299 insertions(+), 12 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c index e7e316b75e87..aed2a4930fb0 100644 --- a/drivers/iio/accel/adxl372.c +++ b/drivers/iio/accel/adxl372.c @@ -5,6 +5,7 @@ * Copyright 2018 Analog Devices Inc. */ +#include #include #include #include @@ -113,6 +114,11 @@ #define ADXL372_STATUS_1_AWAKE(x) (((x) >> 6) & 0x1) #define ADXL372_STATUS_1_ERR_USR_REGS(x) (((x) >> 7) & 0x1) +/* ADXL372_STATUS_2 */ +#define ADXL372_STATUS_2_INACT(x) (((x) >> 4) & 0x1) +#define ADXL372_STATUS_2_ACT(x) (((x) >> 5) & 0x1) +#define ADXL372_STATUS_2_AC2(x) (((x) >> 6) & 0x1) + /* ADXL372_INT1_MAP */ #define ADXL372_INT1_MAP_DATA_RDY_MSK BIT(0) #define ADXL372_INT1_MAP_DATA_RDY_MODE(x) (((x) & 0x1) << 0) @@ -131,8 +137,17 @@ #define ADXL372_INT1_MAP_LOW_MSK BIT(7) #define ADXL372_INT1_MAP_LOW_MODE(x) (((x) & 0x1) << 7) +/* ADX372_THRESH */ +#define ADXL372_THRESH_VAL_H_MSK GENMASK(10, 3) +#define ADXL372_THRESH_VAL_H_SEL(x) FIELD_GET(ADXL372_THRESH_VAL_H_MSK, x) +#define ADXL372_THRESH_VAL_L_MSK GENMASK(2, 0) +#define ADXL372_THRESH_VAL_L_SEL(x) FIELD_GET(ADXL372_THRESH_VAL_L_MSK, x) + /* The ADXL372 includes a deep, 512 sample FIFO buffer */ #define ADXL372_FIFO_SIZE 512 +#define ADXL372_X_AXIS_EN(x) ((x) & BIT(0)) +#define ADXL372_Y_AXIS_EN(x) ((x) & BIT(1)) +#define ADXL372_Z_AXIS_EN(x) ((x) & BIT(2)) /* * At +/- 200g with 12-bit resolution, scale is computed as: @@ -222,6 +237,20 @@ static const struct adxl372_axis_lookup adxl372_axis_lookup_table[] = { { BIT(0) | BIT(1) | BIT(2), ADXL372_XYZ_FIFO }, }; +static const struct iio_event_spec adxl372_events[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE), + .mask_shared_by_all = BIT(IIO_EV_INFO_PERIOD) | BIT(IIO_EV_INFO_ENABLE), + }, { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_VALUE), + .mask_shared_by_all = BIT(IIO_EV_INFO_PERIOD) | BIT(IIO_EV_INFO_ENABLE), + }, +}; + #define ADXL372_ACCEL_CHANNEL(index, reg, axis) { \ .type = IIO_ACCEL, \ .address = reg, \ @@ -239,6 +268,8 @@ static const struct adxl372_axis_lookup adxl372_axis_lookup_table[] = { .shift = 4, \ .endianness = IIO_BE, \ }, \ + .event_spec = adxl372_events, \ + .num_event_specs = ARRAY_SIZE(adxl372_events) \ } static const struct iio_chan_spec adxl372_channels[] = { @@ -252,8 +283,10 @@ struct adxl372_state { struct device *dev; struct regmap *regmap; struct iio_trigger *dready_trig; + struct iio_trigger *peak_datardy_trig; enum adxl372_fifo_mode fifo_mode; enum adxl372_fifo_format fifo_format; + unsigned int fifo_axis_mask; enum adxl372_op_mode op_mode; enum adxl372_act_proc_mode act_proc_mode; enum adxl372_odr odr; @@ -261,10 +294,12 @@ struct adxl372_state { u32 act_time_ms; u32 inact_time_ms; u8 fifo_set_size; - u8 int1_bitmask; - u8 int2_bitmask; + unsigned long int1_bitmask; + unsigned long int2_bitmask; u16 watermark; __be16 fifo_buf[ADXL372_FIFO_SIZE]; + bool peak_fifo_mode_en; + struct mutex threshold_m; /* lock for threshold */ }; static const unsigned long adxl372_channel_masks[] = { @@ -276,6 +311,46 @@ static const unsigned long adxl372_channel_masks[] = { 0 }; +static ssize_t adxl372_read_threshold_value(struct iio_dev *indio_dev, unsigned int addr, + u16 *threshold) +{ + struct adxl372_state *st = iio_priv(indio_dev); + __be16 raw_regval; + u16 regval; + int ret; + + ret = regmap_bulk_read(st->regmap, addr, &raw_regval, sizeof(raw_regval)); + if (ret < 0) + return ret; + + regval = be16_to_cpu(raw_regval); + regval >>= 5; + + *threshold = regval; + + return 0; +} + +static ssize_t adxl372_write_threshold_value(struct iio_dev *indio_dev, unsigned int addr, + u16 threshold) +{ + struct adxl372_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&st->threshold_m); + ret = regmap_write(st->regmap, addr, ADXL372_THRESH_VAL_H_SEL(threshold)); + if (ret < 0) + goto unlock; + + ret = regmap_update_bits(st->regmap, addr + 1, GENMASK(7, 5), + ADXL372_THRESH_VAL_L_SEL(threshold) << 5); + +unlock: + mutex_unlock(&st->threshold_m); + + return ret; +} + static int adxl372_read_axis(struct adxl372_state *st, u8 addr) { __be16 regval; @@ -453,8 +528,8 @@ static int adxl372_set_inactivity_time_ms(struct adxl372_state *st, } static int adxl372_set_interrupts(struct adxl372_state *st, - unsigned char int1_bitmask, - unsigned char int2_bitmask) + unsigned long int1_bitmask, + unsigned long int2_bitmask) { int ret; @@ -523,6 +598,39 @@ static int adxl372_get_status(struct adxl372_state *st, return ret; } +static void adxl372_arrange_axis_data(struct adxl372_state *st, __be16 *sample) +{ + __be16 axis_sample[3]; + int i = 0; + + memset(axis_sample, 0, 3 * sizeof(__be16)); + if (ADXL372_X_AXIS_EN(st->fifo_axis_mask)) + axis_sample[i++] = sample[0]; + if (ADXL372_Y_AXIS_EN(st->fifo_axis_mask)) + axis_sample[i++] = sample[1]; + if (ADXL372_Z_AXIS_EN(st->fifo_axis_mask)) + axis_sample[i++] = sample[2]; + + memcpy(sample, axis_sample, 3 * sizeof(__be16)); +} + +static void adxl372_push_event(struct iio_dev *indio_dev, s64 timestamp, u8 status2) +{ + unsigned int ev_dir = IIO_EV_DIR_NONE; + + if (ADXL372_STATUS_2_ACT(status2)) + ev_dir = IIO_EV_DIR_RISING; + + if (ADXL372_STATUS_2_INACT(status2)) + ev_dir = IIO_EV_DIR_FALLING; + + if (ev_dir != IIO_EV_DIR_NONE) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z, + IIO_EV_TYPE_THRESH, ev_dir), + timestamp); +} + static irqreturn_t adxl372_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; @@ -536,6 +644,8 @@ static irqreturn_t adxl372_trigger_handler(int irq, void *p) if (ret < 0) goto err; + adxl372_push_event(indio_dev, iio_get_time_ns(indio_dev), status2); + if (st->fifo_mode != ADXL372_FIFO_BYPASSED && ADXL372_STATUS_1_FIFO_FULL(status1)) { /* @@ -554,8 +664,12 @@ static irqreturn_t adxl372_trigger_handler(int irq, void *p) goto err; /* Each sample is 2 bytes */ - for (i = 0; i < fifo_entries; i += st->fifo_set_size) + for (i = 0; i < fifo_entries; i += st->fifo_set_size) { + /* filter peak detection data */ + if (st->peak_fifo_mode_en) + adxl372_arrange_axis_data(st, &st->fifo_buf[i]); iio_push_to_buffers(indio_dev, &st->fifo_buf[i]); + } } err: iio_trigger_notify_done(indio_dev->trig); @@ -723,6 +837,129 @@ static int adxl372_write_raw(struct iio_dev *indio_dev, } } +static int adxl372_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 adxl372_state *st = iio_priv(indio_dev); + unsigned int addr; + u16 raw_value; + int ret; + + switch (info) { + case IIO_EV_INFO_VALUE: + switch (dir) { + case IIO_EV_DIR_RISING: + addr = ADXL372_X_THRESH_ACT_H + 2 * chan->scan_index; + ret = adxl372_read_threshold_value(indio_dev, addr, &raw_value); + if (ret < 0) + return ret; + *val = raw_value * ADXL372_USCALE; + *val2 = 1000000; + return IIO_VAL_FRACTIONAL; + case IIO_EV_DIR_FALLING: + addr = ADXL372_X_THRESH_INACT_H + 2 * chan->scan_index; + ret = adxl372_read_threshold_value(indio_dev, addr, &raw_value); + if (ret < 0) + return ret; + *val = raw_value * ADXL372_USCALE; + *val2 = 1000000; + return IIO_VAL_FRACTIONAL; + default: + return -EINVAL; + } + case IIO_EV_INFO_PERIOD: + switch (dir) { + case IIO_EV_DIR_RISING: + *val = st->act_time_ms; + *val2 = 1000; + return IIO_VAL_FRACTIONAL; + case IIO_EV_DIR_FALLING: + *val = st->inact_time_ms; + *val2 = 1000; + return IIO_VAL_FRACTIONAL; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int adxl372_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 adxl372_state *st = iio_priv(indio_dev); + unsigned int val_ms; + unsigned int addr; + u16 raw_val; + + switch (info) { + case IIO_EV_INFO_VALUE: + raw_val = DIV_ROUND_UP(val * 1000000, ADXL372_USCALE); + switch (dir) { + case IIO_EV_DIR_RISING: + addr = ADXL372_X_THRESH_ACT_H + 2 * chan->scan_index; + return adxl372_write_threshold_value(indio_dev, addr, raw_val); + case IIO_EV_DIR_FALLING: + addr = ADXL372_X_THRESH_INACT_H + 2 * chan->scan_index; + return adxl372_write_threshold_value(indio_dev, addr, raw_val); + default: + return -EINVAL; + } + case IIO_EV_INFO_PERIOD: + val_ms = val * 1000 + DIV_ROUND_UP(val2, 1000); + switch (dir) { + case IIO_EV_DIR_RISING: + return adxl372_set_activity_time_ms(st, val_ms); + case IIO_EV_DIR_FALLING: + return adxl372_set_inactivity_time_ms(st, val_ms); + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int adxl372_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 adxl372_state *st = iio_priv(indio_dev); + + switch (dir) { + case IIO_EV_DIR_RISING: + return FIELD_GET(ADXL372_INT1_MAP_ACT_MSK, st->int1_bitmask); + case IIO_EV_DIR_FALLING: + return FIELD_GET(ADXL372_INT1_MAP_INACT_MSK, st->int1_bitmask); + default: + return -EINVAL; + } +} + +static int adxl372_write_event_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, + enum iio_event_type type, enum iio_event_direction dir, + int state) +{ + struct adxl372_state *st = iio_priv(indio_dev); + + switch (dir) { + case IIO_EV_DIR_RISING: + set_mask_bits(&st->int1_bitmask, ADXL372_INT1_MAP_ACT_MSK, + ADXL372_INT1_MAP_ACT_MODE(state)); + break; + case IIO_EV_DIR_FALLING: + set_mask_bits(&st->int1_bitmask, ADXL372_INT1_MAP_INACT_MSK, + ADXL372_INT1_MAP_INACT_MODE(state)); + break; + default: + return -EINVAL; + } + + return adxl372_set_interrupts(st, st->int1_bitmask, 0); +} + static ssize_t adxl372_show_filter_freq_avail(struct device *dev, struct device_attribute *attr, char *buf) @@ -795,7 +1032,8 @@ static int adxl372_buffer_postenable(struct iio_dev *indio_dev) unsigned int mask; int i, ret; - ret = adxl372_set_interrupts(st, ADXL372_INT1_MAP_FIFO_FULL_MSK, 0); + st->int1_bitmask |= ADXL372_INT1_MAP_FIFO_FULL_MSK; + ret = adxl372_set_interrupts(st, st->int1_bitmask, 0); if (ret < 0) return ret; @@ -810,13 +1048,22 @@ static int adxl372_buffer_postenable(struct iio_dev *indio_dev) return -EINVAL; st->fifo_format = adxl372_axis_lookup_table[i].fifo_format; + st->fifo_axis_mask = adxl372_axis_lookup_table[i].bits; st->fifo_set_size = bitmap_weight(indio_dev->active_scan_mask, indio_dev->masklength); + + /* Configure the FIFO to store sets of impact event peak. */ + if (st->peak_fifo_mode_en) { + st->fifo_set_size = 3; + st->fifo_format = ADXL372_XYZ_PEAK_FIFO; + } + /* * The 512 FIFO samples can be allotted in several ways, such as: * 170 sample sets of concurrent 3-axis data * 256 sample sets of concurrent 2-axis data (user selectable) * 512 sample sets of single-axis data + * 170 sets of impact event peak (x, y, z) */ if ((st->watermark * st->fifo_set_size) > ADXL372_FIFO_SIZE) st->watermark = (ADXL372_FIFO_SIZE / st->fifo_set_size); @@ -826,7 +1073,8 @@ static int adxl372_buffer_postenable(struct iio_dev *indio_dev) ret = adxl372_configure_fifo(st); if (ret < 0) { st->fifo_mode = ADXL372_FIFO_BYPASSED; - adxl372_set_interrupts(st, 0, 0); + st->int1_bitmask &= ~ADXL372_INT1_MAP_FIFO_FULL_MSK; + adxl372_set_interrupts(st, st->int1_bitmask, 0); return ret; } @@ -837,7 +1085,8 @@ static int adxl372_buffer_predisable(struct iio_dev *indio_dev) { struct adxl372_state *st = iio_priv(indio_dev); - adxl372_set_interrupts(st, 0, 0); + st->int1_bitmask &= ~ADXL372_INT1_MAP_FIFO_FULL_MSK; + adxl372_set_interrupts(st, st->int1_bitmask, 0); st->fifo_mode = ADXL372_FIFO_BYPASSED; adxl372_configure_fifo(st); @@ -854,12 +1103,11 @@ static int adxl372_dready_trig_set_state(struct iio_trigger *trig, { struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); struct adxl372_state *st = iio_priv(indio_dev); - unsigned long int mask = 0; if (state) - mask = ADXL372_INT1_MAP_FIFO_FULL_MSK; + st->int1_bitmask |= ADXL372_INT1_MAP_FIFO_FULL_MSK; - return adxl372_set_interrupts(st, mask, 0); + return adxl372_set_interrupts(st, st->int1_bitmask, 0); } static int adxl372_validate_trigger(struct iio_dev *indio_dev, @@ -867,7 +1115,7 @@ static int adxl372_validate_trigger(struct iio_dev *indio_dev, { struct adxl372_state *st = iio_priv(indio_dev); - if (st->dready_trig != trig) + if (st->dready_trig != trig && st->peak_datardy_trig != trig) return -EINVAL; return 0; @@ -878,6 +1126,25 @@ static const struct iio_trigger_ops adxl372_trigger_ops = { .set_trigger_state = adxl372_dready_trig_set_state, }; +static int adxl372_peak_dready_trig_set_state(struct iio_trigger *trig, + bool state) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct adxl372_state *st = iio_priv(indio_dev); + + if (state) + st->int1_bitmask |= ADXL372_INT1_MAP_FIFO_FULL_MSK; + + st->peak_fifo_mode_en = state; + + return adxl372_set_interrupts(st, st->int1_bitmask, 0); +} + +static const struct iio_trigger_ops adxl372_peak_data_trigger_ops = { + .validate_device = &iio_trigger_validate_own_device, + .set_trigger_state = adxl372_peak_dready_trig_set_state, +}; + static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("400 800 1600 3200 6400"); static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available, 0444, adxl372_show_filter_freq_avail, NULL, 0); @@ -897,6 +1164,10 @@ static const struct iio_info adxl372_info = { .attrs = &adxl372_attrs_group, .read_raw = adxl372_read_raw, .write_raw = adxl372_write_raw, + .read_event_config = adxl372_read_event_config, + .write_event_config = adxl372_write_event_config, + .read_event_value = adxl372_read_event_value, + .write_event_value = adxl372_write_event_value, .debugfs_reg_access = &adxl372_reg_access, .hwfifo_set_watermark = adxl372_set_watermark, }; @@ -925,6 +1196,8 @@ int adxl372_probe(struct device *dev, struct regmap *regmap, st->regmap = regmap; st->irq = irq; + mutex_init(&st->threshold_m); + indio_dev->channels = adxl372_channels; indio_dev->num_channels = ARRAY_SIZE(adxl372_channels); indio_dev->available_scan_masks = adxl372_channel_masks; @@ -955,13 +1228,27 @@ int adxl372_probe(struct device *dev, struct regmap *regmap, if (st->dready_trig == NULL) return -ENOMEM; + st->peak_datardy_trig = devm_iio_trigger_alloc(dev, + "%s-dev%d-peak", + indio_dev->name, + indio_dev->id); + if (!st->peak_datardy_trig) + return -ENOMEM; + st->dready_trig->ops = &adxl372_trigger_ops; + st->peak_datardy_trig->ops = &adxl372_peak_data_trigger_ops; st->dready_trig->dev.parent = dev; + st->peak_datardy_trig->dev.parent = dev; iio_trigger_set_drvdata(st->dready_trig, indio_dev); + iio_trigger_set_drvdata(st->peak_datardy_trig, indio_dev); ret = devm_iio_trigger_register(dev, st->dready_trig); if (ret < 0) return ret; + ret = devm_iio_trigger_register(dev, st->peak_datardy_trig); + if (ret < 0) + return ret; + indio_dev->trig = iio_trigger_get(st->dready_trig); ret = devm_request_threaded_irq(dev, st->irq, -- cgit v1.2.3 From 65e02d0b5039f393c1918e992322ebbb5f077490 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Wed, 26 Aug 2020 07:20:11 +0200 Subject: iio: buffer-dmaengine: adjust `bytes_used` with residue info A transfer may fall shorter than the bytes in the block. This information is available in the residue from the DMA engine, so we can compute actual `bytes_used` with that by subtracting the residue. Signed-off-by: Alexandru Ardelean Signed-off-by: Lars-Peter Clausen Link: https://lore.kernel.org/r/20200826052011.13348-1-lars@metafoo.de Signed-off-by: Jonathan Cameron --- drivers/iio/buffer/industrialio-buffer-dmaengine.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c index 6dedf12b69a4..5789bda0745b 100644 --- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c +++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c @@ -45,7 +45,8 @@ static struct dmaengine_buffer *iio_buffer_to_dmaengine_buffer( return container_of(buffer, struct dmaengine_buffer, queue.buffer); } -static void iio_dmaengine_buffer_block_done(void *data) +static void iio_dmaengine_buffer_block_done(void *data, + const struct dmaengine_result *result) { struct iio_dma_buffer_block *block = data; unsigned long flags; @@ -53,6 +54,7 @@ static void iio_dmaengine_buffer_block_done(void *data) spin_lock_irqsave(&block->queue->list_lock, flags); list_del(&block->head); spin_unlock_irqrestore(&block->queue->list_lock, flags); + block->bytes_used -= result->residue; iio_dma_buffer_block_done(block); } @@ -74,7 +76,7 @@ static int iio_dmaengine_buffer_submit_block(struct iio_dma_buffer_queue *queue, if (!desc) return -ENOMEM; - desc->callback = iio_dmaengine_buffer_block_done; + desc->callback_result = iio_dmaengine_buffer_block_done; desc->callback_param = block; cookie = dmaengine_submit(desc); -- cgit v1.2.3 From 5265b267e303ed07d922e0c353feec1fef1805cc Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 31 Aug 2020 12:08:06 +0300 Subject: iio: accel: bma220: Fix returned codes from bma220_init(), bma220_deinit() Potentially bma220_init() and bma220_deinit() may return positive codes. Fix the logic to return proper error codes instead. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200831090813.78841-1-andriy.shevchenko@linux.intel.com Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bma220_spi.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c index da8b36cc8628..3247b9c8abcb 100644 --- a/drivers/iio/accel/bma220_spi.c +++ b/drivers/iio/accel/bma220_spi.c @@ -198,10 +198,12 @@ static int bma220_init(struct spi_device *spi) /* Make sure the chip is powered on */ ret = bma220_read_reg(spi, BMA220_REG_SUSPEND); + if (ret == BMA220_SUSPEND_WAKE) + ret = bma220_read_reg(spi, BMA220_REG_SUSPEND); if (ret < 0) return ret; - else if (ret == BMA220_SUSPEND_WAKE) - return bma220_read_reg(spi, BMA220_REG_SUSPEND); + if (ret == BMA220_SUSPEND_WAKE) + return -EBUSY; return 0; } @@ -212,10 +214,12 @@ static int bma220_deinit(struct spi_device *spi) /* Make sure the chip is powered off */ ret = bma220_read_reg(spi, BMA220_REG_SUSPEND); + if (ret == BMA220_SUSPEND_SLEEP) + ret = bma220_read_reg(spi, BMA220_REG_SUSPEND); if (ret < 0) return ret; - else if (ret == BMA220_SUSPEND_SLEEP) - return bma220_read_reg(spi, BMA220_REG_SUSPEND); + if (ret == BMA220_SUSPEND_SLEEP) + return -EBUSY; return 0; } @@ -245,7 +249,7 @@ static int bma220_probe(struct spi_device *spi) indio_dev->available_scan_masks = bma220_accel_scan_masks; ret = bma220_init(data->spi_device); - if (ret < 0) + if (ret) return ret; ret = iio_triggered_buffer_setup(indio_dev, iio_pollfunc_store_time, -- cgit v1.2.3 From 938d1b3873fc2ceee4569042852e54d9deeb9ec1 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 31 Aug 2020 12:08:07 +0300 Subject: iio: accel: bma220: Convert to use ->read_avail() Convert to use ->read_avail() instead of open-coded attribute handling. While here, fix the typo in array definition and append comma in case of the future extension. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200831090813.78841-2-andriy.shevchenko@linux.intel.com Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bma220_spi.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c index 3247b9c8abcb..4774668ea7dc 100644 --- a/drivers/iio/accel/bma220_spi.c +++ b/drivers/iio/accel/bma220_spi.c @@ -30,7 +30,6 @@ #define BMA220_SUSPEND_WAKE 0x00 #define BMA220_DEVICE_NAME "bma220" -#define BMA220_SCALE_AVAILABLE "0.623 1.248 2.491 4.983" #define BMA220_ACCEL_CHANNEL(index, reg, axis) { \ .type = IIO_ACCEL, \ @@ -55,19 +54,8 @@ enum bma220_axis { AXIS_Z, }; -static IIO_CONST_ATTR(in_accel_scale_available, BMA220_SCALE_AVAILABLE); - -static struct attribute *bma220_attributes[] = { - &iio_const_attr_in_accel_scale_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group bma220_attribute_group = { - .attrs = bma220_attributes, -}; - -static const int bma220_scale_table[][4] = { - {0, 623000}, {1, 248000}, {2, 491000}, {4, 983000} +static const int bma220_scale_table[][2] = { + {0, 623000}, {1, 248000}, {2, 491000}, {4, 983000}, }; struct bma220_data { @@ -182,10 +170,26 @@ static int bma220_write_raw(struct iio_dev *indio_dev, return -EINVAL; } +static int bma220_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SCALE: + *vals = (int *)bma220_scale_table; + *type = IIO_VAL_INT_PLUS_MICRO; + *length = ARRAY_SIZE(bma220_scale_table) * 2; + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + static const struct iio_info bma220_info = { .read_raw = bma220_read_raw, .write_raw = bma220_write_raw, - .attrs = &bma220_attribute_group, + .read_avail = bma220_read_avail, }; static int bma220_init(struct spi_device *spi) -- cgit v1.2.3 From 700e63dadacdb7eee04650b6e8c66824d585aaf3 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 31 Aug 2020 12:08:08 +0300 Subject: iio: accel: bma220: Use dev_get_drvdata() directly Instead of using to_spi_dev() + spi_get_drvdata(), use dev_get_drvdata() to make code simpler. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200831090813.78841-3-andriy.shevchenko@linux.intel.com Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bma220_spi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c index 4774668ea7dc..cddd45c38ecf 100644 --- a/drivers/iio/accel/bma220_spi.c +++ b/drivers/iio/accel/bma220_spi.c @@ -289,8 +289,7 @@ static int bma220_remove(struct spi_device *spi) #ifdef CONFIG_PM_SLEEP static int bma220_suspend(struct device *dev) { - struct bma220_data *data = - iio_priv(spi_get_drvdata(to_spi_device(dev))); + struct bma220_data *data = iio_priv(dev_get_drvdata(dev)); /* The chip can be suspended/woken up by a simple register read. */ return bma220_read_reg(data->spi_device, BMA220_REG_SUSPEND); @@ -298,8 +297,7 @@ static int bma220_suspend(struct device *dev) static int bma220_resume(struct device *dev) { - struct bma220_data *data = - iio_priv(spi_get_drvdata(to_spi_device(dev))); + struct bma220_data *data = iio_priv(dev_get_drvdata(dev)); return bma220_read_reg(data->spi_device, BMA220_REG_SUSPEND); } -- cgit v1.2.3 From 4d9a167a3436b960b25900fb9539d953657cf501 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 31 Aug 2020 12:08:09 +0300 Subject: iio: accel: bma220: Mark PM functions as __maybe_unused Instead of using ugly ifdeffery, mark PM functions as __maybe_unused. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200831090813.78841-4-andriy.shevchenko@linux.intel.com Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bma220_spi.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c index cddd45c38ecf..094fd010270d 100644 --- a/drivers/iio/accel/bma220_spi.c +++ b/drivers/iio/accel/bma220_spi.c @@ -286,8 +286,7 @@ static int bma220_remove(struct spi_device *spi) return bma220_deinit(spi); } -#ifdef CONFIG_PM_SLEEP -static int bma220_suspend(struct device *dev) +static __maybe_unused int bma220_suspend(struct device *dev) { struct bma220_data *data = iio_priv(dev_get_drvdata(dev)); @@ -295,7 +294,7 @@ static int bma220_suspend(struct device *dev) return bma220_read_reg(data->spi_device, BMA220_REG_SUSPEND); } -static int bma220_resume(struct device *dev) +static __maybe_unused int bma220_resume(struct device *dev) { struct bma220_data *data = iio_priv(dev_get_drvdata(dev)); @@ -304,11 +303,6 @@ static int bma220_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(bma220_pm_ops, bma220_suspend, bma220_resume); -#define BMA220_PM_OPS (&bma220_pm_ops) -#else -#define BMA220_PM_OPS NULL -#endif - static const struct spi_device_id bma220_spi_id[] = { {"bma220", 0}, {} @@ -326,7 +320,7 @@ MODULE_DEVICE_TABLE(spi, bma220_spi_id); static struct spi_driver bma220_driver = { .driver = { .name = "bma220_spi", - .pm = BMA220_PM_OPS, + .pm = &bma220_pm_ops, .acpi_match_table = ACPI_PTR(bma220_acpi_id), }, .probe = bma220_probe, -- cgit v1.2.3 From 846afc1dbcbf878b3c8e685910ad6ce90d79de4b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 31 Aug 2020 12:08:10 +0300 Subject: iio: accel: bma220: Drop ACPI_PTR() and accompanying ifdeffery The driver is quite likely used only on ACPI based platforms and rarely build with CONFIG_ACPI=n. Even though, the few dozens of bytes is better than ugly ifdeffery and inclusion of heavy header. As a result, replace acpi.h with mod_devicetable.h. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200831090813.78841-5-andriy.shevchenko@linux.intel.com Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bma220_spi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c index 094fd010270d..044902ac8e29 100644 --- a/drivers/iio/accel/bma220_spi.c +++ b/drivers/iio/accel/bma220_spi.c @@ -5,8 +5,8 @@ * Copyright (c) 2016, Intel Corporation. */ -#include #include +#include #include #include #include @@ -308,20 +308,18 @@ static const struct spi_device_id bma220_spi_id[] = { {} }; -#ifdef CONFIG_ACPI static const struct acpi_device_id bma220_acpi_id[] = { {"BMA0220", 0}, {} }; MODULE_DEVICE_TABLE(spi, bma220_spi_id); -#endif static struct spi_driver bma220_driver = { .driver = { .name = "bma220_spi", .pm = &bma220_pm_ops, - .acpi_match_table = ACPI_PTR(bma220_acpi_id), + .acpi_match_table = bma220_acpi_id, }, .probe = bma220_probe, .remove = bma220_remove, -- cgit v1.2.3 From df9f7d4c330d1ca3e124d73a137a7df32ca3ac33 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 31 Aug 2020 12:08:11 +0300 Subject: iio: accel: bma220: Group IIO headers together Group IIO headers together and follow the common pattern of header inclusion, i.e. more generic first. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200831090813.78841-6-andriy.shevchenko@linux.intel.com Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bma220_spi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c index 044902ac8e29..73927f9c9b01 100644 --- a/drivers/iio/accel/bma220_spi.c +++ b/drivers/iio/accel/bma220_spi.c @@ -8,10 +8,11 @@ #include #include #include +#include + #include #include #include -#include #include #include -- cgit v1.2.3 From 2b09b41dba04092fc198a5098908345f756db160 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 31 Aug 2020 12:08:12 +0300 Subject: iio: accel: bma220: Use BIT() and GENMASK() macros Code is better to read when numbers of bit are explicitly used. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200831090813.78841-7-andriy.shevchenko@linux.intel.com Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bma220_spi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c index 73927f9c9b01..efdf22e0a23a 100644 --- a/drivers/iio/accel/bma220_spi.c +++ b/drivers/iio/accel/bma220_spi.c @@ -5,6 +5,7 @@ * Copyright (c) 2016, Intel Corporation. */ +#include #include #include #include @@ -24,8 +25,8 @@ #define BMA220_REG_SUSPEND 0x18 #define BMA220_CHIP_ID 0xDD -#define BMA220_READ_MASK 0x80 -#define BMA220_RANGE_MASK 0x03 +#define BMA220_READ_MASK BIT(7) +#define BMA220_RANGE_MASK GENMASK(1, 0) #define BMA220_DATA_SHIFT 2 #define BMA220_SUSPEND_SLEEP 0xFF #define BMA220_SUSPEND_WAKE 0x00 -- cgit v1.2.3 From f530f882463c046f851401fa4380cee3e523e0e3 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 31 Aug 2020 12:08:13 +0300 Subject: iio: accel: bma220: Remove unneeded blank lines There are few blank lines that split structure definitions with their users. Remove them to increase readability. While here, update copyright year. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200831090813.78841-8-andriy.shevchenko@linux.intel.com Signed-off-by: Jonathan Cameron --- drivers/iio/accel/bma220_spi.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c index efdf22e0a23a..3c9b0c6954e6 100644 --- a/drivers/iio/accel/bma220_spi.c +++ b/drivers/iio/accel/bma220_spi.c @@ -2,7 +2,7 @@ /** * BMA220 Digital triaxial acceleration sensor driver * - * Copyright (c) 2016, Intel Corporation. + * Copyright (c) 2016,2020 Intel Corporation. */ #include @@ -302,7 +302,6 @@ static __maybe_unused int bma220_resume(struct device *dev) return bma220_read_reg(data->spi_device, BMA220_REG_SUSPEND); } - static SIMPLE_DEV_PM_OPS(bma220_pm_ops, bma220_suspend, bma220_resume); static const struct spi_device_id bma220_spi_id[] = { @@ -314,7 +313,6 @@ static const struct acpi_device_id bma220_acpi_id[] = { {"BMA0220", 0}, {} }; - MODULE_DEVICE_TABLE(spi, bma220_spi_id); static struct spi_driver bma220_driver = { @@ -327,7 +325,6 @@ static struct spi_driver bma220_driver = { .remove = bma220_remove, .id_table = bma220_spi_id, }; - module_spi_driver(bma220_driver); MODULE_AUTHOR("Tiberiu Breana "); -- cgit v1.2.3 From 2f0472a1f80e6230f126aa0af76e89f85abc37bd Mon Sep 17 00:00:00 2001 From: kernel test robot Date: Tue, 1 Sep 2020 19:30:07 +0100 Subject: drivers/iio/humidity/hdc2010.c:305:2-3: Unneeded semicolon Remove unneeded semicolon. Generated by: scripts/coccinelle/misc/semicolon.cocci Fixes: 0115a63c9993 ("iio: humidity: Add TI HDC20x0 support") CC: Eugene Zaikonnikov Signed-off-by: kernel test robot Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/hdc2010.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/humidity/hdc2010.c b/drivers/iio/humidity/hdc2010.c index 744cb0f535b3..83f5b9f60780 100644 --- a/drivers/iio/humidity/hdc2010.c +++ b/drivers/iio/humidity/hdc2010.c @@ -302,7 +302,7 @@ static int hdc2010_probe(struct i2c_client *client, if (hdc2010_update_drdy_config(data, HDC2010_AMM, 0)) dev_warn(&client->dev, "Unable to restore default AMM\n"); return ret; - }; + } data->measurement_config = tmp; -- cgit v1.2.3 From aa06b6f4d8e36fa9f183b4f7a44d5c63acac33e2 Mon Sep 17 00:00:00 2001 From: Alex Dewar Date: Fri, 4 Sep 2020 18:04:16 +0100 Subject: iio: adc: rockchip_saradc: Allow compile-testing with !ARM There seems no reason to allow for compile-testing on ARM only, so remove this restriction. Build-tested with allyesconfig on x86. Signed-off-by: Alex Dewar Reviewed-by: Heiko Stuebner Link: https://lore.kernel.org/r/20200904170416.16061-1-alex.dewar90@gmail.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index f495d01a79b9..e7a9c1834d39 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -863,7 +863,7 @@ config RN5T618_ADC config ROCKCHIP_SARADC tristate "Rockchip SARADC driver" - depends on ARCH_ROCKCHIP || (ARM && COMPILE_TEST) + depends on ARCH_ROCKCHIP || COMPILE_TEST depends on RESET_CONTROLLER help Say yes here to build support for the SARADC found in SoCs from -- cgit v1.2.3 From 52f5b683e50a9bf106c07196ffadda58f199678b Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 1 Sep 2020 08:19:43 -0700 Subject: iio: sx9310: Prefer async probe On one board I found that: probe of 5-0028 returned 1 after 259547 usecs While some of this time is attributable to the pile of i2c transfers that we do at probe time, the lion's share (over 200 ms) is sitting waiting in the polling loop in sx9310_init_compensation() waiting for the hardware to indicate that it's done. There's no reason to block probe of all other devices on our probe. Turn on async probe. Signed-off-by: Douglas Anderson Reviewed-by: Stephen Boyd Reviewed-by: Daniel Campello Link: https://lore.kernel.org/r/20200901081920.v2.1.Id02b2f451b3eed71ddd580f4b8b44b3e33e84970@changeid Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/sx9310.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/iio') diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c index 9d72d08ab9e7..6d3f4ab8c6b2 100644 --- a/drivers/iio/proximity/sx9310.c +++ b/drivers/iio/proximity/sx9310.c @@ -1056,6 +1056,13 @@ static struct i2c_driver sx9310_driver = { .acpi_match_table = sx9310_acpi_match, .of_match_table = sx9310_of_match, .pm = &sx9310_pm_ops, + + /* + * Lots of i2c transfers in probe + over 200 ms waiting in + * sx9310_init_compensation() mean a slow probe; prefer async + * so we don't delay boot if we're builtin to the kernel. + */ + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .probe_new = sx9310_probe, .id_table = sx9310_id, -- cgit v1.2.3 From dde8ceec9e29fe2abf4fabee7d5a0445d0b75b66 Mon Sep 17 00:00:00 2001 From: Crt Mori Date: Sun, 6 Sep 2020 23:02:31 +0200 Subject: iio: temperature: mlx90632: Interface to change object ambient temperature Since object temperature might be different than the sensor temperature the infrared sensors should provide an interface to inject ambient temperature. This was in past done via write to ambient temperature interface (in_temp_ambient_raw), but I think most people did not know about it. This solution introduces a new iio type of the CALIBAMBIENT which is hopefully more descriptive and more explicit about the purpose and capabilities of the sensors. Signed-off-by: Crt Mori Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200906210231.383976-1-cmo@melexis.com Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 8 ++++++++ drivers/iio/industrialio-core.c | 1 + drivers/iio/temperature/mlx90632.c | 9 +++++++-- include/linux/iio/types.h | 1 + 4 files changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers/iio') diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index c20334454dbf..a9d51810a3ba 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1758,6 +1758,14 @@ Contact: linux-iio@vger.kernel.org Description: One of the following thermocouple types: B, E, J, K, N, R, S, T. +What: /sys/bus/iio/devices/iio:deviceX/in_temp_object_calibambient +What: /sys/bus/iio/devices/iio:deviceX/in_tempX_object_calibambient +KernelVersion: 5.10 +Contact: linux-iio@vger.kernel.org +Description: + Calibrated ambient temperature for object temperature + calculation in milli degrees Celsius. + What: /sys/bus/iio/devices/iio:deviceX/in_intensity_x_raw What: /sys/bus/iio/devices/iio:deviceX/in_intensity_y_raw What: /sys/bus/iio/devices/iio:deviceX/in_intensity_z_raw diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 59003dc44e60..8ddc6dfc8ed4 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -166,6 +166,7 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_CALIBEMISSIVITY] = "calibemissivity", [IIO_CHAN_INFO_OVERSAMPLING_RATIO] = "oversampling_ratio", [IIO_CHAN_INFO_THERMOCOUPLE_TYPE] = "thermocouple_type", + [IIO_CHAN_INFO_CALIBAMBIENT] = "calibambient", }; #if defined(CONFIG_DEBUG_FS) diff --git a/drivers/iio/temperature/mlx90632.c b/drivers/iio/temperature/mlx90632.c index 472a7fb20615..503fe54a0bb9 100644 --- a/drivers/iio/temperature/mlx90632.c +++ b/drivers/iio/temperature/mlx90632.c @@ -761,7 +761,9 @@ static int mlx90632_read_raw(struct iio_dev *indio_dev, *val2 = data->emissivity * 1000; } return IIO_VAL_INT_PLUS_MICRO; - + case IIO_CHAN_INFO_CALIBAMBIENT: + *val = data->object_ambient_temperature; + return IIO_VAL_INT; default: return -EINVAL; } @@ -781,6 +783,9 @@ static int mlx90632_write_raw(struct iio_dev *indio_dev, return -EINVAL; data->emissivity = val * 1000 + val2 / 1000; return 0; + case IIO_CHAN_INFO_CALIBAMBIENT: + data->object_ambient_temperature = val; + return 0; default: return -EINVAL; } @@ -798,7 +803,7 @@ static const struct iio_chan_spec mlx90632_channels[] = { .modified = 1, .channel2 = IIO_MOD_TEMP_OBJECT, .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | - BIT(IIO_CHAN_INFO_CALIBEMISSIVITY), + BIT(IIO_CHAN_INFO_CALIBEMISSIVITY) | BIT(IIO_CHAN_INFO_CALIBAMBIENT), }, }; diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index e6fd3645963c..1e3ed6f55bca 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -59,6 +59,7 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_CALIBEMISSIVITY, IIO_CHAN_INFO_OVERSAMPLING_RATIO, IIO_CHAN_INFO_THERMOCOUPLE_TYPE, + IIO_CHAN_INFO_CALIBAMBIENT, }; #endif /* _IIO_TYPES_H_ */ -- cgit v1.2.3 From 23e0618ca0255d12798acd3ae37fd98d0def7070 Mon Sep 17 00:00:00 2001 From: Christian Eggers Date: Wed, 9 Sep 2020 17:44:39 +0200 Subject: iio: light: as73211: Increase measurement timeout We found some sensors which are much slower (20% at room temperature) than nominal. According to the data sheet, up to 27% is possible. Now I add 33% to the nominal time out, hopefully this is enough. Signed-off-by: Christian Eggers Link: https://lore.kernel.org/r/20200909154439.10308-1-ceggers@arri.de Fixes: 403e5586b52e ("iio: light: as73211: New driver") Signed-off-by: Jonathan Cameron --- drivers/iio/light/as73211.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/light/as73211.c b/drivers/iio/light/as73211.c index b1178dfc1f65..7b32dfaee9b3 100644 --- a/drivers/iio/light/as73211.c +++ b/drivers/iio/light/as73211.c @@ -259,10 +259,9 @@ static int as73211_req_data(struct as73211_data *data) data->osr &= ~AS73211_OSR_SS; /* - * Add some extra margin for the timeout. sensor timing is not as precise - * as our one ... + * Add 33% extra margin for the timeout. fclk,min = fclk,typ - 27%. */ - time_us += time_us / 8; + time_us += time_us / 3; if (data->client->irq) { ret = wait_for_completion_timeout(&data->completion, usecs_to_jiffies(time_us)); if (!ret) { -- cgit v1.2.3 From a5c69204dafc77cde34317e34f2f4fc93afd36df Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 10 Sep 2020 10:52:07 +0200 Subject: iio: adc: stm32: Fix missing return in booster error path Conversion of error paths to dev_err_probe() dropped one return statement. The driver will continue to probe if getting booster regulator fails. Fixes: ce30eeb613cb ("iio: adc: stm32: Simplify with dev_err_probe()") Reported-by: Stephen Rothwell Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/1599727927-7776-1-git-send-email-krzk@kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stm32-adc-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c index 3f27b4817a42..6a0338d33bd8 100644 --- a/drivers/iio/adc/stm32-adc-core.c +++ b/drivers/iio/adc/stm32-adc-core.c @@ -595,7 +595,7 @@ static int stm32_adc_core_switches_probe(struct device *dev, if (IS_ERR(priv->booster)) { ret = PTR_ERR(priv->booster); if (ret != -ENODEV) - dev_err_probe(dev, ret, "can't get booster\n"); + return dev_err_probe(dev, ret, "can't get booster\n"); priv->booster = NULL; } -- cgit v1.2.3 From 5ac65da27ea8631d2032d47c0b9ef06c79d3446a Mon Sep 17 00:00:00 2001 From: Nishant Malpani Date: Thu, 10 Sep 2020 17:57:11 +0530 Subject: iio: gyro: adxrs290: use hook for devm resource unwinding Make use of devm_add_action_or_reset() hook to switch device into STANDBY mode during standard resource unwinding. The patch includes a helper function, in the form of adxrs290_set_mode(), to realise driving the device into STANDBY mode. Signed-off-by: Nishant Malpani Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200910122711.16670-1-nish.malpani25@gmail.com Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/adxrs290.c | 61 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 3 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/gyro/adxrs290.c b/drivers/iio/gyro/adxrs290.c index ff989536d2fb..2864eb443957 100644 --- a/drivers/iio/gyro/adxrs290.c +++ b/drivers/iio/gyro/adxrs290.c @@ -192,15 +192,70 @@ static int adxrs290_set_filter_freq(struct iio_dev *indio_dev, return adxrs290_spi_write_reg(st->spi, ADXRS290_REG_FILTER, val); } +static int adxrs290_set_mode(struct iio_dev *indio_dev, enum adxrs290_mode mode) +{ + struct adxrs290_state *st = iio_priv(indio_dev); + int val, ret; + + if (st->mode == mode) + return 0; + + mutex_lock(&st->lock); + + ret = spi_w8r8(st->spi, ADXRS290_READ_REG(ADXRS290_REG_POWER_CTL)); + if (ret < 0) + goto out_unlock; + + val = ret; + + switch (mode) { + case ADXRS290_MODE_STANDBY: + val &= ~ADXRS290_MEASUREMENT; + break; + case ADXRS290_MODE_MEASUREMENT: + val |= ADXRS290_MEASUREMENT; + break; + default: + ret = -EINVAL; + goto out_unlock; + } + + ret = adxrs290_spi_write_reg(st->spi, ADXRS290_REG_POWER_CTL, val); + if (ret < 0) { + dev_err(&st->spi->dev, "unable to set mode: %d\n", ret); + goto out_unlock; + } + + /* update cached mode */ + st->mode = mode; + +out_unlock: + mutex_unlock(&st->lock); + return ret; +} + +static void adxrs290_chip_off_action(void *data) +{ + struct iio_dev *indio_dev = data; + + adxrs290_set_mode(indio_dev, ADXRS290_MODE_STANDBY); +} + static int adxrs290_initial_setup(struct iio_dev *indio_dev) { struct adxrs290_state *st = iio_priv(indio_dev); + struct spi_device *spi = st->spi; + int ret; + + ret = adxrs290_spi_write_reg(spi, ADXRS290_REG_POWER_CTL, + ADXRS290_MEASUREMENT | ADXRS290_TSM); + if (ret < 0) + return ret; st->mode = ADXRS290_MODE_MEASUREMENT; - return adxrs290_spi_write_reg(st->spi, - ADXRS290_REG_POWER_CTL, - ADXRS290_MEASUREMENT | ADXRS290_TSM); + return devm_add_action_or_reset(&spi->dev, adxrs290_chip_off_action, + indio_dev); } static int adxrs290_read_raw(struct iio_dev *indio_dev, -- cgit v1.2.3 From 672555807f6f62c1604f866743eaedadaa557b23 Mon Sep 17 00:00:00 2001 From: Nishant Malpani Date: Thu, 10 Sep 2020 23:34:48 +0530 Subject: iio: gyro: adxrs290: Add triggered buffer support Provide a way for continuous data capture by setting up buffer support. The data ready signal exposed at the SYNC pin of the ADXRS290 is exploited as a hardware interrupt which triggers to fill the buffer. Triggered buffer setup was tested with both hardware trigger (DATA_RDY) and software triggers (sysfs-trig & hrtimer). Signed-off-by: Nishant Malpani Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200910180450.29696-2-nish.malpani25@gmail.com Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/Kconfig | 2 + drivers/iio/gyro/adxrs290.c | 211 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 199 insertions(+), 14 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig index 024a34139875..5824f2edf975 100644 --- a/drivers/iio/gyro/Kconfig +++ b/drivers/iio/gyro/Kconfig @@ -44,6 +44,8 @@ config ADIS16260 config ADXRS290 tristate "Analog Devices ADXRS290 Dual-Axis MEMS Gyroscope SPI driver" depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER help Say yes here to build support for Analog Devices ADXRS290 programmable digital output gyroscope. diff --git a/drivers/iio/gyro/adxrs290.c b/drivers/iio/gyro/adxrs290.c index 2864eb443957..41b1f995a143 100644 --- a/drivers/iio/gyro/adxrs290.c +++ b/drivers/iio/gyro/adxrs290.c @@ -13,8 +13,12 @@ #include #include +#include #include #include +#include +#include +#include #define ADXRS290_ADI_ID 0xAD #define ADXRS290_MEMS_ID 0x1D @@ -35,7 +39,9 @@ #define ADXRS290_READ BIT(7) #define ADXRS290_TSM BIT(0) #define ADXRS290_MEASUREMENT BIT(1) -#define ADXRS290_SYNC GENMASK(1, 0) +#define ADXRS290_DATA_RDY_OUT BIT(0) +#define ADXRS290_SYNC_MASK GENMASK(1, 0) +#define ADXRS290_SYNC(x) FIELD_PREP(ADXRS290_SYNC_MASK, x) #define ADXRS290_LPF_MASK GENMASK(2, 0) #define ADXRS290_LPF(x) FIELD_PREP(ADXRS290_LPF_MASK, x) #define ADXRS290_HPF_MASK GENMASK(7, 4) @@ -50,6 +56,13 @@ enum adxrs290_mode { ADXRS290_MODE_MEASUREMENT, }; +enum adxrs290_scan_index { + ADXRS290_IDX_X, + ADXRS290_IDX_Y, + ADXRS290_IDX_TEMP, + ADXRS290_IDX_TS, +}; + struct adxrs290_state { struct spi_device *spi; /* Serialize reads and their subsequent processing */ @@ -57,6 +70,12 @@ struct adxrs290_state { enum adxrs290_mode mode; unsigned int lpf_3db_freq_idx; unsigned int hpf_3db_freq_idx; + struct iio_trigger *dready_trig; + /* Ensure correct alignment of timestamp when present */ + struct { + s16 channels[3]; + s64 ts __aligned(8); + } buffer; }; /* @@ -270,24 +289,34 @@ 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; + switch (chan->type) { case IIO_ANGL_VEL: ret = adxrs290_get_rate_data(indio_dev, ADXRS290_READ_REG(chan->address), val); if (ret < 0) - return ret; + break; - return IIO_VAL_INT; + ret = IIO_VAL_INT; + break; case IIO_TEMP: ret = adxrs290_get_temp_data(indio_dev, val); if (ret < 0) - return ret; + break; - return IIO_VAL_INT; + ret = IIO_VAL_INT; + break; default: - return -EINVAL; + ret = -EINVAL; + break; } + + iio_device_release_direct_mode(indio_dev); + return ret; case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_ANGL_VEL: @@ -334,34 +363,52 @@ static int adxrs290_write_raw(struct iio_dev *indio_dev, long mask) { struct adxrs290_state *st = iio_priv(indio_dev); - int lpf_idx, hpf_idx; + int ret, lpf_idx, hpf_idx; + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; switch (mask) { case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: lpf_idx = adxrs290_find_match(adxrs290_lpf_3db_freq_hz_table, ARRAY_SIZE(adxrs290_lpf_3db_freq_hz_table), val, val2); - if (lpf_idx < 0) - return -EINVAL; + if (lpf_idx < 0) { + ret = -EINVAL; + break; + } + /* caching the updated state of the low-pass filter */ st->lpf_3db_freq_idx = lpf_idx; /* retrieving the current state of the high-pass filter */ hpf_idx = st->hpf_3db_freq_idx; - return adxrs290_set_filter_freq(indio_dev, lpf_idx, hpf_idx); + ret = adxrs290_set_filter_freq(indio_dev, lpf_idx, hpf_idx); + break; + case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: hpf_idx = adxrs290_find_match(adxrs290_hpf_3db_freq_hz_table, ARRAY_SIZE(adxrs290_hpf_3db_freq_hz_table), val, val2); - if (hpf_idx < 0) - return -EINVAL; + if (hpf_idx < 0) { + ret = -EINVAL; + break; + } + /* caching the updated state of the high-pass filter */ st->hpf_3db_freq_idx = hpf_idx; /* retrieving the current state of the low-pass filter */ lpf_idx = st->lpf_3db_freq_idx; - return adxrs290_set_filter_freq(indio_dev, lpf_idx, hpf_idx); + ret = adxrs290_set_filter_freq(indio_dev, lpf_idx, hpf_idx); + break; + + default: + ret = -EINVAL; + break; } - return -EINVAL; + iio_device_release_direct_mode(indio_dev); + return ret; } static int adxrs290_read_avail(struct iio_dev *indio_dev, @@ -389,6 +436,72 @@ static int adxrs290_read_avail(struct iio_dev *indio_dev, } } +static int adxrs290_data_rdy_trigger_set_state(struct iio_trigger *trig, + bool state) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct adxrs290_state *st = iio_priv(indio_dev); + int ret; + u8 val; + + val = state ? ADXRS290_SYNC(ADXRS290_DATA_RDY_OUT) : 0; + + ret = adxrs290_spi_write_reg(st->spi, ADXRS290_REG_DATA_RDY, val); + if (ret < 0) + dev_err(&st->spi->dev, "failed to start data rdy interrupt\n"); + + return ret; +} + +static int adxrs290_reset_trig(struct iio_trigger *trig) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + int val; + + /* + * Data ready interrupt is reset after a read of the data registers. + * Here, we only read the 16b DATAY registers as that marks the end of + * a read of the data registers and initiates a reset for the interrupt + * line. + */ + adxrs290_get_rate_data(indio_dev, + ADXRS290_READ_REG(ADXRS290_REG_DATAY0), &val); + + return 0; +} + +static const struct iio_trigger_ops adxrs290_trigger_ops = { + .set_trigger_state = &adxrs290_data_rdy_trigger_set_state, + .validate_device = &iio_trigger_validate_own_device, + .try_reenable = &adxrs290_reset_trig, +}; + +static irqreturn_t adxrs290_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct adxrs290_state *st = iio_priv(indio_dev); + u8 tx = ADXRS290_READ_REG(ADXRS290_REG_DATAX0); + int ret; + + mutex_lock(&st->lock); + + /* exercise a bulk data capture starting from reg DATAX0... */ + ret = spi_write_then_read(st->spi, &tx, sizeof(tx), st->buffer.channels, + sizeof(st->buffer.channels)); + if (ret < 0) + goto out_unlock_notify; + + iio_push_to_buffers_with_timestamp(indio_dev, &st->buffer, + pf->timestamp); + +out_unlock_notify: + mutex_unlock(&st->lock); + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + #define ADXRS290_ANGL_VEL_CHANNEL(reg, axis) { \ .type = IIO_ANGL_VEL, \ .address = reg, \ @@ -401,6 +514,13 @@ static int adxrs290_read_avail(struct iio_dev *indio_dev, .info_mask_shared_by_type_available = \ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \ BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \ + .scan_index = ADXRS290_IDX_##axis, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_LE, \ + }, \ } static const struct iio_chan_spec adxrs290_channels[] = { @@ -411,7 +531,20 @@ static const struct iio_chan_spec adxrs290_channels[] = { .address = ADXRS290_REG_TEMP0, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .scan_index = ADXRS290_IDX_TEMP, + .scan_type = { + .sign = 's', + .realbits = 12, + .storagebits = 16, + .endianness = IIO_LE, + }, }, + IIO_CHAN_SOFT_TIMESTAMP(ADXRS290_IDX_TS), +}; + +static const unsigned long adxrs290_avail_scan_masks[] = { + BIT(ADXRS290_IDX_X) | BIT(ADXRS290_IDX_Y) | BIT(ADXRS290_IDX_TEMP), + 0 }; static const struct iio_info adxrs290_info = { @@ -420,6 +553,44 @@ static const struct iio_info adxrs290_info = { .read_avail = &adxrs290_read_avail, }; +static int adxrs290_probe_trigger(struct iio_dev *indio_dev) +{ + struct adxrs290_state *st = iio_priv(indio_dev); + int ret; + + if (!st->spi->irq) { + dev_info(&st->spi->dev, "no irq, using polling\n"); + return 0; + } + + st->dready_trig = devm_iio_trigger_alloc(&st->spi->dev, "%s-dev%d", + indio_dev->name, + indio_dev->id); + if (!st->dready_trig) + return -ENOMEM; + + st->dready_trig->dev.parent = &st->spi->dev; + st->dready_trig->ops = &adxrs290_trigger_ops; + iio_trigger_set_drvdata(st->dready_trig, indio_dev); + + ret = devm_request_irq(&st->spi->dev, st->spi->irq, + &iio_trigger_generic_data_rdy_poll, + IRQF_ONESHOT, "adxrs290_irq", st->dready_trig); + if (ret < 0) + return dev_err_probe(&st->spi->dev, ret, + "request irq %d failed\n", st->spi->irq); + + ret = devm_iio_trigger_register(&st->spi->dev, st->dready_trig); + if (ret) { + dev_err(&st->spi->dev, "iio trigger register failed\n"); + return ret; + } + + indio_dev->trig = iio_trigger_get(st->dready_trig); + + return 0; +} + static int adxrs290_probe(struct spi_device *spi) { struct iio_dev *indio_dev; @@ -439,6 +610,7 @@ static int adxrs290_probe(struct spi_device *spi) indio_dev->channels = adxrs290_channels; indio_dev->num_channels = ARRAY_SIZE(adxrs290_channels); indio_dev->info = &adxrs290_info; + indio_dev->available_scan_masks = adxrs290_avail_scan_masks; mutex_init(&st->lock); @@ -478,6 +650,17 @@ static int adxrs290_probe(struct spi_device *spi) st->lpf_3db_freq_idx = val; st->hpf_3db_freq_idx = val2; + ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, + &iio_pollfunc_store_time, + &adxrs290_trigger_handler, NULL); + if (ret < 0) + return dev_err_probe(&spi->dev, ret, + "iio triggered buffer setup failed\n"); + + ret = adxrs290_probe_trigger(indio_dev); + if (ret < 0) + return ret; + return devm_iio_device_register(&spi->dev, indio_dev); } -- cgit v1.2.3 From d3e0e14d65178d73ee0f991934c5fa89737e3922 Mon Sep 17 00:00:00 2001 From: Nishant Malpani Date: Thu, 10 Sep 2020 23:34:50 +0530 Subject: iio: gyro: adxrs290: Add debugfs register access support Extend support to read/write byte data from/to the device using debugfs iio interface. Signed-off-by: Nishant Malpani Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200910180450.29696-4-nish.malpani25@gmail.com Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/adxrs290.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers/iio') diff --git a/drivers/iio/gyro/adxrs290.c b/drivers/iio/gyro/adxrs290.c index 41b1f995a143..ca6fc234076e 100644 --- a/drivers/iio/gyro/adxrs290.c +++ b/drivers/iio/gyro/adxrs290.c @@ -436,6 +436,31 @@ static int adxrs290_read_avail(struct iio_dev *indio_dev, } } +static int adxrs290_reg_access_rw(struct spi_device *spi, unsigned int reg, + unsigned int *readval) +{ + int ret; + + ret = spi_w8r8(spi, ADXRS290_READ_REG(reg)); + if (ret < 0) + return ret; + + *readval = ret; + + return 0; +} + +static int adxrs290_reg_access(struct iio_dev *indio_dev, unsigned int reg, + unsigned int writeval, unsigned int *readval) +{ + struct adxrs290_state *st = iio_priv(indio_dev); + + if (readval) + return adxrs290_reg_access_rw(st->spi, reg, readval); + else + return adxrs290_spi_write_reg(st->spi, reg, writeval); +} + static int adxrs290_data_rdy_trigger_set_state(struct iio_trigger *trig, bool state) { @@ -551,6 +576,7 @@ static const struct iio_info adxrs290_info = { .read_raw = &adxrs290_read_raw, .write_raw = &adxrs290_write_raw, .read_avail = &adxrs290_read_avail, + .debugfs_reg_access = &adxrs290_reg_access, }; static int adxrs290_probe_trigger(struct iio_dev *indio_dev) -- cgit v1.2.3 From 2544ea7bd075948dcb0bdebfae739eb235c69728 Mon Sep 17 00:00:00 2001 From: Sergiu Cuciurean Date: Wed, 16 Sep 2020 12:23:49 +0300 Subject: iio: stm32-dac: Replace indio_dev->mlock with own device lock As part of the general cleanup of indio_dev->mlock, this change replaces it with a local lock. The lock protects against potential races when reading the CR reg and then updating, so that the state of pm_runtime is consistent between the two operations. This is part of a bigger cleanup. Link: https://lore.kernel.org/linux-iio/CA+U=Dsoo6YABe5ODLp+eFNPGFDjk5ZeQEceGkqjxXcVEhLWubw@mail.gmail.com/ Signed-off-by: Sergiu Cuciurean Signed-off-by: Alexandru Ardelean Reviewed-by: Fabrice Gasnier Link: https://lore.kernel.org/r/20200916092349.75647-1-alexandru.ardelean@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/dac/stm32-dac.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/dac/stm32-dac.c b/drivers/iio/dac/stm32-dac.c index 092c796fa3d9..12dec68c16f7 100644 --- a/drivers/iio/dac/stm32-dac.c +++ b/drivers/iio/dac/stm32-dac.c @@ -26,9 +26,12 @@ /** * struct stm32_dac - private data of DAC driver * @common: reference to DAC common data + * @lock: lock to protect against potential races when reading + * and update CR, to keep it in sync with pm_runtime */ struct stm32_dac { struct stm32_dac_common *common; + struct mutex lock; }; static int stm32_dac_is_enabled(struct iio_dev *indio_dev, int channel) @@ -58,10 +61,10 @@ static int stm32_dac_set_enable_state(struct iio_dev *indio_dev, int ch, int ret; /* already enabled / disabled ? */ - mutex_lock(&indio_dev->mlock); + mutex_lock(&dac->lock); ret = stm32_dac_is_enabled(indio_dev, ch); if (ret < 0 || enable == !!ret) { - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&dac->lock); return ret < 0 ? ret : 0; } @@ -69,13 +72,13 @@ static int stm32_dac_set_enable_state(struct iio_dev *indio_dev, int ch, ret = pm_runtime_get_sync(dev); if (ret < 0) { pm_runtime_put_noidle(dev); - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&dac->lock); return ret; } } ret = regmap_update_bits(dac->common->regmap, STM32_DAC_CR, msk, en); - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&dac->lock); if (ret < 0) { dev_err(&indio_dev->dev, "%s failed\n", en ? "Enable" : "Disable"); @@ -327,6 +330,8 @@ static int stm32_dac_probe(struct platform_device *pdev) indio_dev->info = &stm32_dac_iio_info; indio_dev->modes = INDIO_DIRECT_MODE; + mutex_init(&dac->lock); + ret = stm32_dac_chan_of_init(indio_dev); if (ret < 0) return ret; -- cgit v1.2.3 From 20be66c193be1a758c507fe28e8f77ad407d5039 Mon Sep 17 00:00:00 2001 From: Sergiu Cuciurean Date: Wed, 16 Sep 2020 12:25:35 +0300 Subject: iio: dac: ti-dac7612: Replace indio_dev->mlock with own device lock As part of the general cleanup of indio_dev->mlock, this change replaces it with a local lock on the device's state from potential concurrent write accesses from userspace. The write operation requires an SPI write, then toggling of a GPIO, so the lock aims to protect the sanity of the entire sequence of operation. This is part of a bigger cleanup. Link: https://lore.kernel.org/linux-iio/CA+U=Dsoo6YABe5ODLp+eFNPGFDjk5ZeQEceGkqjxXcVEhLWubw@mail.gmail.com/ Signed-off-by: Sergiu Cuciurean Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20200916092535.76527-1-alexandru.ardelean@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ti-dac7612.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/dac/ti-dac7612.c b/drivers/iio/dac/ti-dac7612.c index 07c9f39d54f1..4c0f4b5e9ff4 100644 --- a/drivers/iio/dac/ti-dac7612.c +++ b/drivers/iio/dac/ti-dac7612.c @@ -22,6 +22,14 @@ struct dac7612 { struct gpio_desc *loaddacs; uint16_t cache[2]; + /* + * Lock to protect the state of the device from potential concurrent + * write accesses from userspace. The write operation requires an + * SPI write, then toggling of a GPIO, so the lock aims to protect + * the sanity of the entire sequence of operation. + */ + struct mutex lock; + /* * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. @@ -101,9 +109,9 @@ static int dac7612_write_raw(struct iio_dev *iio_dev, if (val == priv->cache[chan->channel]) return 0; - mutex_lock(&iio_dev->mlock); + mutex_lock(&priv->lock); ret = dac7612_cmd_single(priv, chan->channel, val); - mutex_unlock(&iio_dev->mlock); + mutex_unlock(&priv->lock); return ret; } @@ -145,6 +153,8 @@ static int dac7612_probe(struct spi_device *spi) iio_dev->num_channels = ARRAY_SIZE(priv->cache); iio_dev->name = spi_get_device_id(spi)->name; + mutex_init(&priv->lock); + for (i = 0; i < ARRAY_SIZE(priv->cache); i++) { ret = dac7612_cmd_single(priv, i, 0); if (ret) -- cgit v1.2.3 From f0e64305cf741c6f6f5fff2545dcb0d23218b2e7 Mon Sep 17 00:00:00 2001 From: Sergiu Cuciurean Date: Wed, 16 Sep 2020 12:27:31 +0300 Subject: iio: frequency: adf4350: Replace indio_dev->mlock with own device lock As part of the general cleanup of indio_dev->mlock, this change replaces it with a local lock. The lock protect the state of the device from potential concurrent writes. The device is configured via a sequence of SPI writes, and this lock is meant to prevent the start of another sequence before another one has finished. This is part of a bigger cleanup. Link: https://lore.kernel.org/linux-iio/CA+U=Dsoo6YABe5ODLp+eFNPGFDjk5ZeQEceGkqjxXcVEhLWubw@mail.gmail.com/ Signed-off-by: Sergiu Cuciurean Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20200916092731.77220-1-alexandru.ardelean@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/frequency/adf4350.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index 409c9c47161e..82c050a3899d 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -47,6 +47,13 @@ struct adf4350_state { unsigned long regs[6]; unsigned long regs_hw[6]; unsigned long long freq_req; + /* + * Lock to protect the state of the device from potential concurrent + * writes. The device is configured via a sequence of SPI writes, + * and this lock is meant to prevent the start of another sequence + * before another one has finished. + */ + struct mutex lock; /* * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. @@ -99,7 +106,7 @@ static int adf4350_reg_access(struct iio_dev *indio_dev, if (reg > ADF4350_REG5) return -EINVAL; - mutex_lock(&indio_dev->mlock); + mutex_lock(&st->lock); if (readval == NULL) { st->regs[reg] = writeval & ~(BIT(0) | BIT(1) | BIT(2)); ret = adf4350_sync_config(st); @@ -107,7 +114,7 @@ static int adf4350_reg_access(struct iio_dev *indio_dev, *readval = st->regs_hw[reg]; ret = 0; } - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&st->lock); return ret; } @@ -254,7 +261,7 @@ static ssize_t adf4350_write(struct iio_dev *indio_dev, if (ret) return ret; - mutex_lock(&indio_dev->mlock); + mutex_lock(&st->lock); switch ((u32)private) { case ADF4350_FREQ: ret = adf4350_set_freq(st, readin); @@ -295,7 +302,7 @@ static ssize_t adf4350_write(struct iio_dev *indio_dev, default: ret = -EINVAL; } - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&st->lock); return ret ? ret : len; } @@ -309,7 +316,7 @@ static ssize_t adf4350_read(struct iio_dev *indio_dev, unsigned long long val; int ret = 0; - mutex_lock(&indio_dev->mlock); + mutex_lock(&st->lock); switch ((u32)private) { case ADF4350_FREQ: val = (u64)((st->r0_int * st->r1_mod) + st->r0_fract) * @@ -338,7 +345,7 @@ static ssize_t adf4350_read(struct iio_dev *indio_dev, ret = -EINVAL; val = 0; } - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&st->lock); return ret < 0 ? ret : sprintf(buf, "%llu\n", val); } @@ -539,6 +546,8 @@ static int adf4350_probe(struct spi_device *spi) indio_dev->channels = &adf4350_chan; indio_dev->num_channels = 1; + mutex_init(&st->lock); + st->chspc = pdata->channel_spacing; if (clk) { st->clk = clk; -- cgit v1.2.3 From b79a22ee37ee44f5b63a28955000e7ae7240d9ab Mon Sep 17 00:00:00 2001 From: Nuno Sá Date: Tue, 15 Sep 2020 14:02:49 +0200 Subject: iio: adis16201: Use Managed device functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the adis managed device functions to setup the buffer and the trigger. The ultimate goal will be to completely drop the non devm version from the lib. Since we are here, drop the `.remove` callback by further using devm functions. Signed-off-by: Nuno Sá Link: https://lore.kernel.org/r/20200915120258.161587-2-nuno.sa@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/accel/adis16201.c | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/accel/adis16201.c b/drivers/iio/accel/adis16201.c index 59a24c355a1a..f955cccb3e77 100644 --- a/drivers/iio/accel/adis16201.c +++ b/drivers/iio/accel/adis16201.c @@ -281,34 +281,15 @@ static int adis16201_probe(struct spi_device *spi) if (ret) return ret; - ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL); + ret = devm_adis_setup_buffer_and_trigger(st, indio_dev, NULL); if (ret) return ret; ret = adis_initial_startup(st); if (ret) - goto error_cleanup_buffer_trigger; - - ret = iio_device_register(indio_dev); - if (ret < 0) - goto error_cleanup_buffer_trigger; - - return 0; - -error_cleanup_buffer_trigger: - adis_cleanup_buffer_and_trigger(st, indio_dev); - return ret; -} - -static int adis16201_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct adis *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - adis_cleanup_buffer_and_trigger(st, indio_dev); + return ret; - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static struct spi_driver adis16201_driver = { @@ -316,7 +297,6 @@ static struct spi_driver adis16201_driver = { .name = "adis16201", }, .probe = adis16201_probe, - .remove = adis16201_remove, }; module_spi_driver(adis16201_driver); -- cgit v1.2.3 From 17ff204ca827d09499f1cb42879edace49bd6b05 Mon Sep 17 00:00:00 2001 From: Nuno Sá Date: Tue, 15 Sep 2020 14:02:50 +0200 Subject: iio: adis16209: Use Managed device functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the adis managed device functions to setup the buffer and the trigger. The ultimate goal will be to completely drop the non devm version from the lib. Since we are here, drop the `.remove` callback by further using devm functions. Signed-off-by: Nuno Sá Link: https://lore.kernel.org/r/20200915120258.161587-3-nuno.sa@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/accel/adis16209.c | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/accel/adis16209.c b/drivers/iio/accel/adis16209.c index 3d5538e2f76e..4a841aec6268 100644 --- a/drivers/iio/accel/adis16209.c +++ b/drivers/iio/accel/adis16209.c @@ -291,33 +291,15 @@ static int adis16209_probe(struct spi_device *spi) if (ret) return ret; - ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL); + ret = devm_adis_setup_buffer_and_trigger(st, indio_dev, NULL); if (ret) return ret; ret = adis_initial_startup(st); if (ret) - goto error_cleanup_buffer_trigger; - ret = iio_device_register(indio_dev); - if (ret) - goto error_cleanup_buffer_trigger; - - return 0; - -error_cleanup_buffer_trigger: - adis_cleanup_buffer_and_trigger(st, indio_dev); - return ret; -} - -static int adis16209_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct adis *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - adis_cleanup_buffer_and_trigger(st, indio_dev); + return ret; - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static struct spi_driver adis16209_driver = { @@ -325,7 +307,6 @@ static struct spi_driver adis16209_driver = { .name = "adis16209", }, .probe = adis16209_probe, - .remove = adis16209_remove, }; module_spi_driver(adis16209_driver); -- cgit v1.2.3 From 77802e097f1c07a0440a027bffdf9b177994451e Mon Sep 17 00:00:00 2001 From: Nuno Sá Date: Tue, 15 Sep 2020 14:02:51 +0200 Subject: iio: adis16136: Use Managed device functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the adis managed device functions to setup the buffer and the trigger. The ultimate goal will be to completely drop the non devm version from the lib. Since we are here, drop the `.remove` callback by further using devm functions. Signed-off-by: Nuno Sá Link: https://lore.kernel.org/r/20200915120258.161587-4-nuno.sa@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/adis16136.c | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c index d8a96f6bbae2..a11ae9db0d11 100644 --- a/drivers/iio/gyro/adis16136.c +++ b/drivers/iio/gyro/adis16136.c @@ -523,6 +523,11 @@ static const struct adis16136_chip_info adis16136_chip_info[] = { }, }; +static void adis16136_stop(void *data) +{ + adis16136_stop_device(data); +} + static int adis16136_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); @@ -552,38 +557,23 @@ static int adis16136_probe(struct spi_device *spi) if (ret) return ret; - ret = adis_setup_buffer_and_trigger(&adis16136->adis, indio_dev, NULL); + ret = devm_adis_setup_buffer_and_trigger(&adis16136->adis, indio_dev, NULL); if (ret) return ret; ret = adis16136_initial_setup(indio_dev); if (ret) - goto error_cleanup_buffer; + return ret; - ret = iio_device_register(indio_dev); + ret = devm_add_action_or_reset(&spi->dev, adis16136_stop, indio_dev); if (ret) - goto error_stop_device; - - adis16136_debugfs_init(indio_dev); - - return 0; - -error_stop_device: - adis16136_stop_device(indio_dev); -error_cleanup_buffer: - adis_cleanup_buffer_and_trigger(&adis16136->adis, indio_dev); - return ret; -} - -static int adis16136_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct adis16136 *adis16136 = iio_priv(indio_dev); + return ret; - iio_device_unregister(indio_dev); - adis16136_stop_device(indio_dev); + ret = devm_iio_device_register(&spi->dev, indio_dev); + if (ret) + return ret; - adis_cleanup_buffer_and_trigger(&adis16136->adis, indio_dev); + adis16136_debugfs_init(indio_dev); return 0; } @@ -603,7 +593,6 @@ static struct spi_driver adis16136_driver = { }, .id_table = adis16136_ids, .probe = adis16136_probe, - .remove = adis16136_remove, }; module_spi_driver(adis16136_driver); -- cgit v1.2.3 From 5a9b7ca638461a0a5f91fd1cab8db2d496a2399b Mon Sep 17 00:00:00 2001 From: Nuno Sá Date: Tue, 15 Sep 2020 14:02:52 +0200 Subject: iio: adis16260: Use Managed device functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the adis managed device functions to setup the buffer and the trigger. The ultimate goal will be to completely drop the non devm version from the lib. Since we are here, drop the `.remove` callback by further using devm functions. Signed-off-by: Nuno Sá Link: https://lore.kernel.org/r/20200915120258.161587-5-nuno.sa@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/adis16260.c | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c index e638d56e1574..e7c9a3e31c45 100644 --- a/drivers/iio/gyro/adis16260.c +++ b/drivers/iio/gyro/adis16260.c @@ -359,6 +359,11 @@ static const struct adis_data adis16260_data = { BIT(ADIS16260_DIAG_STAT_POWER_LOW_BIT), }; +static void adis16260_stop(void *data) +{ + adis16260_stop_device(data); +} + static int adis16260_probe(struct spi_device *spi) { const struct spi_device_id *id; @@ -390,35 +395,20 @@ static int adis16260_probe(struct spi_device *spi) if (ret) return ret; - ret = adis_setup_buffer_and_trigger(&adis16260->adis, indio_dev, NULL); + ret = devm_adis_setup_buffer_and_trigger(&adis16260->adis, indio_dev, NULL); if (ret) return ret; /* Get the device into a sane initial state */ ret = adis_initial_startup(&adis16260->adis); if (ret) - goto error_cleanup_buffer_trigger; - ret = iio_device_register(indio_dev); - if (ret) - goto error_cleanup_buffer_trigger; - - return 0; - -error_cleanup_buffer_trigger: - adis_cleanup_buffer_and_trigger(&adis16260->adis, indio_dev); - return ret; -} - -static int adis16260_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct adis16260 *adis16260 = iio_priv(indio_dev); + return ret; - iio_device_unregister(indio_dev); - adis16260_stop_device(indio_dev); - adis_cleanup_buffer_and_trigger(&adis16260->adis, indio_dev); + ret = devm_add_action_or_reset(&spi->dev, adis16260_stop, indio_dev); + if (ret) + return ret; - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } /* @@ -441,7 +431,6 @@ static struct spi_driver adis16260_driver = { .name = "adis16260", }, .probe = adis16260_probe, - .remove = adis16260_remove, .id_table = adis16260_id, }; module_spi_driver(adis16260_driver); -- cgit v1.2.3 From f13aa06442258275093addec9cb9ec907d82b2b5 Mon Sep 17 00:00:00 2001 From: Nuno Sá Date: Tue, 15 Sep 2020 14:02:53 +0200 Subject: iio: adis16400: Use Managed device functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the adis managed device functions to setup the buffer and the trigger. The ultimate goal will be to completely drop the non devm version from the lib. Since we are here, drop the `.remove` callback by further using devm functions. Signed-off-by: Nuno Sá Link: https://lore.kernel.org/r/20200915120258.161587-6-nuno.sa@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis16400.c | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c index 1ebe3e50d3e6..889c8c2a19f4 100644 --- a/drivers/iio/imu/adis16400.c +++ b/drivers/iio/imu/adis16400.c @@ -1164,6 +1164,12 @@ static void adis16400_setup_chan_mask(struct adis16400_state *st) st->avail_scan_mask[0] |= BIT(ch->scan_index); } } + +static void adis16400_stop(void *data) +{ + adis16400_stop_device(data); +} + static int adis16400_probe(struct spi_device *spi) { struct adis16400_state *st; @@ -1201,37 +1207,24 @@ static int adis16400_probe(struct spi_device *spi) if (ret) return ret; - ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev, - adis16400_trigger_handler); + ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, adis16400_trigger_handler); if (ret) return ret; /* Get the device into a sane initial state */ ret = adis16400_initial_setup(indio_dev); if (ret) - goto error_cleanup_buffer; - ret = iio_device_register(indio_dev); - if (ret) - goto error_cleanup_buffer; - - adis16400_debugfs_init(indio_dev); - return 0; - -error_cleanup_buffer: - adis_cleanup_buffer_and_trigger(&st->adis, indio_dev); - return ret; -} - -static int adis16400_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct adis16400_state *st = iio_priv(indio_dev); + return ret; - iio_device_unregister(indio_dev); - adis16400_stop_device(indio_dev); + ret = devm_add_action_or_reset(&spi->dev, adis16400_stop, indio_dev); + if (ret) + return ret; - adis_cleanup_buffer_and_trigger(&st->adis, indio_dev); + ret = devm_iio_device_register(&spi->dev, indio_dev); + if (ret) + return ret; + adis16400_debugfs_init(indio_dev); return 0; } @@ -1261,7 +1254,6 @@ static struct spi_driver adis16400_driver = { }, .id_table = adis16400_id, .probe = adis16400_probe, - .remove = adis16400_remove, }; module_spi_driver(adis16400_driver); -- cgit v1.2.3 From fa623cddc040930207b57fa0c4767bbb8f7ac8a1 Mon Sep 17 00:00:00 2001 From: Nuno Sá Date: Tue, 15 Sep 2020 14:02:54 +0200 Subject: iio: adis16460: Use Managed device functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the adis managed device functions to setup the buffer and the trigger. The ultimate goal will be to completely drop the non devm version from the lib. Since we are here, drop the `.remove` callback by further using devm functions. Signed-off-by: Nuno Sá Link: https://lore.kernel.org/r/20200915120258.161587-7-nuno.sa@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis16460.c | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/imu/adis16460.c b/drivers/iio/imu/adis16460.c index b26a5f1bc51a..74a161e39733 100644 --- a/drivers/iio/imu/adis16460.c +++ b/drivers/iio/imu/adis16460.c @@ -403,7 +403,7 @@ static int adis16460_probe(struct spi_device *spi) if (ret) return ret; - ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL); + ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL); if (ret) return ret; @@ -411,30 +411,14 @@ static int adis16460_probe(struct spi_device *spi) ret = __adis_initial_startup(&st->adis); if (ret) - goto error_cleanup_buffer; + return ret; - ret = iio_device_register(indio_dev); + ret = devm_iio_device_register(&spi->dev, indio_dev); if (ret) - goto error_cleanup_buffer; + return ret; adis16460_debugfs_init(indio_dev); - return 0; - -error_cleanup_buffer: - adis_cleanup_buffer_and_trigger(&st->adis, indio_dev); - return ret; -} - -static int adis16460_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct adis16460 *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - - adis_cleanup_buffer_and_trigger(&st->adis, indio_dev); - return 0; } @@ -457,7 +441,6 @@ static struct spi_driver adis16460_driver = { }, .id_table = adis16460_ids, .probe = adis16460_probe, - .remove = adis16460_remove, }; module_spi_driver(adis16460_driver); -- cgit v1.2.3 From 514f641b3b2af794df90d61f4346e5858177665d Mon Sep 17 00:00:00 2001 From: Nuno Sá Date: Tue, 15 Sep 2020 14:02:55 +0200 Subject: iio: adis16480: Use Managed device functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the adis managed device functions to setup the buffer and the trigger. The ultimate goal will be to completely drop the non devm version from the lib. Since we are here, drop the `.remove` callback by further using devm functions. Signed-off-by: Nuno Sá Link: https://lore.kernel.org/r/20200915120258.161587-8-nuno.sa@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis16480.c | 55 +++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 30 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c index 1eb4f98076f1..dfe86c589325 100644 --- a/drivers/iio/imu/adis16480.c +++ b/drivers/iio/imu/adis16480.c @@ -1212,6 +1212,16 @@ static int adis16480_get_ext_clocks(struct adis16480 *st) return 0; } +static void adis16480_stop(void *data) +{ + adis16480_stop_device(data); +} + +static void adis16480_clk_disable(void *data) +{ + clk_disable_unprepare(data); +} + static int adis16480_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); @@ -1245,18 +1255,26 @@ static int adis16480_probe(struct spi_device *spi) if (ret) return ret; + ret = devm_add_action_or_reset(&spi->dev, adis16480_stop, indio_dev); + if (ret) + return ret; + ret = adis16480_config_irq_pin(spi->dev.of_node, st); if (ret) - goto error_stop_device; + return ret; ret = adis16480_get_ext_clocks(st); if (ret) - goto error_stop_device; + return ret; if (!IS_ERR_OR_NULL(st->ext_clk)) { ret = adis16480_ext_clk_config(st, spi->dev.of_node, true); if (ret) - goto error_stop_device; + return ret; + + ret = devm_add_action_or_reset(&spi->dev, adis16480_clk_disable, st->ext_clk); + if (ret) + return ret; st->clk_freq = clk_get_rate(st->ext_clk); st->clk_freq *= 1000; /* micro */ @@ -1264,38 +1282,16 @@ static int adis16480_probe(struct spi_device *spi) st->clk_freq = st->chip_info->int_clk; } - ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL); + ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL); if (ret) - goto error_clk_disable_unprepare; + return ret; - ret = iio_device_register(indio_dev); + ret = devm_iio_device_register(&spi->dev, indio_dev); if (ret) - goto error_cleanup_buffer; + return ret; adis16480_debugfs_init(indio_dev); - return 0; - -error_cleanup_buffer: - adis_cleanup_buffer_and_trigger(&st->adis, indio_dev); -error_clk_disable_unprepare: - clk_disable_unprepare(st->ext_clk); -error_stop_device: - adis16480_stop_device(indio_dev); - return ret; -} - -static int adis16480_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct adis16480 *st = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - adis16480_stop_device(indio_dev); - - adis_cleanup_buffer_and_trigger(&st->adis, indio_dev); - clk_disable_unprepare(st->ext_clk); - return 0; } @@ -1338,7 +1334,6 @@ static struct spi_driver adis16480_driver = { }, .id_table = adis16480_ids, .probe = adis16480_probe, - .remove = adis16480_remove, }; module_spi_driver(adis16480_driver); -- cgit v1.2.3 From d8f0cd76684e679d4a8ec4929fcdf6c3a030a007 Mon Sep 17 00:00:00 2001 From: Nuno Sá Date: Tue, 15 Sep 2020 14:02:58 +0200 Subject: iio: adis: Drop non Managed device functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop `adis_setup_buffer_and_trigger()`. All users were updated to use the devm version of this function. This avoids having almost the same code repeated. Signed-off-by: Nuno Sá Link: https://lore.kernel.org/r/20200915120258.161587-11-nuno.sa@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis_buffer.c | 64 +++--------------------------------------- drivers/iio/imu/adis_trigger.c | 60 --------------------------------------- include/linux/iio/imu/adis.h | 27 ------------------ 3 files changed, 4 insertions(+), 147 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c index 5b4225ee09b9..df6144285470 100644 --- a/drivers/iio/imu/adis_buffer.c +++ b/drivers/iio/imu/adis_buffer.c @@ -169,48 +169,6 @@ static void adis_buffer_cleanup(void *arg) kfree(adis->xfer); } -/** - * adis_setup_buffer_and_trigger() - Sets up buffer and trigger for the adis device - * @adis: The adis device. - * @indio_dev: The IIO device. - * @trigger_handler: Optional trigger handler, may be NULL. - * - * Returns 0 on success, a negative error code otherwise. - * - * This function sets up the buffer and trigger for a adis devices. If - * 'trigger_handler' is NULL the default trigger handler will be used. The - * default trigger handler will simply read the registers assigned to the - * currently active channels. - * - * adis_cleanup_buffer_and_trigger() should be called to free the resources - * allocated by this function. - */ -int adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, - irqreturn_t (*trigger_handler)(int, void *)) -{ - int ret; - - if (!trigger_handler) - trigger_handler = adis_trigger_handler; - - ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, - trigger_handler, NULL); - if (ret) - return ret; - - if (adis->spi->irq) { - ret = adis_probe_trigger(adis, indio_dev); - if (ret) - goto error_buffer_cleanup; - } - return 0; - -error_buffer_cleanup: - iio_triggered_buffer_cleanup(indio_dev); - return ret; -} -EXPORT_SYMBOL_GPL(adis_setup_buffer_and_trigger); - /** * devm_adis_setup_buffer_and_trigger() - Sets up buffer and trigger for * the managed adis device @@ -220,7 +178,10 @@ EXPORT_SYMBOL_GPL(adis_setup_buffer_and_trigger); * * Returns 0 on success, a negative error code otherwise. * - * This function perfoms exactly the same as adis_setup_buffer_and_trigger() + * This function sets up the buffer and trigger for a adis devices. If + * 'trigger_handler' is NULL the default trigger handler will be used. The + * default trigger handler will simply read the registers assigned to the + * currently active channels. */ int devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, @@ -248,20 +209,3 @@ devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, } EXPORT_SYMBOL_GPL(devm_adis_setup_buffer_and_trigger); -/** - * adis_cleanup_buffer_and_trigger() - Free buffer and trigger resources - * @adis: The adis device. - * @indio_dev: The IIO device. - * - * Frees resources allocated by adis_setup_buffer_and_trigger() - */ -void adis_cleanup_buffer_and_trigger(struct adis *adis, - struct iio_dev *indio_dev) -{ - if (adis->spi->irq) - adis_remove_trigger(adis); - kfree(adis->buffer); - kfree(adis->xfer); - iio_triggered_buffer_cleanup(indio_dev); -} -EXPORT_SYMBOL_GPL(adis_cleanup_buffer_and_trigger); diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c index 8afe71947c00..64e0ba51cb18 100644 --- a/drivers/iio/imu/adis_trigger.c +++ b/drivers/iio/imu/adis_trigger.c @@ -55,53 +55,6 @@ static int adis_validate_irq_flag(struct adis *adis) return 0; } -/** - * adis_probe_trigger() - Sets up trigger for a adis device - * @adis: The adis device - * @indio_dev: The IIO device - * - * Returns 0 on success or a negative error code - * - * adis_remove_trigger() should be used to free the trigger. - */ -int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) -{ - int ret; - - adis->trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, - indio_dev->id); - if (adis->trig == NULL) - return -ENOMEM; - - adis_trigger_setup(adis); - - ret = adis_validate_irq_flag(adis); - if (ret) - return ret; - - ret = request_irq(adis->spi->irq, - &iio_trigger_generic_data_rdy_poll, - adis->irq_flag, - indio_dev->name, - adis->trig); - if (ret) - goto error_free_trig; - - ret = iio_trigger_register(adis->trig); - - indio_dev->trig = iio_trigger_get(adis->trig); - if (ret) - goto error_free_irq; - - return 0; - -error_free_irq: - free_irq(adis->spi->irq, adis->trig); -error_free_trig: - iio_trigger_free(adis->trig); - return ret; -} -EXPORT_SYMBOL_GPL(adis_probe_trigger); /** * devm_adis_probe_trigger() - Sets up trigger for a managed adis device @@ -137,16 +90,3 @@ int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) } EXPORT_SYMBOL_GPL(devm_adis_probe_trigger); -/** - * adis_remove_trigger() - Remove trigger for a adis devices - * @adis: The adis device - * - * Removes the trigger previously registered with adis_probe_trigger(). - */ -void adis_remove_trigger(struct adis *adis) -{ - iio_trigger_unregister(adis->trig); - free_irq(adis->spi->irq, adis->trig); - iio_trigger_free(adis->trig); -} -EXPORT_SYMBOL_GPL(adis_remove_trigger); diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index 2df67448f0d1..01ba691da2f3 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -517,14 +517,8 @@ struct adis_burst { int devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, irq_handler_t trigger_handler); -int adis_setup_buffer_and_trigger(struct adis *adis, - struct iio_dev *indio_dev, irqreturn_t (*trigger_handler)(int, void *)); -void adis_cleanup_buffer_and_trigger(struct adis *adis, - struct iio_dev *indio_dev); int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev); -int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev); -void adis_remove_trigger(struct adis *adis); int adis_update_scan_mode(struct iio_dev *indio_dev, const unsigned long *scan_mask); @@ -538,33 +532,12 @@ devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, return 0; } -static inline int adis_setup_buffer_and_trigger(struct adis *adis, - struct iio_dev *indio_dev, irqreturn_t (*trigger_handler)(int, void *)) -{ - return 0; -} - -static inline void adis_cleanup_buffer_and_trigger(struct adis *adis, - struct iio_dev *indio_dev) -{ -} - static inline int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) { return 0; } -static inline int adis_probe_trigger(struct adis *adis, - struct iio_dev *indio_dev) -{ - return 0; -} - -static inline void adis_remove_trigger(struct adis *adis) -{ -} - #define adis_update_scan_mode NULL #endif /* CONFIG_IIO_BUFFER */ -- cgit v1.2.3 From d4a4b78a0c0411820f131bcca4a14552089b7cbc Mon Sep 17 00:00:00 2001 From: Liu Shixin Date: Mon, 14 Sep 2020 14:54:01 +0800 Subject: iio: adc: palmas_gpadc: use module_platform_driver to simplify the code module_platform_driver() makes the code simpler by eliminating boilerplate code. Signed-off-by: Liu Shixin Link: https://lore.kernel.org/r/20200914065401.3726354-1-liushixin2@huawei.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/palmas_gpadc.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/palmas_gpadc.c b/drivers/iio/adc/palmas_gpadc.c index 1ca6570be66a..889b88768b63 100644 --- a/drivers/iio/adc/palmas_gpadc.c +++ b/drivers/iio/adc/palmas_gpadc.c @@ -834,18 +834,7 @@ static struct platform_driver palmas_gpadc_driver = { .of_match_table = of_palmas_gpadc_match_tbl, }, }; - -static int __init palmas_gpadc_init(void) -{ - return platform_driver_register(&palmas_gpadc_driver); -} -module_init(palmas_gpadc_init); - -static void __exit palmas_gpadc_exit(void) -{ - platform_driver_unregister(&palmas_gpadc_driver); -} -module_exit(palmas_gpadc_exit); +module_platform_driver(palmas_gpadc_driver); MODULE_DESCRIPTION("palmas GPADC driver"); MODULE_AUTHOR("Pradeep Goudagunta"); -- cgit v1.2.3 From 6026af6a53dffb50db87ef264294dff57ed3a845 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Wed, 16 Sep 2020 11:31:28 +0300 Subject: iio: adc: ad9467: refine mismatch vs unknown chip-id messages We should probably print what the expected chip-ID is. We already have that information available, based on the device specified via device-tree. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20200916083128.73729-1-alexandru.ardelean@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad9467.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c index 1e8fd83b9bc2..9c3ab46e4d88 100644 --- a/drivers/iio/adc/ad9467.c +++ b/drivers/iio/adc/ad9467.c @@ -390,7 +390,8 @@ static int ad9467_probe(struct spi_device *spi) id = ad9467_spi_read(spi, AN877_ADC_REG_CHIP_ID); if (id != conv->chip_info->id) { - dev_err(&spi->dev, "Unrecognized CHIP_ID 0x%X\n", id); + dev_err(&spi->dev, "Mismatch CHIP_ID, got 0x%X, expected 0x%X\n", + id, conv->chip_info->id); return -ENODEV; } -- cgit v1.2.3 From 13ca1a1be50180ccd700cff00a342156b1cdae8e Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Wed, 16 Sep 2020 11:22:21 +0300 Subject: iio: adc: ad9467: return ENODEV vs EINVAL in ad9467_setup() The proper error code should be ENODEV (vs EINVAL) in case the chip ID isn't recognized. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20200916082221.72851-1-alexandru.ardelean@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad9467.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c index 9c3ab46e4d88..f068256cfca9 100644 --- a/drivers/iio/adc/ad9467.c +++ b/drivers/iio/adc/ad9467.c @@ -324,7 +324,7 @@ static int ad9467_setup(struct ad9467_state *st, unsigned int chip_id) AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT; return 0; default: - return -EINVAL; + return -ENODEV; } } -- cgit v1.2.3 From 14b15f3f9c92c34342af508ef9c83df29bb28029 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Tue, 15 Sep 2020 21:26:21 +0200 Subject: iio: adc: meson-saradc: Make the of_device_id array style consistent Use only one line for the closing bracket of the last entry and the opening bracket for the next one to keep the style across the whole array consistent. Also add a "sentinel" comment to the last entry and remove the comma to ensure that there won't be any entry after it. No functional changes. Signed-off-by: Martin Blumenstingl Link: https://lore.kernel.org/r/20200915192621.13202-1-martin.blumenstingl@googlemail.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/meson_saradc.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c index a9d06e8a576a..743c5a47eed8 100644 --- a/drivers/iio/adc/meson_saradc.c +++ b/drivers/iio/adc/meson_saradc.c @@ -1150,16 +1150,13 @@ static const struct of_device_id meson_sar_adc_of_match[] = { { .compatible = "amlogic,meson8-saradc", .data = &meson_sar_adc_meson8_data, - }, - { + }, { .compatible = "amlogic,meson8b-saradc", .data = &meson_sar_adc_meson8b_data, - }, - { + }, { .compatible = "amlogic,meson8m2-saradc", .data = &meson_sar_adc_meson8m2_data, - }, - { + }, { .compatible = "amlogic,meson-gxbb-saradc", .data = &meson_sar_adc_gxbb_data, }, { @@ -1175,7 +1172,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); -- cgit v1.2.3 From e16e0a778fec8ac1b3755c9c4a322eaea37e8a47 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Thu, 17 Sep 2020 15:59:51 +0300 Subject: iio: buffer: split buffer sysfs creation to take buffer as primary arg Currently the iio_buffer_{alloc,free}_sysfs_and_mask() take 'indio_dev' as primary argument. This change splits the main logic into a private function that takes an IIO buffer as primary argument. That way, the functions can be extended to configure the sysfs for multiple buffers. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20200917125951.861-1-alexandru.ardelean@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-buffer.c | 46 +++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 16 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index a7d7e5143ed2..a4f6bb96d4f4 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -1264,26 +1264,14 @@ static struct attribute *iio_buffer_attrs[] = { &dev_attr_data_available.attr, }; -int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) +static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer, + struct iio_dev *indio_dev) { struct iio_dev_attr *p; struct attribute **attr; - struct iio_buffer *buffer = indio_dev->buffer; int ret, i, attrn, attrcount; const struct iio_chan_spec *channels; - channels = indio_dev->channels; - if (channels) { - int ml = indio_dev->masklength; - - for (i = 0; i < indio_dev->num_channels; i++) - ml = max(ml, channels[i].scan_index + 1); - indio_dev->masklength = ml; - } - - if (!buffer) - return 0; - attrcount = 0; if (buffer->attrs) { while (buffer->attrs[attrcount] != NULL) @@ -1367,19 +1355,45 @@ error_cleanup_dynamic: return ret; } -void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev) +int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) { struct iio_buffer *buffer = indio_dev->buffer; + const struct iio_chan_spec *channels; + int i; + + channels = indio_dev->channels; + if (channels) { + int ml = indio_dev->masklength; + + for (i = 0; i < indio_dev->num_channels; i++) + ml = max(ml, channels[i].scan_index + 1); + indio_dev->masklength = ml; + } if (!buffer) - return; + return 0; + + return __iio_buffer_alloc_sysfs_and_mask(buffer, indio_dev); +} +static void __iio_buffer_free_sysfs_and_mask(struct iio_buffer *buffer) +{ bitmap_free(buffer->scan_mask); kfree(buffer->buffer_group.attrs); kfree(buffer->scan_el_group.attrs); iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list); } +void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev) +{ + struct iio_buffer *buffer = indio_dev->buffer; + + if (!buffer) + return; + + __iio_buffer_free_sysfs_and_mask(buffer); +} + /** * iio_validate_scan_mask_onehot() - Validates that exactly one channel is selected * @indio_dev: the iio device -- cgit v1.2.3 From d563d4d834641bae50564bd1e6e48187b630c563 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 13 Sep 2020 14:21:13 +0100 Subject: iio:imu:adis16400: Sort out missing kernel doc. I'd like to be enable W=1 for all IIO builds as it catches real issues as well as more minor documentation issues such as this (also good to fix though!) drivers/iio/imu/adis16400.c:183: warning: Function parameter or member 'avail_scan_mask' not described in 'adis16400_state' Signed-off-by: Jonathan Cameron Acked-by: Alexandru Ardelean Cc: Alexandru Ardelean Link: https://lore.kernel.org/r/20200913132115.800131-2-jic23@kernel.org --- drivers/iio/imu/adis16400.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/iio') diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c index 889c8c2a19f4..73433f7feb31 100644 --- a/drivers/iio/imu/adis16400.c +++ b/drivers/iio/imu/adis16400.c @@ -173,6 +173,8 @@ struct adis16400_chip_info { * @variant: chip variant info * @filt_int: integer part of requested filter frequency * @adis: adis device + * @avail_scan_mask: NULL terminated array of bitmaps of channels + * that must be enabled together **/ struct adis16400_state { struct adis16400_chip_info *variant; -- cgit v1.2.3 From 19061b3c590d20ed555cbe848427ef5e69d18559 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:05 +0100 Subject: iio:potentiometer:ad5272: Drop of_match_ptr and CONFIG_OF protections. These prevent use of this driver with ACPI via PRP0001 and are an example of an anti pattern I'm trying to remove from IIO. Drop them to remove this restriction. Also added mod_devicetable.h include given use of struct of_device_id which is defined in that header. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Phil Reid Link: https://lore.kernel.org/r/20200910173242.621168-2-jic23@kernel.org --- drivers/iio/potentiometer/ad5272.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/potentiometer/ad5272.c b/drivers/iio/potentiometer/ad5272.c index 933afcf7e925..70c45d346df0 100644 --- a/drivers/iio/potentiometer/ad5272.c +++ b/drivers/iio/potentiometer/ad5272.c @@ -15,6 +15,7 @@ #include #include #include +#include #define AD5272_RDAC_WR 1 #define AD5272_RDAC_RD 2 @@ -192,7 +193,6 @@ static int ad5272_probe(struct i2c_client *client, return devm_iio_device_register(dev, indio_dev); } -#if defined(CONFIG_OF) static const struct of_device_id ad5272_dt_ids[] = { { .compatible = "adi,ad5272-020", .data = (void *)AD5272_020 }, { .compatible = "adi,ad5272-050", .data = (void *)AD5272_050 }, @@ -202,7 +202,6 @@ static const struct of_device_id ad5272_dt_ids[] = { {} }; MODULE_DEVICE_TABLE(of, ad5272_dt_ids); -#endif /* CONFIG_OF */ static const struct i2c_device_id ad5272_id[] = { { "ad5272-020", AD5272_020 }, @@ -217,7 +216,7 @@ MODULE_DEVICE_TABLE(i2c, ad5272_id); static struct i2c_driver ad5272_driver = { .driver = { .name = "ad5272", - .of_match_table = of_match_ptr(ad5272_dt_ids), + .of_match_table = ad5272_dt_ids, }, .probe = ad5272_probe, .id_table = ad5272_id, -- cgit v1.2.3 From c34bed923d40ef197412b0fa0b4b79892b7f6035 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:06 +0100 Subject: iio:potentiometer:ds1803: Drop of_match_ptr and CONFIG_OF protections These prevent use of this driver with ACPI via PRP0001 and are an example of an anti pattern I'm trying to remove from IIO. Drop them to remove this restriction. Also switch of.h for mod_devicetable.h include given use of struct of_device_id which is defined in that header. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Slawomir Stepien Link: https://lore.kernel.org/r/20200910173242.621168-3-jic23@kernel.org --- drivers/iio/potentiometer/ds1803.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/potentiometer/ds1803.c b/drivers/iio/potentiometer/ds1803.c index 5c061ab8f46c..20b45407eaac 100644 --- a/drivers/iio/potentiometer/ds1803.c +++ b/drivers/iio/potentiometer/ds1803.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #define DS1803_MAX_POS 255 #define DS1803_WRITE(chan) (0xa8 | ((chan) + 1)) @@ -134,7 +134,6 @@ static int ds1803_probe(struct i2c_client *client, return devm_iio_device_register(dev, indio_dev); } -#if defined(CONFIG_OF) static const struct of_device_id ds1803_dt_ids[] = { { .compatible = "maxim,ds1803-010", .data = &ds1803_cfg[DS1803_010] }, { .compatible = "maxim,ds1803-050", .data = &ds1803_cfg[DS1803_050] }, @@ -142,7 +141,6 @@ static const struct of_device_id ds1803_dt_ids[] = { {} }; MODULE_DEVICE_TABLE(of, ds1803_dt_ids); -#endif /* CONFIG_OF */ static const struct i2c_device_id ds1803_id[] = { { "ds1803-010", DS1803_010 }, @@ -155,7 +153,7 @@ MODULE_DEVICE_TABLE(i2c, ds1803_id); static struct i2c_driver ds1803_driver = { .driver = { .name = "ds1803", - .of_match_table = of_match_ptr(ds1803_dt_ids), + .of_match_table = ds1803_dt_ids, }, .probe = ds1803_probe, .id_table = ds1803_id, -- cgit v1.2.3 From 458c7665f82afe361746107212ff6122d8d3f8f7 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:07 +0100 Subject: iio:potentiometer:max5432: Drop of_match_ptr and use generic fw accessors These prevent use of this driver with ACPI via PRP0001 and are an example of an anti pattern I'm trying to remove from IIO. Drop them to remove this restriction. Also switch headers to reflect this change. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Reviewed-by: Martin Kaiser Link: https://lore.kernel.org/r/20200910173242.621168-4-jic23@kernel.org --- drivers/iio/potentiometer/max5432.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/potentiometer/max5432.c b/drivers/iio/potentiometer/max5432.c index 280de9c54471..aed3b6ab82a2 100644 --- a/drivers/iio/potentiometer/max5432.c +++ b/drivers/iio/potentiometer/max5432.c @@ -11,8 +11,8 @@ #include #include #include -#include -#include +#include +#include /* All chip variants have 32 wiper positions. */ #define MAX5432_MAX_POS 31 @@ -100,7 +100,7 @@ static int max5432_probe(struct i2c_client *client, data = iio_priv(indio_dev); data->client = client; - data->ohm = (unsigned long)of_device_get_match_data(dev); + data->ohm = (unsigned long)device_get_match_data(dev); indio_dev->info = &max5432_info; indio_dev->channels = max5432_channels; @@ -122,7 +122,7 @@ MODULE_DEVICE_TABLE(of, max5432_dt_ids); static struct i2c_driver max5432_driver = { .driver = { .name = "max5432", - .of_match_table = of_match_ptr(max5432_dt_ids), + .of_match_table = max5432_dt_ids, }, .probe = max5432_probe, }; -- cgit v1.2.3 From 1c372dd71da4aeadf341b9751733a6d3653b97c6 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:08 +0100 Subject: iio:potentiometer:max5481: Drop of_match_ptr and CONFIG_OF protections. These prevent use of this driver with ACPI via PRP0001 and are an example of an anti pattern I'm trying to remove from IIO. Whilst this driver has an ACPI binding, it is not of a form that is valid under ACPI so will be dropped shortly. Also switch to device_get_match_data() and switch headers. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Maury Anderson Cc: Matthew Weber Cc: Slawomir Stepien Link: https://lore.kernel.org/r/20200910173242.621168-5-jic23@kernel.org --- drivers/iio/potentiometer/max5481.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/potentiometer/max5481.c b/drivers/iio/potentiometer/max5481.c index 5f5988189796..6d1e1a57cba1 100644 --- a/drivers/iio/potentiometer/max5481.c +++ b/drivers/iio/potentiometer/max5481.c @@ -11,8 +11,8 @@ #include #include #include -#include -#include +#include +#include #include /* write wiper reg */ @@ -117,7 +117,6 @@ static const struct iio_info max5481_info = { .write_raw = max5481_write_raw, }; -#if defined(CONFIG_OF) static const struct of_device_id max5481_match[] = { { .compatible = "maxim,max5481", .data = &max5481_cfg[max5481] }, { .compatible = "maxim,max5482", .data = &max5481_cfg[max5482] }, @@ -126,7 +125,6 @@ static const struct of_device_id max5481_match[] = { { } }; MODULE_DEVICE_TABLE(of, max5481_match); -#endif static int max5481_probe(struct spi_device *spi) { @@ -144,7 +142,7 @@ static int max5481_probe(struct spi_device *spi) data->spi = spi; - data->cfg = of_device_get_match_data(&spi->dev); + data->cfg = device_get_match_data(&spi->dev); if (!data->cfg) data->cfg = &max5481_cfg[id->driver_data]; @@ -198,7 +196,7 @@ MODULE_DEVICE_TABLE(acpi, max5481_acpi_match); static struct spi_driver max5481_driver = { .driver = { .name = "max5481", - .of_match_table = of_match_ptr(max5481_match), + .of_match_table = max5481_match, .acpi_match_table = ACPI_PTR(max5481_acpi_match), }, .probe = max5481_probe, -- cgit v1.2.3 From 9c5149cd92e477b83550a28e486e3c72c2724257 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:09 +0100 Subject: iio:potentiometer:max5481: Drop invalid ACPI binding. Given that an ACPI binding must start with 3 or 4 capitals, this cannot represent a valid binding. It seems unlikely anything out there is using it. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Maury Anderson Cc: Matthew Weber Cc: Slawomir Stepien Link: https://lore.kernel.org/r/20200910173242.621168-6-jic23@kernel.org --- drivers/iio/potentiometer/max5481.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/potentiometer/max5481.c b/drivers/iio/potentiometer/max5481.c index 6d1e1a57cba1..a88ed0eb3adc 100644 --- a/drivers/iio/potentiometer/max5481.c +++ b/drivers/iio/potentiometer/max5481.c @@ -7,7 +7,6 @@ * https://datasheets.maximintegrated.com/en/ds/MAX5481-MAX5484.pdf */ -#include #include #include #include @@ -182,22 +181,10 @@ static const struct spi_device_id max5481_id_table[] = { }; MODULE_DEVICE_TABLE(spi, max5481_id_table); -#if defined(CONFIG_ACPI) -static const struct acpi_device_id max5481_acpi_match[] = { - { "max5481", max5481 }, - { "max5482", max5482 }, - { "max5483", max5483 }, - { "max5484", max5484 }, - { } -}; -MODULE_DEVICE_TABLE(acpi, max5481_acpi_match); -#endif - static struct spi_driver max5481_driver = { .driver = { .name = "max5481", .of_match_table = max5481_match, - .acpi_match_table = ACPI_PTR(max5481_acpi_match), }, .probe = max5481_probe, .remove = max5481_remove, -- cgit v1.2.3 From 6fad8ae45692a12596d88f6e26103e35624c65c7 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:10 +0100 Subject: iio:potentiometer:mcp4018: Drop of_match_ptr and CONFIG_OF protections. These prevent use of this driver with ACPI via PRP0001 and are an example of an anti pattern I'm trying to remove from IIO. Also use device_get_match_data() rather than devicetree only version. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Peter Rosin Link: https://lore.kernel.org/r/20200910173242.621168-7-jic23@kernel.org --- drivers/iio/potentiometer/mcp4018.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/potentiometer/mcp4018.c b/drivers/iio/potentiometer/mcp4018.c index fd0579ad3c83..c0e171fec062 100644 --- a/drivers/iio/potentiometer/mcp4018.c +++ b/drivers/iio/potentiometer/mcp4018.c @@ -16,8 +16,8 @@ #include #include #include -#include -#include +#include +#include #define MCP4018_WIPER_MAX 127 @@ -116,8 +116,6 @@ static const struct i2c_device_id mcp4018_id[] = { }; MODULE_DEVICE_TABLE(i2c, mcp4018_id); -#ifdef CONFIG_OF - #define MCP4018_COMPATIBLE(of_compatible, cfg) { \ .compatible = of_compatible, \ .data = &mcp4018_cfg[cfg], \ @@ -140,8 +138,6 @@ static const struct of_device_id mcp4018_of_match[] = { }; MODULE_DEVICE_TABLE(of, mcp4018_of_match); -#endif - static int mcp4018_probe(struct i2c_client *client) { struct device *dev = &client->dev; @@ -161,7 +157,7 @@ static int mcp4018_probe(struct i2c_client *client) i2c_set_clientdata(client, indio_dev); data->client = client; - data->cfg = of_device_get_match_data(dev); + data->cfg = device_get_match_data(dev); if (!data->cfg) data->cfg = &mcp4018_cfg[i2c_match_id(mcp4018_id, client)->driver_data]; @@ -176,7 +172,7 @@ static int mcp4018_probe(struct i2c_client *client) static struct i2c_driver mcp4018_driver = { .driver = { .name = "mcp4018", - .of_match_table = of_match_ptr(mcp4018_of_match), + .of_match_table = mcp4018_of_match, }, .probe_new = mcp4018_probe, .id_table = mcp4018_id, -- cgit v1.2.3 From a51a834997861e720fddf81f942e090a6be26233 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:11 +0100 Subject: iio:potentiometer:mcp4131: Drop of_match_ptr and use generic fw interfaces. This change allows the use of the driver with ACPI via PRP0001 and remove an example of an anti pattern I'm trying to remove from IIO. Also adjust includes to reflect this change. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Slawomir Stepien Link: https://lore.kernel.org/r/20200910173242.621168-8-jic23@kernel.org --- drivers/iio/potentiometer/mcp4131.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/potentiometer/mcp4131.c b/drivers/iio/potentiometer/mcp4131.c index 2923ce250fc3..7c8c18ab8764 100644 --- a/drivers/iio/potentiometer/mcp4131.c +++ b/drivers/iio/potentiometer/mcp4131.c @@ -37,9 +37,9 @@ #include #include #include +#include #include -#include -#include +#include #include #define MCP4131_WRITE (0x00 << 2) @@ -252,7 +252,7 @@ static int mcp4131_probe(struct spi_device *spi) data = iio_priv(indio_dev); spi_set_drvdata(spi, indio_dev); data->spi = spi; - data->cfg = of_device_get_match_data(&spi->dev); + data->cfg = device_get_match_data(&spi->dev); if (!data->cfg) { devid = spi_get_device_id(spi)->driver_data; data->cfg = &mcp4131_cfg[devid]; @@ -479,7 +479,7 @@ MODULE_DEVICE_TABLE(spi, mcp4131_id); static struct spi_driver mcp4131_driver = { .driver = { .name = "mcp4131", - .of_match_table = of_match_ptr(mcp4131_dt_ids), + .of_match_table = mcp4131_dt_ids, }, .probe = mcp4131_probe, .id_table = mcp4131_id, -- cgit v1.2.3 From 20e39f3aa278667a50d3b5b6f467538ab0e1d5ce Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:12 +0100 Subject: iio:potentiometer:mcp4531: Drop of_match_ptr and CONFIG_OF protections. These prevent use of this driver with ACPI via PRP0001 and are an example of an anti pattern I'm trying to remove from IIO. Hence drop them from this driver. Also switch to device_get_match_data() from of_ variant and adjust headers to reflect the change. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Peter Rosin Link: https://lore.kernel.org/r/20200910173242.621168-9-jic23@kernel.org --- drivers/iio/potentiometer/mcp4531.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/potentiometer/mcp4531.c b/drivers/iio/potentiometer/mcp4531.c index 95efc4b40514..c25f84b4a270 100644 --- a/drivers/iio/potentiometer/mcp4531.c +++ b/drivers/iio/potentiometer/mcp4531.c @@ -28,8 +28,8 @@ #include #include #include -#include -#include +#include +#include #include @@ -275,8 +275,6 @@ static const struct i2c_device_id mcp4531_id[] = { }; MODULE_DEVICE_TABLE(i2c, mcp4531_id); -#ifdef CONFIG_OF - #define MCP4531_COMPATIBLE(of_compatible, cfg) { \ .compatible = of_compatible, \ .data = &mcp4531_cfg[cfg], \ @@ -350,7 +348,6 @@ static const struct of_device_id mcp4531_of_match[] = { { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, mcp4531_of_match); -#endif static int mcp4531_probe(struct i2c_client *client) { @@ -371,7 +368,7 @@ static int mcp4531_probe(struct i2c_client *client) i2c_set_clientdata(client, indio_dev); data->client = client; - data->cfg = of_device_get_match_data(dev); + data->cfg = device_get_match_data(dev); if (!data->cfg) data->cfg = &mcp4531_cfg[i2c_match_id(mcp4531_id, client)->driver_data]; @@ -386,7 +383,7 @@ static int mcp4531_probe(struct i2c_client *client) static struct i2c_driver mcp4531_driver = { .driver = { .name = "mcp4531", - .of_match_table = of_match_ptr(mcp4531_of_match), + .of_match_table = mcp4531_of_match, }, .probe_new = mcp4531_probe, .id_table = mcp4531_id, -- cgit v1.2.3 From b49e6eb1c7dffd86af7aaf922380ce2e231e8492 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:13 +0100 Subject: iio:dac:ad5446: Drop of_match_ptr and CONFIG_OF protections These prevent use of this driver with ACPI via PRP0001 and are an example of an anti pattern I'm trying to remove from IIO. Hence drop them from this driver. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Michael Hennerich Link: https://lore.kernel.org/r/20200910173242.621168-10-jic23@kernel.org --- drivers/iio/dac/ad5446.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c index 935a6177569f..d87e21016863 100644 --- a/drivers/iio/dac/ad5446.c +++ b/drivers/iio/dac/ad5446.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -478,13 +479,11 @@ static const struct spi_device_id ad5446_spi_ids[] = { }; MODULE_DEVICE_TABLE(spi, ad5446_spi_ids); -#ifdef CONFIG_OF static const struct of_device_id ad5446_of_ids[] = { { .compatible = "ti,dac7512" }, { } }; MODULE_DEVICE_TABLE(of, ad5446_of_ids); -#endif static int ad5446_spi_probe(struct spi_device *spi) { @@ -502,7 +501,7 @@ static int ad5446_spi_remove(struct spi_device *spi) static struct spi_driver ad5446_spi_driver = { .driver = { .name = "ad5446", - .of_match_table = of_match_ptr(ad5446_of_ids), + .of_match_table = ad5446_of_ids, }, .probe = ad5446_spi_probe, .remove = ad5446_spi_remove, -- cgit v1.2.3 From 23636b479a39719ea1bbc5687048245f9b0ea22b Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:14 +0100 Subject: iio:dac:ad5592r: Drop of_match_ptr and ACPI_PTR protections. These result in a very small reduction in driver size, but at the cost of more complex build and slightly harder to read code. In the case of of_match_ptr it also prevents use of PRP0001 ACPI based identification. In this particular case we have a valid ACPI/PNP ID that I am assuming was issued by Analog Devices. That should be used in preference to PRP0001 but doesn't mean we should prevent that route. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Michael Hennerich Cc: Lars-Peter Clausen Link: https://lore.kernel.org/r/20200910173242.621168-11-jic23@kernel.org --- drivers/iio/dac/ad5592r.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/dac/ad5592r.c b/drivers/iio/dac/ad5592r.c index 49308ad13c4b..41f651500668 100644 --- a/drivers/iio/dac/ad5592r.c +++ b/drivers/iio/dac/ad5592r.c @@ -10,9 +10,8 @@ #include #include -#include +#include #include -#include #define AD5592R_GPIO_READBACK_EN BIT(10) #define AD5592R_LDAC_READBACK_EN BIT(6) @@ -157,8 +156,8 @@ MODULE_DEVICE_TABLE(acpi, ad5592r_acpi_match); static struct spi_driver ad5592r_spi_driver = { .driver = { .name = "ad5592r", - .of_match_table = of_match_ptr(ad5592r_of_match), - .acpi_match_table = ACPI_PTR(ad5592r_acpi_match), + .of_match_table = ad5592r_of_match, + .acpi_match_table = ad5592r_acpi_match, }, .probe = ad5592r_spi_probe, .remove = ad5592r_spi_remove, -- cgit v1.2.3 From fe506cc5af0b5c44ce593467c0500dd16bf78919 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:15 +0100 Subject: iio:dac:ad5593r: Drop of_match_ptr and ACPI_PTR protections. These result in a very small reduction in driver size, but at the cost of more complex build and slightly harder to read code. In the case of of_match_ptr it also prevents use of PRP0001 ACPI based identification. In this particular case we have a valid ACPI/PNP ID that I am assuming was issued by Analog Devices. That should be used in preference to PRP0001 but doesn't mean we should prevent that route. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Michael Hennerich Cc: Lars-Peter Clausen Link: https://lore.kernel.org/r/20200910173242.621168-12-jic23@kernel.org --- drivers/iio/dac/ad5593r.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/dac/ad5593r.c b/drivers/iio/dac/ad5593r.c index 1fbe9c019c7f..5b4df36fdc2a 100644 --- a/drivers/iio/dac/ad5593r.c +++ b/drivers/iio/dac/ad5593r.c @@ -11,8 +11,7 @@ #include #include #include -#include -#include +#include #define AD5593R_MODE_CONF (0 << 4) #define AD5593R_MODE_DAC_WRITE (1 << 4) @@ -124,8 +123,8 @@ MODULE_DEVICE_TABLE(acpi, ad5593r_acpi_match); static struct i2c_driver ad5593r_driver = { .driver = { .name = "ad5593r", - .of_match_table = of_match_ptr(ad5593r_of_match), - .acpi_match_table = ACPI_PTR(ad5593r_acpi_match), + .of_match_table = ad5593r_of_match, + .acpi_match_table = ad5593r_acpi_match, }, .probe = ad5593r_i2c_probe, .remove = ad5593r_i2c_remove, -- cgit v1.2.3 From 34860a19a3ac5546757cacfba191cb2b635835c3 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:16 +0100 Subject: iio:dac:ad7303: Drop of_match_ptr protection This prevents use of this driver with ACPI via PRP0001 and are an example of an anti pattern I'm trying to remove from IIO. Also add mod_devicetable.h include given struct of_device_id is declared there. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Michael Hennerich Cc: Lars-Peter Clausen Link: https://lore.kernel.org/r/20200910173242.621168-13-jic23@kernel.org --- drivers/iio/dac/ad7303.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/dac/ad7303.c b/drivers/iio/dac/ad7303.c index 4460aa57a33f..20c85c2a636c 100644 --- a/drivers/iio/dac/ad7303.c +++ b/drivers/iio/dac/ad7303.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -287,7 +288,7 @@ MODULE_DEVICE_TABLE(spi, ad7303_spi_ids); static struct spi_driver ad7303_driver = { .driver = { .name = "ad7303", - .of_match_table = of_match_ptr(ad7303_spi_of_match), + .of_match_table = ad7303_spi_of_match, }, .probe = ad7303_probe, .remove = ad7303_remove, -- cgit v1.2.3 From 2de887b0cfc7ec9dbfe3fa458599419689e4c5d6 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:17 +0100 Subject: iio:dac:mcp4725: drop of_match_ptr and use generic fw properties This enables use of ACPI PRP0001 and removes an antipattern I am trying to stop people copying in IIO. This particular case is more complex than most because it allowed probing via sysfs with out a fwnode but would presumably always have then failed. Now the code will assume that properties are the defaults if not specified or the firmware node is not present. This relaxation of the constraints should not break any existing cases and may enable some new ones. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Peter Meerwald Link: https://lore.kernel.org/r/20200910173242.621168-14-jic23@kernel.org --- drivers/iio/dac/mcp4725.c | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c index ee174d224110..beb9a15b7c74 100644 --- a/drivers/iio/dac/mcp4725.c +++ b/drivers/iio/dac/mcp4725.c @@ -16,8 +16,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -357,29 +357,16 @@ static const struct iio_info mcp4725_info = { .attrs = &mcp4725_attribute_group, }; -#ifdef CONFIG_OF static int mcp4725_probe_dt(struct device *dev, struct mcp4725_platform_data *pdata) { - struct device_node *np = dev->of_node; - - if (!np) - return -ENODEV; - /* check if is the vref-supply defined */ - pdata->use_vref = of_property_read_bool(np, "vref-supply"); + pdata->use_vref = device_property_read_bool(dev, "vref-supply"); pdata->vref_buffered = - of_property_read_bool(np, "microchip,vref-buffered"); + device_property_read_bool(dev, "microchip,vref-buffered"); return 0; } -#else -static int mcp4725_probe_dt(struct device *dev, - struct mcp4725_platform_data *platform_data) -{ - return -ENODEV; -} -#endif static int mcp4725_probe(struct i2c_client *client, const struct i2c_device_id *id) @@ -398,8 +385,8 @@ static int mcp4725_probe(struct i2c_client *client, data = iio_priv(indio_dev); i2c_set_clientdata(client, indio_dev); data->client = client; - if (client->dev.of_node) - data->id = (enum chip_id)of_device_get_match_data(&client->dev); + if (dev_fwnode(&client->dev)) + data->id = (enum chip_id)device_get_match_data(&client->dev); else data->id = id->driver_data; pdata = dev_get_platdata(&client->dev); @@ -519,7 +506,6 @@ static const struct i2c_device_id mcp4725_id[] = { }; MODULE_DEVICE_TABLE(i2c, mcp4725_id); -#ifdef CONFIG_OF static const struct of_device_id mcp4725_of_match[] = { { .compatible = "microchip,mcp4725", @@ -532,12 +518,11 @@ static const struct of_device_id mcp4725_of_match[] = { { } }; MODULE_DEVICE_TABLE(of, mcp4725_of_match); -#endif static struct i2c_driver mcp4725_driver = { .driver = { .name = MCP4725_DRV_NAME, - .of_match_table = of_match_ptr(mcp4725_of_match), + .of_match_table = mcp4725_of_match, .pm = &mcp4725_pm_ops, }, .probe = mcp4725_probe, -- cgit v1.2.3 From 40f84dd0e60c5ed5c21ab8204d24604db0612dbc Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:18 +0100 Subject: iio:dac:ti-dac082s085: Drop of_match_ptr and CONFIG_OF protections These prevent the use of this driver with ACPI via PRP0001 and are an example of an anti pattern I'm trying to remove from IIO. Hence drop them from this driver. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Lukas Wunner Link: https://lore.kernel.org/r/20200910173242.621168-15-jic23@kernel.org --- drivers/iio/dac/ti-dac082s085.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/dac/ti-dac082s085.c b/drivers/iio/dac/ti-dac082s085.c index 86bfb1c3f9b9..de33c1fc6e0b 100644 --- a/drivers/iio/dac/ti-dac082s085.c +++ b/drivers/iio/dac/ti-dac082s085.c @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -324,7 +325,6 @@ static int ti_dac_remove(struct spi_device *spi) return 0; } -#ifdef CONFIG_OF static const struct of_device_id ti_dac_of_id[] = { { .compatible = "ti,dac082s085" }, { .compatible = "ti,dac102s085" }, @@ -335,7 +335,6 @@ static const struct of_device_id ti_dac_of_id[] = { { } }; MODULE_DEVICE_TABLE(of, ti_dac_of_id); -#endif static const struct spi_device_id ti_dac_spi_id[] = { { "dac082s085", dual_8bit }, @@ -351,7 +350,7 @@ MODULE_DEVICE_TABLE(spi, ti_dac_spi_id); static struct spi_driver ti_dac_driver = { .driver = { .name = "ti-dac082s085", - .of_match_table = of_match_ptr(ti_dac_of_id), + .of_match_table = ti_dac_of_id, }, .probe = ti_dac_probe, .remove = ti_dac_remove, -- cgit v1.2.3 From 16723c6eaa9ec12145e178415e9861689221c664 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:19 +0100 Subject: iio:dac:ti-dac5571: Drop of_match_ptr and CONFIG_OF protections These prevent the use of this driver with ACPI via PRP0001 and are an example of an anti pattern I'm trying to remove from IIO. Hence drop them from this driver. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Sean Nyekjaer Link: https://lore.kernel.org/r/20200910173242.621168-16-jic23@kernel.org --- drivers/iio/dac/ti-dac5571.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/dac/ti-dac5571.c b/drivers/iio/dac/ti-dac5571.c index d303b19814e7..d3295767a079 100644 --- a/drivers/iio/dac/ti-dac5571.c +++ b/drivers/iio/dac/ti-dac5571.c @@ -18,8 +18,7 @@ #include #include #include -#include -#include +#include #include enum chip_id { @@ -384,7 +383,6 @@ static int dac5571_remove(struct i2c_client *i2c) return 0; } -#ifdef CONFIG_OF static const struct of_device_id dac5571_of_id[] = { {.compatible = "ti,dac5571"}, {.compatible = "ti,dac6571"}, @@ -398,7 +396,6 @@ static const struct of_device_id dac5571_of_id[] = { {} }; MODULE_DEVICE_TABLE(of, dac5571_of_id); -#endif static const struct i2c_device_id dac5571_id[] = { {"dac5571", single_8bit}, @@ -417,7 +414,7 @@ MODULE_DEVICE_TABLE(i2c, dac5571_id); static struct i2c_driver dac5571_driver = { .driver = { .name = "ti-dac5571", - .of_match_table = of_match_ptr(dac5571_of_id), + .of_match_table = dac5571_of_id, }, .probe = dac5571_probe, .remove = dac5571_remove, -- cgit v1.2.3 From 4c55fb8c9917246d1d0c77cc7c13673a0f480d78 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:20 +0100 Subject: iio:potentiostat:lmp91000: Drop of_match_ptr and use generic fw accessors This change allows use of this driver with ACPI via PRP0001 and removes an example of an anti pattern I'm trying to remove from IIO. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Acked-by: Matt Ranostay Link: https://lore.kernel.org/r/20200910173242.621168-17-jic23@kernel.org --- drivers/iio/potentiostat/lmp91000.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/potentiostat/lmp91000.c b/drivers/iio/potentiostat/lmp91000.c index 67ae635a05f3..f34ca769dc20 100644 --- a/drivers/iio/potentiostat/lmp91000.c +++ b/drivers/iio/potentiostat/lmp91000.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include @@ -205,13 +205,12 @@ static const struct iio_info lmp91000_info = { static int lmp91000_read_config(struct lmp91000_data *data) { struct device *dev = data->dev; - struct device_node *np = dev->of_node; unsigned int reg, val; int i, ret; - ret = of_property_read_u32(np, "ti,tia-gain-ohm", &val); + ret = device_property_read_u32(dev, "ti,tia-gain-ohm", &val); if (ret) { - if (!of_property_read_bool(np, "ti,external-tia-resistor")) { + if (!device_property_read_bool(dev, "ti,external-tia-resistor")) { dev_err(dev, "no ti,tia-gain-ohm defined and external resistor not specified\n"); return ret; } @@ -232,7 +231,7 @@ static int lmp91000_read_config(struct lmp91000_data *data) return ret; } - ret = of_property_read_u32(np, "ti,rload-ohm", &val); + ret = device_property_read_u32(dev, "ti,rload-ohm", &val); if (ret) { val = 100; dev_info(dev, "no ti,rload-ohm defined, default to %d\n", val); @@ -422,7 +421,7 @@ MODULE_DEVICE_TABLE(i2c, lmp91000_id); static struct i2c_driver lmp91000_driver = { .driver = { .name = LMP91000_DRV_NAME, - .of_match_table = of_match_ptr(lmp91000_of_match), + .of_match_table = lmp91000_of_match, }, .probe = lmp91000_probe, .remove = lmp91000_remove, -- cgit v1.2.3 From eb25d0aa4ae02cc31d77c9b677713d3be37761d8 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:21 +0100 Subject: iio:pressure:icp10100: Drop of_match_ptr and CONFIG_OF protections These prevents use of this driver with ACPI via PRP0001 and are an example of an anti pattern I'm trying to remove from IIO. Hence drop them from this driver. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Jean-Baptiste Maneyrol Link: https://lore.kernel.org/r/20200910173242.621168-18-jic23@kernel.org --- drivers/iio/pressure/icp10100.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/pressure/icp10100.c b/drivers/iio/pressure/icp10100.c index 90c0df068bbb..48759fc4bf18 100644 --- a/drivers/iio/pressure/icp10100.c +++ b/drivers/iio/pressure/icp10100.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -645,7 +646,7 @@ static struct i2c_driver icp10100_driver = { .driver = { .name = "icp10100", .pm = &icp10100_pm, - .of_match_table = of_match_ptr(icp10100_of_match), + .of_match_table = icp10100_of_match, }, .probe = icp10100_probe, .id_table = icp10100_id, -- cgit v1.2.3 From 0e62470652faed4a657123373a5ff725320d0b3d Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:22 +0100 Subject: iio:pressure:ms5611: Drop of_match_ptr and CONFIG_OF protections These prevents use of this driver with ACPI via PRP0001 and are an example of an anti pattern I'm trying to remove from IIO. Hence drop them from this driver. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Tomasz Duszynski Link: https://lore.kernel.org/r/20200910173242.621168-19-jic23@kernel.org --- drivers/iio/pressure/ms5611_i2c.c | 6 ++---- drivers/iio/pressure/ms5611_spi.c | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/pressure/ms5611_i2c.c b/drivers/iio/pressure/ms5611_i2c.c index 072c106dd66d..7c04f730430c 100644 --- a/drivers/iio/pressure/ms5611_i2c.c +++ b/drivers/iio/pressure/ms5611_i2c.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include @@ -113,14 +113,12 @@ static int ms5611_i2c_remove(struct i2c_client *client) return ms5611_remove(i2c_get_clientdata(client)); } -#if defined(CONFIG_OF) static const struct of_device_id ms5611_i2c_matches[] = { { .compatible = "meas,ms5611" }, { .compatible = "meas,ms5607" }, { } }; MODULE_DEVICE_TABLE(of, ms5611_i2c_matches); -#endif static const struct i2c_device_id ms5611_id[] = { { "ms5611", MS5611 }, @@ -132,7 +130,7 @@ MODULE_DEVICE_TABLE(i2c, ms5611_id); static struct i2c_driver ms5611_driver = { .driver = { .name = "ms5611", - .of_match_table = of_match_ptr(ms5611_i2c_matches) + .of_match_table = ms5611_i2c_matches, }, .id_table = ms5611_id, .probe = ms5611_i2c_probe, diff --git a/drivers/iio/pressure/ms5611_spi.c b/drivers/iio/pressure/ms5611_spi.c index 4799aa57135e..45d3a7d5be8e 100644 --- a/drivers/iio/pressure/ms5611_spi.c +++ b/drivers/iio/pressure/ms5611_spi.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include @@ -115,14 +115,12 @@ static int ms5611_spi_remove(struct spi_device *spi) return ms5611_remove(spi_get_drvdata(spi)); } -#if defined(CONFIG_OF) static const struct of_device_id ms5611_spi_matches[] = { { .compatible = "meas,ms5611" }, { .compatible = "meas,ms5607" }, { } }; MODULE_DEVICE_TABLE(of, ms5611_spi_matches); -#endif static const struct spi_device_id ms5611_id[] = { { "ms5611", MS5611 }, @@ -134,7 +132,7 @@ MODULE_DEVICE_TABLE(spi, ms5611_id); static struct spi_driver ms5611_driver = { .driver = { .name = "ms5611", - .of_match_table = of_match_ptr(ms5611_spi_matches) + .of_match_table = ms5611_spi_matches }, .id_table = ms5611_id, .probe = ms5611_spi_probe, -- cgit v1.2.3 From 444f5f854b35260361a9a6448b151740b86194af Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:23 +0100 Subject: iio:pressure:ms5637: Drop of_match_ptr protection This prevents use of this driver with ACPI via PRP0001 and is an example of an anti pattern I'm trying to remove from IIO. Hence drop from this driver. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Ludovic Tancerel Link: https://lore.kernel.org/r/20200910173242.621168-20-jic23@kernel.org --- drivers/iio/pressure/ms5637.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/pressure/ms5637.c b/drivers/iio/pressure/ms5637.c index 05e0ef7260d5..5b59a4137d32 100644 --- a/drivers/iio/pressure/ms5637.c +++ b/drivers/iio/pressure/ms5637.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -192,7 +193,7 @@ static struct i2c_driver ms5637_driver = { .id_table = ms5637_id, .driver = { .name = "ms5637", - .of_match_table = of_match_ptr(ms5637_of_match), + .of_match_table = ms5637_of_match, }, }; -- cgit v1.2.3 From a409d2b6391376180d4440a4336d4e67ee4fd754 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:24 +0100 Subject: iio:pressure:zpa2326: Drop of_match_ptr protection This prevents use of this driver with ACPI via PRP0001 and is an example of an anti pattern I'm trying to remove from IIO. Hence drop from this driver. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Gregor Boirie Link: https://lore.kernel.org/r/20200910173242.621168-21-jic23@kernel.org --- drivers/iio/pressure/zpa2326_i2c.c | 6 ++---- drivers/iio/pressure/zpa2326_spi.c | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/pressure/zpa2326_i2c.c b/drivers/iio/pressure/zpa2326_i2c.c index 1a65791ba279..95d9739444c4 100644 --- a/drivers/iio/pressure/zpa2326_i2c.c +++ b/drivers/iio/pressure/zpa2326_i2c.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include "zpa2326.h" /* @@ -66,18 +66,16 @@ static const struct i2c_device_id zpa2326_i2c_ids[] = { }; MODULE_DEVICE_TABLE(i2c, zpa2326_i2c_ids); -#if defined(CONFIG_OF) static const struct of_device_id zpa2326_i2c_matches[] = { { .compatible = "murata,zpa2326" }, { } }; MODULE_DEVICE_TABLE(of, zpa2326_i2c_matches); -#endif static struct i2c_driver zpa2326_i2c_driver = { .driver = { .name = "zpa2326-i2c", - .of_match_table = of_match_ptr(zpa2326_i2c_matches), + .of_match_table = zpa2326_i2c_matches, .pm = ZPA2326_PM_OPS, }, .probe = zpa2326_probe_i2c, diff --git a/drivers/iio/pressure/zpa2326_spi.c b/drivers/iio/pressure/zpa2326_spi.c index f37a4c738c75..85201a4bae44 100644 --- a/drivers/iio/pressure/zpa2326_spi.c +++ b/drivers/iio/pressure/zpa2326_spi.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include "zpa2326.h" /* @@ -70,18 +70,16 @@ static const struct spi_device_id zpa2326_spi_ids[] = { }; MODULE_DEVICE_TABLE(spi, zpa2326_spi_ids); -#if defined(CONFIG_OF) static const struct of_device_id zpa2326_spi_matches[] = { { .compatible = "murata,zpa2326" }, { } }; MODULE_DEVICE_TABLE(of, zpa2326_spi_matches); -#endif static struct spi_driver zpa2326_spi_driver = { .driver = { .name = "zpa2326-spi", - .of_match_table = of_match_ptr(zpa2326_spi_matches), + .of_match_table = zpa2326_spi_matches, .pm = ZPA2326_PM_OPS, }, .probe = zpa2326_probe_spi, -- cgit v1.2.3 From c5b411bc9a7058d57afd43d4d075e7a34a242b9e Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:25 +0100 Subject: iio:temperature:tsys01: Drop of_match_ptr protection This prevents use of this driver with ACPI via PRP0001 and is an example of an anti pattern I'm trying to remove from IIO. Hence drop from this driver. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Ludovic Tancerel Link: https://lore.kernel.org/r/20200910173242.621168-22-jic23@kernel.org --- drivers/iio/temperature/tsys01.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/temperature/tsys01.c b/drivers/iio/temperature/tsys01.c index 2c631a1ca33b..bbfbad9a8767 100644 --- a/drivers/iio/temperature/tsys01.c +++ b/drivers/iio/temperature/tsys01.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -222,7 +223,7 @@ static struct i2c_driver tsys01_driver = { .id_table = tsys01_id, .driver = { .name = "tsys01", - .of_match_table = of_match_ptr(tsys01_of_match), + .of_match_table = tsys01_of_match, }, }; -- cgit v1.2.3 From b5c35aedf98d9060c85969dbb6b79511d2c3c54c Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:26 +0100 Subject: iio:temperature:tmp007: Drop of_match_ptr protection This prevents use of this driver with ACPI via PRP0001 and is an example of an anti pattern I'm trying to remove from IIO. Hence drop from this driver. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20200910173242.621168-23-jic23@kernel.org --- drivers/iio/temperature/tmp007.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/temperature/tmp007.c b/drivers/iio/temperature/tmp007.c index f90fe9e5617b..ad2b35c65548 100644 --- a/drivers/iio/temperature/tmp007.c +++ b/drivers/iio/temperature/tmp007.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include @@ -578,7 +578,7 @@ MODULE_DEVICE_TABLE(i2c, tmp007_id); static struct i2c_driver tmp007_driver = { .driver = { .name = "tmp007", - .of_match_table = of_match_ptr(tmp007_of_match), + .of_match_table = tmp007_of_match, .pm = &tmp007_pm_ops, }, .probe = tmp007_probe, -- cgit v1.2.3 From 184ac728db0354c9a8b467027a5a125ab9ef18ee Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:27 +0100 Subject: iio:resolver:ad2s1200: Drop of_match_ptr protection This prevents use of this driver with ACPI via PRP0001 and is an example of an anti pattern I'm trying to remove from IIO. Hence drop from this driver. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200910173242.621168-24-jic23@kernel.org --- drivers/iio/resolver/ad2s1200.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/resolver/ad2s1200.c b/drivers/iio/resolver/ad2s1200.c index 6007abad116b..9746bd935628 100644 --- a/drivers/iio/resolver/ad2s1200.c +++ b/drivers/iio/resolver/ad2s1200.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -192,7 +193,7 @@ MODULE_DEVICE_TABLE(spi, ad2s1200_id); static struct spi_driver ad2s1200_driver = { .driver = { .name = DRV_NAME, - .of_match_table = of_match_ptr(ad2s1200_of_match), + .of_match_table = ad2s1200_of_match, }, .probe = ad2s1200_probe, .id_table = ad2s1200_id, -- cgit v1.2.3 From 4d36d4df68d3db9aca1e0785f464b5092f39952b Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:28 +0100 Subject: iio:chemical:ams-iaq-core: Drop of_match_ptr protection This prevents use of this driver with ACPI via PRP0001 and is an example of an anti pattern I'm trying to remove from IIO. Hence drop from this driver. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Acked-by: Matt Ranostay Link: https://lore.kernel.org/r/20200910173242.621168-25-jic23@kernel.org --- drivers/iio/chemical/ams-iaq-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/chemical/ams-iaq-core.c b/drivers/iio/chemical/ams-iaq-core.c index 8c1b64fd424a..97be3669c554 100644 --- a/drivers/iio/chemical/ams-iaq-core.c +++ b/drivers/iio/chemical/ams-iaq-core.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -177,7 +178,7 @@ MODULE_DEVICE_TABLE(of, ams_iaqcore_dt_ids); static struct i2c_driver ams_iaqcore_driver = { .driver = { .name = "ams-iaq-core", - .of_match_table = of_match_ptr(ams_iaqcore_dt_ids), + .of_match_table = ams_iaqcore_dt_ids, }, .probe = ams_iaqcore_probe, .id_table = ams_iaqcore_id, -- cgit v1.2.3 From a867e8986759bf25251c8cad3798cba0e4c25a6e Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:29 +0100 Subject: iio:chemical:atlas-sensor: Drop of_match_ptr and use generic fw accessors of_match_ptr() prevents use of this driver with ACPI via PRP0001 and is an example of an anti pattern I'm trying to remove from IIO. Hence drop from this driver and use generic fw accessors to check if there is a fw_node and get the id. It might be neater to use pointers rather than indexes for the device_data but that is another issue and should be handled separately. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Acked-by: Matt Ranostay Link: https://lore.kernel.org/r/20200910173242.621168-26-jic23@kernel.org --- drivers/iio/chemical/atlas-sensor.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/chemical/atlas-sensor.c b/drivers/iio/chemical/atlas-sensor.c index 43069636fcd5..cdab9d04dedd 100644 --- a/drivers/iio/chemical/atlas-sensor.c +++ b/drivers/iio/chemical/atlas-sensor.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include @@ -620,7 +620,6 @@ static int atlas_probe(struct i2c_client *client, { struct atlas_data *data; struct atlas_device *chip; - const struct of_device_id *of_id; struct iio_trigger *trig; struct iio_dev *indio_dev; int ret; @@ -629,11 +628,10 @@ static int atlas_probe(struct i2c_client *client, if (!indio_dev) return -ENOMEM; - of_id = of_match_device(atlas_dt_ids, &client->dev); - if (!of_id) + if (!dev_fwnode(&client->dev)) chip = &atlas_devices[id->driver_data]; else - chip = &atlas_devices[(unsigned long)of_id->data]; + chip = &atlas_devices[(unsigned long)device_get_match_data(&client->dev)]; indio_dev->info = &atlas_info; indio_dev->name = ATLAS_DRV_NAME; @@ -775,7 +773,7 @@ static const struct dev_pm_ops atlas_pm_ops = { static struct i2c_driver atlas_driver = { .driver = { .name = ATLAS_DRV_NAME, - .of_match_table = of_match_ptr(atlas_dt_ids), + .of_match_table = atlas_dt_ids, .pm = &atlas_pm_ops, }, .probe = atlas_probe, -- cgit v1.2.3 From cb26d236861ca6a3354f1623ae5b9c049fd2f972 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:30 +0100 Subject: iio:chemical:sgp30: Use local variable dev to simplify code This cleans up the code at bit, but is primarily here as a precusor to the next patch. I've only done this for the two functions which use the dev pointer repeatedly. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Andreas Brauchli Link: https://lore.kernel.org/r/20200910173242.621168-27-jic23@kernel.org --- drivers/iio/chemical/sgp30.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/chemical/sgp30.c b/drivers/iio/chemical/sgp30.c index 2c4086c48136..410565aa20b6 100644 --- a/drivers/iio/chemical/sgp30.c +++ b/drivers/iio/chemical/sgp30.c @@ -409,6 +409,7 @@ static int sgp_read_raw(struct iio_dev *indio_dev, static int sgp_check_compat(struct sgp_data *data, unsigned int product_id) { + struct device *dev = &data->client->dev; const struct sgp_version *supported_versions; u16 ix, num_fs; u16 product, generation, major, minor; @@ -416,21 +417,20 @@ static int sgp_check_compat(struct sgp_data *data, /* driver does not match product */ generation = SGP_VERS_GEN(data); if (generation != 0) { - dev_err(&data->client->dev, + dev_err(dev, "incompatible product generation %d != 0", generation); return -ENODEV; } product = SGP_VERS_PRODUCT(data); if (product != product_id) { - dev_err(&data->client->dev, - "sensor reports a different product: 0x%04hx\n", + dev_err(dev, "sensor reports a different product: 0x%04hx\n", product); return -ENODEV; } if (SGP_VERS_RESERVED(data)) - dev_warn(&data->client->dev, "reserved bit is set\n"); + dev_warn(dev, "reserved bit is set\n"); /* engineering samples are not supported: no interface guarantees */ if (SGP_VERS_ENG_BIT(data)) @@ -456,8 +456,7 @@ static int sgp_check_compat(struct sgp_data *data, minor >= supported_versions[ix].minor) return 0; } - dev_err(&data->client->dev, "unsupported sgp version: %d.%d\n", - major, minor); + dev_err(dev, "unsupported sgp version: %d.%d\n", major, minor); return -ENODEV; } @@ -499,17 +498,18 @@ static const struct of_device_id sgp_dt_ids[] = { static int sgp_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; struct iio_dev *indio_dev; struct sgp_data *data; const struct of_device_id *of_id; unsigned long product_id; 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; - of_id = of_match_device(sgp_dt_ids, &client->dev); + of_id = of_match_device(sgp_dt_ids, dev); if (of_id) product_id = (unsigned long)of_id->data; else @@ -541,9 +541,9 @@ static int sgp_probe(struct i2c_client *client, sgp_init(data); - ret = devm_iio_device_register(&client->dev, indio_dev); + ret = devm_iio_device_register(dev, indio_dev); if (ret) { - dev_err(&client->dev, "failed to register iio device\n"); + dev_err(dev, "failed to register iio device\n"); return ret; } -- cgit v1.2.3 From 6ac282edd653d28b4d64744c7ad05e9a4e1aeaf4 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:31 +0100 Subject: iio:chemical:sgp30: Drop of_match_ptr and use generic fw accessors This change allow the driver to be used with ACPI PRP0001 and removes an antipattern that I want to avoid being copied into new IIO drivers. The handling of match_data uses a different approach as device_get_match_data doesn't distinguish between no match, and a match but with NULL data. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Andreas Brauchli Link: https://lore.kernel.org/r/20200910173242.621168-28-jic23@kernel.org --- drivers/iio/chemical/sgp30.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/chemical/sgp30.c b/drivers/iio/chemical/sgp30.c index 410565aa20b6..c2d93b9796ce 100644 --- a/drivers/iio/chemical/sgp30.c +++ b/drivers/iio/chemical/sgp30.c @@ -20,9 +20,9 @@ #include #include #include +#include #include #include -#include #include #include @@ -501,7 +501,6 @@ static int sgp_probe(struct i2c_client *client, struct device *dev = &client->dev; struct iio_dev *indio_dev; struct sgp_data *data; - const struct of_device_id *of_id; unsigned long product_id; int ret; @@ -509,9 +508,8 @@ static int sgp_probe(struct i2c_client *client, if (!indio_dev) return -ENOMEM; - of_id = of_match_device(sgp_dt_ids, dev); - if (of_id) - product_id = (unsigned long)of_id->data; + if (dev_fwnode(dev)) + product_id = (unsigned long)device_get_match_data(dev); else product_id = id->driver_data; @@ -576,7 +574,7 @@ MODULE_DEVICE_TABLE(of, sgp_dt_ids); static struct i2c_driver sgp_driver = { .driver = { .name = "sgp30", - .of_match_table = of_match_ptr(sgp_dt_ids), + .of_match_table = sgp_dt_ids, }, .probe = sgp_probe, .remove = sgp_remove, -- cgit v1.2.3 From e12b3a6150f1ce271e2a5282d3cfd116a144d796 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:32 +0100 Subject: iio:chemical:vz89x: Introduce local struct device pointer. Avoids lots of repetition of &client->dev and will make the next patch tidier. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Acked-by: Matt Ranostay Link: https://lore.kernel.org/r/20200910173242.621168-29-jic23@kernel.org --- drivers/iio/chemical/vz89x.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/chemical/vz89x.c b/drivers/iio/chemical/vz89x.c index 5586eb8e12cd..3cd469578590 100644 --- a/drivers/iio/chemical/vz89x.c +++ b/drivers/iio/chemical/vz89x.c @@ -352,12 +352,13 @@ MODULE_DEVICE_TABLE(of, vz89x_dt_ids); static int vz89x_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; struct iio_dev *indio_dev; struct vz89x_data *data; const struct of_device_id *of_id; int chip_id; - 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); @@ -370,7 +371,7 @@ static int vz89x_probe(struct i2c_client *client, else return -EOPNOTSUPP; - of_id = of_match_device(vz89x_dt_ids, &client->dev); + of_id = of_match_device(vz89x_dt_ids, dev); if (!of_id) chip_id = id->driver_data; else @@ -383,13 +384,13 @@ static int vz89x_probe(struct i2c_client *client, mutex_init(&data->lock); indio_dev->info = &vz89x_info; - indio_dev->name = dev_name(&client->dev); + indio_dev->name = dev_name(dev); indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = data->chip->channels; indio_dev->num_channels = data->chip->num_channels; - return devm_iio_device_register(&client->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } static const struct i2c_device_id vz89x_id[] = { -- cgit v1.2.3 From b3fce99a57377673eaf7c89ae9a42f4fd60966e2 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:33 +0100 Subject: iio:chemical:vz89x: Drop of_match_ptr protection and use generic fw accessors This change allow the driver to be used with ACPI PRP0001 and removes an antipattern that I want to avoid being copied into new IIO drivers. The handling of match_data uses a different approach as device_get_match_data() doesn't distinguish between no match, and a match but with NULL data. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Acked-by: Matt Ranostay Link: https://lore.kernel.org/r/20200910173242.621168-30-jic23@kernel.org --- drivers/iio/chemical/vz89x.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/chemical/vz89x.c b/drivers/iio/chemical/vz89x.c index 3cd469578590..23b22a5f5c1c 100644 --- a/drivers/iio/chemical/vz89x.c +++ b/drivers/iio/chemical/vz89x.c @@ -10,8 +10,7 @@ #include #include #include -#include -#include +#include #include #include @@ -355,7 +354,6 @@ static int vz89x_probe(struct i2c_client *client, struct device *dev = &client->dev; struct iio_dev *indio_dev; struct vz89x_data *data; - const struct of_device_id *of_id; int chip_id; indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); @@ -371,11 +369,10 @@ static int vz89x_probe(struct i2c_client *client, else return -EOPNOTSUPP; - of_id = of_match_device(vz89x_dt_ids, dev); - if (!of_id) + if (!dev_fwnode(dev)) chip_id = id->driver_data; else - chip_id = (unsigned long)of_id->data; + chip_id = (unsigned long)device_get_match_data(dev); i2c_set_clientdata(client, indio_dev); data->client = client; @@ -403,7 +400,7 @@ MODULE_DEVICE_TABLE(i2c, vz89x_id); static struct i2c_driver vz89x_driver = { .driver = { .name = "vz89x", - .of_match_table = of_match_ptr(vz89x_dt_ids), + .of_match_table = vz89x_dt_ids, }, .probe = vz89x_probe, .id_table = vz89x_id, -- cgit v1.2.3 From d13643143074102f2264d3cbf8052f57a371dd5f Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:34 +0100 Subject: iio:humidity:hdc100x: Drop of_match_ptr protection. This prevents use of this driver with ACPI via PRP0001 and is an example of an anti pattern I'm trying to remove from IIO. Hence drop from this driver. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Acked-by: Matt Ranostay Link: https://lore.kernel.org/r/20200910173242.621168-31-jic23@kernel.org --- drivers/iio/humidity/hdc100x.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/humidity/hdc100x.c b/drivers/iio/humidity/hdc100x.c index 071cb2b12bb6..2a957f19048e 100644 --- a/drivers/iio/humidity/hdc100x.c +++ b/drivers/iio/humidity/hdc100x.c @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -417,7 +418,7 @@ MODULE_DEVICE_TABLE(of, hdc100x_dt_ids); static struct i2c_driver hdc100x_driver = { .driver = { .name = "hdc100x", - .of_match_table = of_match_ptr(hdc100x_dt_ids), + .of_match_table = hdc100x_dt_ids, }, .probe = hdc100x_probe, .id_table = hdc100x_id, -- cgit v1.2.3 From c457b7efa302a8c3706176636f7f2702556f93ab Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:35 +0100 Subject: iio:proximity:as3935: Use local struct device pointer to simplify code. This makes the existing code easier to read and will make the following patch a little simpler. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Acked-by: Matt Ranostay Link: https://lore.kernel.org/r/20200910173242.621168-32-jic23@kernel.org --- drivers/iio/proximity/as3935.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c index c339e7339ec8..4df8d53d65fb 100644 --- a/drivers/iio/proximity/as3935.c +++ b/drivers/iio/proximity/as3935.c @@ -352,19 +352,20 @@ static void as3935_stop_work(void *data) static int as3935_probe(struct spi_device *spi) { + struct device *dev = &spi->dev; struct iio_dev *indio_dev; struct iio_trigger *trig; struct as3935_state *st; - struct device_node *np = spi->dev.of_node; + struct device_node *np = dev->of_node; int ret; /* Be sure lightning event interrupt is specified */ if (!spi->irq) { - dev_err(&spi->dev, "unable to get event interrupt\n"); + dev_err(dev, "unable to get event interrupt\n"); return -EINVAL; } - indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; @@ -378,14 +379,12 @@ static int as3935_probe(struct spi_device *spi) "ams,tuning-capacitor-pf", &st->tune_cap); if (ret) { st->tune_cap = 0; - dev_warn(&spi->dev, - "no tuning-capacitor-pf set, defaulting to %d", + dev_warn(dev, "no tuning-capacitor-pf set, defaulting to %d", st->tune_cap); } if (st->tune_cap > MAX_PF_CAP) { - dev_err(&spi->dev, - "wrong tuning-capacitor-pf setting of %d\n", + dev_err(dev, "wrong tuning-capacitor-pf setting of %d\n", st->tune_cap); return -EINVAL; } @@ -393,8 +392,7 @@ static int as3935_probe(struct spi_device *spi) ret = of_property_read_u32(np, "ams,nflwdth", &st->nflwdth_reg); if (!ret && st->nflwdth_reg > AS3935_NFLWDTH_MASK) { - dev_err(&spi->dev, - "invalid nflwdth setting of %d\n", + dev_err(dev, "invalid nflwdth setting of %d\n", st->nflwdth_reg); return -EINVAL; } @@ -405,7 +403,7 @@ static int as3935_probe(struct spi_device *spi) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &as3935_info; - trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d", + trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, indio_dev->id); if (!trig) @@ -417,42 +415,42 @@ static int as3935_probe(struct spi_device *spi) iio_trigger_set_drvdata(trig, indio_dev); trig->ops = &iio_interrupt_trigger_ops; - ret = devm_iio_trigger_register(&spi->dev, trig); + ret = devm_iio_trigger_register(dev, trig); if (ret) { - dev_err(&spi->dev, "failed to register trigger\n"); + dev_err(dev, "failed to register trigger\n"); return ret; } - ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, iio_pollfunc_store_time, as3935_trigger_handler, NULL); if (ret) { - dev_err(&spi->dev, "cannot setup iio trigger\n"); + dev_err(dev, "cannot setup iio trigger\n"); return ret; } calibrate_as3935(st); INIT_DELAYED_WORK(&st->work, as3935_event_work); - ret = devm_add_action(&spi->dev, as3935_stop_work, indio_dev); + ret = devm_add_action(dev, as3935_stop_work, indio_dev); if (ret) return ret; - ret = devm_request_irq(&spi->dev, spi->irq, + ret = devm_request_irq(dev, spi->irq, &as3935_interrupt_handler, IRQF_TRIGGER_RISING, - dev_name(&spi->dev), + dev_name(dev), indio_dev); if (ret) { - dev_err(&spi->dev, "unable to request irq\n"); + dev_err(dev, "unable to request irq\n"); return ret; } - ret = devm_iio_device_register(&spi->dev, indio_dev); + ret = devm_iio_device_register(dev, indio_dev); if (ret < 0) { - dev_err(&spi->dev, "unable to register device\n"); + dev_err(dev, "unable to register device\n"); return ret; } return 0; -- cgit v1.2.3 From 00fa493b99894b930e431c05a9dba294c5189120 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:36 +0100 Subject: iio:proximity:as3935: Drop of_match_ptr and use generic fw accessors This change allows the driver to be used with ACPI PRP0001 and removes an antipattern that I want to avoid being copied into new IIO drivers. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Acked-by: Matt Ranostay Link: https://lore.kernel.org/r/20200910173242.621168-33-jic23@kernel.org --- drivers/iio/proximity/as3935.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c index 4df8d53d65fb..b79ada839e01 100644 --- a/drivers/iio/proximity/as3935.c +++ b/drivers/iio/proximity/as3935.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -356,7 +357,6 @@ static int as3935_probe(struct spi_device *spi) struct iio_dev *indio_dev; struct iio_trigger *trig; struct as3935_state *st; - struct device_node *np = dev->of_node; int ret; /* Be sure lightning event interrupt is specified */ @@ -375,7 +375,7 @@ static int as3935_probe(struct spi_device *spi) spi_set_drvdata(spi, indio_dev); mutex_init(&st->lock); - ret = of_property_read_u32(np, + ret = device_property_read_u32(dev, "ams,tuning-capacitor-pf", &st->tune_cap); if (ret) { st->tune_cap = 0; @@ -389,7 +389,7 @@ static int as3935_probe(struct spi_device *spi) return -EINVAL; } - ret = of_property_read_u32(np, + ret = device_property_read_u32(dev, "ams,nflwdth", &st->nflwdth_reg); if (!ret && st->nflwdth_reg > AS3935_NFLWDTH_MASK) { dev_err(dev, "invalid nflwdth setting of %d\n", @@ -471,7 +471,7 @@ MODULE_DEVICE_TABLE(spi, as3935_id); static struct spi_driver as3935_driver = { .driver = { .name = "as3935", - .of_match_table = of_match_ptr(as3935_of_match), + .of_match_table = as3935_of_match, .pm = AS3935_PM_OPS, }, .probe = as3935_probe, -- cgit v1.2.3 From 03303e8425436372472993f988a20262a263fbcf Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:37 +0100 Subject: iio:proximity:pulsedlight: Drop of_match_ptr protection This prevents use of this driver with ACPI via PRP0001 and is an example of an anti pattern I'm trying to remove from IIO. Hence drop from this driver. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Acked-by: Matt Ranostay Link: https://lore.kernel.org/r/20200910173242.621168-34-jic23@kernel.org --- drivers/iio/proximity/pulsedlight-lidar-lite-v2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c index a8e716dbd24e..c685f10b5ae4 100644 --- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c +++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -360,7 +361,7 @@ static const struct dev_pm_ops lidar_pm_ops = { static struct i2c_driver lidar_driver = { .driver = { .name = LIDAR_DRV_NAME, - .of_match_table = of_match_ptr(lidar_dt_ids), + .of_match_table = lidar_dt_ids, .pm = &lidar_pm_ops, }, .probe = lidar_probe, -- cgit v1.2.3 From 8e5a0426dddb6fd94ba2b369c12785474c30e29c Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:38 +0100 Subject: iio:magn:ak8975: Drop of_match_ptr and ACPI_PTR protections. Both would result in only a small size saving. For simplicity it is best to remove them. I also wish to remove both these antipatterns from IIO. Signed-off-by: Jonathan Cameron Tested-by: Jonathan Albrieux Reviewed-by: Andy Shevchenko Acked-by: Jonathan Albrieux Link: https://lore.kernel.org/r/20200910173242.621168-35-jic23@kernel.org --- drivers/iio/magnetometer/ak8975.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 03d71f796177..0141ef3b6476 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -17,7 +18,6 @@ #include #include #include -#include #include #include @@ -773,7 +773,6 @@ static const struct iio_info ak8975_info = { .read_raw = &ak8975_read_raw, }; -#ifdef CONFIG_ACPI static const struct acpi_device_id ak_acpi_match[] = { {"AK8975", AK8975}, {"AK8963", AK8963}, @@ -785,7 +784,6 @@ static const struct acpi_device_id ak_acpi_match[] = { { } }; MODULE_DEVICE_TABLE(acpi, ak_acpi_match); -#endif static void ak8975_fill_buffer(struct iio_dev *indio_dev) { @@ -1075,8 +1073,8 @@ static struct i2c_driver ak8975_driver = { .driver = { .name = "ak8975", .pm = &ak8975_dev_pm_ops, - .of_match_table = of_match_ptr(ak8975_of_match), - .acpi_match_table = ACPI_PTR(ak_acpi_match), + .of_match_table = ak8975_of_match, + .acpi_match_table = ak_acpi_match, }, .probe = ak8975_probe, .remove = ak8975_remove, -- cgit v1.2.3 From 2b4f0172ae688e0c7c70fdedfb4b232dad9df52f Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:39 +0100 Subject: iio:magn:ak8974: Drop of_match_ptr protection This prevents use of this driver with ACPI via PRP0001 and is an example of an anti pattern I'm trying to remove from IIO. Hence drop from this driver. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Linus Walleij Link: https://lore.kernel.org/r/20200910173242.621168-36-jic23@kernel.org --- drivers/iio/magnetometer/ak8974.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c index 7cd9768fbcb2..df5131cf28a9 100644 --- a/drivers/iio/magnetometer/ak8974.c +++ b/drivers/iio/magnetometer/ak8974.c @@ -12,6 +12,7 @@ * Author: Linus Walleij */ #include +#include #include #include #include @@ -1051,7 +1052,7 @@ static struct i2c_driver ak8974_driver = { .driver = { .name = "ak8974", .pm = &ak8974_dev_pm_ops, - .of_match_table = of_match_ptr(ak8974_of_match), + .of_match_table = ak8974_of_match, }, .probe = ak8974_probe, .remove = ak8974_remove, -- cgit v1.2.3 From 7f33a29a747f1db1c1cbc4543bb9bd89369ac9be Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:40 +0100 Subject: iio:humidity:htu21: Drop of_match_ptr protection This prevents use of this driver with ACPI via PRP0001 and is an example of an anti pattern I'm trying to remove from IIO. Hence drop from this driver. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Ludovic Tancerel Link: https://lore.kernel.org/r/20200910173242.621168-37-jic23@kernel.org --- drivers/iio/humidity/htu21.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/humidity/htu21.c b/drivers/iio/humidity/htu21.c index 4f5d9d1c05ab..36df2a102ca4 100644 --- a/drivers/iio/humidity/htu21.c +++ b/drivers/iio/humidity/htu21.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -247,7 +248,7 @@ static struct i2c_driver htu21_driver = { .id_table = htu21_id, .driver = { .name = "htu21", - .of_match_table = of_match_ptr(htu21_of_match), + .of_match_table = htu21_of_match, }, }; -- cgit v1.2.3 From 4231f9d166bb90420b1950b303be078eeda1821a Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:41 +0100 Subject: iio:humidity:si7020: Drop of_match_ptr protection This prevents use of this driver with ACPI via PRP0001 and is an example of an anti pattern I'm trying to remove from IIO. Hence drop from this driver. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: David Barksdale Link: https://lore.kernel.org/r/20200910173242.621168-38-jic23@kernel.org --- drivers/iio/humidity/si7020.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/humidity/si7020.c b/drivers/iio/humidity/si7020.c index a09b5773d377..ab6537f136ba 100644 --- a/drivers/iio/humidity/si7020.c +++ b/drivers/iio/humidity/si7020.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -153,7 +154,7 @@ MODULE_DEVICE_TABLE(of, si7020_dt_ids); static struct i2c_driver si7020_driver = { .driver = { .name = "si7020", - .of_match_table = of_match_ptr(si7020_dt_ids), + .of_match_table = si7020_dt_ids, }, .probe = si7020_probe, .id_table = si7020_id, -- cgit v1.2.3 From 322da39090f0ef07f8196b6c6e42e65a991f9948 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 18:32:42 +0100 Subject: iio:health:max30102: Drop of_match_ptr and use generic fw accessors This enables use of the driver with ACPI PRP0001 and also removes an antipattern that I am trying to clear out of IIO to avoid it being copied into new drivers. Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Acked-by: Matt Ranostay Link: https://lore.kernel.org/r/20200910173242.621168-39-jic23@kernel.org --- drivers/iio/health/max30102.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c index bb504e993f19..543021d8df34 100644 --- a/drivers/iio/health/max30102.c +++ b/drivers/iio/health/max30102.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -323,11 +323,10 @@ static int max30102_get_current_idx(unsigned int val, int *reg) static int max30102_led_init(struct max30102_data *data) { struct device *dev = &data->client->dev; - struct device_node *np = dev->of_node; unsigned int val; int reg, ret; - ret = of_property_read_u32(np, "maxim,red-led-current-microamp", &val); + ret = device_property_read_u32(dev, "maxim,red-led-current-microamp", &val); if (ret) { dev_info(dev, "no red-led-current-microamp set\n"); @@ -346,7 +345,7 @@ static int max30102_led_init(struct max30102_data *data) return ret; if (data->chip_id == max30105) { - ret = of_property_read_u32(np, + ret = device_property_read_u32(dev, "maxim,green-led-current-microamp", &val); if (ret) { dev_info(dev, "no green-led-current-microamp set\n"); @@ -368,7 +367,7 @@ static int max30102_led_init(struct max30102_data *data) return ret; } - ret = of_property_read_u32(np, "maxim,ir-led-current-microamp", &val); + ret = device_property_read_u32(dev, "maxim,ir-led-current-microamp", &val); if (ret) { dev_info(dev, "no ir-led-current-microamp set\n"); @@ -624,7 +623,7 @@ MODULE_DEVICE_TABLE(of, max30102_dt_ids); static struct i2c_driver max30102_driver = { .driver = { .name = MAX30102_DRV_NAME, - .of_match_table = of_match_ptr(max30102_dt_ids), + .of_match_table = max30102_dt_ids, }, .probe = max30102_probe, .remove = max30102_remove, -- cgit v1.2.3 From 3cef2e31b54b5975f45dfd7f88204bb78b03d535 Mon Sep 17 00:00:00 2001 From: Ivan Drobyshevskyi Date: Wed, 16 Sep 2020 10:44:58 +0300 Subject: iio: proximity: vl53l0x: Add IRQ support VL53L0X can be configured to use interrupt pin (GPIO1) to notify host about readiness of new measurement. If interrupt pin is not specified, driver still uses polling. Signed-off-by: Ivan Drobyshevskyi Link: https://lore.kernel.org/r/20200916074458.873359-2-drobyshevskyi@gmail.com Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/vl53l0x-i2c.c | 104 ++++++++++++++++++++++++++++++++---- 1 file changed, 93 insertions(+), 11 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/proximity/vl53l0x-i2c.c b/drivers/iio/proximity/vl53l0x-i2c.c index 5fbda9475ba9..235e125aeb3a 100644 --- a/drivers/iio/proximity/vl53l0x-i2c.c +++ b/drivers/iio/proximity/vl53l0x-i2c.c @@ -4,18 +4,19 @@ * * Copyright (C) 2016 STMicroelectronics Imaging Division. * Copyright (C) 2018 Song Qiang + * Copyright (C) 2020 Ivan Drobyshevskyi * * Datasheet available at * * * Default 7-bit i2c slave address 0x29. * - * TODO: FIFO buffer, continuous mode, interrupts, range selection, - * sensor ID check. + * TODO: FIFO buffer, continuous mode, range selection, sensor ID check. */ #include #include +#include #include #include @@ -29,14 +30,72 @@ #define VL_REG_SYSRANGE_MODE_TIMED BIT(2) #define VL_REG_SYSRANGE_MODE_HISTOGRAM BIT(3) +#define VL_REG_SYSTEM_INTERRUPT_CONFIG_GPIO 0x0A +#define VL_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY BIT(2) + +#define VL_REG_SYSTEM_INTERRUPT_CLEAR 0x0B + #define VL_REG_RESULT_INT_STATUS 0x13 #define VL_REG_RESULT_RANGE_STATUS 0x14 #define VL_REG_RESULT_RANGE_STATUS_COMPLETE BIT(0) struct vl53l0x_data { struct i2c_client *client; + struct completion completion; }; +static irqreturn_t vl53l0x_handle_irq(int irq, void *priv) +{ + struct iio_dev *indio_dev = priv; + struct vl53l0x_data *data = iio_priv(indio_dev); + + complete(&data->completion); + + return IRQ_HANDLED; +} + +static int vl53l0x_configure_irq(struct i2c_client *client, + struct iio_dev *indio_dev) +{ + struct vl53l0x_data *data = iio_priv(indio_dev); + int ret; + + ret = devm_request_irq(&client->dev, client->irq, vl53l0x_handle_irq, + IRQF_TRIGGER_FALLING, indio_dev->name, indio_dev); + if (ret) { + dev_err(&client->dev, "devm_request_irq error: %d\n", ret); + return ret; + } + + ret = i2c_smbus_write_byte_data(data->client, + VL_REG_SYSTEM_INTERRUPT_CONFIG_GPIO, + VL_REG_SYSTEM_INTERRUPT_GPIO_NEW_SAMPLE_READY); + if (ret < 0) + dev_err(&client->dev, "failed to configure IRQ: %d\n", ret); + + return ret; +} + +static void vl53l0x_clear_irq(struct vl53l0x_data *data) +{ + struct device *dev = &data->client->dev; + int ret; + + ret = i2c_smbus_write_byte_data(data->client, + VL_REG_SYSTEM_INTERRUPT_CLEAR, 1); + if (ret < 0) + dev_err(dev, "failed to clear error irq: %d\n", ret); + + ret = i2c_smbus_write_byte_data(data->client, + VL_REG_SYSTEM_INTERRUPT_CLEAR, 0); + if (ret < 0) + dev_err(dev, "failed to clear range irq: %d\n", ret); + + ret = i2c_smbus_read_byte_data(data->client, VL_REG_RESULT_INT_STATUS); + if (ret < 0 || ret & 0x07) + dev_err(dev, "failed to clear irq: %d\n", ret); +} + static int vl53l0x_read_proximity(struct vl53l0x_data *data, const struct iio_chan_spec *chan, int *val) @@ -50,19 +109,31 @@ static int vl53l0x_read_proximity(struct vl53l0x_data *data, if (ret < 0) return ret; - do { - ret = i2c_smbus_read_byte_data(client, - VL_REG_RESULT_RANGE_STATUS); + if (data->client->irq) { + reinit_completion(&data->completion); + + ret = wait_for_completion_timeout(&data->completion, HZ/10); if (ret < 0) return ret; + else if (ret == 0) + return -ETIMEDOUT; - if (ret & VL_REG_RESULT_RANGE_STATUS_COMPLETE) - break; + vl53l0x_clear_irq(data); + } else { + do { + ret = i2c_smbus_read_byte_data(client, + VL_REG_RESULT_RANGE_STATUS); + if (ret < 0) + return ret; - usleep_range(1000, 5000); - } while (--tries); - if (!tries) - return -ETIMEDOUT; + if (ret & VL_REG_RESULT_RANGE_STATUS_COMPLETE) + break; + + usleep_range(1000, 5000); + } while (--tries); + if (!tries) + return -ETIMEDOUT; + } ret = i2c_smbus_read_i2c_block_data(client, VL_REG_RESULT_RANGE_STATUS, 12, buffer); @@ -140,6 +211,17 @@ static int vl53l0x_probe(struct i2c_client *client) indio_dev->num_channels = ARRAY_SIZE(vl53l0x_channels); indio_dev->modes = INDIO_DIRECT_MODE; + /* usage of interrupt is optional */ + if (client->irq) { + int ret; + + init_completion(&data->completion); + + ret = vl53l0x_configure_irq(client, indio_dev); + if (ret) + return ret; + } + return devm_iio_device_register(&client->dev, indio_dev); } -- cgit v1.2.3 From 8a0f412fca6e55765ad04c67037eb3907f0ad076 Mon Sep 17 00:00:00 2001 From: Sergiu Cuciurean Date: Wed, 16 Sep 2020 12:29:28 +0300 Subject: iio: adc: fsl-imx25-gcq: Replace indio_dev->mlock with own device lock As part of the general cleanup of indio_dev->mlock, this change replaces it with a local lock, to protect against any other accesses during the reading of sample. Reading a sample requires multiple consecutive regmap operations and a completion callback, so this requires that no other read occurs until it completes. This is part of a bigger cleanup. Link: https://lore.kernel.org/linux-iio/CA+U=Dsoo6YABe5ODLp+eFNPGFDjk5ZeQEceGkqjxXcVEhLWubw@mail.gmail.com/ Signed-off-by: Sergiu Cuciurean Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20200916092928.78026-1-alexandru.ardelean@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/fsl-imx25-gcq.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c index 8cb51cf7a816..ab5139e911c3 100644 --- a/drivers/iio/adc/fsl-imx25-gcq.c +++ b/drivers/iio/adc/fsl-imx25-gcq.c @@ -40,6 +40,15 @@ struct mx25_gcq_priv { int irq; struct regulator *vref[4]; u32 channel_vref_mv[MX25_NUM_CFGS]; + /* + * Lock to protect the device state during a potential concurrent + * read access from userspace. Reading a raw value requires a sequence + * of register writes, then a wait for a completion callback, + * and finally a register read, during which userspace could issue + * another read request. This lock protects a read access from + * ocurring before another one has finished. + */ + struct mutex lock; }; #define MX25_CQG_CHAN(chan, id) {\ @@ -137,9 +146,9 @@ static int mx25_gcq_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - mutex_lock(&indio_dev->mlock); + mutex_lock(&priv->lock); ret = mx25_gcq_get_raw_value(&indio_dev->dev, chan, priv, val); - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&priv->lock); return ret; case IIO_CHAN_INFO_SCALE: @@ -314,6 +323,8 @@ static int mx25_gcq_probe(struct platform_device *pdev) return PTR_ERR(priv->regs); } + mutex_init(&priv->lock); + init_completion(&priv->completed); ret = mx25_gcq_setup_cfgs(pdev, priv); -- cgit v1.2.3 From 6026292469e7f5d92d381e535c724be4967793d0 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 16 Jul 2020 14:59:28 +0100 Subject: iio: dac: ad7303: Complete 'struct ad7303_state' doc Fixes the following W=1 kernel build warning(s): drivers/iio/dac/ad7303.c:49: warning: Function parameter or member 'vdd_reg' not described in 'ad7303_state' drivers/iio/dac/ad7303.c:49: warning: Function parameter or member 'vref_reg' not described in 'ad7303_state' drivers/iio/dac/ad7303.c:49: warning: Function parameter or member 'lock' not described in 'ad7303_state' Signed-off-by: Lee Jones Cc: Michael Hennerich Cc: Liam Girdwood Cc: Mark Brown Link: https://lore.kernel.org/r/20200716135928.1456727-31-lee.jones@linaro.org Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad7303.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/iio') diff --git a/drivers/iio/dac/ad7303.c b/drivers/iio/dac/ad7303.c index 20c85c2a636c..2e46def9d8ee 100644 --- a/drivers/iio/dac/ad7303.c +++ b/drivers/iio/dac/ad7303.c @@ -30,6 +30,9 @@ * @spi: the device for this driver instance * @config: cached config register value * @dac_cache: current DAC raw value (chip does not support readback) + * @vdd_reg: reference to VDD regulator + * @vref_reg: reference to VREF regulator + * @lock: protect writes and cache updates * @data: spi transfer buffer */ -- cgit v1.2.3 From 1536a8ee142f8e89f156117dc853db723bd668e8 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 16 Jul 2020 14:59:17 +0100 Subject: iio: dac: ad5064: Fix a few kerneldoc misdemeanours Misspelling, missing description. Fixes the following W=1 kernel build warning(s): drivers/iio/dac/ad5064.c:71: warning: bad line: internal vref. drivers/iio/dac/ad5064.c:83: warning: Function parameter or member 'channels' not described in 'ad5064_chip_info' drivers/iio/dac/ad5064.c:125: warning: Function parameter or member 'lock' not described in 'ad5064_state' Signed-off-by: Lee Jones Cc: Michael Hennerich Cc: Liam Girdwood Cc: Mark Brown Link: https://lore.kernel.org/r/20200716135928.1456727-20-lee.jones@linaro.org Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5064.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c index fef503f8012d..82abd4d6886c 100644 --- a/drivers/iio/dac/ad5064.c +++ b/drivers/iio/dac/ad5064.c @@ -68,8 +68,8 @@ enum ad5064_regmap_type { * struct ad5064_chip_info - chip specific information * @shared_vref: whether the vref supply is shared between channels * @internal_vref: internal reference voltage. 0 if the chip has no - internal vref. - * @channel: channel specification + * internal vref. + * @channels: channel specification * @num_channels: number of channels * @regmap_type: register map layout variant */ @@ -98,6 +98,7 @@ typedef int (*ad5064_write_func)(struct ad5064_state *st, unsigned int cmd, * @use_internal_vref: set to true if the internal reference voltage should be * used. * @write: register write callback + * @lock: maintain consistency between cached and dev state * @data: i2c/spi transfer buffers */ @@ -111,7 +112,6 @@ struct ad5064_state { bool use_internal_vref; ad5064_write_func write; - /* Lock used to maintain consistency between cached and dev state */ struct mutex lock; /* -- cgit v1.2.3 From c5e6c649b4c4ed52d4cefeba8bf303d37db96893 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 16 Jul 2020 14:59:15 +0100 Subject: iio: adc: ad7949: Fix misspelling issue Fixes the following W=1 kernel build warning(s): drivers/iio/adc/ad7949.c:58: warning: Function parameter or member 'indio_dev' not described in 'ad7949_adc_chip' Signed-off-by: Lee Jones Cc: Michael Hennerich Cc: Charles-Antoine Couret Link: https://lore.kernel.org/r/20200716135928.1456727-18-lee.jones@linaro.org Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7949.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/ad7949.c b/drivers/iio/adc/ad7949.c index d9566a83988a..5d597e5050f6 100644 --- a/drivers/iio/adc/ad7949.c +++ b/drivers/iio/adc/ad7949.c @@ -39,7 +39,7 @@ static const struct ad7949_adc_spec ad7949_adc_spec[] = { * struct ad7949_adc_chip - AD ADC chip * @lock: protects write sequences * @vref: regulator generating Vref - * @iio_dev: reference to iio structure + * @indio_dev: reference to iio structure * @spi: reference to spi structure * @resolution: resolution of the chip * @cfg: copy of the configuration register -- cgit v1.2.3 From ee21014b102e01a62851e02d64f2c1b9d70309bc Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 16 Jul 2020 14:59:13 +0100 Subject: iio: dummy: iio_dummy_evgen: Demote file header and supply description for 'irq_sim_domain' File headers are not good candidates for kerneldoc. Fixes the following W=1 kernel build warning(s): drivers/iio/dummy/iio_dummy_evgen.c:30: warning: Cannot understand * @regs: irq regs we are faking on line 30 - I thought it was a doc line drivers/iio/dummy/iio_dummy_evgen.c:42: warning: Function parameter or member 'irq_sim_domain' not described in 'iio_dummy_eventgen' Signed-off-by: Lee Jones Cc: Marc Zyngier Cc: Bartosz Golaszewski Link: https://lore.kernel.org/r/20200716135928.1456727-16-lee.jones@linaro.org Signed-off-by: Jonathan Cameron --- drivers/iio/dummy/iio_dummy_evgen.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/dummy/iio_dummy_evgen.c b/drivers/iio/dummy/iio_dummy_evgen.c index ee85d596e528..5a0072727ba4 100644 --- a/drivers/iio/dummy/iio_dummy_evgen.c +++ b/drivers/iio/dummy/iio_dummy_evgen.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/** +/* * Copyright (c) 2011 Jonathan Cameron * * Companion module to the iio simple dummy example driver. @@ -27,11 +27,13 @@ #define IIO_EVENTGEN_NO 10 /** + * struct iio_dummy_eventgen - event generator specific state * @regs: irq regs we are faking * @lock: protect the evgen state * @inuse: mask of which irqs are connected * @irq_sim: interrupt simulator * @base: base of irq range + * @irq_sim_domain: irq simulator domain */ struct iio_dummy_eventgen { struct iio_dummy_regs regs[IIO_EVENTGEN_NO]; -- cgit v1.2.3 From faeda9190758fbd127e60ec147f7b6cae60f8578 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 16 Jul 2020 14:59:10 +0100 Subject: iio: gyro: adis16080: Fix formatting issue Kerneldoc expects attributes/parameters to be in '@*.: ' format. Fixes the following W=1 kernel build warning(s): drivers/iio/gyro/adis16080.c:49: warning: Function parameter or member 'lock' not described in 'adis16080_state' Signed-off-by: Lee Jones Cc: Michael Hennerich Cc: Barry Song <21cnbao@gmail.com> Link: https://lore.kernel.org/r/20200716135928.1456727-13-lee.jones@linaro.org Signed-off-by: Jonathan Cameron --- drivers/iio/gyro/adis16080.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/gyro/adis16080.c b/drivers/iio/gyro/adis16080.c index 6e5e2d98943c..e2f4d943e220 100644 --- a/drivers/iio/gyro/adis16080.c +++ b/drivers/iio/gyro/adis16080.c @@ -38,7 +38,7 @@ struct adis16080_chip_info { * @us: actual spi_device to write data * @info: chip specific parameters * @buf: transmit or receive buffer - * @lock lock to protect buffer during reads + * @lock: lock to protect buffer during reads **/ struct adis16080_state { struct spi_device *us; -- cgit v1.2.3 From ed33833ea822212a961e920b7b3c33dd299837cd Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 16 Jul 2020 14:59:03 +0100 Subject: iio: chemical: sgp30: Add description for sgp_read_cmd()'s 'duration_us' Fixes the following W=1 kernel build warning(s): drivers/iio/chemical/sgp30.c:236: warning: Function parameter or member 'duration_us' not described in 'sgp_read_cmd' Signed-off-by: Lee Jones Cc: Andreas Brauchli Cc: Pascal Sachs Link: https://lore.kernel.org/r/20200716135928.1456727-6-lee.jones@linaro.org Signed-off-by: Jonathan Cameron --- drivers/iio/chemical/sgp30.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/iio') diff --git a/drivers/iio/chemical/sgp30.c b/drivers/iio/chemical/sgp30.c index c2d93b9796ce..1029c457be15 100644 --- a/drivers/iio/chemical/sgp30.c +++ b/drivers/iio/chemical/sgp30.c @@ -227,6 +227,7 @@ static int sgp_verify_buffer(const struct sgp_data *data, * @cmd: SGP Command to issue * @buf: Raw data buffer to use * @word_count: Num words to read, excluding CRC bytes + * @duration_us: Time taken to sensor to take a reading and data to be ready. * * Return: 0 on success, negative error otherwise. */ -- cgit v1.2.3 From 5fe68a4d85bfd7d0ed1a4bcfb12120e2b7dd26f5 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 22 Jul 2020 15:25:15 +0100 Subject: iio:dac:ad5592r: Fix use of true for IIO_SHARED_BY_TYPE struct iio_chan_spec_ext_info shared element is of type enum iio_shared_by, not boolean. It's like the enum value will for IIO_SHARED_BY_TYPE == 1 == true, hence no actual problem has been observed. CC [M] drivers/iio/dac/ad5592r-base.o 491 | .shared = true, | Fixes: 56ca9db862bf ("iio: dac: Add support for the AD5592R/AD5593R ADCs/DACs") Signed-off-by: Jonathan Cameron Acked-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20200722142515.897378-1-jic23@kernel.org --- drivers/iio/dac/ad5592r-base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/dac/ad5592r-base.c b/drivers/iio/dac/ad5592r-base.c index cc4875660a69..456bf5292c44 100644 --- a/drivers/iio/dac/ad5592r-base.c +++ b/drivers/iio/dac/ad5592r-base.c @@ -488,7 +488,7 @@ static const struct iio_chan_spec_ext_info ad5592r_ext_info[] = { { .name = "scale_available", .read = ad5592r_show_scale_available, - .shared = true, + .shared = IIO_SHARED_BY_TYPE, }, {}, }; -- cgit v1.2.3 From b004fe33034cc64f72c20923be71cf1e6c9a624c Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 6 Jul 2020 14:02:58 +0300 Subject: iio: dac: ad5592r: un-indent code-block for scale read The next rework may require an unindentation of a code block in ad5592r_read_raw(), which would make review a bit more difficult. This change unindents the code block for reading the scale of the non-temperature channels. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20200706110259.23947-2-alexandru.ardelean@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5592r-base.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/dac/ad5592r-base.c b/drivers/iio/dac/ad5592r-base.c index 456bf5292c44..008f103c5ef2 100644 --- a/drivers/iio/dac/ad5592r-base.c +++ b/drivers/iio/dac/ad5592r-base.c @@ -376,7 +376,7 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev, { struct ad5592r_state *st = iio_priv(iio_dev); u16 read_val; - int ret; + int ret, mult; switch (m) { case IIO_CHAN_INFO_RAW: @@ -414,23 +414,21 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev, *val = div_s64_rem(tmp, 1000000000LL, val2); return IIO_VAL_INT_PLUS_MICRO; - } else { - int mult; + } - mutex_lock(&st->lock); + 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); + 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; + *val *= ++mult; - *val2 = chan->scan_type.realbits; - ret = IIO_VAL_FRACTIONAL_LOG2; - } + *val2 = chan->scan_type.realbits; + ret = IIO_VAL_FRACTIONAL_LOG2; break; case IIO_CHAN_INFO_OFFSET: ret = ad5592r_get_vref(st); -- cgit v1.2.3 From c8bb10c50d60cf4bd083eb7f7956999942694c90 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 6 Jul 2020 14:02:59 +0300 Subject: iio: dac: ad5592r: localize locks only where needed in ad5592r_read_raw() Since there was a recently discovered issue with these locks, it probably makes sense to cleanup the code a bit, to prevent it from being used as an example/reference. This change moves the lock only where it is explicitly needed to protect resources from potential concurrent accesses. It also reworks the switch statements to do direct returns vs caching the return value on a variable. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20200706110259.23947-3-alexandru.ardelean@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5592r-base.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/dac/ad5592r-base.c b/drivers/iio/dac/ad5592r-base.c index 008f103c5ef2..63514e3c6c18 100644 --- a/drivers/iio/dac/ad5592r-base.c +++ b/drivers/iio/dac/ad5592r-base.c @@ -380,32 +380,32 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev, switch (m) { case IIO_CHAN_INFO_RAW: - mutex_lock(&st->lock); - if (!chan->output) { + mutex_lock(&st->lock); ret = st->ops->read_adc(st, chan->channel, &read_val); + mutex_unlock(&st->lock); if (ret) - goto unlock; + return ret; if ((read_val >> 12 & 0x7) != (chan->channel & 0x7)) { dev_err(st->dev, "Error while reading channel %u\n", chan->channel); - ret = -EIO; - goto unlock; + return -EIO; } read_val &= GENMASK(11, 0); } else { + mutex_lock(&st->lock); read_val = st->cached_dac[chan->channel]; + mutex_unlock(&st->lock); } dev_dbg(st->dev, "Channel %u read: 0x%04hX\n", chan->channel, read_val); *val = (int) read_val; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: *val = ad5592r_get_vref(st); @@ -425,11 +425,13 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev, mult = !!(st->cached_gp_ctrl & AD5592R_REG_CTRL_ADC_RANGE); + mutex_unlock(&st->lock); + *val *= ++mult; *val2 = chan->scan_type.realbits; - ret = IIO_VAL_FRACTIONAL_LOG2; - break; + + return IIO_VAL_FRACTIONAL_LOG2; case IIO_CHAN_INFO_OFFSET: ret = ad5592r_get_vref(st); @@ -439,15 +441,13 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev, *val = (-34365 * 25) / ret; else *val = (-75365 * 25) / ret; - ret = IIO_VAL_INT; - break; + + mutex_unlock(&st->lock); + + return IIO_VAL_INT; default: return -EINVAL; } - -unlock: - mutex_unlock(&st->lock); - return ret; } static int ad5592r_write_raw_get_fmt(struct iio_dev *indio_dev, -- cgit v1.2.3 From c9561fd21a06f854d3df6db7dd83b38e91ed6e93 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 13 Sep 2020 14:21:15 +0100 Subject: iio:core: Tidy up kernel-doc. One comment isn't kernel-doc at all, but starts with /** and another is simply missing a parameter that was introduced recently. Signed-off-by: Jonathan Cameron Acked-by: Alexandru Ardelean Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200913132115.800131-4-jic23@kernel.org --- drivers/iio/industrialio-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 8ddc6dfc8ed4..6e388293c828 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -170,7 +170,7 @@ static const char * const iio_chan_info_postfix[] = { }; #if defined(CONFIG_DEBUG_FS) -/** +/* * There's also a CONFIG_DEBUG_FS guard in include/linux/iio/iio.h for * iio_get_debugfs_dentry() to make it inline if CONFIG_DEBUG_FS is undefined */ @@ -1525,6 +1525,7 @@ struct device_type iio_device_type = { /** * iio_device_alloc() - allocate an iio_dev from a driver + * @parent: Parent device. * @sizeof_priv: Space to allocate for private structure. **/ struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv) -- cgit v1.2.3 From cd7798cbd28044a3026619e36993160ba8fa118d Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 13 Sep 2020 14:21:14 +0100 Subject: iio: Add __printf() attributes to various allocation functions A partial set of these was added to IIO a long time back. This fills in some gaps in coverage highlighted by building with W=1 Signed-off-by: Jonathan Cameron Reviewed-by: Alexandru Ardelean Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200913132115.800131-3-jic23@kernel.org --- drivers/iio/industrialio-trigger.c | 3 ++- include/linux/iio/iio.h | 3 ++- include/linux/iio/trigger_consumer.h | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index 6f16357fd732..583bb51f65a7 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -516,7 +516,8 @@ static void iio_trig_subirqunmask(struct irq_data *d) trig->subirqs[d->irq - trig->subirq_base].enabled = true; } -static struct iio_trigger *viio_trigger_alloc(const char *fmt, va_list vargs) +static __printf(1, 0) +struct iio_trigger *viio_trigger_alloc(const char *fmt, va_list vargs) { struct iio_trigger *trig; int i; diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index e2df67a3b9ab..2e45b3ceafa7 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -691,8 +691,9 @@ static inline void *iio_priv(const struct iio_dev *indio_dev) void iio_device_free(struct iio_dev *indio_dev); struct iio_dev *devm_iio_device_alloc(struct device *parent, int sizeof_priv); +__printf(2, 3) struct iio_trigger *devm_iio_trigger_alloc(struct device *dev, - const char *fmt, ...); + const char *fmt, ...); /** * iio_buffer_enabled() - helper function to test if the buffer is enabled * @indio_dev: IIO device structure for device diff --git a/include/linux/iio/trigger_consumer.h b/include/linux/iio/trigger_consumer.h index 3aa2f132dd67..2c05dfad88d7 100644 --- a/include/linux/iio/trigger_consumer.h +++ b/include/linux/iio/trigger_consumer.h @@ -38,7 +38,7 @@ struct iio_poll_func { }; -struct iio_poll_func +__printf(5, 6) struct iio_poll_func *iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p), irqreturn_t (*thread)(int irq, void *p), int type, -- cgit v1.2.3 From e8a26c5b767b5ffc541f1c80336f2faa802441f4 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 13 Sep 2020 12:25:46 +0100 Subject: iio:magn:hmc5843: Fix passing true where iio_shared_by enum required. So it's obvious that the code is wrong in passing true, but I'm assuming that will actually evaluate to 1 and hence IIO_SHARED_BY_TYPE. The documentation however has this attribute as IIO_SHARED_BY_ALL. My current assumption is the documentation is wrong. If anyone knows otherwise please shout out! Fixes: 7247645f6865 ("iio: hmc5843: Move hmc5843 out of staging") Signed-off-by: Jonathan Cameron Reviewed-by: Matt Ranostay Reviewed-by: Lars-Peter Clausen Reviewed-by: Andy Shevchenko Tested-by: H. Nikolaus Schaller Link: https://lore.kernel.org/r/20200913112546.715624-1-jic23@kernel.org --- drivers/iio/magnetometer/hmc5843_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/magnetometer/hmc5843_core.c b/drivers/iio/magnetometer/hmc5843_core.c index 1474ba63babe..780faea61d82 100644 --- a/drivers/iio/magnetometer/hmc5843_core.c +++ b/drivers/iio/magnetometer/hmc5843_core.c @@ -245,7 +245,7 @@ static const struct iio_enum hmc5843_meas_conf_enum = { }; static const struct iio_chan_spec_ext_info hmc5843_ext_info[] = { - IIO_ENUM("meas_conf", true, &hmc5843_meas_conf_enum), + IIO_ENUM("meas_conf", IIO_SHARED_BY_TYPE, &hmc5843_meas_conf_enum), IIO_ENUM_AVAILABLE("meas_conf", &hmc5843_meas_conf_enum), IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, hmc5843_get_mount_matrix), { } @@ -259,7 +259,7 @@ static const struct iio_enum hmc5983_meas_conf_enum = { }; static const struct iio_chan_spec_ext_info hmc5983_ext_info[] = { - IIO_ENUM("meas_conf", true, &hmc5983_meas_conf_enum), + IIO_ENUM("meas_conf", IIO_SHARED_BY_TYPE, &hmc5983_meas_conf_enum), IIO_ENUM_AVAILABLE("meas_conf", &hmc5983_meas_conf_enum), IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, hmc5843_get_mount_matrix), { } -- cgit v1.2.3 From 9e7c7d92747f653c528d8af9e4244ac7a9cb048d Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 13 Sep 2020 13:12:27 +0100 Subject: iio:accel:bma180: Fix use of true when should be iio_shared_by enum Given a value of 1 corresponds to IIO_SHARE_BY_TYPE I have replaced it with that. Should cause no functional change. Fixes: fdadbce0da42 ("iio: add Bosch BMA180 acceleration sensor driver") Signed-off-by: Jonathan Cameron Reviewed-by: Matt Ranostay Reviewed-by: Lars-Peter Clausen Reviewed-by: Andy Shevchenko Cc: Oleksandr Kravchenko Cc: Peter Meerwald Cc: Jonathan Bakker Link: https://lore.kernel.org/r/20200913121227.764626-1-jic23@kernel.org --- drivers/iio/accel/bma180.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index 448faed001fd..6b74c2b04c15 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -673,7 +673,7 @@ static const struct iio_chan_spec_ext_info bma023_ext_info[] = { }; static const struct iio_chan_spec_ext_info bma180_ext_info[] = { - IIO_ENUM("power_mode", true, &bma180_power_mode_enum), + IIO_ENUM("power_mode", IIO_SHARED_BY_TYPE, &bma180_power_mode_enum), IIO_ENUM_AVAILABLE("power_mode", &bma180_power_mode_enum), IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, bma180_accel_get_mount_matrix), { } -- cgit v1.2.3 From 36e322ec5dd24f1d0840061ffe406458669bccf1 Mon Sep 17 00:00:00 2001 From: Nuno Sá Date: Thu, 17 Sep 2020 17:52:20 +0200 Subject: iio: adis: Move burst mode into adis_data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add burst mode variables in the per device specific data structure. As some drivers support multiple devices with different burst sizes it makes sense this data to be in `adis_data`. While moving the variables, there are two main differences: 1. The `en`variable is dropped. If a device supports burst mode, it will just use it as it will has better performance for almost all real use cases. 2. Replace `extra_len` by `burst_len`. Users should now explicitly define the length of the burst buffer as it is typically constant. This also allows to remove the following line from the library: ``` /* All but the timestamp channel */ burst_length = (indio_dev->num_channels - 1) * sizeof(u16); ``` The library should not assume that a timestamp channel is defined. Moreover, most parts also include some diagnostic data, crc, etc.. in the burst buffer that needed to be included in an `extra_len` variable which is not that nice. On top of this, some devices already start to have some 32bit size channels ... This patch is also a move to completely drop the `struct adis_burst` from the library. Signed-off-by: Nuno Sá Signed-off-by: Jonathan Cameron Link: https://lore.kernel.org/r/20200917155223.218500-2-nuno.sa@analog.com --- drivers/iio/imu/adis_buffer.c | 12 +++++------- include/linux/iio/imu/adis.h | 9 +++++++++ 2 files changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c index df6144285470..ac354321f63a 100644 --- a/drivers/iio/imu/adis_buffer.c +++ b/drivers/iio/imu/adis_buffer.c @@ -26,12 +26,10 @@ static int adis_update_scan_mode_burst(struct iio_dev *indio_dev, unsigned int burst_length, burst_max_length; u8 *tx; - /* All but the timestamp channel */ - burst_length = (indio_dev->num_channels - 1) * sizeof(u16); - burst_length += adis->burst->extra_len + adis->burst_extra_len; + burst_length = adis->data->burst_len + adis->burst_extra_len; - if (adis->burst->burst_max_len) - burst_max_length = adis->burst->burst_max_len; + if (adis->data->burst_max_len) + burst_max_length = adis->data->burst_max_len; else burst_max_length = burst_length; @@ -47,7 +45,7 @@ static int adis_update_scan_mode_burst(struct iio_dev *indio_dev, } tx = adis->buffer + burst_max_length; - tx[0] = ADIS_READ_REG(adis->burst->reg_cmd); + tx[0] = ADIS_READ_REG(adis->data->burst_reg_cmd); tx[1] = 0; adis->xfer[0].tx_buf = tx; @@ -76,7 +74,7 @@ int adis_update_scan_mode(struct iio_dev *indio_dev, kfree(adis->xfer); kfree(adis->buffer); - if (adis->burst && adis->burst->en) + if (adis->data->burst_len) return adis_update_scan_mode_burst(indio_dev, scan_mask); scan_count = indio_dev->scan_bytes / 2; diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index 01ba691da2f3..c502ea3b9199 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -51,6 +51,11 @@ struct adis_timeout { * @timeouts: Chip specific delays * @enable_irq: Hook for ADIS devices that have a special IRQ enable/disable * @has_paging: True if ADIS device has paged registers + * @burst_reg_cmd: Register command that triggers burst + * @burst_len: Burst size in the SPI RX buffer. If @burst_max_len is defined, + * this should be the minimum size supported by the device. + * @burst_max_len: Holds the maximum burst size when the device supports + * more than one burst mode with different sizes */ struct adis_data { unsigned int read_delay; @@ -75,6 +80,10 @@ struct adis_data { int (*enable_irq)(struct adis *adis, bool enable); bool has_paging; + + unsigned int burst_reg_cmd; + unsigned int burst_len; + unsigned int burst_max_len; }; /** -- cgit v1.2.3 From f81d053bb4614fd2b71d774521f9016b6e8548e7 Mon Sep 17 00:00:00 2001 From: Nuno Sá Date: Thu, 17 Sep 2020 17:52:21 +0200 Subject: iio: adis16400: Drop adis_burst usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Burst mode variables are now part of the `adis_data` struct. The driver also has now to explicitly define the length of the burst buffer. Signed-off-by: Nuno Sá Signed-off-by: Jonathan Cameron Link: https://lore.kernel.org/r/20200917155223.218500-3-nuno.sa@analog.com --- drivers/iio/imu/adis16400.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c index 73433f7feb31..54af2ed664f6 100644 --- a/drivers/iio/imu/adis16400.c +++ b/drivers/iio/imu/adis16400.c @@ -319,11 +319,6 @@ enum adis16400_chip_variant { ADIS16448, }; -static struct adis_burst adis16400_burst = { - .en = true, - .reg_cmd = ADIS16400_GLOB_CMD, -}; - static int adis16334_get_freq(struct adis16400_state *st) { int ret; @@ -949,7 +944,7 @@ static const char * const adis16400_status_error_msgs[] = { [ADIS16400_DIAG_STAT_POWER_LOW] = "Power supply below 4.75V", }; -#define ADIS16400_DATA(_timeouts) \ +#define ADIS16400_DATA(_timeouts, _burst_len) \ { \ .msc_ctrl_reg = ADIS16400_MSC_CTRL, \ .glob_cmd_reg = ADIS16400_GLOB_CMD, \ @@ -975,6 +970,8 @@ static const char * const adis16400_status_error_msgs[] = { BIT(ADIS16400_DIAG_STAT_POWER_HIGH) | \ BIT(ADIS16400_DIAG_STAT_POWER_LOW), \ .timeouts = (_timeouts), \ + .burst_reg_cmd = ADIS16400_GLOB_CMD, \ + .burst_len = (_burst_len) \ } static const struct adis_timeout adis16300_timeouts = { @@ -1025,7 +1022,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, - .adis_data = ADIS16400_DATA(&adis16300_timeouts), + .adis_data = ADIS16400_DATA(&adis16300_timeouts, 18), }, [ADIS16334] = { .channels = adis16334_channels, @@ -1038,7 +1035,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 67850, /* 25 C = 0x00 */ .set_freq = adis16334_set_freq, .get_freq = adis16334_get_freq, - .adis_data = ADIS16400_DATA(&adis16334_timeouts), + .adis_data = ADIS16400_DATA(&adis16334_timeouts, 0), }, [ADIS16350] = { .channels = adis16350_channels, @@ -1050,7 +1047,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .flags = ADIS16400_NO_BURST | ADIS16400_HAS_SLOW_MODE, .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, - .adis_data = ADIS16400_DATA(&adis16300_timeouts), + .adis_data = ADIS16400_DATA(&adis16300_timeouts, 0), }, [ADIS16360] = { .channels = adis16350_channels, @@ -1063,7 +1060,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, - .adis_data = ADIS16400_DATA(&adis16300_timeouts), + .adis_data = ADIS16400_DATA(&adis16300_timeouts, 28), }, [ADIS16362] = { .channels = adis16350_channels, @@ -1076,7 +1073,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, - .adis_data = ADIS16400_DATA(&adis16362_timeouts), + .adis_data = ADIS16400_DATA(&adis16362_timeouts, 28), }, [ADIS16364] = { .channels = adis16350_channels, @@ -1089,7 +1086,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, - .adis_data = ADIS16400_DATA(&adis16362_timeouts), + .adis_data = ADIS16400_DATA(&adis16362_timeouts, 28), }, [ADIS16367] = { .channels = adis16350_channels, @@ -1102,7 +1099,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, - .adis_data = ADIS16400_DATA(&adis16300_timeouts), + .adis_data = ADIS16400_DATA(&adis16300_timeouts, 28), }, [ADIS16400] = { .channels = adis16400_channels, @@ -1114,7 +1111,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, - .adis_data = ADIS16400_DATA(&adis16400_timeouts), + .adis_data = ADIS16400_DATA(&adis16400_timeouts, 24), }, [ADIS16445] = { .channels = adis16445_channels, @@ -1128,7 +1125,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */ .set_freq = adis16334_set_freq, .get_freq = adis16334_get_freq, - .adis_data = ADIS16400_DATA(&adis16445_timeouts), + .adis_data = ADIS16400_DATA(&adis16445_timeouts, 16), }, [ADIS16448] = { .channels = adis16448_channels, @@ -1142,7 +1139,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */ .set_freq = adis16334_set_freq, .get_freq = adis16334_get_freq, - .adis_data = ADIS16400_DATA(&adis16448_timeouts), + .adis_data = ADIS16400_DATA(&adis16448_timeouts, 24), } }; @@ -1198,9 +1195,6 @@ static int adis16400_probe(struct spi_device *spi) if (!(st->variant->flags & ADIS16400_NO_BURST)) { adis16400_setup_chan_mask(st); indio_dev->available_scan_masks = st->avail_scan_mask; - st->adis.burst = &adis16400_burst; - if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) - st->adis.burst_extra_len = sizeof(u16); } adis16400_data = &st->variant->adis_data; -- cgit v1.2.3 From 0dfaa465fc734fec8554f9a700594ea28242dc75 Mon Sep 17 00:00:00 2001 From: Nuno Sá Date: Thu, 17 Sep 2020 17:52:22 +0200 Subject: iio: adis16475: Drop adis_burst usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Burst mode variables are now part of the `adis_data` struct. The driver also has now to explicitly define the length of the burst buffer. Signed-off-by: Nuno Sá Signed-off-by: Jonathan Cameron Link: https://lore.kernel.org/r/20200917155223.218500-4-nuno.sa@analog.com --- drivers/iio/imu/adis16475.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c index 35d10ccb66c2..197d48240991 100644 --- a/drivers/iio/imu/adis16475.c +++ b/drivers/iio/imu/adis16475.c @@ -565,6 +565,9 @@ static int adis16475_enable_irq(struct adis *adis, bool enable) BIT(ADIS16475_DIAG_STAT_CLK), \ .enable_irq = adis16475_enable_irq, \ .timeouts = (_timeouts), \ + .burst_reg_cmd = ADIS16475_REG_GLOB_CMD, \ + .burst_len = ADIS16475_BURST_MAX_DATA, \ + .burst_max_len = ADIS16475_BURST32_MAX_DATA \ } static const struct adis16475_sync adis16475_sync_mode[] = { @@ -910,20 +913,6 @@ static const struct iio_info adis16475_info = { .debugfs_reg_access = adis_debugfs_reg_access, }; -static struct adis_burst adis16475_burst = { - .en = true, - .reg_cmd = ADIS16475_REG_GLOB_CMD, - /* - * adis_update_scan_mode_burst() sets the burst length in respect with - * the number of channels and allocates 16 bits for each. However, - * adis1647x devices also need space for DIAG_STAT, DATA_CNTR or - * TIME_STAMP (depending on the clock mode but for us these bytes are - * don't care...) and CRC. - */ - .extra_len = 3 * sizeof(u16), - .burst_max_len = ADIS16475_BURST32_MAX_DATA, -}; - static bool adis16475_validate_crc(const u8 *buffer, u16 crc, const bool burst32) { @@ -1279,7 +1268,6 @@ static int adis16475_probe(struct spi_device *spi) st = iio_priv(indio_dev); spi_set_drvdata(spi, indio_dev); - st->adis.burst = &adis16475_burst; st->info = device_get_match_data(&spi->dev); if (!st->info) -- cgit v1.2.3 From 44a76de8ca4d13b157c49a16d0ef47ccff91a2e3 Mon Sep 17 00:00:00 2001 From: Mario Tesi Date: Thu, 17 Sep 2020 18:47:16 +0200 Subject: iio: imu: st_lsm6dsx: Scaling factor type set to IIO_VAL_INT_PLUS_NANO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Scaling factor values for Acc lead to an unacceptable rounding of the full scale (FS) calculated by some SensorHAL on Android devices. For examples setting FS to 4g the in_accel_x_scale, in_accel_y_scale and in_accel_z_scale are 0.001196 on 6 decimal digits and the FS is 0.001196 × ((2^15) − 1) ~= 39.1893 m/s^2. Android CTS R10 SensorParameterRangeTest test expects a value greater than 39.20 m/s^2 so this test fails (ACCELEROMETER_MAX_RANGE = 4 * 9.80). Using 9 decimal digits the new scale factor is 0.001196411 and the FS now is 0.001196411 × ((2^15)−1) ~= 39.2028 m/s^2. This patch extends to IIO_VAL_INT_PLUS_NANO type the scaling factor to all IMU devices where SensorParameterRangeTest CTS test fails. Signed-off-by: Mario Tesi Acked-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron Link: https://lore.kernel.org/r/1600361236-2285-1-git-send-email-martepisa@gmail.com --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 134 +++++++++++++++------------ 1 file changed, 77 insertions(+), 57 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index 346c24281d26..42f485634d04 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -157,10 +157,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x20, .mask = GENMASK(4, 3), }, - .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, - .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, - .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, - .fs_avl[3] = { IIO_G_TO_M_S_2(732), 0x1 }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61000), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(732000), 0x1 }, .fs_len = 4, }, [ST_LSM6DSX_ID_GYRO] = { @@ -169,9 +169,9 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .mask = GENMASK(4, 3), }, - .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, - .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, - .fs_avl[2] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750000), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(70000000), 0x3 }, .fs_len = 3, }, }, @@ -259,10 +259,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x10, .mask = GENMASK(3, 2), }, - .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, - .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, - .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, - .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61000), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 }, .fs_len = 4, }, [ST_LSM6DSX_ID_GYRO] = { @@ -270,10 +270,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x11, .mask = GENMASK(3, 2), }, - .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, - .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, - .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, - .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750000), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 }, + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 }, .fs_len = 4, }, }, @@ -425,10 +425,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x10, .mask = GENMASK(3, 2), }, - .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, - .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, - .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, - .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61000), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 }, .fs_len = 4, }, [ST_LSM6DSX_ID_GYRO] = { @@ -436,10 +436,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x11, .mask = GENMASK(3, 2), }, - .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, - .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, - .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, - .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750000), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 }, + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 }, .fs_len = 4, }, }, @@ -600,10 +600,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x10, .mask = GENMASK(3, 2), }, - .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, - .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, - .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, - .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61000), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 }, .fs_len = 4, }, [ST_LSM6DSX_ID_GYRO] = { @@ -611,10 +611,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x11, .mask = GENMASK(3, 2), }, - .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, - .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, - .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, - .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750000), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 }, + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 }, .fs_len = 4, }, }, @@ -816,10 +816,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x10, .mask = GENMASK(3, 2), }, - .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, - .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, - .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, - .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61000), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 }, .fs_len = 4, }, [ST_LSM6DSX_ID_GYRO] = { @@ -827,10 +827,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x11, .mask = GENMASK(3, 2), }, - .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, - .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, - .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, - .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750000), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 }, + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 }, .fs_len = 4, }, }, @@ -1021,10 +1021,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x10, .mask = GENMASK(3, 2), }, - .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, - .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, - .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, - .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61000), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 }, .fs_len = 4, }, [ST_LSM6DSX_ID_GYRO] = { @@ -1032,10 +1032,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x11, .mask = GENMASK(3, 2), }, - .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, - .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, - .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, - .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750000), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 }, + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 }, .fs_len = 4, }, }, @@ -1200,10 +1200,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x10, .mask = GENMASK(3, 2), }, - .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, - .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, - .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, - .fs_avl[3] = { IIO_G_TO_M_S_2(488), 0x1 }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61000), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122000), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244000), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(488000), 0x1 }, .fs_len = 4, }, [ST_LSM6DSX_ID_GYRO] = { @@ -1211,10 +1211,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x11, .mask = GENMASK(3, 2), }, - .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750), 0x0 }, - .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 }, - .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000), 0x2 }, - .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000), 0x3 }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(8750000), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(17500000), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(35000000), 0x2 }, + .fs_avl[3] = { IIO_DEGREE_TO_RAD(70000000), 0x3 }, .fs_len = 4, }, }, @@ -1598,7 +1598,7 @@ static int st_lsm6dsx_read_raw(struct iio_dev *iio_dev, case IIO_CHAN_INFO_SCALE: *val = 0; *val2 = sensor->gain; - ret = IIO_VAL_INT_PLUS_MICRO; + ret = IIO_VAL_INT_PLUS_NANO; break; default: ret = -EINVAL; @@ -1836,13 +1836,31 @@ static ssize_t st_lsm6dsx_sysfs_scale_avail(struct device *dev, fs_table = &hw->settings->fs_table[sensor->id]; for (i = 0; i < fs_table->fs_len; i++) - len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ", + len += scnprintf(buf + len, PAGE_SIZE - len, "0.%09u ", fs_table->fs_avl[i].gain); buf[len - 1] = '\n'; return len; } +static int st_lsm6dsx_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ANGL_VEL: + case IIO_ACCEL: + return IIO_VAL_INT_PLUS_NANO; + default: + return IIO_VAL_INT_PLUS_MICRO; + } + default: + return IIO_VAL_INT_PLUS_MICRO; + } +} + static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(st_lsm6dsx_sysfs_sampling_frequency_avail); static IIO_DEVICE_ATTR(in_accel_scale_available, 0444, st_lsm6dsx_sysfs_scale_avail, NULL, 0); @@ -1868,6 +1886,7 @@ static const struct iio_info st_lsm6dsx_acc_info = { .read_event_config = st_lsm6dsx_read_event_config, .write_event_config = st_lsm6dsx_write_event_config, .hwfifo_set_watermark = st_lsm6dsx_set_watermark, + .write_raw_get_fmt = st_lsm6dsx_write_raw_get_fmt, }; static struct attribute *st_lsm6dsx_gyro_attributes[] = { @@ -1885,6 +1904,7 @@ static const struct iio_info st_lsm6dsx_gyro_info = { .read_raw = st_lsm6dsx_read_raw, .write_raw = st_lsm6dsx_write_raw, .hwfifo_set_watermark = st_lsm6dsx_set_watermark, + .write_raw_get_fmt = st_lsm6dsx_write_raw_get_fmt, }; static int st_lsm6dsx_get_drdy_pin(struct st_lsm6dsx_hw *hw, int *drdy_pin) -- cgit v1.2.3 From d390ff735d0a61e4703bf124866ef6d4be7fdc64 Mon Sep 17 00:00:00 2001 From: Sergiu Cuciurean Date: Wed, 16 Sep 2020 12:31:23 +0300 Subject: iio: adc: exynos_adc: Replace indio_dev->mlock with own device lock As part of the general cleanup of indio_dev->mlock, this change replaces it with a local lock, to protect potential concurrent access to the completion callback during a conversion. This is part of a bigger cleanup. Link: https://lore.kernel.org/linux-iio/CA+U=Dsoo6YABe5ODLp+eFNPGFDjk5ZeQEceGkqjxXcVEhLWubw@mail.gmail.com/ Signed-off-by: Sergiu Cuciurean Signed-off-by: Alexandru Ardelean Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200916093123.78954-1-alexandru.ardelean@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/exynos_adc.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c index 20477b249f2a..99f4404e9fd1 100644 --- a/drivers/iio/adc/exynos_adc.c +++ b/drivers/iio/adc/exynos_adc.c @@ -138,6 +138,16 @@ struct exynos_adc { bool read_ts; u32 ts_x; u32 ts_y; + + /* + * Lock to protect from potential concurrent access to the + * completion callback during a manual conversion. For this driver + * a wait-callback is used to wait for the conversion result, + * so in the meantime no other read request (or conversion start) + * must be performed, otherwise it would interfere with the + * current conversion result. + */ + struct mutex lock; }; struct exynos_adc_data { @@ -542,7 +552,7 @@ static int exynos_read_raw(struct iio_dev *indio_dev, return -EINVAL; } - mutex_lock(&indio_dev->mlock); + mutex_lock(&info->lock); reinit_completion(&info->completion); /* Select the channel to be used and Trigger conversion */ @@ -562,7 +572,7 @@ static int exynos_read_raw(struct iio_dev *indio_dev, ret = IIO_VAL_INT; } - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&info->lock); return ret; } @@ -573,7 +583,7 @@ static int exynos_read_s3c64xx_ts(struct iio_dev *indio_dev, int *x, int *y) unsigned long timeout; int ret; - mutex_lock(&indio_dev->mlock); + mutex_lock(&info->lock); info->read_ts = true; reinit_completion(&info->completion); @@ -598,7 +608,7 @@ static int exynos_read_s3c64xx_ts(struct iio_dev *indio_dev, int *x, int *y) } info->read_ts = false; - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&info->lock); return ret; } @@ -868,6 +878,8 @@ static int exynos_adc_probe(struct platform_device *pdev) indio_dev->channels = exynos_adc_iio_channels; indio_dev->num_channels = info->data->num_channels; + mutex_init(&info->lock); + ret = request_irq(info->irq, exynos_adc_isr, 0, dev_name(&pdev->dev), info); if (ret < 0) { -- cgit v1.2.3 From f71e41e23e129640f620b65fc362a6da02580310 Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Sun, 9 Aug 2020 10:55:51 -0700 Subject: iio:imu:st_lsm6dsx: check st_lsm6dsx_shub_read_output return Potential error return is not checked. This can lead to use of undefined data. Detected by clang static analysis. st_lsm6dsx_shub.c:540:8: warning: Assigned value is garbage or undefined *val = (s16)le16_to_cpu(*((__le16 *)data)); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Fixes: c91c1c844ebd ("iio: imu: st_lsm6dsx: add i2c embedded controller support") Signed-off-by: Tom Rix Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200809175551.6794-1-trix@redhat.com Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/iio') diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c index ed83471dc7dd..8c8d8870ca07 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c @@ -313,6 +313,8 @@ st_lsm6dsx_shub_read(struct st_lsm6dsx_sensor *sensor, u8 addr, err = st_lsm6dsx_shub_read_output(hw, data, len & ST_LS6DSX_READ_OP_MASK); + if (err < 0) + return err; st_lsm6dsx_shub_master_enable(sensor, false); -- cgit v1.2.3 From 10ab7cfd5522f0041028556dac864a003e158556 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 22 Jul 2020 16:50:41 +0100 Subject: iio:gyro:itg3200: Fix timestamp alignment and prevent data leak. One of a class of bugs pointed out by Lars in a recent review. iio_push_to_buffers_with_timestamp assumes the buffer used is aligned to the size of the timestamp (8 bytes). This is not guaranteed in this driver which uses a 16 byte array of smaller elements on the stack. This is fixed by using an explicit c structure. As there are no holes in the structure, there is no possiblity of data leakage in this case. The explicit alignment of ts is not strictly necessary but potentially makes the code slightly less fragile. It also removes the possibility of this being cut and paste into another driver where the alignment isn't already true. Fixes: 36e0371e7764 ("iio:itg3200: Use iio_push_to_buffers_with_timestamp()") Reported-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Link: https://lore.kernel.org/r/20200722155103.979802-6-jic23@kernel.org --- drivers/iio/gyro/itg3200_buffer.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/gyro/itg3200_buffer.c b/drivers/iio/gyro/itg3200_buffer.c index d3fbe9d86467..1c3c1bd53374 100644 --- a/drivers/iio/gyro/itg3200_buffer.c +++ b/drivers/iio/gyro/itg3200_buffer.c @@ -46,13 +46,20 @@ static irqreturn_t itg3200_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct itg3200 *st = iio_priv(indio_dev); - __be16 buf[ITG3200_SCAN_ELEMENTS + sizeof(s64)/sizeof(u16)]; - - int ret = itg3200_read_all_channels(st->i2c, buf); + /* + * Ensure correct alignment and padding including for the + * timestamp that may be inserted. + */ + struct { + __be16 buf[ITG3200_SCAN_ELEMENTS]; + s64 ts __aligned(8); + } scan; + + int ret = itg3200_read_all_channels(st->i2c, scan.buf); if (ret < 0) goto error_ret; - iio_push_to_buffers_with_timestamp(indio_dev, buf, pf->timestamp); + iio_push_to_buffers_with_timestamp(indio_dev, &scan, pf->timestamp); iio_trigger_notify_done(indio_dev->trig); -- cgit v1.2.3 From 0456ecf34d466261970e0ff92b2b9c78a4908637 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 22 Jul 2020 16:50:44 +0100 Subject: iio:light:si1145: Fix timestamp alignment and prevent data leak. One of a class of bugs pointed out by Lars in a recent review. iio_push_to_buffers_with_timestamp assumes the buffer used is aligned to the size of the timestamp (8 bytes). This is not guaranteed in this driver which uses a 24 byte array of smaller elements on the stack. As Lars also noted this anti pattern can involve a leak of data to userspace and that indeed can happen here. We close both issues by moving to a suitable array in the iio_priv() data with alignment explicitly requested. This data is allocated with kzalloc so no data can leak appart from previous readings. Depending on the enabled channels, the location of the timestamp can be at various aligned offsets through the buffer. As such we any use of a structure to enforce this alignment would incorrectly suggest a single location for the timestamp. Comments adjusted to express this clearly in the code. Fixes: ac45e57f1590 ("iio: light: Add driver for Silabs si1132, si1141/2/3 and si1145/6/7 ambient light, uv index and proximity sensors") Reported-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Peter Meerwald-Stadler Cc: Link: https://lore.kernel.org/r/20200722155103.979802-9-jic23@kernel.org --- drivers/iio/light/si1145.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/light/si1145.c b/drivers/iio/light/si1145.c index 155faaea8c72..087ef953041d 100644 --- a/drivers/iio/light/si1145.c +++ b/drivers/iio/light/si1145.c @@ -168,6 +168,7 @@ struct si1145_part_info { * @part_info: Part information * @trig: Pointer to iio trigger * @meas_rate: Value of MEAS_RATE register. Only set in HW in auto mode + * @buffer: Used to pack data read from sensor. */ struct si1145_data { struct i2c_client *client; @@ -179,6 +180,14 @@ struct si1145_data { bool autonomous; struct iio_trigger *trig; int meas_rate; + /* + * Ensure timestamp will be naturally aligned if present. + * Maximum buffer size (may be only partly used if not all + * channels are enabled): + * 6*2 bytes channels data + 4 bytes alignment + + * 8 bytes timestamp + */ + u8 buffer[24] __aligned(8); }; /* @@ -440,12 +449,6 @@ static irqreturn_t si1145_trigger_handler(int irq, void *private) struct iio_poll_func *pf = private; struct iio_dev *indio_dev = pf->indio_dev; struct si1145_data *data = iio_priv(indio_dev); - /* - * Maximum buffer size: - * 6*2 bytes channels data + 4 bytes alignment + - * 8 bytes timestamp - */ - u8 buffer[24]; int i, j = 0; int ret; u8 irq_status = 0; @@ -478,7 +481,7 @@ static irqreturn_t si1145_trigger_handler(int irq, void *private) ret = i2c_smbus_read_i2c_block_data_or_emulated( data->client, indio_dev->channels[i].address, - sizeof(u16) * run, &buffer[j]); + sizeof(u16) * run, &data->buffer[j]); if (ret < 0) goto done; j += run * sizeof(u16); @@ -493,7 +496,7 @@ static irqreturn_t si1145_trigger_handler(int irq, void *private) goto done; } - iio_push_to_buffers_with_timestamp(indio_dev, buffer, + iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, iio_get_time_ns(indio_dev)); done: -- cgit v1.2.3 From c14edb4d0bdc53f969ea84c7f384472c28b1a9f8 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 22 Jul 2020 16:50:52 +0100 Subject: iio:imu:st_lsm6dsx Fix alignment and data leak issues One of a class of bugs pointed out by Lars in a recent review. iio_push_to_buffers_with_timestamp assumes the buffer used is aligned to the size of the timestamp (8 bytes). This is not guaranteed in this driver which uses an array of smaller elements on the stack. As Lars also noted this anti pattern can involve a leak of data to userspace and that indeed can happen here. We close both issues by moving to an array of suitable structures in the iio_priv() data. This data is allocated with kzalloc so no data can leak apart from previous readings. For the tagged path the data is aligned by using __aligned(8) for the buffer on the stack. There has been a lot of churn in this driver, so likely backports may be needed for stable. Fixes: 290a6ce11d93 ("iio: imu: add support to lsm6dsx driver") Reported-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Lorenzo Bianconi Cc: Link: https://lore.kernel.org/r/20200722155103.979802-17-jic23@kernel.org --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 6 ++++ drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 42 ++++++++++++++++---------- 2 files changed, 32 insertions(+), 16 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index d80ba2e688ed..9275346a9cc1 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -383,6 +383,7 @@ struct st_lsm6dsx_sensor { * @iio_devs: Pointers to acc/gyro iio_dev instances. * @settings: Pointer to the specific sensor settings in use. * @orientation: sensor chip orientation relative to main hardware. + * @scan: Temporary buffers used to align data before iio_push_to_buffers() */ struct st_lsm6dsx_hw { struct device *dev; @@ -411,6 +412,11 @@ struct st_lsm6dsx_hw { const struct st_lsm6dsx_settings *settings; struct iio_mount_matrix orientation; + /* Ensure natural alignment of buffer elements */ + struct { + __le16 channels[3]; + s64 ts __aligned(8); + } scan[3]; }; static __maybe_unused const struct iio_event_spec st_lsm6dsx_event = { diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c index 7de10bd636ea..12ed0a2e55e4 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -353,9 +353,6 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) int err, sip, acc_sip, gyro_sip, ts_sip, ext_sip, read_len, offset; u16 fifo_len, pattern_len = hw->sip * ST_LSM6DSX_SAMPLE_SIZE; u16 fifo_diff_mask = hw->settings->fifo_ops.fifo_diff.mask; - u8 gyro_buff[ST_LSM6DSX_IIO_BUFF_SIZE]; - u8 acc_buff[ST_LSM6DSX_IIO_BUFF_SIZE]; - u8 ext_buff[ST_LSM6DSX_IIO_BUFF_SIZE]; bool reset_ts = false; __le16 fifo_status; s64 ts = 0; @@ -416,19 +413,22 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) while (acc_sip > 0 || gyro_sip > 0 || ext_sip > 0) { if (gyro_sip > 0 && !(sip % gyro_sensor->decimator)) { - memcpy(gyro_buff, &hw->buff[offset], - ST_LSM6DSX_SAMPLE_SIZE); - offset += ST_LSM6DSX_SAMPLE_SIZE; + memcpy(hw->scan[ST_LSM6DSX_ID_GYRO].channels, + &hw->buff[offset], + sizeof(hw->scan[ST_LSM6DSX_ID_GYRO].channels)); + offset += sizeof(hw->scan[ST_LSM6DSX_ID_GYRO].channels); } if (acc_sip > 0 && !(sip % acc_sensor->decimator)) { - memcpy(acc_buff, &hw->buff[offset], - ST_LSM6DSX_SAMPLE_SIZE); - offset += ST_LSM6DSX_SAMPLE_SIZE; + memcpy(hw->scan[ST_LSM6DSX_ID_ACC].channels, + &hw->buff[offset], + sizeof(hw->scan[ST_LSM6DSX_ID_ACC].channels)); + offset += sizeof(hw->scan[ST_LSM6DSX_ID_ACC].channels); } if (ext_sip > 0 && !(sip % ext_sensor->decimator)) { - memcpy(ext_buff, &hw->buff[offset], - ST_LSM6DSX_SAMPLE_SIZE); - offset += ST_LSM6DSX_SAMPLE_SIZE; + memcpy(hw->scan[ST_LSM6DSX_ID_EXT0].channels, + &hw->buff[offset], + sizeof(hw->scan[ST_LSM6DSX_ID_EXT0].channels)); + offset += sizeof(hw->scan[ST_LSM6DSX_ID_EXT0].channels); } if (ts_sip-- > 0) { @@ -458,19 +458,22 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) if (gyro_sip > 0 && !(sip % gyro_sensor->decimator)) { iio_push_to_buffers_with_timestamp( hw->iio_devs[ST_LSM6DSX_ID_GYRO], - gyro_buff, gyro_sensor->ts_ref + ts); + &hw->scan[ST_LSM6DSX_ID_GYRO], + gyro_sensor->ts_ref + ts); gyro_sip--; } if (acc_sip > 0 && !(sip % acc_sensor->decimator)) { iio_push_to_buffers_with_timestamp( hw->iio_devs[ST_LSM6DSX_ID_ACC], - acc_buff, acc_sensor->ts_ref + ts); + &hw->scan[ST_LSM6DSX_ID_ACC], + acc_sensor->ts_ref + ts); acc_sip--; } if (ext_sip > 0 && !(sip % ext_sensor->decimator)) { iio_push_to_buffers_with_timestamp( hw->iio_devs[ST_LSM6DSX_ID_EXT0], - ext_buff, ext_sensor->ts_ref + ts); + &hw->scan[ST_LSM6DSX_ID_EXT0], + ext_sensor->ts_ref + ts); ext_sip--; } sip++; @@ -555,7 +558,14 @@ int st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw) { u16 pattern_len = hw->sip * ST_LSM6DSX_TAGGED_SAMPLE_SIZE; u16 fifo_len, fifo_diff_mask; - u8 iio_buff[ST_LSM6DSX_IIO_BUFF_SIZE], tag; + /* + * Alignment needed as this can ultimately be passed to a + * call to iio_push_to_buffers_with_timestamp() which + * must be passed a buffer that is aligned to 8 bytes so + * as to allow insertion of a naturally aligned timestamp. + */ + u8 iio_buff[ST_LSM6DSX_IIO_BUFF_SIZE] __aligned(8); + u8 tag; bool reset_ts = false; int i, err, read_len; __le16 fifo_status; -- cgit v1.2.3 From 39e91f3be4cba51c1560bcda3a343ed1f64dc916 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 22 Jul 2020 16:51:00 +0100 Subject: iio:adc:ti-adc0832 Fix alignment issue with timestamp One of a class of bugs pointed out by Lars in a recent review. iio_push_to_buffers_with_timestamp assumes the buffer used is aligned to the size of the timestamp (8 bytes). This is not guaranteed in this driver which uses an array of smaller elements on the stack. We fix this issues by moving to a suitable structure in the iio_priv() data with alignment explicitly requested. This data is allocated with kzalloc so no data can leak apart from previous readings. Note that previously no data could leak 'including' previous readings but I don't think it is an issue to potentially leak them like this now does. In this case the postioning of the timestamp is depends on what other channels are enabled. As such we cannot use a structure to make the alignment explicit as it would be missleading by suggesting only one possible location for the timestamp. Fixes: 815bbc87462a ("iio: ti-adc0832: add triggered buffer support") Reported-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Akinobu Mita Cc: Link: https://lore.kernel.org/r/20200722155103.979802-25-jic23@kernel.org --- drivers/iio/adc/ti-adc0832.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/ti-adc0832.c b/drivers/iio/adc/ti-adc0832.c index c7a085dce1f4..0261b3cfc92b 100644 --- a/drivers/iio/adc/ti-adc0832.c +++ b/drivers/iio/adc/ti-adc0832.c @@ -29,6 +29,12 @@ struct adc0832 { struct regulator *reg; struct mutex lock; u8 mux_bits; + /* + * Max size needed: 16x 1 byte ADC data + 8 bytes timestamp + * May be shorter if not all channels are enabled subject + * to the timestamp remaining 8 byte aligned. + */ + u8 data[24] __aligned(8); u8 tx_buf[2] ____cacheline_aligned; u8 rx_buf[2]; @@ -200,7 +206,6 @@ static irqreturn_t adc0832_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct adc0832 *adc = iio_priv(indio_dev); - u8 data[24] = { }; /* 16x 1 byte ADC data + 8 bytes timestamp */ int scan_index; int i = 0; @@ -218,10 +223,10 @@ static irqreturn_t adc0832_trigger_handler(int irq, void *p) goto out; } - data[i] = ret; + adc->data[i] = ret; i++; } - iio_push_to_buffers_with_timestamp(indio_dev, data, + iio_push_to_buffers_with_timestamp(indio_dev, adc->data, iio_get_time_ns(indio_dev)); out: mutex_unlock(&adc->lock); -- cgit v1.2.3 From 293e809b2e8e608b65a949101aaf7c0bd1224247 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 22 Jul 2020 16:51:01 +0100 Subject: iio:adc:ti-adc12138 Fix alignment issue with timestamp One of a class of bugs pointed out by Lars in a recent review. iio_push_to_buffers_with_timestamp assumes the buffer used is aligned to the size of the timestamp (8 bytes). This is not guaranteed in this driver which uses an array of smaller elements on the stack. We move to a suitable structure in the iio_priv() data with alignment explicitly requested. This data is allocated with kzalloc so no data can leak apart from previous readings. Note that previously no leak at all could occur, but previous readings should never be a problem. In this case the timestamp location depends on what other channels are enabled. As such we can't use a structure without misleading by suggesting only one possible timestamp location. Fixes: 50a6edb1b6e0 ("iio: adc: add ADC12130/ADC12132/ADC12138 ADC driver") Reported-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Akinobu Mita Cc: Link: https://lore.kernel.org/r/20200722155103.979802-26-jic23@kernel.org --- drivers/iio/adc/ti-adc12138.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/ti-adc12138.c b/drivers/iio/adc/ti-adc12138.c index e485719cd2c4..fcd5d39dd03e 100644 --- a/drivers/iio/adc/ti-adc12138.c +++ b/drivers/iio/adc/ti-adc12138.c @@ -47,6 +47,12 @@ struct adc12138 { struct completion complete; /* The number of cclk periods for the S/H's acquisition time */ unsigned int acquisition_time; + /* + * Maximum size needed: 16x 2 bytes ADC data + 8 bytes timestamp. + * Less may be need if not all channels are enabled, as long as + * the 8 byte alignment of the timestamp is maintained. + */ + __be16 data[20] __aligned(8); u8 tx_buf[2] ____cacheline_aligned; u8 rx_buf[2]; @@ -329,7 +335,6 @@ static irqreturn_t adc12138_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct adc12138 *adc = iio_priv(indio_dev); - __be16 data[20] = { }; /* 16x 2 bytes ADC data + 8 bytes timestamp */ __be16 trash; int ret; int scan_index; @@ -345,7 +350,7 @@ static irqreturn_t adc12138_trigger_handler(int irq, void *p) reinit_completion(&adc->complete); ret = adc12138_start_and_read_conv(adc, scan_chan, - i ? &data[i - 1] : &trash); + i ? &adc->data[i - 1] : &trash); if (ret) { dev_warn(&adc->spi->dev, "failed to start conversion\n"); @@ -362,7 +367,7 @@ static irqreturn_t adc12138_trigger_handler(int irq, void *p) } if (i) { - ret = adc12138_read_conv_data(adc, &data[i - 1]); + ret = adc12138_read_conv_data(adc, &adc->data[i - 1]); if (ret) { dev_warn(&adc->spi->dev, "failed to get conversion data\n"); @@ -370,7 +375,7 @@ static irqreturn_t adc12138_trigger_handler(int irq, void *p) } } - iio_push_to_buffers_with_timestamp(indio_dev, data, + iio_push_to_buffers_with_timestamp(indio_dev, adc->data, iio_get_time_ns(indio_dev)); out: mutex_unlock(&adc->lock); -- cgit v1.2.3 From 6b0cc5dce0725ae8f1a2883514da731c55eeb35e Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 22 Jul 2020 16:50:53 +0100 Subject: iio:imu:inv_mpu6050 Fix dma and ts alignment and data leak issues. This case is a bit different to the rest of the series. The driver was doing a regmap_bulk_read into a buffer that wasn't dma safe as it was on the stack with no guarantee of it being in a cacheline on it's own. Fixing that also dealt with the data leak and alignment issues that Lars-Peter pointed out. Also removed some unaligned handling as we are now aligned. Fixes tag is for the dma safe buffer issue. Potentially we would need to backport timestamp alignment futher but that is a totally different patch. Fixes: fd64df16f40e ("iio: imu: inv_mpu6050: Add SPI support for MPU6000") Reported-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Reviewed-by: Jean-Baptiste Maneyrol Cc: Link: https://lore.kernel.org/r/20200722155103.979802-18-jic23@kernel.org --- drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 12 +++++++++--- drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 12 +++++------- 2 files changed, 14 insertions(+), 10 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index cd38b3fccc7b..eb522b38acf3 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -122,6 +122,13 @@ struct inv_mpu6050_chip_config { u8 user_ctrl; }; +/* + * Maximum of 6 + 6 + 2 + 7 (for MPU9x50) = 21 round up to 24 and plus 8. + * May be less if fewer channels are enabled, as long as the timestamp + * remains 8 byte aligned + */ +#define INV_MPU6050_OUTPUT_DATA_SIZE 32 + /** * struct inv_mpu6050_hw - Other important hardware information. * @whoami: Self identification byte from WHO_AM_I register @@ -165,6 +172,7 @@ struct inv_mpu6050_hw { * @magn_raw_to_gauss: coefficient to convert mag raw value to Gauss. * @magn_orient: magnetometer sensor chip orientation if available. * @suspended_sensors: sensors mask of sensors turned off for suspend + * @data: dma safe buffer used for bulk reads. */ struct inv_mpu6050_state { struct mutex lock; @@ -190,6 +198,7 @@ struct inv_mpu6050_state { s32 magn_raw_to_gauss[3]; struct iio_mount_matrix magn_orient; unsigned int suspended_sensors; + u8 data[INV_MPU6050_OUTPUT_DATA_SIZE] ____cacheline_aligned; }; /*register and associated bit definition*/ @@ -334,9 +343,6 @@ struct inv_mpu6050_state { #define INV_ICM20608_TEMP_OFFSET 8170 #define INV_ICM20608_TEMP_SCALE 3059976 -/* 6 + 6 + 2 + 7 (for MPU9x50) = 21 round up to 24 and plus 8 */ -#define INV_MPU6050_OUTPUT_DATA_SIZE 32 - #define INV_MPU6050_REG_INT_PIN_CFG 0x37 #define INV_MPU6050_ACTIVE_HIGH 0x00 #define INV_MPU6050_ACTIVE_LOW 0x80 diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c index b533fa2dad0a..d8e6b88ddffc 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "inv_mpu_iio.h" /** @@ -121,7 +120,6 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) struct inv_mpu6050_state *st = iio_priv(indio_dev); size_t bytes_per_datum; int result; - u8 data[INV_MPU6050_OUTPUT_DATA_SIZE]; u16 fifo_count; s64 timestamp; int int_status; @@ -160,11 +158,11 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) * read fifo_count register to know how many bytes are inside the FIFO * right now */ - result = regmap_bulk_read(st->map, st->reg->fifo_count_h, data, - INV_MPU6050_FIFO_COUNT_BYTE); + result = regmap_bulk_read(st->map, st->reg->fifo_count_h, + st->data, INV_MPU6050_FIFO_COUNT_BYTE); if (result) goto end_session; - fifo_count = get_unaligned_be16(&data[0]); + fifo_count = be16_to_cpup((__be16 *)&st->data[0]); /* * Handle fifo overflow by resetting fifo. @@ -182,7 +180,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) inv_mpu6050_update_period(st, pf->timestamp, nb); for (i = 0; i < nb; ++i) { result = regmap_bulk_read(st->map, st->reg->fifo_r_w, - data, bytes_per_datum); + st->data, bytes_per_datum); if (result) goto flush_fifo; /* skip first samples if needed */ @@ -191,7 +189,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) continue; } timestamp = inv_mpu6050_get_timestamp(st); - iio_push_to_buffers_with_timestamp(indio_dev, data, timestamp); + iio_push_to_buffers_with_timestamp(indio_dev, st->data, timestamp); } end_session: -- cgit v1.2.3 From da83df66265b79c956f556b97554a0f23431c11f Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 22 Jul 2020 16:50:54 +0100 Subject: iio:imu:inv_mpu6050: Use regmap_noinc_read for fifo reads. We should not be assuming that we are reading a sequence of registers as here we are doing a read of a lot of data from a single register address. Not marked for stable as by coincidence it being wrong doesn't make any difference. Suggested-by: Jean-Baptiste Maneyrol Signed-off-by: Jonathan Cameron Reviewed-by: Jean-Baptiste Maneyrol Link: https://lore.kernel.org/r/20200722155103.979802-19-jic23@kernel.org --- drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c index d8e6b88ddffc..45c37525c2f1 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c @@ -179,8 +179,8 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) nb = fifo_count / bytes_per_datum; inv_mpu6050_update_period(st, pf->timestamp, nb); for (i = 0; i < nb; ++i) { - result = regmap_bulk_read(st->map, st->reg->fifo_r_w, - st->data, bytes_per_datum); + result = regmap_noinc_read(st->map, st->reg->fifo_r_w, + st->data, bytes_per_datum); if (result) goto flush_fifo; /* skip first samples if needed */ -- cgit v1.2.3 From 1f026587a57cfd62dd4495d8fb508edcf1453329 Mon Sep 17 00:00:00 2001 From: Wang Qing Date: Tue, 22 Sep 2020 19:06:56 +0800 Subject: iio:light:gp2ap002 fix spelling typo in comments Change the comment typo: "definately" -> "definitely". Signed-off-by: Wang Qing Link: https://lore.kernel.org/r/1600772818-30882-1-git-send-email-wangqing@vivo.com Signed-off-by: Jonathan Cameron --- drivers/iio/light/gp2ap002.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/light/gp2ap002.c b/drivers/iio/light/gp2ap002.c index d5e1cd27eb46..7ba7aa59437c 100644 --- a/drivers/iio/light/gp2ap002.c +++ b/drivers/iio/light/gp2ap002.c @@ -566,7 +566,7 @@ static int gp2ap002_probe(struct i2c_client *client, /* * Initialize the device and signal to runtime PM that now we are - * definately up and using power. + * definitely up and using power. */ ret = gp2ap002_init(gp2ap002); if (ret) { -- cgit v1.2.3 From f2f45a53646fbe026f12f8b64be6a5def1591384 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 21 Sep 2020 13:31:55 +0300 Subject: iio: event: use short-hand variable in iio_device_{un}register_eventset functions With the recent 'iio_dev_opaque' variable name, these two functions are looking a bit ugly. This change uses an 'ev_int' variable for the iio_device_{un}register_eventset functions to make the code a little easier to read. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20200921103156.194748-1-alexandru.ardelean@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-event.c | 50 +++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 26 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index 2ab4d4c44427..a85919eb7c4a 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -477,6 +477,7 @@ static const char *iio_event_group_name = "events"; int iio_device_register_eventset(struct iio_dev *indio_dev) { struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); + struct iio_event_interface *ev_int; struct iio_dev_attr *p; int ret = 0, attrcount_orig = 0, attrcount, attrn; struct attribute **attr; @@ -485,14 +486,15 @@ int iio_device_register_eventset(struct iio_dev *indio_dev) iio_check_for_dynamic_events(indio_dev))) return 0; - iio_dev_opaque->event_interface = - kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL); - if (iio_dev_opaque->event_interface == NULL) + ev_int = kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL); + if (ev_int == NULL) return -ENOMEM; - INIT_LIST_HEAD(&iio_dev_opaque->event_interface->dev_attr_list); + iio_dev_opaque->event_interface = ev_int; + + INIT_LIST_HEAD(&ev_int->dev_attr_list); - iio_setup_ev_int(iio_dev_opaque->event_interface); + iio_setup_ev_int(ev_int); if (indio_dev->info->event_attrs != NULL) { attr = indio_dev->info->event_attrs->attrs; while (*attr++ != NULL) @@ -506,34 +508,29 @@ int iio_device_register_eventset(struct iio_dev *indio_dev) attrcount += ret; } - iio_dev_opaque->event_interface->group.name = iio_event_group_name; - iio_dev_opaque->event_interface->group.attrs = kcalloc(attrcount + 1, - sizeof(iio_dev_opaque->event_interface->group.attrs[0]), - GFP_KERNEL); - if (iio_dev_opaque->event_interface->group.attrs == NULL) { + ev_int->group.name = iio_event_group_name; + ev_int->group.attrs = kcalloc(attrcount + 1, + sizeof(ev_int->group.attrs[0]), + GFP_KERNEL); + if (ev_int->group.attrs == NULL) { ret = -ENOMEM; goto error_free_setup_event_lines; } if (indio_dev->info->event_attrs) - memcpy(iio_dev_opaque->event_interface->group.attrs, + memcpy(ev_int->group.attrs, indio_dev->info->event_attrs->attrs, - sizeof(iio_dev_opaque->event_interface->group.attrs[0]) - *attrcount_orig); + sizeof(ev_int->group.attrs[0]) * attrcount_orig); attrn = attrcount_orig; /* Add all elements from the list. */ - list_for_each_entry(p, - &iio_dev_opaque->event_interface->dev_attr_list, - l) - iio_dev_opaque->event_interface->group.attrs[attrn++] = - &p->dev_attr.attr; - indio_dev->groups[indio_dev->groupcounter++] = - &iio_dev_opaque->event_interface->group; + list_for_each_entry(p, &ev_int->dev_attr_list, l) + ev_int->group.attrs[attrn++] = &p->dev_attr.attr; + indio_dev->groups[indio_dev->groupcounter++] = &ev_int->group; return 0; error_free_setup_event_lines: - iio_free_chan_devattr_list(&iio_dev_opaque->event_interface->dev_attr_list); - kfree(iio_dev_opaque->event_interface); + iio_free_chan_devattr_list(&ev_int->dev_attr_list); + kfree(ev_int); iio_dev_opaque->event_interface = NULL; return ret; } @@ -557,10 +554,11 @@ void iio_device_wakeup_eventset(struct iio_dev *indio_dev) void iio_device_unregister_eventset(struct iio_dev *indio_dev) { struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); + struct iio_event_interface *ev_int = iio_dev_opaque->event_interface; - if (iio_dev_opaque->event_interface == NULL) + if (ev_int == NULL) return; - iio_free_chan_devattr_list(&iio_dev_opaque->event_interface->dev_attr_list); - kfree(iio_dev_opaque->event_interface->group.attrs); - kfree(iio_dev_opaque->event_interface); + iio_free_chan_devattr_list(&ev_int->dev_attr_list); + kfree(ev_int->group.attrs); + kfree(ev_int); } -- cgit v1.2.3 From a3598d14dc571b484529956b33f3fdd9d2b2b97e Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 21 Sep 2020 13:31:56 +0300 Subject: iio: event: NULL-ify IIO device's event_interface ref during unregister Though we know that the iio_device_unregister_eventset() call is followed by the free-ing of the IIO device object, we should not make this assumption in the iio_device_unregister_eventset() function. It should allow for the clean unregistering of the event-set, allowing a re-register should we decide to implement this at some point later. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20200921103156.194748-2-alexandru.ardelean@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-event.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/iio') diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index a85919eb7c4a..99ba657b8568 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -561,4 +561,5 @@ void iio_device_unregister_eventset(struct iio_dev *indio_dev) iio_free_chan_devattr_list(&ev_int->dev_attr_list); kfree(ev_int->group.attrs); kfree(ev_int); + iio_dev_opaque->event_interface = NULL; } -- cgit v1.2.3 From 48404cf57852224c052e2e40d4dc50dd398c7a58 Mon Sep 17 00:00:00 2001 From: Michael Auchter Date: Tue, 22 Sep 2020 09:44:20 -0500 Subject: iio: adc: ad7291: convert to device tree There are no in-tree users of the platform data for this driver, so remove it and convert the driver to use device tree instead. Signed-off-by: Michael Auchter Link: https://lore.kernel.org/r/20200922144422.542669-1-michael.auchter@ni.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7291.c | 35 +++++++++++++++++++++-------------- include/linux/platform_data/ad7291.h | 13 ------------- 2 files changed, 21 insertions(+), 27 deletions(-) delete mode 100644 include/linux/platform_data/ad7291.h (limited to 'drivers/iio') diff --git a/drivers/iio/adc/ad7291.c b/drivers/iio/adc/ad7291.c index 62fde2aad282..2301a0e27f23 100644 --- a/drivers/iio/adc/ad7291.c +++ b/drivers/iio/adc/ad7291.c @@ -20,8 +20,6 @@ #include #include -#include - /* * Simplified handling * @@ -465,7 +463,6 @@ static const struct iio_info ad7291_info = { static int ad7291_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct ad7291_platform_data *pdata = client->dev.platform_data; struct ad7291_chip_info *chip; struct iio_dev *indio_dev; int ret; @@ -475,16 +472,6 @@ static int ad7291_probe(struct i2c_client *client, return -ENOMEM; chip = iio_priv(indio_dev); - if (pdata && pdata->use_external_ref) { - chip->reg = devm_regulator_get(&client->dev, "vref"); - if (IS_ERR(chip->reg)) - return PTR_ERR(chip->reg); - - ret = regulator_enable(chip->reg); - if (ret) - return ret; - } - mutex_init(&chip->state_lock); /* this is only used for device removal purposes */ i2c_set_clientdata(client, indio_dev); @@ -495,8 +482,21 @@ static int ad7291_probe(struct i2c_client *client, AD7291_T_SENSE_MASK | /* Tsense always enabled */ AD7291_ALERT_POLARITY; /* set irq polarity low level */ - if (pdata && pdata->use_external_ref) + chip->reg = devm_regulator_get_optional(&client->dev, "vref"); + if (IS_ERR(chip->reg)) { + if (PTR_ERR(chip->reg) != -ENODEV) + return PTR_ERR(chip->reg); + + chip->reg = NULL; + } + + if (chip->reg) { + ret = regulator_enable(chip->reg); + if (ret) + return ret; + chip->command |= AD7291_EXT_REF; + } indio_dev->name = id->name; indio_dev->channels = ad7291_channels; @@ -567,9 +567,16 @@ static const struct i2c_device_id ad7291_id[] = { MODULE_DEVICE_TABLE(i2c, ad7291_id); +static const struct of_device_id ad7291_of_match[] = { + { .compatible = "adi,ad7291" }, + {} +}; +MODULE_DEVICE_TABLE(of, ad7291_of_match); + static struct i2c_driver ad7291_driver = { .driver = { .name = KBUILD_MODNAME, + .of_match_table = ad7291_of_match, }, .probe = ad7291_probe, .remove = ad7291_remove, diff --git a/include/linux/platform_data/ad7291.h b/include/linux/platform_data/ad7291.h deleted file mode 100644 index b1fd1530c9a5..000000000000 --- a/include/linux/platform_data/ad7291.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __IIO_AD7291_H__ -#define __IIO_AD7291_H__ - -/** - * struct ad7291_platform_data - AD7291 platform data - * @use_external_ref: Whether to use an external or internal reference voltage - */ -struct ad7291_platform_data { - bool use_external_ref; -}; - -#endif -- cgit v1.2.3 From 4c6e3dbc6b4877c77ea329f7ae813971854c035b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 21 Sep 2020 22:49:39 +0200 Subject: iio: ssp: use PLATFORM_DEVID_NONE Use PLATFORM_DEVID_NONE define instead of "-1" value because: - it brings some meaning, - it might point attention why auto device ID was not used. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200921204939.20341-1-krzk@kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/common/ssp_sensors/ssp_dev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/common/ssp_sensors/ssp_dev.c b/drivers/iio/common/ssp_sensors/ssp_dev.c index a94dbcf491ce..1aee87100038 100644 --- a/drivers/iio/common/ssp_sensors/ssp_dev.c +++ b/drivers/iio/common/ssp_sensors/ssp_dev.c @@ -503,7 +503,8 @@ static int ssp_probe(struct spi_device *spi) return -ENODEV; } - ret = mfd_add_devices(&spi->dev, -1, sensorhub_sensor_devs, + ret = mfd_add_devices(&spi->dev, PLATFORM_DEVID_NONE, + sensorhub_sensor_devs, ARRAY_SIZE(sensorhub_sensor_devs), NULL, 0, NULL); if (ret < 0) { dev_err(&spi->dev, "mfd add devices fail\n"); -- cgit v1.2.3 From cbc4ca3525777f3934bd5684e8ec908135dcbcd4 Mon Sep 17 00:00:00 2001 From: Wang ShaoBo Date: Fri, 18 Sep 2020 16:28:37 +0800 Subject: iio: adc: at91-sama5d2_adc: Use devm_platform_get_and_ioremap_resource() Make use of devm_platform_get_and_ioremap_resource() provided by driver core platform instead of duplicated analogue. Signed-off-by: Wang ShaoBo Link: https://lore.kernel.org/r/20200918082837.32610-1-bobo.shaobowang@huawei.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91-sama5d2_adc.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index de9583d6cddd..ad7d9819f83c 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -1764,17 +1764,13 @@ static int at91_adc_probe(struct platform_device *pdev) mutex_init(&st->lock); INIT_WORK(&st->touch_st.workq, at91_adc_workq_handler); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -EINVAL; + st->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(st->base)) + return PTR_ERR(st->base); /* if we plan to use DMA, we need the physical address of the regs */ st->dma_st.phys_addr = res->start; - st->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(st->base)) - return PTR_ERR(st->base); - st->irq = platform_get_irq(pdev, 0); if (st->irq <= 0) { if (!st->irq) -- cgit v1.2.3 From 57e5b8bfd633b9237f0072ef8faeef9545a61ea1 Mon Sep 17 00:00:00 2001 From: Wang ShaoBo Date: Fri, 18 Sep 2020 16:31:42 +0800 Subject: iio: adc: stm32-dfsdm: Use devm_platform_get_and_ioremap_resource() Make use of devm_platform_get_and_ioremap_resource() provided by driver core platform instead of duplicated analogue, dev_err() is removed because it has been done in devm_ioremap_resource(). Signed-off-by: Wang ShaoBo Link: https://lore.kernel.org/r/20200918083142.32816-1-bobo.shaobowang@huawei.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stm32-dfsdm-core.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/stm32-dfsdm-core.c b/drivers/iio/adc/stm32-dfsdm-core.c index 0b8bea88b011..42a7377704a4 100644 --- a/drivers/iio/adc/stm32-dfsdm-core.c +++ b/drivers/iio/adc/stm32-dfsdm-core.c @@ -226,16 +226,13 @@ static int stm32_dfsdm_parse_of(struct platform_device *pdev, if (!node) return -EINVAL; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "Failed to get memory resource\n"); - return -ENODEV; - } - priv->dfsdm.phys_base = res->start; - priv->dfsdm.base = devm_ioremap_resource(&pdev->dev, res); + priv->dfsdm.base = devm_platform_get_and_ioremap_resource(pdev, 0, + &res); if (IS_ERR(priv->dfsdm.base)) return PTR_ERR(priv->dfsdm.base); + priv->dfsdm.phys_base = res->start; + /* * "dfsdm" clock is mandatory for DFSDM peripheral clocking. * "dfsdm" or "audio" clocks can be used as source clock for -- cgit v1.2.3 From 25918a9c641c3c73ae94354605860c06fd73a05e Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Wed, 23 Sep 2020 15:18:10 +0300 Subject: iio: buffer-dmaengine: remove non managed alloc/free This is to encourage the use of devm_iio_dmaengine_buffer_alloc(). Currently the managed version of the DMAEngine buffer alloc is the only function used from this part of the framework. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20200923121810.944075-1-alexandru.ardelean@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/buffer/industrialio-buffer-dmaengine.c | 6 ++---- include/linux/iio/buffer-dmaengine.h | 4 ---- 2 files changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c index 5789bda0745b..93b4e9e6bb55 100644 --- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c +++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c @@ -159,7 +159,7 @@ static const struct attribute *iio_dmaengine_buffer_attrs[] = { * Once done using the buffer iio_dmaengine_buffer_free() should be used to * release it. */ -struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev, +static struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev, const char *channel) { struct dmaengine_buffer *dmaengine_buffer; @@ -211,7 +211,6 @@ err_free: kfree(dmaengine_buffer); return ERR_PTR(ret); } -EXPORT_SYMBOL(iio_dmaengine_buffer_alloc); /** * iio_dmaengine_buffer_free() - Free dmaengine buffer @@ -219,7 +218,7 @@ EXPORT_SYMBOL(iio_dmaengine_buffer_alloc); * * Frees a buffer previously allocated with iio_dmaengine_buffer_alloc(). */ -void iio_dmaengine_buffer_free(struct iio_buffer *buffer) +static void iio_dmaengine_buffer_free(struct iio_buffer *buffer) { struct dmaengine_buffer *dmaengine_buffer = iio_buffer_to_dmaengine_buffer(buffer); @@ -229,7 +228,6 @@ void iio_dmaengine_buffer_free(struct iio_buffer *buffer) iio_buffer_put(buffer); } -EXPORT_SYMBOL_GPL(iio_dmaengine_buffer_free); static void __devm_iio_dmaengine_buffer_free(struct device *dev, void *res) { diff --git a/include/linux/iio/buffer-dmaengine.h b/include/linux/iio/buffer-dmaengine.h index 0e503db71289..5b502291d6a4 100644 --- a/include/linux/iio/buffer-dmaengine.h +++ b/include/linux/iio/buffer-dmaengine.h @@ -10,10 +10,6 @@ struct iio_buffer; struct device; -struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev, - const char *channel); -void iio_dmaengine_buffer_free(struct iio_buffer *buffer); - struct iio_buffer *devm_iio_dmaengine_buffer_alloc(struct device *dev, const char *channel); -- cgit v1.2.3 From 337dbb6ec1acc2e0c7f16b08ddd670faf204fcc8 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Thu, 24 Sep 2020 11:05:15 +0300 Subject: iio: adc: ad9467: wrap a axi-adc chip-info into a ad9467_chip_info type There are 2 chip constants that can be added to the chip-info part. The default output-mode and the VREF mask. When adding new chips to this driver, these can be easily omitted, because these also need to be updated in 2 switch statements. However, if adding them in the chip-info constants, they are updated in a single place and propagated in both switch statements. Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron Link: https://lore.kernel.org/r/20200924080518.96410-2-alexandru.ardelean@analog.com --- drivers/iio/adc/ad9467.c | 62 ++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 33 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c index f068256cfca9..85f5a014bd2d 100644 --- a/drivers/iio/adc/ad9467.c +++ b/drivers/iio/adc/ad9467.c @@ -88,6 +88,15 @@ enum { ID_AD9467, }; +struct ad9467_chip_info { + struct adi_axi_adc_chip_info axi_adc_info; + unsigned int default_output_mode; + unsigned int vref_mask; +}; + +#define to_ad9467_chip_info(_info) \ + container_of(_info, struct ad9467_chip_info, axi_adc_info) + struct ad9467_state { struct spi_device *spi; struct clk *clk; @@ -186,35 +195,31 @@ static const struct iio_chan_spec ad9467_channels[] = { AD9467_CHAN(0, 0, 16, 'S'), }; -static const struct adi_axi_adc_chip_info ad9467_chip_tbl[] = { +static const struct ad9467_chip_info ad9467_chip_tbl[] = { [ID_AD9467] = { - .id = CHIPID_AD9467, - .max_rate = 250000000UL, - .scale_table = ad9467_scale_table, - .num_scales = ARRAY_SIZE(ad9467_scale_table), - .channels = ad9467_channels, - .num_channels = ARRAY_SIZE(ad9467_channels), + .axi_adc_info = { + .id = CHIPID_AD9467, + .max_rate = 250000000UL, + .scale_table = ad9467_scale_table, + .num_scales = ARRAY_SIZE(ad9467_scale_table), + .channels = ad9467_channels, + .num_channels = ARRAY_SIZE(ad9467_channels), + }, + .default_output_mode = AD9467_DEF_OUTPUT_MODE, + .vref_mask = AD9467_REG_VREF_MASK, }, }; static int ad9467_get_scale(struct adi_axi_adc_conv *conv, int *val, int *val2) { const struct adi_axi_adc_chip_info *info = conv->chip_info; + const struct ad9467_chip_info *info1 = to_ad9467_chip_info(info); struct ad9467_state *st = adi_axi_adc_conv_priv(conv); - unsigned int i, vref_val, vref_mask; + unsigned int i, vref_val; vref_val = ad9467_spi_read(st->spi, AN877_ADC_REG_VREF); - switch (info->id) { - case CHIPID_AD9467: - vref_mask = AD9467_REG_VREF_MASK; - break; - default: - vref_mask = 0xFFFF; - break; - } - - vref_val &= vref_mask; + vref_val &= info1->vref_mask; for (i = 0; i < info->num_scales; i++) { if (vref_val == info->scale_table[i][1]) @@ -316,18 +321,6 @@ static int ad9467_preenable_setup(struct adi_axi_adc_conv *conv) return ad9467_outputmode_set(st->spi, st->output_mode); } -static int ad9467_setup(struct ad9467_state *st, unsigned int chip_id) -{ - switch (chip_id) { - case CHIPID_AD9467: - st->output_mode = AD9467_DEF_OUTPUT_MODE | - AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT; - return 0; - default: - return -ENODEV; - } -} - static void ad9467_clk_disable(void *data) { struct ad9467_state *st = data; @@ -337,7 +330,7 @@ static void ad9467_clk_disable(void *data) static int ad9467_probe(struct spi_device *spi) { - const struct adi_axi_adc_chip_info *info; + const struct ad9467_chip_info *info; struct adi_axi_adc_conv *conv; struct ad9467_state *st; unsigned int id; @@ -386,7 +379,7 @@ static int ad9467_probe(struct spi_device *spi) spi_set_drvdata(spi, st); - conv->chip_info = info; + conv->chip_info = &info->axi_adc_info; id = ad9467_spi_read(spi, AN877_ADC_REG_CHIP_ID); if (id != conv->chip_info->id) { @@ -400,7 +393,10 @@ static int ad9467_probe(struct spi_device *spi) conv->read_raw = ad9467_read_raw; conv->preenable_setup = ad9467_preenable_setup; - return ad9467_setup(st, id); + st->output_mode = info->default_output_mode | + AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT; + + return 0; } static const struct of_device_id ad9467_of_match[] = { -- cgit v1.2.3 From 4606d0f4b05faad88fdf8472d7b2f0d600546f5e Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 24 Sep 2020 11:05:16 +0300 Subject: iio: adc: ad9467: add support for AD9434 high-speed ADC The AD9434 is a 12-bit monolithic sampling analog-to-digital converter (ADC) optimized for high performance, low power, and ease of use. The part operates at up to a 500 MSPS conversion rate and is optimized for outstanding dynamic performance in wideband carrier and broadband systems. All necessary functions, including a sample-and-hold and voltage reference, are included on the chip to provide a complete signal conversion solution. The VREF pin can be used to monitor the internal reference or provide an external voltage reference (external reference mode must be enabled through the SPI port). The ADC requires a 1.8 V analog voltage supply and a differential clock for full performance operation. The digital outputs are LVDS (ANSI-644) compatible and support twos complement, offset binary format, or Gray code. A data clock output is available for proper output data timing. Link: https://www.analog.com/media/en/technical-documentation/data-sheets/AD9434.pdf The driver supports the same register set as the AD9467, so the support for this chip is added to the 'ad9467' driver. Signed-off-by: Michael Hennerich Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron Link: https://lore.kernel.org/r/20200924080518.96410-3-alexandru.ardelean@analog.com --- drivers/iio/adc/ad9467.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c index 85f5a014bd2d..54a5864bc698 100644 --- a/drivers/iio/adc/ad9467.c +++ b/drivers/iio/adc/ad9467.c @@ -76,6 +76,14 @@ /* AN877_ADC_REG_OUTPUT_DELAY */ #define AN877_ADC_DCO_DELAY_ENABLE 0x80 +/* + * Analog Devices AD9434 12-Bit, 370/500 MSPS ADC + */ + +#define CHIPID_AD9434 0x6A +#define AD9434_DEF_OUTPUT_MODE 0x00 +#define AD9434_REG_VREF_MASK 0xC0 + /* * Analog Devices AD9467 16-Bit, 200/250 MSPS ADC */ @@ -85,6 +93,7 @@ #define AD9467_REG_VREF_MASK 0x0F enum { + ID_AD9434, ID_AD9467, }; @@ -158,6 +167,13 @@ static int ad9467_reg_access(struct adi_axi_adc_conv *conv, unsigned int reg, return 0; } +static const unsigned int ad9434_scale_table[][2] = { + {1600, 0x1C}, {1580, 0x1D}, {1550, 0x1E}, {1520, 0x1F}, {1500, 0x00}, + {1470, 0x01}, {1440, 0x02}, {1420, 0x03}, {1390, 0x04}, {1360, 0x05}, + {1340, 0x06}, {1310, 0x07}, {1280, 0x08}, {1260, 0x09}, {1230, 0x0A}, + {1200, 0x0B}, {1180, 0x0C}, +}; + static const unsigned int ad9467_scale_table[][2] = { {2000, 0}, {2100, 6}, {2200, 7}, {2300, 8}, {2400, 9}, {2500, 10}, @@ -191,11 +207,27 @@ static void __ad9467_get_scale(struct adi_axi_adc_conv *conv, int index, }, \ } +static const struct iio_chan_spec ad9434_channels[] = { + AD9467_CHAN(0, 0, 12, 'S'), +}; + static const struct iio_chan_spec ad9467_channels[] = { AD9467_CHAN(0, 0, 16, 'S'), }; static const struct ad9467_chip_info ad9467_chip_tbl[] = { + [ID_AD9434] = { + .axi_adc_info = { + .id = CHIPID_AD9434, + .max_rate = 500000000UL, + .scale_table = ad9434_scale_table, + .num_scales = ARRAY_SIZE(ad9434_scale_table), + .channels = ad9434_channels, + .num_channels = ARRAY_SIZE(ad9434_channels), + }, + .default_output_mode = AD9434_DEF_OUTPUT_MODE, + .vref_mask = AD9434_REG_VREF_MASK, + }, [ID_AD9467] = { .axi_adc_info = { .id = CHIPID_AD9467, @@ -400,6 +432,7 @@ static int ad9467_probe(struct spi_device *spi) } static const struct of_device_id ad9467_of_match[] = { + { .compatible = "adi,ad9434", .data = &ad9467_chip_tbl[ID_AD9434], }, { .compatible = "adi,ad9467", .data = &ad9467_chip_tbl[ID_AD9467], }, {} }; -- cgit v1.2.3 From eb61343dfd214afd9eacba958fda0e31b1f31b19 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 24 Sep 2020 11:05:17 +0300 Subject: iio: adc: ad9467: add support for AD9265 high-speed ADC The AD9265 is a 16-bit, 125 MSPS analog-to-digital converter (ADC). The AD9265 is designed to support communications applications where high performance combined with low cost, small size, and versatility is desired. The ADC core features a multistage, differential pipelined architecture with integrated output error correction logic to provide 16-bit accuracy at 125 MSPS data rates and guarantees no missing codes over the full operating temperature range. The ADC features a wide bandwidth differential sample-and-hold analog input amplifier supporting a variety of user-selectable input ranges. It is suitable for multiplexed systems that switch full-scale voltage levels in successive channels and for sampling single-channel inputs at frequencies well beyond the Nyquist rate. Combined with power and cost savings over previously available ADCs, the AD9265 is suitable for applications in communications, instrumentation and medical imaging. Link: https://www.analog.com/media/en/technical-documentation/data-sheets/AD9434.pdf The driver supports the same register set as the AD9467, so the support for this chip is added to the 'ad9467' driver. Signed-off-by: Michael Hennerich Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron Link: https://lore.kernel.org/r/20200924080518.96410-4-alexandru.ardelean@analog.com --- drivers/iio/adc/ad9467.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c index 54a5864bc698..19a45dd43796 100644 --- a/drivers/iio/adc/ad9467.c +++ b/drivers/iio/adc/ad9467.c @@ -76,6 +76,14 @@ /* AN877_ADC_REG_OUTPUT_DELAY */ #define AN877_ADC_DCO_DELAY_ENABLE 0x80 +/* + * Analog Devices AD9265 16-Bit, 125/105/80 MSPS ADC + */ + +#define CHIPID_AD9265 0x64 +#define AD9265_DEF_OUTPUT_MODE 0x40 +#define AD9265_REG_VREF_MASK 0xC0 + /* * Analog Devices AD9434 12-Bit, 370/500 MSPS ADC */ @@ -93,6 +101,7 @@ #define AD9467_REG_VREF_MASK 0x0F enum { + ID_AD9265, ID_AD9434, ID_AD9467, }; @@ -167,6 +176,10 @@ static int ad9467_reg_access(struct adi_axi_adc_conv *conv, unsigned int reg, return 0; } +static const unsigned int ad9265_scale_table[][2] = { + {1250, 0x00}, {1500, 0x40}, {1750, 0x80}, {2000, 0xC0}, +}; + static const unsigned int ad9434_scale_table[][2] = { {1600, 0x1C}, {1580, 0x1D}, {1550, 0x1E}, {1520, 0x1F}, {1500, 0x00}, {1470, 0x01}, {1440, 0x02}, {1420, 0x03}, {1390, 0x04}, {1360, 0x05}, @@ -216,6 +229,18 @@ static const struct iio_chan_spec ad9467_channels[] = { }; static const struct ad9467_chip_info ad9467_chip_tbl[] = { + [ID_AD9265] = { + .axi_adc_info = { + .id = CHIPID_AD9265, + .max_rate = 125000000UL, + .scale_table = ad9265_scale_table, + .num_scales = ARRAY_SIZE(ad9265_scale_table), + .channels = ad9467_channels, + .num_channels = ARRAY_SIZE(ad9467_channels), + }, + .default_output_mode = AD9265_DEF_OUTPUT_MODE, + .vref_mask = AD9265_REG_VREF_MASK, + }, [ID_AD9434] = { .axi_adc_info = { .id = CHIPID_AD9434, @@ -432,6 +457,7 @@ static int ad9467_probe(struct spi_device *spi) } static const struct of_device_id ad9467_of_match[] = { + { .compatible = "adi,ad9265", .data = &ad9467_chip_tbl[ID_AD9265], }, { .compatible = "adi,ad9434", .data = &ad9467_chip_tbl[ID_AD9434], }, { .compatible = "adi,ad9467", .data = &ad9467_chip_tbl[ID_AD9467], }, {} -- cgit v1.2.3 From 2e2366c2d14193d3b95bab1fb484a9377224962b Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Wed, 23 Sep 2020 16:03:39 +0300 Subject: iio: cros_ec: unify hw fifo attributes into the core file The intent here is to minimize the use of iio_buffer_set_attrs(). Since we are planning to add support for multiple IIO buffers per IIO device, the issue has to do with: 1. Accessing 'indio_dev->buffer' directly (as is done with 'iio_buffer_set_attrs(indio_dev->buffer, )'). 2. The way that the buffer attributes would get handled or expanded when there are more buffers per IIO device. Current a sysfs kobj_type expands into a 'device' object that expands into an 'iio_dev' object. We will need to change this, so that the sysfs attributes for IIO buffers expand into IIO buffers at some point. Right now, the current IIO framework works fine for the '1 IIO device == 1 IIO buffer' case (that is now). Signed-off-by: Alexandru Ardelean Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20200923130339.997902-1-alexandru.ardelean@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/accel/cros_ec_accel_legacy.c | 2 +- drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c | 3 ++- drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c | 5 ++--- drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c | 11 ++++++++--- drivers/iio/light/cros_ec_light_prox.c | 5 ++--- drivers/iio/pressure/cros_ec_baro.c | 5 ++--- include/linux/iio/common/cros_ec_sensors_core.h | 4 ++-- 7 files changed, 19 insertions(+), 16 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c b/drivers/iio/accel/cros_ec_accel_legacy.c index b6f3471b62dc..8f1232c38e0d 100644 --- a/drivers/iio/accel/cros_ec_accel_legacy.c +++ b/drivers/iio/accel/cros_ec_accel_legacy.c @@ -215,7 +215,7 @@ static int cros_ec_accel_legacy_probe(struct platform_device *pdev) return -ENOMEM; ret = cros_ec_sensors_core_init(pdev, indio_dev, true, - cros_ec_sensors_capture, NULL); + cros_ec_sensors_capture, NULL, false); if (ret) return ret; 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 af801e203623..752f59037715 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 @@ -97,7 +97,8 @@ static int cros_ec_lid_angle_probe(struct platform_device *pdev) if (!indio_dev) return -ENOMEM; - ret = cros_ec_sensors_core_init(pdev, indio_dev, false, NULL, NULL); + ret = cros_ec_sensors_core_init(pdev, indio_dev, false, NULL, + NULL, false); if (ret) return ret; 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 130ab8ce0269..57038ca48d93 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c @@ -236,12 +236,11 @@ static int cros_ec_sensors_probe(struct platform_device *pdev) ret = cros_ec_sensors_core_init(pdev, indio_dev, true, cros_ec_sensors_capture, - cros_ec_sensors_push_data); + cros_ec_sensors_push_data, + true); if (ret) return ret; - iio_buffer_set_attrs(indio_dev->buffer, cros_ec_sensor_fifo_attributes); - indio_dev->info = &ec_sensors_info; state = iio_priv(indio_dev); for (channel = state->channels, i = CROS_EC_SENSOR_X; 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 1bc6efa47316..c62cacc04672 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 @@ -177,12 +177,11 @@ static ssize_t hwfifo_watermark_max_show(struct device *dev, static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0); -const struct attribute *cros_ec_sensor_fifo_attributes[] = { +static const struct attribute *cros_ec_sensor_fifo_attributes[] = { &iio_dev_attr_hwfifo_timeout.dev_attr.attr, &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr, NULL, }; -EXPORT_SYMBOL_GPL(cros_ec_sensor_fifo_attributes); int cros_ec_sensors_push_data(struct iio_dev *indio_dev, s16 *data, @@ -241,6 +240,7 @@ static void cros_ec_sensors_core_clean(void *arg) * for backward compatibility. * @push_data: function to call when cros_ec_sensorhub receives * a sample for that sensor. + * @has_hw_fifo: Set true if this device has/uses a HW FIFO * * Return: 0 on success, -errno on failure. */ @@ -248,7 +248,8 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, struct iio_dev *indio_dev, bool physical_device, cros_ec_sensors_capture_t trigger_capture, - cros_ec_sensorhub_push_data_cb_t push_data) + cros_ec_sensorhub_push_data_cb_t push_data, + bool has_hw_fifo) { struct device *dev = &pdev->dev; struct cros_ec_sensors_core_state *state = iio_priv(indio_dev); @@ -361,6 +362,10 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, NULL); if (ret) return ret; + + if (has_hw_fifo) + iio_buffer_set_attrs(indio_dev->buffer, + cros_ec_sensor_fifo_attributes); } } diff --git a/drivers/iio/light/cros_ec_light_prox.c b/drivers/iio/light/cros_ec_light_prox.c index fed79ba27fda..75d6b5fcf2cc 100644 --- a/drivers/iio/light/cros_ec_light_prox.c +++ b/drivers/iio/light/cros_ec_light_prox.c @@ -182,12 +182,11 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev) ret = cros_ec_sensors_core_init(pdev, indio_dev, true, cros_ec_sensors_capture, - cros_ec_sensors_push_data); + cros_ec_sensors_push_data, + true); if (ret) return ret; - iio_buffer_set_attrs(indio_dev->buffer, cros_ec_sensor_fifo_attributes); - indio_dev->info = &cros_ec_light_prox_info; state = iio_priv(indio_dev); state->core.type = state->core.resp->info.type; diff --git a/drivers/iio/pressure/cros_ec_baro.c b/drivers/iio/pressure/cros_ec_baro.c index f0938b6fbba0..aa043cb9ac42 100644 --- a/drivers/iio/pressure/cros_ec_baro.c +++ b/drivers/iio/pressure/cros_ec_baro.c @@ -139,12 +139,11 @@ static int cros_ec_baro_probe(struct platform_device *pdev) ret = cros_ec_sensors_core_init(pdev, indio_dev, true, cros_ec_sensors_capture, - cros_ec_sensors_push_data); + cros_ec_sensors_push_data, + true); if (ret) return ret; - iio_buffer_set_attrs(indio_dev->buffer, cros_ec_sensor_fifo_attributes); - indio_dev->info = &cros_ec_baro_info; state = iio_priv(indio_dev); state->core.type = state->core.resp->info.type; diff --git a/include/linux/iio/common/cros_ec_sensors_core.h b/include/linux/iio/common/cros_ec_sensors_core.h index caa8bb279a34..c9b80be82440 100644 --- a/include/linux/iio/common/cros_ec_sensors_core.h +++ b/include/linux/iio/common/cros_ec_sensors_core.h @@ -96,7 +96,8 @@ struct platform_device; int cros_ec_sensors_core_init(struct platform_device *pdev, struct iio_dev *indio_dev, bool physical_device, cros_ec_sensors_capture_t trigger_capture, - cros_ec_sensorhub_push_data_cb_t push_data); + cros_ec_sensorhub_push_data_cb_t push_data, + bool has_hw_fifo); irqreturn_t cros_ec_sensors_capture(int irq, void *p); int cros_ec_sensors_push_data(struct iio_dev *indio_dev, @@ -125,6 +126,5 @@ extern const struct dev_pm_ops cros_ec_sensors_pm_ops; /* List of extended channel specification for all sensors. */ extern const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[]; -extern const struct attribute *cros_ec_sensor_fifo_attributes[]; #endif /* __CROS_EC_SENSORS_CORE_H */ -- cgit v1.2.3 From 3cd137f591e18588f730a2c53f291d65382050d0 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Thu, 24 Sep 2020 14:17:56 +0300 Subject: iio: dma-buffer: Kconfig: Provide titles for IIO DMA Kconfig symbols For some embedded systems, a workflow involving external kernel modules that implement IIO devices is more practical than working with in-tree sources. Kconfig symbols without any titles do not show up in menuconfig, and as such are more difficult to configure granularly, as they need to be selected by potentially unused/un-needed drivers. This change adds titles to the IIO DMA Kconfig symbols to address this. This change also updates DMAengine -> DMAEngine, which is the correct/nitpick-y name of the framework. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20200924111758.196367-2-alexandru.ardelean@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/buffer/Kconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/buffer/Kconfig b/drivers/iio/buffer/Kconfig index 63f265c8b466..747d21f84188 100644 --- a/drivers/iio/buffer/Kconfig +++ b/drivers/iio/buffer/Kconfig @@ -11,7 +11,7 @@ config IIO_BUFFER_CB usage. That is, those where the data is pushed to the consumer. config IIO_BUFFER_DMA - tristate + tristate "Industrial I/O DMA buffer infrastructure" help Provides the generic IIO DMA buffer infrastructure that can be used by drivers for devices with DMA support to implement the IIO buffer. @@ -20,13 +20,13 @@ config IIO_BUFFER_DMA infrastructure. config IIO_BUFFER_DMAENGINE - tristate + tristate "Industrial I/O DMA buffer integration with DMAEngine" select IIO_BUFFER_DMA help Provides a bonding of the generic IIO DMA buffer infrastructure with the - DMAengine framework. This can be used by converter drivers with a DMA port + DMAEngine framework. This can be used by converter drivers with a DMA port connected to an external DMA controller which is supported by the - DMAengine framework. + DMAEngine framework. Should be selected by drivers that want to use this functionality. -- cgit v1.2.3 From a132e5f4f3f0c94cfe05259cdc08c70813a20759 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Thu, 24 Sep 2020 14:17:57 +0300 Subject: iio: Kconfig: Provide title for IIO_TRIGGERED_EVENT symbol For some embedded systems, a workflow involving external kernel modules that implement IIO devices is more practical than working with in-tree sources. Kconfig symbols without any titles do not show up in menuconfig, and as such are more difficult to configure granularly, as they need to be selected by potentially unused/un-needed drivers. Albeit, the IIO_TRIGGERED_EVENT is used by a single mainline driver, this could allow for some out-of-tree drivers to use this kmod. This change adds a title to the IIO_TRIGGERED_EVENT Kconfig symbol. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20200924111758.196367-3-alexandru.ardelean@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index d5c073a8aa3e..267553386c71 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig @@ -63,7 +63,7 @@ config IIO_SW_TRIGGER using the API provided. config IIO_TRIGGERED_EVENT - tristate + tristate "Enable triggered events support" select IIO_TRIGGER help Provides helper functions for setting up triggered events. -- cgit v1.2.3 From c8283ba8e28c6863d0b8703a4e567d6555c43ac2 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Thu, 24 Sep 2020 14:17:58 +0300 Subject: iio: buffer: Kconfig: add title for IIO_TRIGGERED_BUFFER symbol For some embedded systems, a workflow involving external kernel modules that implement IIO devices is more practical than working with in-tree sources. Kconfig symbols without any titles do not show up in menuconfig, and as such are more difficult to configure granularly, as they need to be selected by potentially unused/un-needed drivers. This change adds a title to the IIO_TRIGGERED_BUFFER Kconfig symbol. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20200924111758.196367-4-alexandru.ardelean@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/buffer/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/buffer/Kconfig b/drivers/iio/buffer/Kconfig index 747d21f84188..047b931591a9 100644 --- a/drivers/iio/buffer/Kconfig +++ b/drivers/iio/buffer/Kconfig @@ -48,7 +48,7 @@ config IIO_KFIFO_BUF often to read from the buffer. config IIO_TRIGGERED_BUFFER - tristate + tristate "Industrial I/O triggered buffer support" select IIO_TRIGGER select IIO_KFIFO_BUF help -- cgit v1.2.3 From b07c47bfab6f5c4c7182d23e854bbceaf7829c85 Mon Sep 17 00:00:00 2001 From: Nuno Sá Date: Fri, 25 Sep 2020 11:10:44 +0200 Subject: iio: ltc2983: Fix of_node refcounting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When returning or breaking early from a `for_each_available_child_of_node()` loop, we need to explicitly call `of_node_put()` on the child node to possibly release the node. Fixes: f110f3188e563 ("iio: temperature: Add support for LTC2983") Signed-off-by: Nuno Sá Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20200925091045.302-1-nuno.sa@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/temperature/ltc2983.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c index 55ff28a0f1c7..3b5ba26d7d86 100644 --- a/drivers/iio/temperature/ltc2983.c +++ b/drivers/iio/temperature/ltc2983.c @@ -1285,18 +1285,20 @@ static int ltc2983_parse_dt(struct ltc2983_data *st) ret = of_property_read_u32(child, "reg", &sensor.chan); if (ret) { dev_err(dev, "reg property must given for child nodes\n"); - return ret; + goto put_child; } /* check if we have a valid channel */ if (sensor.chan < LTC2983_MIN_CHANNELS_NR || sensor.chan > LTC2983_MAX_CHANNELS_NR) { + ret = -EINVAL; dev_err(dev, "chan:%d must be from 1 to 20\n", sensor.chan); - return -EINVAL; + goto put_child; } else if (channel_avail_mask & BIT(sensor.chan)) { + ret = -EINVAL; dev_err(dev, "chan:%d already in use\n", sensor.chan); - return -EINVAL; + goto put_child; } ret = of_property_read_u32(child, "adi,sensor-type", @@ -1304,7 +1306,7 @@ static int ltc2983_parse_dt(struct ltc2983_data *st) if (ret) { dev_err(dev, "adi,sensor-type property must given for child nodes\n"); - return ret; + goto put_child; } dev_dbg(dev, "Create new sensor, type %u, chann %u", @@ -1334,13 +1336,15 @@ static int ltc2983_parse_dt(struct ltc2983_data *st) st->sensors[chan] = ltc2983_adc_new(child, st, &sensor); } else { dev_err(dev, "Unknown sensor type %d\n", sensor.type); - return -EINVAL; + ret = -EINVAL; + goto put_child; } if (IS_ERR(st->sensors[chan])) { dev_err(dev, "Failed to create sensor %ld", PTR_ERR(st->sensors[chan])); - return PTR_ERR(st->sensors[chan]); + ret = PTR_ERR(st->sensors[chan]); + goto put_child; } /* set generic sensor parameters */ st->sensors[chan]->chan = sensor.chan; @@ -1351,6 +1355,9 @@ static int ltc2983_parse_dt(struct ltc2983_data *st) } return 0; +put_child: + of_node_put(child); + return ret; } static int ltc2983_setup(struct ltc2983_data *st, bool assign_iio) -- cgit v1.2.3 From b8a533f3c24b3b8f1fdbefc5ada6a7d5733d63e6 Mon Sep 17 00:00:00 2001 From: Nuno Sá Date: Fri, 25 Sep 2020 11:10:45 +0200 Subject: iio: ad7292: Fix of_node refcounting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When returning or breaking early from a `for_each_available_child_of_node()` loop, we need to explicitly call `of_node_put()` on the child node to possibly release the node. Fixes: 506d2e317a0a0 ("iio: adc: Add driver support for AD7292") Signed-off-by: Nuno Sá Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20200925091045.302-2-nuno.sa@analog.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7292.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/ad7292.c b/drivers/iio/adc/ad7292.c index 2eafbe7ac7c7..ab204e9199e9 100644 --- a/drivers/iio/adc/ad7292.c +++ b/drivers/iio/adc/ad7292.c @@ -310,8 +310,10 @@ static int ad7292_probe(struct spi_device *spi) for_each_available_child_of_node(spi->dev.of_node, child) { diff_channels = of_property_read_bool(child, "diff-channels"); - if (diff_channels) + if (diff_channels) { + of_node_put(child); break; + } } if (diff_channels) { -- cgit v1.2.3 From 1a198794451449113fa86994ed491d6986802c23 Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Wed, 23 Sep 2020 15:17:48 +0300 Subject: iio: adc: at91-sama5d2_adc: fix DMA conversion crash After the move of the postenable code to preenable, the DMA start was done before the DMA init, which is not correct. The DMA is initialized in set_watermark. Because of this, we need to call the DMA start functions in set_watermark, after the DMA init, instead of preenable hook, when the DMA is not properly setup yet. Fixes: f3c034f61775 ("iio: at91-sama5d2_adc: adjust iio_triggered_buffer_{predisable,postenable} positions") Signed-off-by: Eugen Hristev Link: https://lore.kernel.org/r/20200923121748.49384-1-eugen.hristev@microchip.com Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91-sama5d2_adc.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index ad7d9819f83c..b917a4714a9c 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -884,7 +884,7 @@ static bool at91_adc_current_chan_is_touch(struct iio_dev *indio_dev) AT91_SAMA5D2_MAX_CHAN_IDX + 1); } -static int at91_adc_buffer_preenable(struct iio_dev *indio_dev) +static int at91_adc_buffer_prepare(struct iio_dev *indio_dev) { int ret; u8 bit; @@ -901,7 +901,7 @@ static int at91_adc_buffer_preenable(struct iio_dev *indio_dev) /* we continue with the triggered buffer */ ret = at91_adc_dma_start(indio_dev); if (ret) { - dev_err(&indio_dev->dev, "buffer postenable failed\n"); + dev_err(&indio_dev->dev, "buffer prepare failed\n"); return ret; } @@ -989,7 +989,6 @@ static int at91_adc_buffer_postdisable(struct iio_dev *indio_dev) } static const struct iio_buffer_setup_ops at91_buffer_setup_ops = { - .preenable = &at91_adc_buffer_preenable, .postdisable = &at91_adc_buffer_postdisable, }; @@ -1563,6 +1562,7 @@ static void at91_adc_dma_disable(struct platform_device *pdev) static int at91_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val) { struct at91_adc_state *st = iio_priv(indio_dev); + int ret; if (val > AT91_HWFIFO_MAX_SIZE) return -EINVAL; @@ -1586,7 +1586,15 @@ static int at91_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val) else if (val > 1) at91_adc_dma_init(to_platform_device(&indio_dev->dev)); - return 0; + /* + * We can start the DMA only after setting the watermark and + * having the DMA initialization completed + */ + ret = at91_adc_buffer_prepare(indio_dev); + if (ret) + at91_adc_dma_disable(to_platform_device(&indio_dev->dev)); + + return ret; } static int at91_adc_update_scan_mode(struct iio_dev *indio_dev, -- cgit v1.2.3 From c537d3457542a398caa1fe58e0976c5f83cf7281 Mon Sep 17 00:00:00 2001 From: Fabrice Gasnier Date: Wed, 1 Jul 2020 16:55:28 +0200 Subject: iio: adc: stm32-adc: fix runtime autosuspend delay when slow polling When the ADC is runtime suspended and starting a conversion, the stm32-adc driver calls pm_runtime_get_sync() that gets cascaded to the parent (e.g. runtime resume of stm32-adc-core driver). This also kicks the autosuspend delay (e.g. 2s) of the parent. Once the ADC is active, calling pm_runtime_get_sync() again (upon a new capture) won't kick the autosuspend delay for the parent (stm32-adc-core driver) as already active. Currently, this makes the stm32-adc-core driver go in suspend state every 2s when doing slow polling. As an example, doing a capture, e.g. cat in_voltageY_raw at a 0.2s rate, the auto suspend delay for the parent isn't refreshed. Once it expires, the parent immediately falls into runtime suspended state, in between two captures, as soon as the child driver falls into runtime suspend state: - e.g. after 2s, + child calls pm_runtime_put_autosuspend() + 100ms autosuspend delay of the child. - stm32-adc-core switches off regulators, clocks and so on. - They get switched on back again 100ms later in this example (at 2.2s). So, use runtime_idle() callback in stm32-adc-core driver to call pm_runtime_mark_last_busy() for the parent driver (stm32-adc-core), to avoid this. Fixes: 9bdbb1139ca1 ("iio: adc: stm32-adc: add power management support") Signed-off-by: Fabrice Gasnier Reviewed-by: Ulf Hansson Link: https://lore.kernel.org/r/1593615328-5180-1-git-send-email-fabrice.gasnier@st.com Signed-off-by: Jonathan Cameron --- drivers/iio/adc/stm32-adc-core.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c index 6a0338d33bd8..cd870c089182 100644 --- a/drivers/iio/adc/stm32-adc-core.c +++ b/drivers/iio/adc/stm32-adc-core.c @@ -769,6 +769,13 @@ static int stm32_adc_core_runtime_resume(struct device *dev) { return stm32_adc_core_hw_start(dev); } + +static int stm32_adc_core_runtime_idle(struct device *dev) +{ + pm_runtime_mark_last_busy(dev); + + return 0; +} #endif static const struct dev_pm_ops stm32_adc_core_pm_ops = { @@ -776,7 +783,7 @@ static const struct dev_pm_ops stm32_adc_core_pm_ops = { pm_runtime_force_resume) SET_RUNTIME_PM_OPS(stm32_adc_core_runtime_suspend, stm32_adc_core_runtime_resume, - NULL) + stm32_adc_core_runtime_idle) }; static const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg = { -- cgit v1.2.3 From da4410d4078ba4ead9d6f1027d6db77c5a74ecee Mon Sep 17 00:00:00 2001 From: Tobias Jordan Date: Sat, 26 Sep 2020 18:19:46 +0200 Subject: iio: adc: gyroadc: fix leak of device node iterator Add missing of_node_put calls when exiting the for_each_child_of_node loop in rcar_gyroadc_parse_subdevs early. Also add goto-exception handling for the error paths in that loop. Fixes: 059c53b32329 ("iio: adc: Add Renesas GyroADC driver") Signed-off-by: Tobias Jordan Link: https://lore.kernel.org/r/20200926161946.GA10240@agrajag.zerfleddert.de Cc: Signed-off-by: Jonathan Cameron --- drivers/iio/adc/rcar-gyroadc.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers/iio') diff --git a/drivers/iio/adc/rcar-gyroadc.c b/drivers/iio/adc/rcar-gyroadc.c index dcaefc108ff6..9f38cf3c7dc2 100644 --- a/drivers/iio/adc/rcar-gyroadc.c +++ b/drivers/iio/adc/rcar-gyroadc.c @@ -357,7 +357,7 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev) num_channels = ARRAY_SIZE(rcar_gyroadc_iio_channels_3); break; default: - return -EINVAL; + goto err_e_inval; } /* @@ -374,7 +374,7 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev) dev_err(dev, "Failed to get child reg property of ADC \"%pOFn\".\n", child); - return ret; + goto err_of_node_put; } /* Channel number is too high. */ @@ -382,7 +382,7 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev) dev_err(dev, "Only %i channels supported with %pOFn, but reg = <%i>.\n", num_channels, child, reg); - return -EINVAL; + goto err_e_inval; } } @@ -391,7 +391,7 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev) dev_err(dev, "Channel %i uses different ADC mode than the rest.\n", reg); - return -EINVAL; + goto err_e_inval; } /* Channel is valid, grab the regulator. */ @@ -401,7 +401,8 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev) if (IS_ERR(vref)) { dev_dbg(dev, "Channel %i 'vref' supply not connected.\n", reg); - return PTR_ERR(vref); + ret = PTR_ERR(vref); + goto err_of_node_put; } priv->vref[reg] = vref; @@ -425,8 +426,10 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev) * attached to the GyroADC at a time, so if we found it, * we can stop parsing here. */ - if (childmode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) + if (childmode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) { + of_node_put(child); break; + } } if (first) { @@ -435,6 +438,12 @@ static int rcar_gyroadc_parse_subdevs(struct iio_dev *indio_dev) } return 0; + +err_e_inval: + ret = -EINVAL; +err_of_node_put: + of_node_put(child); + return ret; } static void rcar_gyroadc_deinit_supplies(struct iio_dev *indio_dev) -- cgit v1.2.3