From 4ffa22fd22a7cbde1a1394b2707ea73593dc0fda Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Thu, 23 Jul 2020 09:29:43 +0300 Subject: [PATCH 01/96] 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 --- Documentation/ABI/testing/sysfs-bus-iio | 2 ++ drivers/iio/industrialio-core.c | 1 + include/uapi/linux/iio/types.h | 1 + tools/iio/iio_event_monitor.c | 2 ++ 4 files changed, 6 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 5c62bfb0f3f5..405181fde40a 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1564,6 +1564,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_concentration_ethanol_raw What: /sys/bus/iio/devices/iio:deviceX/in_concentrationX_ethanol_raw What: /sys/bus/iio/devices/iio:deviceX/in_concentration_h2_raw What: /sys/bus/iio/devices/iio:deviceX/in_concentrationX_h2_raw +What: /sys/bus/iio/devices/iio:deviceX/in_concentration_o2_raw +What: /sys/bus/iio/devices/iio:deviceX/in_concentrationX_o2_raw What: /sys/bus/iio/devices/iio:deviceX/in_concentration_voc_raw What: /sys/bus/iio/devices/iio:deviceX/in_concentrationX_voc_raw KernelVersion: 4.3 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 */ diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h index fdd81affca4b..48c13147c0a8 100644 --- a/include/uapi/linux/iio/types.h +++ b/include/uapi/linux/iio/types.h @@ -94,6 +94,7 @@ enum iio_modifier { IIO_MOD_PM10, IIO_MOD_ETHANOL, IIO_MOD_H2, + IIO_MOD_O2, }; enum iio_event_type { diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c index f115d166c985..bb03859db89d 100644 --- a/tools/iio/iio_event_monitor.c +++ b/tools/iio/iio_event_monitor.c @@ -119,6 +119,7 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_PM2P5] = "pm2p5", [IIO_MOD_PM4] = "pm4", [IIO_MOD_PM10] = "pm10", + [IIO_MOD_O2] = "o2", }; static bool event_is_known(struct iio_event_data *event) @@ -211,6 +212,7 @@ static bool event_is_known(struct iio_event_data *event) case IIO_MOD_PM2P5: case IIO_MOD_PM4: case IIO_MOD_PM10: + case IIO_MOD_O2: break; default: return false; From 6da3a6ce281fa7a51e1e3af0fa6d9e52bd9bf11a Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Thu, 23 Jul 2020 09:29:44 +0300 Subject: [PATCH 02/96] 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(-) 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); From a507801275559a4c89b4a7ebbba983104ee2bd06 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Wed, 22 Jul 2020 10:22:01 +0300 Subject: [PATCH 03/96] 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(-) 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; + return ret; - 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 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); From 9b3b3b284ad550ca6cd5049e84728d4939148b9d Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Wed, 22 Jul 2020 10:25:46 +0300 Subject: [PATCH 04/96] 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(-) 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); From 5579db2cd5dd4032407114287dd0f97e07478e99 Mon Sep 17 00:00:00 2001 From: Stefan Popa Date: Wed, 22 Jul 2020 10:30:03 +0300 Subject: [PATCH 05/96] 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(+) 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, From 6f762972b2a766d9d03fc05de8d0880e90b98df1 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 20 Jul 2020 16:52:37 +0300 Subject: [PATCH 06/96] 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(+) 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. From 33825b27c918d8c9be50c2a4fdee30cb706bdad8 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Mon, 20 Jul 2020 00:03:29 -0700 Subject: [PATCH 07/96] dt-bindings: iio: chemical: add O2 EZO module documentation Cc: devicetree@vger.kernel.org Signed-off-by: Matt Ranostay Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/chemical/atlas,sensor.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/chemical/atlas,sensor.yaml b/Documentation/devicetree/bindings/iio/chemical/atlas,sensor.yaml index 9a89b34bdd8f..d55c6e737020 100644 --- a/Documentation/devicetree/bindings/iio/chemical/atlas,sensor.yaml +++ b/Documentation/devicetree/bindings/iio/chemical/atlas,sensor.yaml @@ -19,6 +19,7 @@ description: | http://www.atlas-scientific.com/_files/_datasheets/_oem/pH_oem_datasheet.pdf http://www.atlas-scientific.com/_files/_datasheets/_oem/RTD_oem_datasheet.pdf http://www.atlas-scientific.com/_files/_datasheets/_probe/EZO_CO2_Datasheet.pdf + https://www.atlas-scientific.com/files/EZO_O2_datasheet.pdf properties: compatible: @@ -29,6 +30,7 @@ properties: - atlas,ph-sm - atlas,rtd-sm - atlas,co2-ezo + - atlas,o2-ezo reg: maxItems: 1 From 4d55cb8e78df3d6bb40ff4abf02bb15d1145846c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 20 Jul 2020 16:51:33 +0300 Subject: [PATCH 08/96] 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(-) 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) { } From 96f962511b0fddf0136aad89cd324e6af5f67d16 Mon Sep 17 00:00:00 2001 From: Ankit Baluni Date: Wed, 29 Jul 2020 13:41:55 +0530 Subject: [PATCH 09/96] Staging: iio: Fixed a punctuation and a spelling mistake. Added a missing comma and changed 'it it useful' to 'it is useful'. Signed-off-by: Ankit Baluni Reviewed-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- drivers/staging/iio/Documentation/overview.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/Documentation/overview.txt b/drivers/staging/iio/Documentation/overview.txt index ebdc64f451d7..00409d5dab4e 100644 --- a/drivers/staging/iio/Documentation/overview.txt +++ b/drivers/staging/iio/Documentation/overview.txt @@ -9,7 +9,7 @@ The aim is to fill the gap between the somewhat similar hwmon and input subsystems. Hwmon is very much directed at low sample rate sensors used in applications such as fan speed control and temperature measurement. Input is, as its name suggests focused on input -devices. In some cases there is considerable overlap between these and +devices. In some cases, there is considerable overlap between these and IIO. A typical device falling into this category would be connected via SPI @@ -38,7 +38,7 @@ series and Analog Devices ADXL345 accelerometers. Each buffer supports polling to establish when data is available. * Trigger and software buffer support. In many data analysis -applications it it useful to be able to capture data based on some +applications it is useful to be able to capture data based on some external signal (trigger). These triggers might be a data ready signal, a gpio line connected to some external system or an on processor periodic interrupt. A single trigger may initialize data From 2c8920fff1457a41912e8d3e3b9eafb582656440 Mon Sep 17 00:00:00 2001 From: Nishant Malpani Date: Sun, 26 Jul 2020 19:40:16 +0530 Subject: [PATCH 10/96] 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 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"); From 107ce2e3dccceefd91a2af3069de63774cbaccf9 Mon Sep 17 00:00:00 2001 From: Nishant Malpani Date: Sun, 26 Jul 2020 19:40:26 +0530 Subject: [PATCH 11/96] dt-bindings: iio: gyro: Add DT binding doc for ADXRS290 Add devicetree binding document for ADXRS290, a dual-axis MEMS gyroscope. Reviewed-by: Rob Herring Signed-off-by: Nishant Malpani Signed-off-by: Jonathan Cameron --- .../bindings/iio/gyroscope/adi,adxrs290.yaml | 53 +++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 54 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/gyroscope/adi,adxrs290.yaml diff --git a/Documentation/devicetree/bindings/iio/gyroscope/adi,adxrs290.yaml b/Documentation/devicetree/bindings/iio/gyroscope/adi,adxrs290.yaml new file mode 100644 index 000000000000..61adb2c2454b --- /dev/null +++ b/Documentation/devicetree/bindings/iio/gyroscope/adi,adxrs290.yaml @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# Copyright 2020 Analog Devices Inc. +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/gyroscope/adi,adxrs290.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices ADXRS290 Dual-Axis MEMS Gyroscope + +maintainers: + - Nishant Malpani + +description: | + Bindings for the Analog Devices ADXRS290 dual-axis MEMS gyroscope device. + https://www.analog.com/media/en/technical-documentation/data-sheets/ADXRS290.pdf + +properties: + compatible: + const: adi,adxrs290 + + reg: + maxItems: 1 + + spi-max-frequency: + maximum: 5000000 + + spi-cpol: true + + spi-cpha: true + +required: + - compatible + - reg + - spi-max-frequency + - spi-cpol + - spi-cpha + +additionalProperties: false + +examples: + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + gyro@0 { + compatible = "adi,adxrs290"; + reg = <0>; + spi-max-frequency = <5000000>; + spi-cpol; + spi-cpha; + }; + }; +... diff --git a/MAINTAINERS b/MAINTAINERS index e4389d830329..39bf100972e9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1113,6 +1113,7 @@ M: Nishant Malpani L: linux-iio@vger.kernel.org S: Supported F: drivers/iio/gyro/adxrs290.c +F: Documentation/devicetree/bindings/iio/gyroscope/adi,adxrs290.yaml ANALOG DEVICES INC ASOC CODEC DRIVERS M: Lars-Peter Clausen From fde6da59da6284080ec27c2ff92c0c8eef2bf8f3 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 22 Jul 2020 18:12:22 +0100 Subject: [PATCH 12/96] dt-bindings: iio: adc: maxim,max11100 yaml conversion Straight forward conversion for this SPI ADC. Added limits on spi-max-frequency from datasheet (0.1 to 4.8MHz) Signed-off-by: Jonathan Cameron Reviewed-by: Jacopo Mondi Reviewed-by: Rob Herring --- .../devicetree/bindings/iio/adc/max11100.txt | 18 ------- .../bindings/iio/adc/maxim,max11100.yaml | 49 +++++++++++++++++++ 2 files changed, 49 insertions(+), 18 deletions(-) delete mode 100644 Documentation/devicetree/bindings/iio/adc/max11100.txt create mode 100644 Documentation/devicetree/bindings/iio/adc/maxim,max11100.yaml diff --git a/Documentation/devicetree/bindings/iio/adc/max11100.txt b/Documentation/devicetree/bindings/iio/adc/max11100.txt deleted file mode 100644 index b7f7177b8aca..000000000000 --- a/Documentation/devicetree/bindings/iio/adc/max11100.txt +++ /dev/null @@ -1,18 +0,0 @@ -* Maxim max11100 Analog to Digital Converter (ADC) - -Required properties: - - compatible: Should be "maxim,max11100" - - reg: the adc unit address - - vref-supply: phandle to the regulator that provides reference voltage - -Optional properties: - - spi-max-frequency: SPI maximum frequency - -Example: - -max11100: adc@0 { - compatible = "maxim,max11100"; - reg = <0>; - vref-supply = <&adc0_vref>; - spi-max-frequency = <240000>; -}; diff --git a/Documentation/devicetree/bindings/iio/adc/maxim,max11100.yaml b/Documentation/devicetree/bindings/iio/adc/maxim,max11100.yaml new file mode 100644 index 000000000000..0cf87556ef82 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/maxim,max11100.yaml @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/maxim,max11100.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim MAX11100 ADC + +maintainers: + - Jacopo Mondi + +description: | + Single channel 16 bit ADC with SPI interface. + +properties: + compatible: + const: maxim,max11100 + + reg: + maxItems: 1 + + vref-supply: + description: External reference, needed to establish input scaling. + + spi-max-frequency: + minimum: 100000 + maximum: 4800000 + +additionalProperties: false + +required: + - compatible + - reg + - vref-supply + +examples: + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "maxim,max11100"; + reg = <0>; + vref-supply = <&adc_vref>; + spi-max-frequency = <240000>; + }; + }; +... From 65fb06f0bec8d8a929cdae9e68048adf25883f65 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 22 Jul 2020 18:12:24 +0100 Subject: [PATCH 13/96] dt-bindings: iio: adc: maxim,max9611 yaml conversions Straight forward conversion of this binding for this current sense amplifier and ADC. Signed-off-by: Jonathan Cameron Reviewed-by: Jacopo Mondi Reviewed-by: Rob Herring --- .../devicetree/bindings/iio/adc/max9611.txt | 27 ---------- .../bindings/iio/adc/maxim,max9611.yaml | 51 +++++++++++++++++++ 2 files changed, 51 insertions(+), 27 deletions(-) delete mode 100644 Documentation/devicetree/bindings/iio/adc/max9611.txt create mode 100644 Documentation/devicetree/bindings/iio/adc/maxim,max9611.yaml diff --git a/Documentation/devicetree/bindings/iio/adc/max9611.txt b/Documentation/devicetree/bindings/iio/adc/max9611.txt deleted file mode 100644 index ab4f43145ae5..000000000000 --- a/Documentation/devicetree/bindings/iio/adc/max9611.txt +++ /dev/null @@ -1,27 +0,0 @@ -* Maxim max9611/max9612 current sense amplifier with 12-bits ADC interface - -Maxim max9611/max9612 is an high-side current sense amplifier with integrated -12-bits ADC communicating over I2c bus. -The device node for this driver shall be a child of a I2c controller. - -Required properties - - compatible: Should be "maxim,max9611" or "maxim,max9612" - - reg: The 7-bits long I2c address of the device - - shunt-resistor-micro-ohms: Value, in micro Ohms, of the current sense shunt - resistor - -Example: - -&i2c4 { - csa: adc@7c { - compatible = "maxim,max9611"; - reg = <0x7c>; - - shunt-resistor-micro-ohms = <5000>; - }; -}; - -This device node describes a current sense amplifier sitting on I2c4 bus -with address 0x7c (read address is 0xf9, write address is 0xf8). -A sense resistor of 0,005 Ohm is installed between RS+ and RS- current-sensing -inputs. diff --git a/Documentation/devicetree/bindings/iio/adc/maxim,max9611.yaml b/Documentation/devicetree/bindings/iio/adc/maxim,max9611.yaml new file mode 100644 index 000000000000..9475a9e6e920 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/maxim,max9611.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/maxim,max9611.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim MAX9611 and similar current sense amplifiers with integrated ADCs + +maintainers: + - Jacopo Mondi + +description: | + These devices combine a high-side current sense amplifier with a 12 bit ADC. + They have an i2c interface. + +properties: + compatible: + enum: + - maxim,max9611 + - maxim,max9612 + + reg: + maxItems: 1 + + shunt-resistor-micro-ohms: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + Value in micro Ohms of the shunt resistor connected between the RS+ and + RS- inputs, across which the current is measured. Value needed to compute + the scaling of the measured current. + +additionalProperties: false + +required: + - compatible + - reg + - shunt-resistor-micro-ohms + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + adc@7c { + compatible = "maxim,max9611"; + reg = <0x7c>; + shunt-resistor-micro-ohms = <5000>; + }; + }; +... From 781cb90b0529b5bb84c63691fe42a7c26d197aec Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 18 Jul 2020 17:30:40 -0700 Subject: [PATCH 14/96] platform_data: ad7793.h: drop a duplicated word Drop the repeated word "and" in a comment. Signed-off-by: Randy Dunlap Cc: Lars-Peter Clausen Cc: Jonathan Cameron Signed-off-by: Jonathan Cameron --- include/linux/platform_data/ad7793.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/platform_data/ad7793.h b/include/linux/platform_data/ad7793.h index 576c7f962c4e..7c697e58f02a 100644 --- a/include/linux/platform_data/ad7793.h +++ b/include/linux/platform_data/ad7793.h @@ -40,7 +40,7 @@ enum ad7793_bias_voltage { * enum ad7793_refsel - AD7793 reference voltage selection * @AD7793_REFSEL_REFIN1: External reference applied between REFIN1(+) * and REFIN1(-). - * @AD7793_REFSEL_REFIN2: External reference applied between REFIN2(+) and + * @AD7793_REFSEL_REFIN2: External reference applied between REFIN2(+) * and REFIN1(-). Only valid for AD7795/AD7796. * @AD7793_REFSEL_INTERNAL: Internal 1.17 V reference. */ From f70fd25a59d6ed2755772ddc947d59945aa9ca1a Mon Sep 17 00:00:00 2001 From: Calvin Glisson Date: Wed, 5 Aug 2020 15:23:00 -0700 Subject: [PATCH 15/96] staging: iio: ad9834: Remove excess blank line Remove excess blank line after variable declarations. Improves code consistency and readability. Change suggested by checkpatch.pl: CHECK: Please don't use multiple blank lines Signed-off-by: Calvin Glisson Signed-off-by: Jonathan Cameron --- drivers/staging/iio/frequency/ad9834.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c index 77f77a2b2e05..262c3590e64e 100644 --- a/drivers/staging/iio/frequency/ad9834.c +++ b/drivers/staging/iio/frequency/ad9834.c @@ -397,7 +397,6 @@ static int ad9834_probe(struct spi_device *spi) struct regulator *reg; int ret; - reg = devm_regulator_get(&spi->dev, "avdd"); if (IS_ERR(reg)) return PTR_ERR(reg); From 96e55c38bb5bda5883c9f3df963eb7a5a51ce10b Mon Sep 17 00:00:00 2001 From: Christian Eggers Date: Wed, 5 Aug 2020 07:57:43 +0200 Subject: [PATCH 16/96] dt-bindings: iio: light: add AMS AS73211 support Add DT bindings for AMS AS73211 XYZ True Color Sensor. Signed-off-by: Christian Eggers Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/light/ams,as73211.yaml | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/light/ams,as73211.yaml diff --git a/Documentation/devicetree/bindings/iio/light/ams,as73211.yaml b/Documentation/devicetree/bindings/iio/light/ams,as73211.yaml new file mode 100644 index 000000000000..0e8cd02759b3 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/light/ams,as73211.yaml @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/light/ams,as73211.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: AMS AS73211 JENCOLOR(R) Digital XYZ Sensor + +maintainers: + - Christian Eggers + +description: | + XYZ True Color Sensor with I2C Interface + https://ams.com/documents/20143/36005/AS73211_DS000556_3-01.pdf/a65474c0-b302-c2fd-e30a-c98df87616df + +properties: + compatible: + enum: + - ams,as73211 + + reg: + description: + I2C address of the device (0x74...0x77). + maxItems: 1 + + interrupts: + description: + Interrupt specifier for the READY interrupt generated by the device. + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + as73211@74 { + compatible = "ams,as73211"; + reg = <0x74>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_color_sensor>; + interrupt-parent = <&gpio2>; + interrupts = <19 IRQ_TYPE_EDGE_RISING>; /* READY */ + }; + }; +... From 403e5586b52e466893ce3a7b7f3a3ecdc4c82d3e Mon Sep 17 00:00:00 2001 From: Christian Eggers Date: Wed, 5 Aug 2020 07:57:44 +0200 Subject: [PATCH 17/96] 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 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"); From 38a1efc9e7a459d9d5f81dc1dd6f2b10d95a47c6 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 1 Aug 2020 18:58:50 +0100 Subject: [PATCH 18/96] dt-bindings: iio: adc: maxim,max1118 yaml conversion Simple device with a simple conversion. Special handling needed for the max1118 which is the only supported part that has an external reference voltage. Cc: Akinobu Mita Signed-off-by: Jonathan Cameron Reviewed-by: Rob Herring --- .../devicetree/bindings/iio/adc/max1118.txt | 21 ------- .../bindings/iio/adc/maxim,max1118.yaml | 62 +++++++++++++++++++ 2 files changed, 62 insertions(+), 21 deletions(-) delete mode 100644 Documentation/devicetree/bindings/iio/adc/max1118.txt create mode 100644 Documentation/devicetree/bindings/iio/adc/maxim,max1118.yaml diff --git a/Documentation/devicetree/bindings/iio/adc/max1118.txt b/Documentation/devicetree/bindings/iio/adc/max1118.txt deleted file mode 100644 index cf33d0b15a6d..000000000000 --- a/Documentation/devicetree/bindings/iio/adc/max1118.txt +++ /dev/null @@ -1,21 +0,0 @@ -* MAX1117/MAX1118/MAX1119 8-bit, dual-channel ADCs - -Required properties: - - compatible: Should be one of - * "maxim,max1117" - * "maxim,max1118" - * "maxim,max1119" - - reg: spi chip select number for the device - - (max1118 only) vref-supply: The regulator supply for ADC reference voltage - -Recommended properties: - - spi-max-frequency: Definition as per - Documentation/devicetree/bindings/spi/spi-bus.txt - -Example: -adc@0 { - compatible = "maxim,max1118"; - reg = <0>; - vref-supply = <&vdd_supply>; - spi-max-frequency = <1000000>; -}; diff --git a/Documentation/devicetree/bindings/iio/adc/maxim,max1118.yaml b/Documentation/devicetree/bindings/iio/adc/maxim,max1118.yaml new file mode 100644 index 000000000000..e948b3e37b0c --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/maxim,max1118.yaml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/maxim,max1118.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim MAX1118 and similar ADCs + +maintainers: + - Akinobu Mita + +description: | + Dual channel 8bit ADCs. + +properties: + compatible: + enum: + - maxim,max1117 + - maxim,max1118 + - maxim,max1119 + + reg: + maxItems: 1 + + spi-max-frequency: + maximum: 5000000 + + vref-supply: + description: External reference, needed to establish input scaling + +if: + properties: + compatible: + contains: + const: maxim,max1118 +then: + required: + - vref-supply +else: + properties: + vref-supply: false + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "maxim,max1118"; + reg = <0>; + vref-supply = <&adc_vref>; + spi-max-frequency = <1000000>; + }; + }; +... From 1d863d13412a505ce23c15f25304a40e4a2fff2b Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:01 -0600 Subject: [PATCH 19/96] dt-bindings: iio: Add bindings for sx9310 sensor Adds device tree bindings for sx9310 sensor. Signed-off-by: Daniel Campello Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald-Stadler Cc: Rob Herring Reviewed-by: Douglas Anderson [swboyd@chromium.org: Add both regulators and make them optional] Signed-off-by: Stephen Boyd Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../iio/proximity/semtech,sx9310.yaml | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/proximity/semtech,sx9310.yaml diff --git a/Documentation/devicetree/bindings/iio/proximity/semtech,sx9310.yaml b/Documentation/devicetree/bindings/iio/proximity/semtech,sx9310.yaml new file mode 100644 index 000000000000..5739074d3592 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/proximity/semtech,sx9310.yaml @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/proximity/semtech,sx9310.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Semtech's SX9310 capacitive proximity sensor + +maintainers: + - Daniel Campello + +description: | + Semtech's SX9310/SX9311 capacitive proximity/button solution. + + Specifications about the devices can be found at: + https://www.semtech.com/products/smart-sensing/sar-sensors/sx9310 + +properties: + compatible: + enum: + - semtech,sx9310 + - semtech,sx9311 + + reg: + maxItems: 1 + + interrupts: + description: + The sole interrupt generated by the device used to announce the + preceding reading request has finished and that data is + available or that a close/far proximity event has happened. + maxItems: 1 + + vdd-supply: + description: Main power supply + + svdd-supply: + description: Host interface power supply + + "#io-channel-cells": + const: 1 + +required: + - compatible + - reg + - "#io-channel-cells" + +additionalProperties: false + +examples: + - | + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + proximity@28 { + compatible = "semtech,sx9310"; + reg = <0x28>; + interrupt-parent = <&pio>; + interrupts = <5 IRQ_TYPE_LEVEL_LOW 5>; + vdd-supply = <&pp3300_a>; + svdd-supply = <&pp1800_prox>; + #io-channel-cells = <1>; + }; + }; From d9f753f3e9edc0b4c0acdbe2708746242f7c7a79 Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:02 -0600 Subject: [PATCH 20/96] 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(-) 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; From 364e853ceec92cafe2c0d7fe7cc1d89891903234 Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:03 -0600 Subject: [PATCH 21/96] 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(-) 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 = { From ef5bdbab3511a6df31a0f660a7bc1e2494d72f61 Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:04 -0600 Subject: [PATCH 22/96] 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(-) 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, From 9b2cac94698794c49b993db0646c37c2188dcfae Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:05 -0600 Subject: [PATCH 23/96] 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 | 37 ++++++++++++---------------------- 1 file changed, 13 insertions(+), 24 deletions(-) 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; + unsigned int long ddata; - /* 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 + 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); From 01b9cb0dea76c70b3696cdff79c2e8f5772a6356 Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:06 -0600 Subject: [PATCH 24/96] 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(-) 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: From 68aa360a77c6d6695cb68ed34a5413e2b2b80fa6 Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:07 -0600 Subject: [PATCH 25/96] 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(-) 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); From dc46198f27ff72efce2c2fa8ef4ee52fa80c06ec Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:08 -0600 Subject: [PATCH 26/96] 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(-) 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; + 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; } - if (i < 0) { - dev_err(&data->client->dev, - "initial compensation timed out: 0x%02x", val); - ret = -ETIMEDOUT; - } - -out: regmap_write(data->regmap, SX9310_REG_PROX_CTRL0, ctrl0); return ret; } From 124cbc339cabde29a0a4d2b9c51c5068884145b0 Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:09 -0600 Subject: [PATCH 27/96] 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(-) 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 From a917af2ab8573a92b1434f9b45add3438edcbcb2 Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:10 -0600 Subject: [PATCH 28/96] 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(-) 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); From e943bba88ed58080fe23eecbfc0da3fa2839a390 Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:11 -0600 Subject: [PATCH 29/96] 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(-) 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) From de479073fa1eb7031b4f85429102e002521a0a95 Mon Sep 17 00:00:00 2001 From: Daniel Campello Date: Mon, 3 Aug 2020 17:58:12 -0600 Subject: [PATCH 30/96] 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(-) 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); From 2756db5e90ac4b881d5926bdeef75e84a128aa8d Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 3 Aug 2020 17:58:13 -0600 Subject: [PATCH 31/96] 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(-) 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; }; From f86ff7480c3efc7398b366b6d16158768c878d36 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 3 Aug 2020 17:58:14 -0600 Subject: [PATCH 32/96] 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(+) 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); From fe184be8c3528f848f66d51340d42afc92209f0a Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 3 Aug 2020 17:58:15 -0600 Subject: [PATCH 33/96] 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(-) 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; From 0115a63c999363b9558376b61c4037813d9063db Mon Sep 17 00:00:00 2001 From: Eugene Zaikonnikov Date: Fri, 7 Aug 2020 16:17:55 +0200 Subject: [PATCH 34/96] 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 --- .../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 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"); From abfa391721ce8a4ea59c1bc15968a8b2a9f891cb Mon Sep 17 00:00:00 2001 From: Eugene Zaikonnikov Date: Fri, 7 Aug 2020 16:38:53 +0200 Subject: [PATCH 35/96] dt-bindings: iio: humidity: Add TI HDC20x0 support Add device tree bindings for HDC2010/HDC2080 family of humidity and temperature sensors. Signed-off-by: Eugene Zaikonnikov Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/humidity/ti,hdc2010.yaml | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/humidity/ti,hdc2010.yaml diff --git a/Documentation/devicetree/bindings/iio/humidity/ti,hdc2010.yaml b/Documentation/devicetree/bindings/iio/humidity/ti,hdc2010.yaml new file mode 100644 index 000000000000..dc870eb2875f --- /dev/null +++ b/Documentation/devicetree/bindings/iio/humidity/ti,hdc2010.yaml @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/humidity/ti,hdc2010.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: HDC2010/HDC2080 humidity and temperature iio sensors + +maintainers: + - Eugene Zaikonnikov + +description: | + Relative humidity and tempereature sensors on I2C bus + + Datasheets are available at: + http://www.ti.com/product/HDC2010/datasheet + http://www.ti.com/product/HDC2080/datasheet + +properties: + compatible: + enum: + - ti,hdc2010 + - ti,hdc2080 + + vdd-supply: + maxItems: 1 + + reg: + maxItems: 1 + +required: + - compatible + - reg + +examples: + - | + i2c0 { + #address-cells = <1>; + #size-cells = <0>; + + humidity@40 { + compatible = "ti,hdc2010"; + reg = <0x40>; + }; + }; From 5dfb88af3d5204e581985056ccfb601d47252996 Mon Sep 17 00:00:00 2001 From: Vincent Whitchurch Date: Tue, 4 Aug 2020 11:31:38 +0200 Subject: [PATCH 36/96] 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(-) 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); From 245d56d75ea6860c583fbd54382ad82bbd405910 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Tue, 21 Jul 2020 18:14:44 +0100 Subject: [PATCH 37/96] 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(-) 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); From ad5bd081c62be386e8f0fc360e452c6e9e3005a1 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Tue, 21 Jul 2020 18:14:43 +0100 Subject: [PATCH 38/96] 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(-) 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, From 0a4596f5bd5ae3d234803353b14deef26663722e Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Tue, 21 Jul 2020 18:14:42 +0100 Subject: [PATCH 39/96] 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(-) 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, From c458b7ca3fd0c9671caf38630e6f6a006d90e113 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Tue, 21 Jul 2020 18:14:41 +0100 Subject: [PATCH 40/96] 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(-) 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, From ea3e611b29b201612a0e9fcb32727f80d66bc053 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Fri, 14 Aug 2020 06:49:41 -0700 Subject: [PATCH 41/96] 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(-) 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"); From 75caa303d79dd598a300a07f9e5ff7fa23c5cf9b Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Thu, 13 Aug 2020 08:52:20 +0200 Subject: [PATCH 42/96] Documentation: ABI: iio: fix some spelling mistakes This fixes some typos found while browsing the documentation. Cc: trivial@kernel.org Signed-off-by: Ahmad Fatoum Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 405181fde40a..9a9eac151227 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -49,9 +49,9 @@ Description: resulting sampling frequency. In many devices this parameter has an effect on input filters etc. rather than simply controlling when the input is sampled. As this - effects data ready triggers, hardware buffers and the sysfs + affects data ready triggers, hardware buffers and the sysfs direct access interfaces, it may be found in any of the - relevant directories. If it effects all of the above + relevant directories. If it affects all of the above then it is to be found in the base device directory. What: /sys/bus/iio/devices/iio:deviceX/sampling_frequency_available @@ -1013,7 +1013,7 @@ What: /sys/.../events/in_activity_running_thresh_falling_en KernelVersion: 3.19 Contact: linux-iio@vger.kernel.org Description: - Enables or disables activitity events. Depending on direction + Enables or disables activity events. Depending on direction an event is generated when sensor ENTERS or LEAVES a given state. What: /sys/.../events/in_activity_still_thresh_rising_value From 81f434f01722c8f95c59fc24c5e09f508a07a0ca Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 9 Aug 2020 15:13:05 +0100 Subject: [PATCH 43/96] 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(-) 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, From 3c3006f5fceca0019e7e34f504f9317e2a9eefd0 Mon Sep 17 00:00:00 2001 From: Christian Eggers Date: Mon, 10 Aug 2020 07:24:47 +0200 Subject: [PATCH 44/96] iio: documentation: light: Add as73211 sysfs documentation The driver for the as73211 light sensor provides the following not yet documented sysfs entries: - in_intensity_(x|y|z)_raw - in_intensity_(x|y|z)_scale - in_intensity_sampling_frequency(_available) - in_intensity_hardwaregain(_available) - in_intensity_integration_time Signed-off-by: Christian Eggers Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 26 ++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 9a9eac151227..a15176daf9a8 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -40,6 +40,7 @@ Description: buffered samples and events for device X. What: /sys/bus/iio/devices/iio:deviceX/sampling_frequency +What: /sys/bus/iio/devices/iio:deviceX/in_intensity_sampling_frequency What: /sys/bus/iio/devices/iio:deviceX/buffer/sampling_frequency What: /sys/bus/iio/devices/triggerX/sampling_frequency KernelVersion: 2.6.35 @@ -55,6 +56,7 @@ Description: then it is to be found in the base device directory. What: /sys/bus/iio/devices/iio:deviceX/sampling_frequency_available +What: /sys/bus/iio/devices/iio:deviceX/in_intensity_sampling_frequency_available What: /sys/bus/iio/devices/iio:deviceX/in_proximity_sampling_frequency_available What: /sys/.../iio:deviceX/buffer/sampling_frequency_available What: /sys/bus/iio/devices/triggerX/sampling_frequency_available @@ -374,6 +376,9 @@ What: /sys/bus/iio/devices/iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_scale What: /sys/bus/iio/devices/iio:deviceX/in_illuminance_scale What: /sys/bus/iio/devices/iio:deviceX/in_countY_scale What: /sys/bus/iio/devices/iio:deviceX/in_angl_scale +What: /sys/bus/iio/devices/iio:deviceX/in_intensity_x_scale +What: /sys/bus/iio/devices/iio:deviceX/in_intensity_y_scale +What: /sys/bus/iio/devices/iio:deviceX/in_intensity_z_scale KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org Description: @@ -484,6 +489,7 @@ Description: are listed in this attribute. What /sys/bus/iio/devices/iio:deviceX/out_voltageY_hardwaregain +What: /sys/bus/iio/devices/iio:deviceX/in_intensity_hardwaregain What: /sys/bus/iio/devices/iio:deviceX/in_intensity_red_hardwaregain What: /sys/bus/iio/devices/iio:deviceX/in_intensity_green_hardwaregain What: /sys/bus/iio/devices/iio:deviceX/in_intensity_blue_hardwaregain @@ -494,6 +500,13 @@ Description: Hardware applied gain factor. If shared across all channels, _hardwaregain is used. +What: /sys/bus/iio/devices/iio:deviceX/in_intensity_hardwaregain_available +KernelVersion: 5.10 +Contact: linux-iio@vger.kernel.org +Description: + Lists all available hardware applied gain factors. Shared across all + channels. + What: /sys/.../in_accel_filter_low_pass_3db_frequency What: /sys/.../in_magn_filter_low_pass_3db_frequency What: /sys/.../in_anglvel_filter_low_pass_3db_frequency @@ -1333,6 +1346,7 @@ Description: standardised CIE Erythemal Action Spectrum. UV index values range from 0 (low) to >=11 (extreme). +What: /sys/.../iio:deviceX/in_intensity_integration_time What: /sys/.../iio:deviceX/in_intensity_red_integration_time What: /sys/.../iio:deviceX/in_intensity_green_integration_time What: /sys/.../iio:deviceX/in_intensity_blue_integration_time @@ -1342,7 +1356,8 @@ KernelVersion: 3.12 Contact: linux-iio@vger.kernel.org Description: This attribute is used to get/set the integration time in - seconds. + seconds. If shared across all channels of a given type, + _integration_time is used. What: /sys/.../iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_integration_time KernelVersion: 4.0 @@ -1742,3 +1757,12 @@ KernelVersion: 5.5 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_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 +KernelVersion: 5.10 +Contact: linux-iio@vger.kernel.org +Description: + Unscaled light intensity according to CIE 1931/DIN 5033 color space. + Units after application of scale are nano nanowatts per square meter. From 8dd746d1e3cbac2986757e733baa38f6896dd7e0 Mon Sep 17 00:00:00 2001 From: Chris Ruehl Date: Mon, 10 Aug 2020 11:37:52 +0800 Subject: [PATCH 45/96] iio/dac: convert ltc2632.txt to lltc,ltc2632.yaml Conversion of the ltc2632 to yaml format and name the file to 'lltc,ltc2632.yaml'. Signed-off-by: Chris Ruehl Signed-off-by: Jonathan Cameron --- .../bindings/iio/dac/lltc,ltc2632.yaml | 77 +++++++++++++++++++ .../devicetree/bindings/iio/dac/ltc2632.txt | 49 ------------ 2 files changed, 77 insertions(+), 49 deletions(-) create mode 100644 Documentation/devicetree/bindings/iio/dac/lltc,ltc2632.yaml delete mode 100644 Documentation/devicetree/bindings/iio/dac/ltc2632.txt diff --git a/Documentation/devicetree/bindings/iio/dac/lltc,ltc2632.yaml b/Documentation/devicetree/bindings/iio/dac/lltc,ltc2632.yaml new file mode 100644 index 000000000000..edf804d0aca2 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/dac/lltc,ltc2632.yaml @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/iio/dac/lltc,ltc2632.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Linear Technology LTC263x 12-/10-/8-Bit Rail-to-Rail DAC + +maintainers: + - Michael Hennerich + +description: | + Bindings for the Linear Technology LTC2632/2634/2636 DAC + Datasheet can be found here: https://www.analog.com/media/en/technical-documentation/data-sheets/LTC263[246].pdf + +properties: + compatible: + enum: + - lltc,ltc2632-l12 + - lltc,ltc2632-l10 + - lltc,ltc2632-l8 + - lltc,ltc2632-h12 + - lltc,ltc2632-h10 + - lltc,ltc2632-h8 + - lltc,ltc2634-l12 + - lltc,ltc2634-l10 + - lltc,ltc2634-l8 + - lltc,ltc2634-h12 + - lltc,ltc2634-h10 + - lltc,ltc2634-h8 + - lltc,ltc2636-l12 + - lltc,ltc2636-l10 + - lltc,ltc2636-l8 + - lltc,ltc2636-h12 + - lltc,ltc2636-h10 + - lltc,ltc2636-h8 + + reg: + maxItems: 1 + + spi-max-frequency: + maximum: 2000000 + + vref-supply: + description: + Phandle to the external reference voltage supply. This should + only be set if there is an external reference voltage connected to the VREF + pin. If the property is not set the internal reference is used. + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + vref: regulator-vref { + compatible = "regulator-fixed"; + regulator-name = "vref-ltc2632"; + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1250000>; + regulator-always-on; + }; + + spi { + #address-cells = <1>; + #size-cells = <0>; + + dac@0 { + compatible = "lltc,ltc2632"; + reg = <0>; /* CS0 */ + spi-max-frequency = <1000000>; + vref-supply = <&vref>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/iio/dac/ltc2632.txt b/Documentation/devicetree/bindings/iio/dac/ltc2632.txt deleted file mode 100644 index 1ab9570cf219..000000000000 --- a/Documentation/devicetree/bindings/iio/dac/ltc2632.txt +++ /dev/null @@ -1,49 +0,0 @@ -Linear Technology LTC2632/2634/2636 DAC - -Required properties: - - compatible: Has to contain one of the following: - lltc,ltc2632-l12 - lltc,ltc2632-l10 - lltc,ltc2632-l8 - lltc,ltc2632-h12 - lltc,ltc2632-h10 - lltc,ltc2632-h8 - lltc,ltc2634-l12 - lltc,ltc2634-l10 - lltc,ltc2634-l8 - lltc,ltc2634-h12 - lltc,ltc2634-h10 - lltc,ltc2634-h8 - lltc,ltc2636-l12 - lltc,ltc2636-l10 - lltc,ltc2636-l8 - lltc,ltc2636-h12 - lltc,ltc2636-h10 - lltc,ltc2636-h8 - -Property rules described in Documentation/devicetree/bindings/spi/spi-bus.txt -apply. In particular, "reg" and "spi-max-frequency" properties must be given. - -Optional properties: - - vref-supply: Phandle to the external reference voltage supply. This should - only be set if there is an external reference voltage connected to the VREF - pin. If the property is not set the internal reference is used. - -Example: - - vref: regulator-vref { - compatible = "regulator-fixed"; - regulator-name = "vref-ltc2632"; - regulator-min-microvolt = <1250000>; - regulator-max-microvolt = <1250000>; - regulator-always-on; - }; - - spi_master { - dac: ltc2632@0 { - compatible = "lltc,ltc2632-l12"; - reg = <0>; /* CS0 */ - spi-max-frequency = <1000000>; - vref-supply = <&vref>; /* optional */ - }; - }; From 59713492b7866e031e0c66e25f4f034c96f1be5a Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Tue, 26 May 2020 23:02:21 +0200 Subject: [PATCH 46/96] 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(-) 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; }; From f6712ed711236159e99ed48221ba41c931721503 Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Thu, 20 Aug 2020 11:01:26 +0800 Subject: [PATCH 47/96] 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(-) 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; From d947996687344e19da09ec74c618536e99a0e214 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Mon, 17 Aug 2020 03:50:51 +0300 Subject: [PATCH 48/96] dt-bindings: iio: chemical: add Atlas EZO Humidity module documentation Cc: devicetree@vger.kernel.org Signed-off-by: Matt Ranostay Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/chemical/atlas,sensor.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/chemical/atlas,sensor.yaml b/Documentation/devicetree/bindings/iio/chemical/atlas,sensor.yaml index d55c6e737020..4646deeb6f7b 100644 --- a/Documentation/devicetree/bindings/iio/chemical/atlas,sensor.yaml +++ b/Documentation/devicetree/bindings/iio/chemical/atlas,sensor.yaml @@ -20,6 +20,7 @@ description: | http://www.atlas-scientific.com/_files/_datasheets/_oem/RTD_oem_datasheet.pdf http://www.atlas-scientific.com/_files/_datasheets/_probe/EZO_CO2_Datasheet.pdf https://www.atlas-scientific.com/files/EZO_O2_datasheet.pdf + https://www.atlas-scientific.com/files/EZO_HUM_Datasheet.pdf properties: compatible: @@ -31,6 +32,7 @@ properties: - atlas,rtd-sm - atlas,co2-ezo - atlas,o2-ezo + - atlas,hum-ezo reg: maxItems: 1 From dc3ebfcaa51ff9ffa417f23e47c4e1aa01bc501d Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Mon, 17 Aug 2020 03:50:52 +0300 Subject: [PATCH 49/96] 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(-) 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); From 3bdb1255e6b0a49e83412ad0d15eb2b2f7f63482 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:09 +0200 Subject: [PATCH 50/96] 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(-) 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) From c8b9a02361d99364faddbf1193b85d476f35cfd3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:10 +0200 Subject: [PATCH 51/96] 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(-) 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) { From 55dc295200e60fd4a334098dd4c036eff9e9ead3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:11 +0200 Subject: [PATCH 52/96] 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(-) 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; From 1030b5bc68ae572467122bfe7aa48b118e942c52 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:12 +0200 Subject: [PATCH 53/96] 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(-) 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) From 291cb0b37af611503ccacff752ac0fc920b0a21b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:13 +0200 Subject: [PATCH 54/96] 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(-) 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) { From a3e584fab675b833e9923a0f5e76031b027525d9 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:14 +0200 Subject: [PATCH 55/96] 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(-) 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 = From 6d2710ce2c45122eea4ccdb4cee1fd56e6702cea Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:15 +0200 Subject: [PATCH 56/96] 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(-) 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) From ce30eeb613cbde817ae3c041505a3181cccb9d35 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:16 +0200 Subject: [PATCH 57/96] 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 | 71 ++++++++++-------------------- 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, 33 insertions(+), 72 deletions(-) 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; - } + if (IS_ERR(priv->vref)) + return dev_err_probe(&pdev->dev, PTR_ERR(priv->vref), + "vref get failed\n"); - 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->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(&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; - } + 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; } From bfa96be8a49c1548b7d1311022262676d7fc6f30 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:17 +0200 Subject: [PATCH 58/96] 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(-) 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) { From 8facae29c468bd4ac1cabb440cdbac47ac9ac9e1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:18 +0200 Subject: [PATCH 59/96] 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(-) 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", From ed1759093cacbe359597fce1ca0f2831ccb96deb Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:19 +0200 Subject: [PATCH 60/96] 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(-) 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) From a567abf66ec8346ff5e7ad2ed5192136d6c838e7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:20 +0200 Subject: [PATCH 61/96] 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(-) 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) From 75e13a76bf2af7ad890038e9de7235c42a3e5fa6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:21 +0200 Subject: [PATCH 62/96] 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(-) 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) { From 17b7d92324f93066592f52d9b39777a67fa7187b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:22 +0200 Subject: [PATCH 63/96] 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(-) 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) { From eb17f3ed864a29d695e9c5cafd2eea9ee934cdd9 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:23 +0200 Subject: [PATCH 64/96] 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(-) 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) { From 5d2180ce1485863ef2ace9a06fb57f857575142e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:24 +0200 Subject: [PATCH 65/96] 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(-) 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) { From 0d81951dad5a0807277d2751ba2b4f98818b049d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:25 +0200 Subject: [PATCH 66/96] 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(-) 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) { From c10eb9b22cf2f268f1ac78bf1ded7efaf9583940 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:47:26 +0200 Subject: [PATCH 67/96] 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(-) 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) { From 3b0028bd0f03fa60c586cd8c4a6c8265a81dcf9c Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Fri, 28 Aug 2020 16:31:55 -0700 Subject: [PATCH 68/96] docs: abi: iio: Use What: consistently Change "[w|W]hat[:| ]" to What: for consistency. Signed-off-by: Gwendal Grignou Link: https://lore.kernel.org/r/20200828233156.2264689-2-gwendal@chromium.org Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 48 ++++++++++++------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index a15176daf9a8..c20334454dbf 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -406,21 +406,21 @@ Description: Hardware applied calibration offset (assumed to fix production inaccuracies). -What /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibscale -What /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_calibscale -What /sys/bus/iio/devices/iio:deviceX/in_voltageY_i_calibscale -What /sys/bus/iio/devices/iio:deviceX/in_voltageY_q_calibscale -What /sys/bus/iio/devices/iio:deviceX/in_voltage_i_calibscale -What /sys/bus/iio/devices/iio:deviceX/in_voltage_q_calibscale -What /sys/bus/iio/devices/iio:deviceX/in_voltage_calibscale -What /sys/bus/iio/devices/iio:deviceX/in_accel_x_calibscale -What /sys/bus/iio/devices/iio:deviceX/in_accel_y_calibscale -What /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibscale -What /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibscale -What /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibscale -What /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibscale -what /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibscale -what /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibscale +What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibscale +What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_calibscale +What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_i_calibscale +What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_q_calibscale +What: /sys/bus/iio/devices/iio:deviceX/in_voltage_i_calibscale +What: /sys/bus/iio/devices/iio:deviceX/in_voltage_q_calibscale +What: /sys/bus/iio/devices/iio:deviceX/in_voltage_calibscale +What: /sys/bus/iio/devices/iio:deviceX/in_accel_x_calibscale +What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_calibscale +What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibscale +What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibscale +What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibscale +What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibscale +What: /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibscale +What: /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibscale What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_calibscale What: /sys/bus/iio/devices/iio:deviceX/in_pressure_calibscale What: /sys/bus/iio/devices/iio:deviceX/in_illuminance_calibscale @@ -488,7 +488,7 @@ Description: If a discrete set of scale values is available, they are listed in this attribute. -What /sys/bus/iio/devices/iio:deviceX/out_voltageY_hardwaregain +What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_hardwaregain What: /sys/bus/iio/devices/iio:deviceX/in_intensity_hardwaregain What: /sys/bus/iio/devices/iio:deviceX/in_intensity_red_hardwaregain What: /sys/bus/iio/devices/iio:deviceX/in_intensity_green_hardwaregain @@ -763,9 +763,9 @@ What: /sys/.../events/in_voltageY_raw_thresh_falling_value What: /sys/.../events/in_tempY_raw_thresh_rising_value What: /sys/.../events/in_tempY_raw_thresh_falling_value What: /sys/.../events/in_illuminance0_thresh_falling_value -what: /sys/.../events/in_illuminance0_thresh_rising_value -what: /sys/.../events/in_proximity0_thresh_falling_value -what: /sys/.../events/in_proximity0_thresh_rising_value +What: /sys/.../events/in_illuminance0_thresh_rising_value +What: /sys/.../events/in_proximity0_thresh_falling_value +What: /sys/.../events/in_proximity0_thresh_rising_value What: /sys/.../events/in_illuminance_thresh_rising_value What: /sys/.../events/in_illuminance_thresh_falling_value KernelVersion: 2.6.37 @@ -845,11 +845,11 @@ What: /sys/.../events/in_tempY_thresh_rising_hysteresis What: /sys/.../events/in_tempY_thresh_falling_hysteresis What: /sys/.../events/in_tempY_thresh_either_hysteresis What: /sys/.../events/in_illuminance0_thresh_falling_hysteresis -what: /sys/.../events/in_illuminance0_thresh_rising_hysteresis -what: /sys/.../events/in_illuminance0_thresh_either_hysteresis -what: /sys/.../events/in_proximity0_thresh_falling_hysteresis -what: /sys/.../events/in_proximity0_thresh_rising_hysteresis -what: /sys/.../events/in_proximity0_thresh_either_hysteresis +What: /sys/.../events/in_illuminance0_thresh_rising_hysteresis +What: /sys/.../events/in_illuminance0_thresh_either_hysteresis +What: /sys/.../events/in_proximity0_thresh_falling_hysteresis +What: /sys/.../events/in_proximity0_thresh_rising_hysteresis +What: /sys/.../events/in_proximity0_thresh_either_hysteresis KernelVersion: 3.13 Contact: linux-iio@vger.kernel.org Description: From 7e604a3d212ca006802f485f7bac9712a5ddd805 Mon Sep 17 00:00:00 2001 From: Nishant Malpani Date: Tue, 25 Aug 2020 18:15:52 +0530 Subject: [PATCH 69/96] 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(+) 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); From b99095e53a1c01ff8de0928058792711efc00f3c Mon Sep 17 00:00:00 2001 From: Crt Mori Date: Tue, 18 Aug 2020 23:37:33 +0200 Subject: [PATCH 70/96] 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(-) 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); } From 856437dbb85b918c7ed167dea929f1a11aa20cb4 Mon Sep 17 00:00:00 2001 From: Crt Mori Date: Tue, 18 Aug 2020 23:37:34 +0200 Subject: [PATCH 71/96] 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(-) 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; }; From 037697dd264dd35a1f0ee13a3e8e3adb23f46075 Mon Sep 17 00:00:00 2001 From: Crt Mori Date: Tue, 18 Aug 2020 23:37:35 +0200 Subject: [PATCH 72/96] 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(-) 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; } From e02472f74a8120cd5a0be0e7d48c9d95d4cde6a0 Mon Sep 17 00:00:00 2001 From: Crt Mori Date: Tue, 18 Aug 2020 23:37:36 +0200 Subject: [PATCH 73/96] 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(-) 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); From 50677d2882e1844763f455b314fa2225d9da5e56 Mon Sep 17 00:00:00 2001 From: Crt Mori Date: Tue, 18 Aug 2020 23:37:37 +0200 Subject: [PATCH 74/96] 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(-) 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", From b0fc6783d4ae58f796fb183c40dbc7fa3199d51d Mon Sep 17 00:00:00 2001 From: Stefan Popa Date: Mon, 10 Aug 2020 12:32:56 +0300 Subject: [PATCH 75/96] 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(-) 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, From 02a019ff7db58541cb41f0ceca97c560ae752a5e Mon Sep 17 00:00:00 2001 From: Alexandru Tachici Date: Mon, 10 Aug 2020 12:32:57 +0300 Subject: [PATCH 76/96] iio: accel: adxl372: Add additional trigger ABI docs Document use of additional trigger supplied by driver. Signed-off-by: Alexandru Tachici Link: https://lore.kernel.org/r/20200810093257.65929-3-alexandru.tachici@analog.com Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio-accel-adxl372 | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-accel-adxl372 diff --git a/Documentation/ABI/testing/sysfs-bus-iio-accel-adxl372 b/Documentation/ABI/testing/sysfs-bus-iio-accel-adxl372 new file mode 100644 index 000000000000..47e34f865ca1 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-accel-adxl372 @@ -0,0 +1,7 @@ +What: /sys/bus/iio/devices/triggerX/name = "adxl372-devX-peak" +KernelVersion: +Contact: linux-iio@vger.kernel.org +Description: + The adxl372 accelerometer kernel module provides an additional trigger, + which sets the device in a mode in which it will record only the peak acceleration + sensed over the set period of time in the events sysfs. From 71ac24846b7b33906c61ac4fccd74c95c902b546 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 9 Aug 2020 12:17:42 +0100 Subject: [PATCH 77/96] dt-bindings: trivial-devices: Add mcp342x ADCs and drop separate binding doc. These i2c devices have simple bindings, well described by trivial-device.yaml so rather than convert the binding doc to yaml, let us just add them to trivial devices and drop the old binding document. Signed-off-by: Jonathan Cameron Reviewed-by: Rob Herring Cc: Angelo Compagnucci Link: https://lore.kernel.org/r/20200809111753.156236-3-jic23@kernel.org --- .../devicetree/bindings/iio/adc/mcp3422.txt | 19 ------------------- .../devicetree/bindings/trivial-devices.yaml | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 19 deletions(-) delete mode 100644 Documentation/devicetree/bindings/iio/adc/mcp3422.txt diff --git a/Documentation/devicetree/bindings/iio/adc/mcp3422.txt b/Documentation/devicetree/bindings/iio/adc/mcp3422.txt deleted file mode 100644 index 82bcce07255d..000000000000 --- a/Documentation/devicetree/bindings/iio/adc/mcp3422.txt +++ /dev/null @@ -1,19 +0,0 @@ -* Microchip mcp3421/2/3/4/6/7/8 chip family (ADC) - -Required properties: - - compatible: Should be - "microchip,mcp3421" or - "microchip,mcp3422" or - "microchip,mcp3423" or - "microchip,mcp3424" or - "microchip,mcp3425" or - "microchip,mcp3426" or - "microchip,mcp3427" or - "microchip,mcp3428" - - reg: I2C address for the device - -Example: -adc@0 { - compatible = "microchip,mcp3424"; - reg = <0x68>; -}; diff --git a/Documentation/devicetree/bindings/trivial-devices.yaml b/Documentation/devicetree/bindings/trivial-devices.yaml index 4ace8039840a..25cfcc904240 100644 --- a/Documentation/devicetree/bindings/trivial-devices.yaml +++ b/Documentation/devicetree/bindings/trivial-devices.yaml @@ -128,6 +128,22 @@ properties: - mcube,mc3230 # MEMSIC 2-axis 8-bit digital accelerometer - memsic,mxc6225 + # Microchip differential I2C ADC, 1 Channel, 18 bit + - microchip,mcp3421 + # Microchip differential I2C ADC, 2 Channel, 18 bit + - microchip,mcp3422 + # Microchip differential I2C ADC, 2 Channel, 18 bit + - microchip,mcp3423 + # Microchip differential I2C ADC, 4 Channel, 18 bit + - microchip,mcp3424 + # Microchip differential I2C ADC, 1 Channel, 16 bit + - microchip,mcp3425 + # Microchip differential I2C ADC, 2 Channel, 16 bit + - microchip,mcp3426 + # Microchip differential I2C ADC, 2 Channel, 16 bit + - microchip,mcp3427 + # Microchip differential I2C ADC, 4 Channel, 16 bit + - microchip,mcp3428 # Microchip 7-bit Single I2C Digital POT (5k) - microchip,mcp4017-502 # Microchip 7-bit Single I2C Digital POT (10k) From 35edeab4dade40340f74ee7649e9f1c45f673857 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 9 Aug 2020 12:17:43 +0100 Subject: [PATCH 78/96] dt-bindings: iio: adc: ti,adc108s102 yaml conversion Very simple conversion of spi device with reference supply. Added the #io-channel-cells property to allow for consumers. Signed-off-by: Jonathan Cameron Reviewed-by: Rob Herring Cc: Jan Kiszka Link: https://lore.kernel.org/r/20200809111753.156236-4-jic23@kernel.org --- .../bindings/iio/adc/ti,adc108s102.yaml | 47 +++++++++++++++++++ .../bindings/iio/adc/ti-adc108s102.txt | 18 ------- 2 files changed, 47 insertions(+), 18 deletions(-) create mode 100644 Documentation/devicetree/bindings/iio/adc/ti,adc108s102.yaml delete mode 100644 Documentation/devicetree/bindings/iio/adc/ti-adc108s102.txt diff --git a/Documentation/devicetree/bindings/iio/adc/ti,adc108s102.yaml b/Documentation/devicetree/bindings/iio/adc/ti,adc108s102.yaml new file mode 100644 index 000000000000..54955f03df93 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/ti,adc108s102.yaml @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/ti,adc108s102.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments ADC108S102 and ADC128S102 + +maintainers: + - Bogdan Pricop + +description: | + Family of 8 channel, 10/12 bit, SPI, single ended ADCs. + +properties: + compatible: + const: + ti,adc108s102 + + reg: true + vref-supply: true + spi-max-frequency: true + "#io-channel-cells": + const: 1 + +required: + - compatible + - reg + - vref-supply + +additionalProperties: false + +examples: + - | + spi { + #address-cells= <1>; + #size-cells = <0>; + + adc@0 { + compatible = "ti,adc108s102"; + reg = <0>; + vref-supply = <&vdd_supply>; + spi-max-frequency = <1000000>; + #io-channel-cells = <1>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/iio/adc/ti-adc108s102.txt b/Documentation/devicetree/bindings/iio/adc/ti-adc108s102.txt deleted file mode 100644 index bbbbb4a9f58f..000000000000 --- a/Documentation/devicetree/bindings/iio/adc/ti-adc108s102.txt +++ /dev/null @@ -1,18 +0,0 @@ -* Texas Instruments' ADC108S102 and ADC128S102 ADC chip - -Required properties: - - compatible: Should be "ti,adc108s102" - - reg: spi chip select number for the device - - vref-supply: The regulator supply for ADC reference voltage - -Recommended properties: - - spi-max-frequency: Definition as per - Documentation/devicetree/bindings/spi/spi-bus.txt - -Example: -adc@0 { - compatible = "ti,adc108s102"; - reg = <0>; - vref-supply = <&vdd_supply>; - spi-max-frequency = <1000000>; -}; From b713259c30a3337fa3e6ac88925a1ba84fc276d1 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 9 Aug 2020 12:17:44 +0100 Subject: [PATCH 79/96] dt-bindings: iio: adc: lltc,ltc2497 yaml conversion. Very simple binding for this i2c device with a reference supply. Added the #io-channel-cells property to allow for consumers. Signed-off-by: Jonathan Cameron Reviewed-by: Rob Herring Cc: Michael Hennerich Link: https://lore.kernel.org/r/20200809111753.156236-5-jic23@kernel.org --- .../bindings/iio/adc/lltc,ltc2497.yaml | 44 +++++++++++++++++++ .../devicetree/bindings/iio/adc/ltc2497.txt | 13 ------ 2 files changed, 44 insertions(+), 13 deletions(-) create mode 100644 Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml delete mode 100644 Documentation/devicetree/bindings/iio/adc/ltc2497.txt diff --git a/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml b/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml new file mode 100644 index 000000000000..6a176f551d75 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/lltc,ltc2497.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Linear Technology / Analog Devices LTC2497 ADC + +maintainers: + - Michael Hennerich + +description: | + 16bit ADC supporting up to 16 single ended or 8 differential inputs. + I2C interface. + +properties: + compatible: + const: + lltc,ltc2497 + + reg: true + vref-supply: true + "#io-channel-cells": + const: 1 + +required: + - compatible + - reg + - vref-supply + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + adc@76 { + compatible = "lltc,ltc2497"; + reg = <0x76>; + vref-supply = <<c2497_reg>; + #io-channel-cells = <1>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/iio/adc/ltc2497.txt b/Documentation/devicetree/bindings/iio/adc/ltc2497.txt deleted file mode 100644 index a237ed99c0d8..000000000000 --- a/Documentation/devicetree/bindings/iio/adc/ltc2497.txt +++ /dev/null @@ -1,13 +0,0 @@ -* Linear Technology / Analog Devices LTC2497 ADC - -Required properties: - - compatible: Must be "lltc,ltc2497" - - reg: Must contain the ADC I2C address - - vref-supply: The regulator supply for ADC reference voltage - -Example: - ltc2497: adc@76 { - compatible = "lltc,ltc2497"; - reg = <0x76>; - vref-supply = <<c2497_reg>; - }; From cee4a59395f9619acc8b944534890901de8ac4f3 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 9 Aug 2020 12:17:45 +0100 Subject: [PATCH 80/96] dt-bindings: iio: adc: ti,adc161s626 yaml conversion. Simple conversion for this ADC driver. Note that I haven't put limits on the spi-max-sampling-frequency because the adc161s626 doesn't state one clearly defined value. Added the #io-channel-cells property to allow for consumers. Signed-off-by: Jonathan Cameron Reviewed-by: Rob Herring Acked-by: Matt Ranostay Cc: Matt Ranostay Link: https://lore.kernel.org/r/20200809111753.156236-6-jic23@kernel.org --- .../bindings/iio/adc/ti,adc161s626.yaml | 51 +++++++++++++++++++ .../bindings/iio/adc/ti-adc161s626.txt | 18 ------- 2 files changed, 51 insertions(+), 18 deletions(-) create mode 100644 Documentation/devicetree/bindings/iio/adc/ti,adc161s626.yaml delete mode 100644 Documentation/devicetree/bindings/iio/adc/ti-adc161s626.txt diff --git a/Documentation/devicetree/bindings/iio/adc/ti,adc161s626.yaml b/Documentation/devicetree/bindings/iio/adc/ti,adc161s626.yaml new file mode 100644 index 000000000000..3f4f334d6f73 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/ti,adc161s626.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/ti,adc161s626.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments ADC141S626 and ADC161S626 ADCs + +maintainers: + - Matt Ranostay + +description: | + Single channel 14/16bit differential ADCs + +properties: + compatible: + enum: + - ti,adc141s626 + - ti,adc161s626 + + reg: + maxItems: 1 + + spi-max-frequency: true + + vdda-supply: true + + "#io-channel-cells": + const: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "ti,adc161s626"; + vdda-supply = <&vdda_fixed>; + reg = <0>; + spi-max-frequency = <4300000>; + #io-channel-cells = <1>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/iio/adc/ti-adc161s626.txt b/Documentation/devicetree/bindings/iio/adc/ti-adc161s626.txt deleted file mode 100644 index 3d25011f0c99..000000000000 --- a/Documentation/devicetree/bindings/iio/adc/ti-adc161s626.txt +++ /dev/null @@ -1,18 +0,0 @@ -* Texas Instruments ADC141S626 and ADC161S626 chips - -Required properties: - - compatible: Should be "ti,adc141s626" or "ti,adc161s626" - - reg: spi chip select number for the device - - vdda-supply: supply voltage to VDDA pin - -Recommended properties: - - spi-max-frequency: Definition as per - Documentation/devicetree/bindings/spi/spi-bus.txt - -Example: -adc@0 { - compatible = "ti,adc161s626"; - vdda-supply = <&vdda_fixed>; - reg = <0>; - spi-max-frequency = <4300000>; -}; From e6d2aaa942adcc4be71688d9c4ac737cb6cf1327 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 9 Aug 2020 12:17:46 +0100 Subject: [PATCH 81/96] dt-bindings: iio: adc: ti,adc0832 yaml conversion. Simple binding conversion of this SPI ADC binding, with reference voltage. Added the optional property #io-channel-cells to allow for consumers of channels if that makes sense for a given board. Signed-off-by: Jonathan Cameron Reviewed-by: Rob Herring Cc: Akinobu Mita Link: https://lore.kernel.org/r/20200809111753.156236-7-jic23@kernel.org --- .../bindings/iio/adc/ti,adc0832.yaml | 56 +++++++++++++++++++ .../bindings/iio/adc/ti-adc0832.txt | 19 ------- 2 files changed, 56 insertions(+), 19 deletions(-) create mode 100644 Documentation/devicetree/bindings/iio/adc/ti,adc0832.yaml delete mode 100644 Documentation/devicetree/bindings/iio/adc/ti-adc0832.txt diff --git a/Documentation/devicetree/bindings/iio/adc/ti,adc0832.yaml b/Documentation/devicetree/bindings/iio/adc/ti,adc0832.yaml new file mode 100644 index 000000000000..f5a923cc847f --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/ti,adc0832.yaml @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/ti,adc0832.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments ADC0832 and similar ADCs + +maintainers: + - Akinobu Mita + +description: | + 8 bit ADCs with 1, 2, 4 or 8 inputs for single ended or differential + conversion. + +properties: + compatible: + enum: + - ti,adc0831 + - ti,adc0832 + - ti,adc0834 + - ti,adc0838 + + reg: + maxItems: 1 + + spi-max-frequency: true + + vref-supply: + description: External reference, needed to establish input scaling + + "#io-channel-cells": + const: 1 + +required: + - compatible + - reg + - vref-supply + +additionalProperties: false + +examples: + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "ti,adc0832"; + reg = <0>; + vref-supply = <&vdd_supply>; + spi-max-frequency = <200000>; + #io-channel-cells = <1>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/iio/adc/ti-adc0832.txt b/Documentation/devicetree/bindings/iio/adc/ti-adc0832.txt deleted file mode 100644 index d91130587d01..000000000000 --- a/Documentation/devicetree/bindings/iio/adc/ti-adc0832.txt +++ /dev/null @@ -1,19 +0,0 @@ -* Texas Instruments' ADC0831/ADC0832/ADC0832/ADC0838 - -Required properties: - - compatible: Should be one of - * "ti,adc0831" - * "ti,adc0832" - * "ti,adc0834" - * "ti,adc0838" - - reg: spi chip select number for the device - - vref-supply: The regulator supply for ADC reference voltage - - spi-max-frequency: Max SPI frequency to use (< 400000) - -Example: -adc@0 { - compatible = "ti,adc0832"; - reg = <0>; - vref-supply = <&vdd_supply>; - spi-max-frequency = <200000>; -}; From 686b2bd9f41ffbf97cb783aa5377e6bdb32b170a Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 9 Aug 2020 12:17:49 +0100 Subject: [PATCH 82/96] dt-bindings: iio: adc: ti,adc128s052 yaml conversion. Simple binding. Only addition to txt version is as a provider of channels to other devices using the consumer binding. Signed-off-by: Jonathan Cameron Reviewed-by: Rob Herring Cc: Angelo Compagnucci Link: https://lore.kernel.org/r/20200809111753.156236-10-jic23@kernel.org --- .../bindings/iio/adc/ti,adc128s052.yaml | 59 +++++++++++++++++++ .../bindings/iio/adc/ti-adc128s052.txt | 25 -------- 2 files changed, 59 insertions(+), 25 deletions(-) create mode 100644 Documentation/devicetree/bindings/iio/adc/ti,adc128s052.yaml delete mode 100644 Documentation/devicetree/bindings/iio/adc/ti-adc128s052.txt diff --git a/Documentation/devicetree/bindings/iio/adc/ti,adc128s052.yaml b/Documentation/devicetree/bindings/iio/adc/ti,adc128s052.yaml new file mode 100644 index 000000000000..d54a0183f024 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/ti,adc128s052.yaml @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/ti,adc128s052.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments ADC128S052 and similar ADCs + +maintainers: + - Angelo Compagnucci + +description: | + Family of 12 bit SPI ADCs with 2 to 8 channels with a range of different + target sample rates. + +properties: + compatible: + enum: + - ti,adc122s021 + - ti,adc122s051 + - ti,adc122s101 + - ti,adc124s021 + - ti,adc124s051 + - ti,adc124s101 + - ti,adc128s052 + + reg: + maxItems: 1 + + spi-max-frequency: true + + vref-supply: true + + "#io-channel-cells": + const: 1 + +required: + - compatible + - reg + - vref-supply + +additionalProperties: false + +examples: + - | + #include + spi { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "ti,adc128s052"; + reg = <0>; + vref-supply = <&vdd_supply>; + spi-max-frequency = <1000000>; + #io-channel-cells = <1>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/iio/adc/ti-adc128s052.txt b/Documentation/devicetree/bindings/iio/adc/ti-adc128s052.txt deleted file mode 100644 index c07ce1a3f5c4..000000000000 --- a/Documentation/devicetree/bindings/iio/adc/ti-adc128s052.txt +++ /dev/null @@ -1,25 +0,0 @@ -* Texas Instruments' ADC128S052, ADC122S021 and ADC124S021 ADC chip - -Required properties: - - compatible: Should be one of: - - "ti,adc128s052" - - "ti,adc122s021" - - "ti,adc122s051" - - "ti,adc122s101" - - "ti,adc124s021" - - "ti,adc124s051" - - "ti,adc124s101" - - reg: spi chip select number for the device - - vref-supply: The regulator supply for ADC reference voltage - -Recommended properties: - - spi-max-frequency: Definition as per - Documentation/devicetree/bindings/spi/spi-bus.txt - -Example: -adc@0 { - compatible = "ti,adc128s052"; - reg = <0>; - vref-supply = <&vdd_supply>; - spi-max-frequency = <1000000>; -}; From 9727ef55d898167a25816d9f75db87a3a6044bcf Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 9 Aug 2020 12:17:51 +0100 Subject: [PATCH 83/96] dt-bindings: iio: adc: ti,ads8344 yaml conversion Simple binding so easy to convert. Signed-off-by: Jonathan Cameron Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20200809111753.156236-12-jic23@kernel.org --- .../bindings/iio/adc/ti,ads8344.yaml | 51 +++++++++++++++++++ .../bindings/iio/adc/ti-ads8344.txt | 19 ------- 2 files changed, 51 insertions(+), 19 deletions(-) create mode 100644 Documentation/devicetree/bindings/iio/adc/ti,ads8344.yaml delete mode 100644 Documentation/devicetree/bindings/iio/adc/ti-ads8344.txt diff --git a/Documentation/devicetree/bindings/iio/adc/ti,ads8344.yaml b/Documentation/devicetree/bindings/iio/adc/ti,ads8344.yaml new file mode 100644 index 000000000000..b8c398187d5c --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/ti,ads8344.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/ti,ads8344.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments ADS8344 ADC + +maintainers: + - Gregory Clement + +description: | + 16bit 8-channel ADC with single ended inputs. + +properties: + compatible: + const: ti,ads8344 + + reg: + maxItems: 1 + + spi-max-frequency: true + + vref-supply: + description: Supply the 2.5V or 5V reference voltage + + "#io-channel-cells": + const: 1 + +required: + - compatible + - reg + - vref-supply + +additionalProperties: false + +examples: + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "ti,ads8344"; + reg = <0>; + vref-supply = <&refin_supply>; + spi-max-frequency = <10000000>; + #io-channel-cells = <1>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/iio/adc/ti-ads8344.txt b/Documentation/devicetree/bindings/iio/adc/ti-ads8344.txt deleted file mode 100644 index e47c3759a82b..000000000000 --- a/Documentation/devicetree/bindings/iio/adc/ti-ads8344.txt +++ /dev/null @@ -1,19 +0,0 @@ -* Texas Instruments ADS8344 A/DC chip - -Required properties: - - compatible: Must be "ti,ads8344" - - reg: SPI chip select number for the device - - vref-supply: phandle to a regulator node that supplies the - reference voltage - -Recommended properties: - - spi-max-frequency: Definition as per - Documentation/devicetree/bindings/spi/spi-bus.txt - -Example: -adc@0 { - compatible = "ti,ads8344"; - reg = <0>; - vref-supply = <&refin_supply>; - spi-max-frequency = <10000000>; -}; From 9e4e28ac76733af5421ef9113da370c060ac96fa Mon Sep 17 00:00:00 2001 From: Phil Reid Date: Sun, 9 Aug 2020 12:17:52 +0100 Subject: [PATCH 84/96] dt-bindings: iio: adc: tlc4541 - recover accidentally dropped binding doc JC: Seems that I messed up applying the original driver patches, and this file never actually made it into the tree. I have picked up original Ack and Sign-off so as to record the history. Signed-off-by: Phil Reid Signed-off-by: Jonathan Cameron Acked-by: Rob Herring Link: https://lore.kernel.org/r/20200809111753.156236-13-jic23@kernel.org --- .../devicetree/bindings/iio/adc/ti-tlc4541.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/ti-tlc4541.txt diff --git a/Documentation/devicetree/bindings/iio/adc/ti-tlc4541.txt b/Documentation/devicetree/bindings/iio/adc/ti-tlc4541.txt new file mode 100644 index 000000000000..6b2692723a04 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/ti-tlc4541.txt @@ -0,0 +1,17 @@ +* Texas Instruments' TLC4541 + +Required properties: + - compatible: Should be one of + * "ti,tlc4541" + * "ti,tlc3541" + - reg: SPI chip select number for the device + - vref-supply: The regulator supply for ADC reference voltage + - spi-max-frequency: Max SPI frequency to use (<= 200000) + +Example: +adc@0 { + compatible = "ti,tlc4541"; + reg = <0>; + vref-supply = <&vdd_supply>; + spi-max-frequency = <200000>; +}; From e7b61fc4ca5e7c6869f224d56c5c585fea884c94 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 9 Aug 2020 12:17:53 +0100 Subject: [PATCH 85/96] dt-bindings: iio: adc: ti,tlc4541 binding conversion Simple binding so easy to convert. Dropped the stated value of maximum spi bus frequency as it does not seem to correspond to the datasheet. The value of 200kHz is the max sampling frequency of the ADC, not the clock frequency of the SPI bus. Added #io-channel-cells to allow use as a provider of channels to other devices via the consumer binding. Signed-off-by: Jonathan Cameron Reviewed-by: Rob Herring Reviewed-By: Phil Reid Cc: Phil Reid Link: https://lore.kernel.org/r/20200809111753.156236-14-jic23@kernel.org --- .../bindings/iio/adc/ti,tlc4541.yaml | 52 +++++++++++++++++++ .../bindings/iio/adc/ti-tlc4541.txt | 17 ------ 2 files changed, 52 insertions(+), 17 deletions(-) create mode 100644 Documentation/devicetree/bindings/iio/adc/ti,tlc4541.yaml delete mode 100644 Documentation/devicetree/bindings/iio/adc/ti-tlc4541.txt diff --git a/Documentation/devicetree/bindings/iio/adc/ti,tlc4541.yaml b/Documentation/devicetree/bindings/iio/adc/ti,tlc4541.yaml new file mode 100644 index 000000000000..6c2539b3d707 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/ti,tlc4541.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/ti,tlc4541.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments TLC4541 and similar ADCs + +maintainers: + - Phil Reid + +description: | + 14/16bit single channel ADC with SPI interface. + +properties: + compatible: + enum: + - ti,tlc3541 + - ti,tlc4541 + + reg: + maxItems: 1 + + spi-max-frequency: true + + vref-supply: true + + "#io-channel-cells": + const: 1 + +required: + - compatible + - reg + - vref-supply + +additionalProperties: false + +examples: + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "ti,tlc4541"; + reg = <0>; + vref-supply = <&vdd_supply>; + spi-max-frequency = <200000>; + #io-channel-cells = <1>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/iio/adc/ti-tlc4541.txt b/Documentation/devicetree/bindings/iio/adc/ti-tlc4541.txt deleted file mode 100644 index 6b2692723a04..000000000000 --- a/Documentation/devicetree/bindings/iio/adc/ti-tlc4541.txt +++ /dev/null @@ -1,17 +0,0 @@ -* Texas Instruments' TLC4541 - -Required properties: - - compatible: Should be one of - * "ti,tlc4541" - * "ti,tlc3541" - - reg: SPI chip select number for the device - - vref-supply: The regulator supply for ADC reference voltage - - spi-max-frequency: Max SPI frequency to use (<= 200000) - -Example: -adc@0 { - compatible = "ti,tlc4541"; - reg = <0>; - vref-supply = <&vdd_supply>; - spi-max-frequency = <200000>; -}; From 65e02d0b5039f393c1918e992322ebbb5f077490 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Wed, 26 Aug 2020 07:20:11 +0200 Subject: [PATCH 86/96] 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(-) 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); From 8d7eab620713013fab061925775b695a4ff3b258 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 9 Aug 2020 12:17:41 +0100 Subject: [PATCH 87/96] dt-bindings: iio: adc: microchip,mcp3201 yaml conversion. Drops the deprecated compatibles without the vendor name. Whilst the driver continues to support these for old dt blobs, any dt bindings that are actuallly verified against this document should be fixed to add the vendor name. Added the #io-channel-cells property to allow for consumers. Signed-off-by: Jonathan Cameron Reviewed-by: Rob Herring Cc: Oskar Andero Link: https://lore.kernel.org/r/20200809111753.156236-2-jic23@kernel.org --- .../devicetree/bindings/iio/adc/mcp320x.txt | 57 -------------- .../bindings/iio/adc/microchip,mcp3201.yaml | 77 +++++++++++++++++++ 2 files changed, 77 insertions(+), 57 deletions(-) delete mode 100644 Documentation/devicetree/bindings/iio/adc/mcp320x.txt create mode 100644 Documentation/devicetree/bindings/iio/adc/microchip,mcp3201.yaml diff --git a/Documentation/devicetree/bindings/iio/adc/mcp320x.txt b/Documentation/devicetree/bindings/iio/adc/mcp320x.txt deleted file mode 100644 index 56373d643f76..000000000000 --- a/Documentation/devicetree/bindings/iio/adc/mcp320x.txt +++ /dev/null @@ -1,57 +0,0 @@ -* Microchip Analog to Digital Converter (ADC) - -The node for this driver must be a child node of a SPI controller, hence -all mandatory properties described in - - Documentation/devicetree/bindings/spi/spi-bus.txt - -must be specified. - -Required properties: - - compatible: Must be one of the following, depending on the - model: - "mcp3001" (DEPRECATED) - "mcp3002" (DEPRECATED) - "mcp3004" (DEPRECATED) - "mcp3008" (DEPRECATED) - "mcp3201" (DEPRECATED) - "mcp3202" (DEPRECATED) - "mcp3204" (DEPRECATED) - "mcp3208" (DEPRECATED) - "mcp3301" (DEPRECATED) - - "microchip,mcp3001" - "microchip,mcp3002" - "microchip,mcp3004" - "microchip,mcp3008" - "microchip,mcp3201" - "microchip,mcp3202" - "microchip,mcp3204" - "microchip,mcp3208" - "microchip,mcp3301" - "microchip,mcp3550-50" - "microchip,mcp3550-60" - "microchip,mcp3551" - "microchip,mcp3553" - - NOTE: The use of the compatibles with no vendor prefix - is deprecated and only listed because old DT use them. - - - spi-cpha, spi-cpol (boolean): - Either SPI mode (0,0) or (1,1) must be used, so specify - none or both of spi-cpha, spi-cpol. The MCP3550/1/3 - is more efficient in mode (1,1) as only 3 instead of - 4 bytes need to be read from the ADC, but not all SPI - masters support it. - - - vref-supply: Phandle to the external reference voltage supply. - -Examples: -spi_controller { - mcp3x0x@0 { - compatible = "microchip,mcp3002"; - reg = <0>; - spi-max-frequency = <1000000>; - vref-supply = <&vref_reg>; - }; -}; diff --git a/Documentation/devicetree/bindings/iio/adc/microchip,mcp3201.yaml b/Documentation/devicetree/bindings/iio/adc/microchip,mcp3201.yaml new file mode 100644 index 000000000000..cbbac4ce56d6 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/microchip,mcp3201.yaml @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/microchip,mcp3201.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip mcp3201 and similar ADCs + +maintainers: + - Oskar Andero + +description: | + Family of simple ADCs with an I2C inteface. + +properties: + compatible: + enum: + - microchip,mcp3001 + - microchip,mcp3002 + - microchip,mcp3004 + - microchip,mcp3008 + - microchip,mcp3201 + - microchip,mcp3202 + - microchip,mcp3204 + - microchip,mcp3208 + - microchip,mcp3301 + - microchip,mcp3550-50 + - microchip,mcp3550-60 + - microchip,mcp3551 + - microchip,mcp3553 + + reg: + maxItems: 1 + + spi-max-frequency: true + spi-cpha: true + spi-cpol: true + + vref-supply: + description: External reference. + + "#io-channel-cells": + const: 1 + +dependencies: + spi-cpol: [ spi-cpha ] + spi-cpha: [ spi-cpol ] + +required: + - compatible + - reg + - vref-supply + +additionalProperties: false + +examples: + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "microchip,mcp3002"; + reg = <0>; + vref-supply = <&vref_reg>; + spi-cpha; + spi-cpol; + #io-channel-cells = <1>; + }; + adc@1 { + compatible = "microchip,mcp3002"; + reg = <1>; + vref-supply = <&vref_reg>; + spi-max-frequency = <1500000>; + }; + }; +... From 5265b267e303ed07d922e0c353feec1fef1805cc Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 31 Aug 2020 12:08:06 +0300 Subject: [PATCH 88/96] 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(-) 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, From 938d1b3873fc2ceee4569042852e54d9deeb9ec1 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 31 Aug 2020 12:08:07 +0300 Subject: [PATCH 89/96] 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(-) 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) From 700e63dadacdb7eee04650b6e8c66824d585aaf3 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 31 Aug 2020 12:08:08 +0300 Subject: [PATCH 90/96] 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(-) 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); } From 4d9a167a3436b960b25900fb9539d953657cf501 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 31 Aug 2020 12:08:09 +0300 Subject: [PATCH 91/96] 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(-) 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, From 846afc1dbcbf878b3c8e685910ad6ce90d79de4b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 31 Aug 2020 12:08:10 +0300 Subject: [PATCH 92/96] 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(-) 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, From df9f7d4c330d1ca3e124d73a137a7df32ca3ac33 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 31 Aug 2020 12:08:11 +0300 Subject: [PATCH 93/96] 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(-) 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 From 2b09b41dba04092fc198a5098908345f756db160 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 31 Aug 2020 12:08:12 +0300 Subject: [PATCH 94/96] 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(-) 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 From f530f882463c046f851401fa4380cee3e523e0e3 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 31 Aug 2020 12:08:13 +0300 Subject: [PATCH 95/96] 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(-) 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 "); From 2f0472a1f80e6230f126aa0af76e89f85abc37bd Mon Sep 17 00:00:00 2001 From: kernel test robot Date: Tue, 1 Sep 2020 19:30:07 +0100 Subject: [PATCH 96/96] 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(-) 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;