From c0af3b61b50810fd73926be0d5f59cd6d8f8ac52 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 18 Aug 2019 13:23:06 +0200 Subject: [PATCH 01/27] iio: accel: kxcjk1013: Improve comments on KIOX010A and KIOX020A ACPI ids The KIOX010A and KIOX020A ACPI ids go hand in hand, they are used in yoga style 2-in-1s, with KIOX010A indicating the KXCJ91008 sensor in the display of the 2-in-1 and KIOX020A indicating the KXCJ91008 sensor in the base. Improve the existing comment on the "KIOX010A" kx_acpi_match table entry to make clear we are talking about a yoga-style (360 degree hinges) device here and add a similar comment to the "KIOX020A" entry. Signed-off-by: Hans de Goede Signed-off-by: Jonathan Cameron --- drivers/iio/accel/kxcjk-1013.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index 6645771aa349..fee535d6e45b 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -1486,8 +1486,8 @@ static const struct acpi_device_id kx_acpi_match[] = { {"KIOX0008", KXCJ91008}, {"KIOX0009", KXTJ21009}, {"KIOX000A", KXCJ91008}, - {"KIOX010A", KXCJ91008}, /* KXCJ91008 inside the display of a 2-in-1 */ - {"KIOX020A", KXCJ91008}, + {"KIOX010A", KXCJ91008}, /* KXCJ91008 in the display of a yoga 2-in-1 */ + {"KIOX020A", KXCJ91008}, /* KXCJ91008 in the base of a yoga 2-in-1 */ {"KXTJ1009", KXTJ21009}, {"KXJ2109", KXTJ21009}, {"SMO8500", KXCJ91008}, From 519808425e1941563ca25af5caefe7261f6cc8a4 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Fri, 16 Aug 2019 09:28:35 +0300 Subject: [PATCH 02/27] iio: imu: adis16460: fix variable signedness Caught via static-analysis checker: ``` drivers/iio/imu/adis16460.c 152 static int adis16460_set_freq(struct iio_dev *indio_dev, int val, int val2) 153 { 154 struct adis16460 *st = iio_priv(indio_dev); 155 unsigned int t; ^^^^^^^^^^^^^^ 156 157 t = val * 1000 + val2 / 1000; 158 if (t <= 0) ^^^^^^ Unsigned is not less than zero. ``` The types of `val` && `val2` are obtained from the IIO `write_raw` hook, so userspace can provide negative values, which can cause weird behavior after conversion to unsigned. This patch changes the sign of variable `t` so that -EINVAL will be returned for negative values as well. Fixes: db6ed4d23dd1 ("iio: imu: Add support for the ADIS16460 IMU") Reported-by: Dan Carpenter Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/imu/adis16460.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/imu/adis16460.c b/drivers/iio/imu/adis16460.c index 1ef11640ee20..6aed9e84abbf 100644 --- a/drivers/iio/imu/adis16460.c +++ b/drivers/iio/imu/adis16460.c @@ -152,7 +152,7 @@ static int adis16460_debugfs_init(struct iio_dev *indio_dev) static int adis16460_set_freq(struct iio_dev *indio_dev, int val, int val2) { struct adis16460 *st = iio_priv(indio_dev); - unsigned int t; + int t; t = val * 1000 + val2 / 1000; if (t <= 0) From 4be27c2a185da8438951620b2822c8547df428ad Mon Sep 17 00:00:00 2001 From: Mircea Caprioru Date: Mon, 12 Aug 2019 12:00:34 +0300 Subject: [PATCH 03/27] staging: iio: adc: ad7192: Remove platform data This patch removes the reference voltage entry from the platform_data structure. This is no longer needed since the reference voltage is obtained from the device tree. With this we also remove the entire ad7192.h file. The undefined reference voltage warning is promoted to an error signaling a problem with the device tree. Signed-off-by: Mircea Caprioru Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 14 ++---------- drivers/staging/iio/adc/ad7192.h | 37 -------------------------------- 2 files changed, 2 insertions(+), 49 deletions(-) delete mode 100644 drivers/staging/iio/adc/ad7192.h diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index df06e0570f9b..81ea2639c67c 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -25,8 +25,6 @@ #include #include -#include "ad7192.h" - /* Registers */ #define AD7192_REG_COMM 0 /* Communications Register (WO, 8-bit) */ #define AD7192_REG_STAT 0 /* Status Register (RO, 8-bit) */ @@ -666,16 +664,10 @@ static int ad7192_channels_config(struct iio_dev *indio_dev) static int ad7192_probe(struct spi_device *spi) { - const struct ad7192_platform_data *pdata = dev_get_platdata(&spi->dev); struct ad7192_state *st; struct iio_dev *indio_dev; int ret, voltage_uv = 0; - if (!pdata) { - dev_err(&spi->dev, "no platform data?\n"); - return -ENODEV; - } - if (!spi->irq) { dev_err(&spi->dev, "no IRQ?\n"); return -ENODEV; @@ -713,12 +705,10 @@ static int ad7192_probe(struct spi_device *spi) voltage_uv = regulator_get_voltage(st->avdd); - if (pdata->vref_mv) - st->int_vref_mv = pdata->vref_mv; - else if (voltage_uv) + if (voltage_uv) st->int_vref_mv = voltage_uv / 1000; else - dev_warn(&spi->dev, "reference voltage undefined\n"); + dev_err(&spi->dev, "Device tree error, reference voltage undefined\n"); spi_set_drvdata(spi, indio_dev); st->devid = spi_get_device_id(spi)->driver_data; diff --git a/drivers/staging/iio/adc/ad7192.h b/drivers/staging/iio/adc/ad7192.h deleted file mode 100644 index f3669e1df084..000000000000 --- a/drivers/staging/iio/adc/ad7192.h +++ /dev/null @@ -1,37 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * AD7190 AD7192 AD7195 SPI ADC driver - * - * Copyright 2011 Analog Devices Inc. - */ -#ifndef IIO_ADC_AD7192_H_ -#define IIO_ADC_AD7192_H_ - -/* - * TODO: struct ad7192_platform_data needs to go into include/linux/iio - */ - -/** - * struct ad7192_platform_data - platform/board specific information - * @vref_mv: the external reference voltage in millivolt - * @clock_source_sel: [0..3] - * 0 External 4.92 MHz clock connected from MCLK1 to MCLK2 - * 1 External Clock applied to MCLK2 - * 2 Internal 4.92 MHz Clock not available at the MCLK2 pin - * 3 Internal 4.92 MHz Clock available at the MCLK2 pin - * @ext_clk_Hz: the external clock frequency in Hz, if not set - * the driver uses the internal clock (16.776 MHz) - * @refin2_en: REFIN1/REFIN2 Reference Select (AD7190/2 only) - * @rej60_en: 50/60Hz notch filter enable - * @sinc3_en: SINC3 filter enable (default SINC4) - * @chop_en: CHOP mode enable - * @buf_en: buffered input mode enable - * @unipolar_en: unipolar mode enable - * @burnout_curr_en: constant current generators on AIN(+|-) enable - */ - -struct ad7192_platform_data { - u16 vref_mv; -}; - -#endif /* IIO_ADC_AD7192_H_ */ From 77f6a23092c0f5fcf85c6c8894ccc436d8d0d9aa Mon Sep 17 00:00:00 2001 From: Mircea Caprioru Date: Wed, 14 Aug 2019 10:31:47 +0300 Subject: [PATCH 04/27] staging: iio: adc: ad7192: Add low_pass_3db_filter_frequency By adding this option we are able to remove the sync3 field and dt binding. When setting the required cutoff frequency we also determine the ADC configuration for chop and sync filter. Signed-off-by: Mircea Caprioru Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 149 +++++++++++++++++++++++++++---- 1 file changed, 133 insertions(+), 16 deletions(-) diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 81ea2639c67c..e6b660489165 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -143,6 +143,10 @@ #define AD7192_EXT_FREQ_MHZ_MAX 5120000 #define AD7192_INT_FREQ_MHZ 4915200 +#define AD7192_NO_SYNC_FILTER 1 +#define AD7192_SYNC3_FILTER 3 +#define AD7192_SYNC4_FILTER 4 + /* NOTE: * The AD7190/2/5 features a dual use data out ready DOUT/RDY output. * In order to avoid contentions on the SPI bus, it's therefore necessary @@ -250,7 +254,7 @@ static int ad7192_of_clock_select(struct ad7192_state *st) static int ad7192_setup(struct ad7192_state *st, struct device_node *np) { struct iio_dev *indio_dev = spi_get_drvdata(st->sd.spi); - bool rej60_en, sinc3_en, refin2_en, chop_en; + bool rej60_en, refin2_en; bool buf_en, bipolar, burnout_curr_en; unsigned long long scale_uv; int i, ret, id; @@ -282,24 +286,12 @@ static int ad7192_setup(struct ad7192_state *st, struct device_node *np) if (rej60_en) st->mode |= AD7192_MODE_REJ60; - sinc3_en = of_property_read_bool(np, "adi,sinc3-filter-enable"); - if (sinc3_en) - st->mode |= AD7192_MODE_SINC3; - refin2_en = of_property_read_bool(np, "adi,refin2-pins-enable"); if (refin2_en && st->devid != ID_AD7195) st->conf |= AD7192_CONF_REFSEL; - chop_en = of_property_read_bool(np, "adi,chop-enable"); - if (chop_en) { - st->conf |= AD7192_CONF_CHOP; - if (sinc3_en) - st->f_order = 3; /* SINC 3rd order */ - else - st->f_order = 4; /* SINC 4th order */ - } else { - st->f_order = 1; - } + st->conf &= ~AD7192_CONF_CHOP; + st->f_order = AD7192_NO_SYNC_FILTER; buf_en = of_property_read_bool(np, "adi,buffer-enable"); if (buf_en) @@ -311,7 +303,7 @@ static int ad7192_setup(struct ad7192_state *st, struct device_node *np) burnout_curr_en = of_property_read_bool(np, "adi,burnout-currents-enable"); - if (burnout_curr_en && buf_en && !chop_en) { + if (burnout_curr_en && buf_en) { st->conf |= AD7192_CONF_BURN; } else if (burnout_curr_en) { dev_warn(&st->sd.spi->dev, @@ -409,6 +401,49 @@ static ssize_t ad7192_set(struct device *dev, return ret ? ret : len; } +static void ad7192_get_available_filter_freq(struct ad7192_state *st, + int *freq) +{ + unsigned int fadc; + + /* Formulas for filter at page 25 of the datasheet */ + fadc = DIV_ROUND_CLOSEST(st->fclk, + AD7192_SYNC4_FILTER * AD7192_MODE_RATE(st->mode)); + freq[0] = DIV_ROUND_CLOSEST(fadc * 240, 1024); + + fadc = DIV_ROUND_CLOSEST(st->fclk, + AD7192_SYNC3_FILTER * AD7192_MODE_RATE(st->mode)); + freq[1] = DIV_ROUND_CLOSEST(fadc * 240, 1024); + + fadc = DIV_ROUND_CLOSEST(st->fclk, AD7192_MODE_RATE(st->mode)); + freq[2] = DIV_ROUND_CLOSEST(fadc * 230, 1024); + freq[3] = DIV_ROUND_CLOSEST(fadc * 272, 1024); +} + +static ssize_t ad7192_show_filter_avail(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct ad7192_state *st = iio_priv(indio_dev); + unsigned int freq_avail[4], i; + size_t len = 0; + + ad7192_get_available_filter_freq(st, freq_avail); + + for (i = 0; i < ARRAY_SIZE(freq_avail); i++) + len += scnprintf(buf + len, PAGE_SIZE - len, + "%d.%d ", freq_avail[i] / 1000, + freq_avail[i] % 1000); + + buf[len - 1] = '\n'; + + return len; +} + +static IIO_DEVICE_ATTR(filter_low_pass_3db_frequency_available, + 0444, ad7192_show_filter_avail, NULL, 0); + static IIO_DEVICE_ATTR(bridge_switch_en, 0644, ad7192_show_bridge_switch, ad7192_set, AD7192_REG_GPOCON); @@ -418,6 +453,7 @@ static IIO_DEVICE_ATTR(ac_excitation_en, 0644, AD7192_REG_MODE); static struct attribute *ad7192_attributes[] = { + &iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr, &iio_dev_attr_bridge_switch_en.dev_attr.attr, &iio_dev_attr_ac_excitation_en.dev_attr.attr, NULL @@ -428,6 +464,7 @@ static const struct attribute_group ad7192_attribute_group = { }; static struct attribute *ad7195_attributes[] = { + &iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr, &iio_dev_attr_bridge_switch_en.dev_attr.attr, NULL }; @@ -441,6 +478,75 @@ static unsigned int ad7192_get_temp_scale(bool unipolar) return unipolar ? 2815 * 2 : 2815; } +static int ad7192_set_3db_filter_freq(struct ad7192_state *st, + int val, int val2) +{ + int freq_avail[4], i, ret, freq; + unsigned int diff_new, diff_old; + int idx = 0; + + diff_old = U32_MAX; + freq = val * 1000 + val2; + + ad7192_get_available_filter_freq(st, freq_avail); + + for (i = 0; i < ARRAY_SIZE(freq_avail); i++) { + diff_new = abs(freq - freq_avail[i]); + if (diff_new < diff_old) { + diff_old = diff_new; + idx = i; + } + } + + switch (idx) { + case 0: + st->f_order = AD7192_SYNC4_FILTER; + st->mode &= ~AD7192_MODE_SINC3; + + st->conf |= AD7192_CONF_CHOP; + break; + case 1: + st->f_order = AD7192_SYNC3_FILTER; + st->mode |= AD7192_MODE_SINC3; + + st->conf |= AD7192_CONF_CHOP; + break; + case 2: + st->f_order = AD7192_NO_SYNC_FILTER; + st->mode &= ~AD7192_MODE_SINC3; + + st->conf &= ~AD7192_CONF_CHOP; + break; + case 3: + st->f_order = AD7192_NO_SYNC_FILTER; + st->mode |= AD7192_MODE_SINC3; + + st->conf &= ~AD7192_CONF_CHOP; + break; + } + + ret = ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); + if (ret < 0) + return ret; + + return ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf); +} + +static int ad7192_get_3db_filter_freq(struct ad7192_state *st) +{ + unsigned int fadc; + + fadc = DIV_ROUND_CLOSEST(st->fclk, + st->f_order * AD7192_MODE_RATE(st->mode)); + + if (st->conf & AD7192_CONF_CHOP) + return DIV_ROUND_CLOSEST(fadc * 240, 1024); + if (st->mode & AD7192_MODE_SINC3) + return DIV_ROUND_CLOSEST(fadc * 272, 1024); + else + return DIV_ROUND_CLOSEST(fadc * 230, 1024); +} + static int ad7192_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, @@ -481,6 +587,10 @@ static int ad7192_read_raw(struct iio_dev *indio_dev, *val = st->fclk / (st->f_order * 1024 * AD7192_MODE_RATE(st->mode)); return IIO_VAL_INT; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + *val = ad7192_get_3db_filter_freq(st); + *val2 = 1000; + return IIO_VAL_FRACTIONAL; } return -EINVAL; @@ -535,6 +645,9 @@ static int ad7192_write_raw(struct iio_dev *indio_dev, st->mode |= AD7192_MODE_RATE(div); ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); break; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + ret = ad7192_set_3db_filter_freq(st, val, val2 / 1000); + break; default: ret = -EINVAL; } @@ -553,6 +666,8 @@ static int ad7192_write_raw_get_fmt(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_NANO; case IIO_CHAN_INFO_SAMP_FREQ: return IIO_VAL_INT; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } @@ -653,6 +768,8 @@ static int ad7192_channels_config(struct iio_dev *indio_dev) for (i = 0; i < indio_dev->num_channels; i++) { *chan = channels[i]; + chan->info_mask_shared_by_all |= + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY); if (chan->type != IIO_TEMP) chan->info_mask_shared_by_type_available |= BIT(IIO_CHAN_INFO_SCALE); From f7356e47032c5f0e9ada486f1d7a90468f2b67da Mon Sep 17 00:00:00 2001 From: Mircea Caprioru Date: Sun, 18 Aug 2019 19:43:54 +0100 Subject: [PATCH 05/27] dt-bindings: iio: adc: ad7192: Add binding documentation for AD7192 This patch add device tree binding documentation for AD7192 adc in YAML format. Signed-off-by: Mircea Caprioru Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/adc/adi,ad7192.yaml | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml new file mode 100644 index 000000000000..676ec42e1438 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml @@ -0,0 +1,121 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# Copyright 2019 Analog Devices Inc. +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/bindings/iio/adc/adi,ad7192.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices AD7192 ADC device driver + +maintainers: + - Michael Hennerich + +description: | + Bindings for the Analog Devices AD7192 ADC device. Datasheet can be + found here: + https://www.analog.com/media/en/technical-documentation/data-sheets/AD7192.pdf + +properties: + compatible: + enum: + - adi,ad7190 + - adi,ad7192 + - adi,ad7193 + - adi,ad7195 + + reg: + maxItems: 1 + + spi-cpol: true + + spi-cpha: true + + clocks: + maxItems: 1 + description: phandle to the master clock (mclk) + + clock-names: + items: + - const: mclk + + interrupts: + maxItems: 1 + + dvdd-supply: + description: DVdd voltage supply + items: + - const: dvdd + + avdd-supply: + description: AVdd voltage supply + items: + - const: avdd + + adi,rejection-60-Hz-enable: + description: | + This bit enables a notch at 60 Hz when the first notch of the sinc + filter is at 50 Hz. When REJ60 is set, a filter notch is placed at + 60 Hz when the sinc filter first notch is at 50 Hz. This allows + simultaneous 50 Hz/ 60 Hz rejection. + type: boolean + + adi,refin2-pins-enable: + description: | + External reference applied between the P1/REFIN2(+) and P0/REFIN2(−) pins. + type: boolean + + adi,buffer-enable: + description: | + Enables the buffer on the analog inputs. If cleared, the analog inputs + are unbuffered, lowering the power consumption of the device. If this + bit is set, the analog inputs are buffered, allowing the user to place + source impedances on the front end without contributing gain errors to + the system. + type: boolean + + adi,burnout-currents-enable: + description: | + When this bit is set to 1, the 500 nA current sources in the signal + path are enabled. When BURN = 0, the burnout currents are disabled. + The burnout currents can be enabled only when the buffer is active + and when chop is disabled. + type: boolean + + bipolar: + description: see Documentation/devicetree/bindings/iio/adc/adc.txt + type: boolean + +required: + - compatible + - reg + - clocks + - clock-names + - interrupts + - dvdd-supply + - avdd-supply + - spi-cpol + - spi-cpha + +examples: + - | + spi0 { + adc@0 { + compatible = "adi,ad7192"; + reg = <0>; + spi-max-frequency = <1000000>; + spi-cpol; + spi-cpha; + clocks = <&ad7192_mclk>; + clock-names = "mclk"; + #interrupt-cells = <2>; + interrupts = <25 0x2>; + interrupt-parent = <&gpio>; + dvdd-supply = <&dvdd>; + avdd-supply = <&avdd>; + + adi,refin2-pins-enable; + adi,rejection-60-Hz-enable; + adi,buffer-enable; + adi,burnout-currents-enable; + }; + }; From 62ed7a81ef81b501a0ef3ecda532a34c6b4deb9b Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Tue, 13 Aug 2019 09:02:34 +0300 Subject: [PATCH 06/27] MAINTAINERS: ftm-quaddec: Fix typo in a filepath Fix typo (s/quadddec/quaddec/) in the path to the documentation. Cc: linux-iio@vger.kernel.org Fixes: 517b2d045aeb ("MAINTAINERS: add counter/ftm-quaddec driver entry") Signed-off-by: Denis Efremov Acked-by: Patrick Havelange Signed-off-by: Jonathan Cameron --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 429d61119980..ac3a5cd6a682 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6329,7 +6329,7 @@ FLEXTIMER FTM-QUADDEC DRIVER M: Patrick Havelange L: linux-iio@vger.kernel.org S: Maintained -F: Documentation/ABI/testing/sysfs-bus-counter-ftm-quadddec +F: Documentation/ABI/testing/sysfs-bus-counter-ftm-quaddec F: Documentation/devicetree/bindings/counter/ftm-quaddec.txt F: drivers/counter/ftm-quaddec.c From b311da85f7944a98fdc45c2fc92d74234e22995c Mon Sep 17 00:00:00 2001 From: Rodrigo Ribeiro Date: Tue, 13 Aug 2019 16:31:01 -0300 Subject: [PATCH 07/27] staging: iio: accel: adis16240: Improve readability on write_raw function Replace shift and minus operation by GENMASK macro and remove the local variables used to store intermediate data. Signed-off-by: Rodrigo Ribeiro Carvalho Reviewed-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/staging/iio/accel/adis16240.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/iio/accel/adis16240.c b/drivers/staging/iio/accel/adis16240.c index 62f4b3b1b457..82099db4bf0c 100644 --- a/drivers/staging/iio/accel/adis16240.c +++ b/drivers/staging/iio/accel/adis16240.c @@ -309,15 +309,12 @@ static int adis16240_write_raw(struct iio_dev *indio_dev, long mask) { struct adis *st = iio_priv(indio_dev); - int bits = 10; - s16 val16; u8 addr; switch (mask) { case IIO_CHAN_INFO_CALIBBIAS: - val16 = val & ((1 << bits) - 1); addr = adis16240_addresses[chan->scan_index][0]; - return adis_write_reg_16(st, addr, val16); + return adis_write_reg_16(st, addr, val & GENMASK(9, 0)); } return -EINVAL; } From 2715a28105c6b2cd75e2a594e45f8b57dde783f0 Mon Sep 17 00:00:00 2001 From: Chuhong Yuan Date: Sun, 11 Aug 2019 20:51:46 +0800 Subject: [PATCH 08/27] iio: adc: max1027: Use device-managed APIs Use device-managed APIs to simplify the code. Signed-off-by: Chuhong Yuan Signed-off-by: Jonathan Cameron --- drivers/iio/adc/max1027.c | 38 +++++++------------------------------- 1 file changed, 7 insertions(+), 31 deletions(-) diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c index da84adfdb819..214883458582 100644 --- a/drivers/iio/adc/max1027.c +++ b/drivers/iio/adc/max1027.c @@ -427,8 +427,9 @@ static int max1027_probe(struct spi_device *spi) return -ENOMEM; } - ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, - &max1027_trigger_handler, NULL); + ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, + &iio_pollfunc_store_time, + &max1027_trigger_handler, NULL); if (ret < 0) { dev_err(&indio_dev->dev, "Failed to setup buffer\n"); return ret; @@ -439,7 +440,7 @@ static int max1027_probe(struct spi_device *spi) if (st->trig == NULL) { ret = -ENOMEM; dev_err(&indio_dev->dev, "Failed to allocate iio trigger\n"); - goto fail_trigger_alloc; + return ret; } st->trig->ops = &max1027_trigger_ops; @@ -454,7 +455,7 @@ static int max1027_probe(struct spi_device *spi) spi->dev.driver->name, st->trig); if (ret < 0) { dev_err(&indio_dev->dev, "Failed to allocate IRQ.\n"); - goto fail_dev_register; + return ret; } /* Disable averaging */ @@ -462,34 +463,10 @@ static int max1027_probe(struct spi_device *spi) ret = spi_write(st->spi, &st->reg, 1); if (ret < 0) { dev_err(&indio_dev->dev, "Failed to configure averaging register\n"); - goto fail_dev_register; + return ret; } - ret = iio_device_register(indio_dev); - if (ret < 0) { - dev_err(&indio_dev->dev, "Failed to register iio device\n"); - goto fail_dev_register; - } - - return 0; - -fail_dev_register: -fail_trigger_alloc: - iio_triggered_buffer_cleanup(indio_dev); - - return ret; -} - -static int max1027_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - - pr_debug("%s: remove(spi = 0x%p)\n", __func__, spi); - - iio_device_unregister(indio_dev); - iio_triggered_buffer_cleanup(indio_dev); - - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static struct spi_driver max1027_driver = { @@ -498,7 +475,6 @@ static struct spi_driver max1027_driver = { .of_match_table = of_match_ptr(max1027_adc_dt_ids), }, .probe = max1027_probe, - .remove = max1027_remove, .id_table = max1027_id, }; module_spi_driver(max1027_driver); From 473d12f7638c93acbd9296a8cd455b203d5eb528 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 19 Jun 2019 17:07:02 +0300 Subject: [PATCH 09/27] iio: hid-sensor-attributes: Convert to use int_pow() Instead of linear approach to calculate power of 10, use generic int_pow() which does it better. Signed-off-by: Andy Shevchenko Signed-off-by: Jonathan Cameron --- .../hid-sensors/hid-sensor-attributes.c | 53 ++++++++----------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c index a8a3fe428d8d..b9dd19b34267 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -68,16 +69,6 @@ static struct { {HID_USAGE_SENSOR_HUMIDITY, 0, 1000, 0}, }; -static int pow_10(unsigned power) -{ - int i; - int ret = 1; - for (i = 0; i < power; ++i) - ret = ret * 10; - - return ret; -} - static void simple_div(int dividend, int divisor, int *whole, int *micro_frac) { @@ -96,14 +87,14 @@ static void simple_div(int dividend, int divisor, int *whole, rem *= 10; exp++; } - *micro_frac = (rem / divisor) * pow_10(6-exp); + *micro_frac = (rem / divisor) * int_pow(10, 6 - exp); } } static void split_micro_fraction(unsigned int no, int exp, int *val1, int *val2) { - *val1 = no/pow_10(exp); - *val2 = no%pow_10(exp) * pow_10(6-exp); + *val1 = no / int_pow(10, exp); + *val2 = no % int_pow(10, exp) * int_pow(10, 6 - exp); } /* @@ -125,7 +116,7 @@ static void convert_from_vtf_format(u32 value, int size, int exp, } exp = hid_sensor_convert_exponent(exp); if (exp >= 0) { - *val1 = sign * value * pow_10(exp); + *val1 = sign * value * int_pow(10, exp); *val2 = 0; } else { split_micro_fraction(value, -exp, val1, val2); @@ -145,10 +136,10 @@ static u32 convert_to_vtf_format(int size, int exp, int val1, int val2) sign = -1; exp = hid_sensor_convert_exponent(exp); if (exp < 0) { - value = abs(val1) * pow_10(-exp); - value += abs(val2) / pow_10(6+exp); + value = abs(val1) * int_pow(10, -exp); + value += abs(val2) / int_pow(10, 6 + exp); } else - value = abs(val1) / pow_10(exp); + value = abs(val1) / int_pow(10, exp); if (sign < 0) value = ((1LL << (size * 8)) - value); @@ -211,12 +202,12 @@ int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st, if (val1 < 0 || val2 < 0) return -EINVAL; - value = val1 * pow_10(6) + val2; + value = val1 * int_pow(10, 6) + val2; if (value) { if (st->poll.units == HID_USAGE_SENSOR_UNITS_MILLISECOND) - value = pow_10(9)/value; + value = int_pow(10, 9) / value; else if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND) - value = pow_10(6)/value; + value = int_pow(10, 6) / value; else value = 0; } @@ -311,34 +302,34 @@ static void adjust_exponent_nano(int *val0, int *val1, int scale0, int rem; if (exp > 0) { - *val0 = scale0 * pow_10(exp); + *val0 = scale0 * int_pow(10, exp); res = 0; if (exp > 9) { *val1 = 0; return; } for (i = 0; i < exp; ++i) { - x = scale1 / pow_10(8 - i); - res += (pow_10(exp - 1 - i) * x); - scale1 = scale1 % pow_10(8 - i); + x = scale1 / int_pow(10, 8 - i); + res += int_pow(10, exp - 1 - i) * x; + scale1 = scale1 % int_pow(10, 8 - i); } *val0 += res; - *val1 = scale1 * pow_10(exp); + *val1 = scale1 * int_pow(10, exp); } else if (exp < 0) { exp = abs(exp); if (exp > 9) { *val0 = *val1 = 0; return; } - *val0 = scale0 / pow_10(exp); - rem = scale0 % pow_10(exp); + *val0 = scale0 / int_pow(10, exp); + rem = scale0 % int_pow(10, exp); res = 0; for (i = 0; i < (9 - exp); ++i) { - x = scale1 / pow_10(8 - i); - res += (pow_10(8 - exp - i) * x); - scale1 = scale1 % pow_10(8 - i); + x = scale1 / int_pow(10, 8 - i); + res += int_pow(10, 8 - exp - i) * x; + scale1 = scale1 % int_pow(10, 8 - i); } - *val1 = rem * pow_10(9 - exp) + res; + *val1 = rem * int_pow(10, 9 - exp) + res; } else { *val0 = scale0; *val1 = scale1; From 8de877d2bba5c3b83f6fce48965fbd89677be097 Mon Sep 17 00:00:00 2001 From: Freeman Liu Date: Thu, 25 Jul 2019 14:33:50 +0800 Subject: [PATCH 10/27] iio: adc: sc27xx: Change to polling mode to read data On Spreadtrum platform, the headphone will read one ADC channel multiple times to identify the headphone type, and the headphone identification is sensitive of the ADC reading time. And we found it will take longer time to reading ADC data by using interrupt mode comparing with the polling mode, thus we should change to polling mode to improve the efficiency of reading data, which can identify the headphone type successfully. Signed-off-by: Freeman Liu Signed-off-by: Baolin Wang Signed-off-by: Jonathan Cameron --- drivers/iio/adc/sc27xx_adc.c | 81 ++++++++++++------------------------ 1 file changed, 27 insertions(+), 54 deletions(-) diff --git a/drivers/iio/adc/sc27xx_adc.c b/drivers/iio/adc/sc27xx_adc.c index c2203a46f0d8..a6c046575ec3 100644 --- a/drivers/iio/adc/sc27xx_adc.c +++ b/drivers/iio/adc/sc27xx_adc.c @@ -3,7 +3,6 @@ #include #include -#include #include #include #include @@ -46,14 +45,18 @@ /* Bits definitions for SC27XX_ADC_INT_CLR registers */ #define SC27XX_ADC_IRQ_CLR BIT(0) +/* Bits definitions for SC27XX_ADC_INT_RAW registers */ +#define SC27XX_ADC_IRQ_RAW BIT(0) + /* Mask definition for SC27XX_ADC_DATA register */ #define SC27XX_ADC_DATA_MASK GENMASK(11, 0) /* Timeout (ms) for the trylock of hardware spinlocks */ #define SC27XX_ADC_HWLOCK_TIMEOUT 5000 -/* Timeout (ms) for ADC data conversion according to ADC datasheet */ -#define SC27XX_ADC_RDY_TIMEOUT 100 +/* Timeout (us) for ADC data conversion according to ADC datasheet */ +#define SC27XX_ADC_RDY_TIMEOUT 1000000 +#define SC27XX_ADC_POLL_RAW_STATUS 500 /* Maximum ADC channel number */ #define SC27XX_ADC_CHANNEL_MAX 32 @@ -72,10 +75,8 @@ struct sc27xx_adc_data { * subsystems which will access the unique ADC controller. */ struct hwspinlock *hwlock; - struct completion completion; int channel_scale[SC27XX_ADC_CHANNEL_MAX]; u32 base; - int value; int irq; }; @@ -188,9 +189,7 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel, int scale, int *val) { int ret; - u32 tmp; - - reinit_completion(&data->completion); + u32 tmp, value, status; ret = hwspin_lock_timeout_raw(data->hwlock, SC27XX_ADC_HWLOCK_TIMEOUT); if (ret) { @@ -203,6 +202,11 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel, if (ret) goto unlock_adc; + ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_INT_CLR, + SC27XX_ADC_IRQ_CLR, SC27XX_ADC_IRQ_CLR); + if (ret) + goto disable_adc; + /* Configure the channel id and scale */ tmp = (scale << SC27XX_ADC_SCALE_SHIFT) & SC27XX_ADC_SCALE_MASK; tmp |= channel & SC27XX_ADC_CHN_ID_MASK; @@ -226,15 +230,22 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel, if (ret) goto disable_adc; - ret = wait_for_completion_timeout(&data->completion, - msecs_to_jiffies(SC27XX_ADC_RDY_TIMEOUT)); - if (!ret) { - dev_err(data->dev, "read ADC data timeout\n"); - ret = -ETIMEDOUT; - } else { - ret = 0; + ret = regmap_read_poll_timeout(data->regmap, + data->base + SC27XX_ADC_INT_RAW, + status, (status & SC27XX_ADC_IRQ_RAW), + SC27XX_ADC_POLL_RAW_STATUS, + SC27XX_ADC_RDY_TIMEOUT); + if (ret) { + dev_err(data->dev, "read adc timeout, status = 0x%x\n", status); + goto disable_adc; } + ret = regmap_read(data->regmap, data->base + SC27XX_ADC_DATA, &value); + if (ret) + goto disable_adc; + + value &= SC27XX_ADC_DATA_MASK; + disable_adc: regmap_update_bits(data->regmap, data->base + SC27XX_ADC_CTL, SC27XX_ADC_EN, 0); @@ -242,32 +253,11 @@ unlock_adc: hwspin_unlock_raw(data->hwlock); if (!ret) - *val = data->value; + *val = value; return ret; } -static irqreturn_t sc27xx_adc_isr(int irq, void *dev_id) -{ - struct sc27xx_adc_data *data = dev_id; - int ret; - - ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_INT_CLR, - SC27XX_ADC_IRQ_CLR, SC27XX_ADC_IRQ_CLR); - if (ret) - return IRQ_RETVAL(ret); - - ret = regmap_read(data->regmap, data->base + SC27XX_ADC_DATA, - &data->value); - if (ret) - return IRQ_RETVAL(ret); - - data->value &= SC27XX_ADC_DATA_MASK; - complete(&data->completion); - - return IRQ_HANDLED; -} - static void sc27xx_adc_volt_ratio(struct sc27xx_adc_data *data, int channel, int scale, u32 *div_numerator, u32 *div_denominator) @@ -454,11 +444,6 @@ static int sc27xx_adc_enable(struct sc27xx_adc_data *data) if (ret) goto disable_adc; - ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_INT_EN, - SC27XX_ADC_IRQ_EN, SC27XX_ADC_IRQ_EN); - if (ret) - goto disable_clk; - /* ADC channel scales' calibration from nvmem device */ ret = sc27xx_adc_scale_calibration(data, true); if (ret) @@ -484,9 +469,6 @@ static void sc27xx_adc_disable(void *_data) { struct sc27xx_adc_data *data = _data; - regmap_update_bits(data->regmap, data->base + SC27XX_ADC_INT_EN, - SC27XX_ADC_IRQ_EN, 0); - /* Disable ADC work clock and controller clock */ regmap_update_bits(data->regmap, SC27XX_ARM_CLK_EN, SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN, 0); @@ -551,7 +533,6 @@ static int sc27xx_adc_probe(struct platform_device *pdev) return ret; } - init_completion(&sc27xx_data->completion); sc27xx_data->dev = dev; ret = sc27xx_adc_enable(sc27xx_data); @@ -566,14 +547,6 @@ static int sc27xx_adc_probe(struct platform_device *pdev) return ret; } - ret = devm_request_threaded_irq(dev, sc27xx_data->irq, NULL, - sc27xx_adc_isr, IRQF_ONESHOT, - pdev->name, sc27xx_data); - if (ret) { - dev_err(dev, "failed to request ADC irq\n"); - return ret; - } - indio_dev->dev.parent = dev; indio_dev->name = dev_name(dev); indio_dev->modes = INDIO_DIRECT_MODE; From a5913d009b28a2386326143c70fdbe577ea9478d Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 12 Aug 2019 14:41:41 +0200 Subject: [PATCH 11/27] tools: iio: add .gitignore The generated files must not be tracked by git. Add a local .gitignore. Signed-off-by: Bartosz Golaszewski Signed-off-by: Jonathan Cameron --- tools/iio/.gitignore | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 tools/iio/.gitignore diff --git a/tools/iio/.gitignore b/tools/iio/.gitignore new file mode 100644 index 000000000000..3758202618bd --- /dev/null +++ b/tools/iio/.gitignore @@ -0,0 +1,4 @@ +iio_event_monitor +iio_generic_buffer +lsiio +include/ From d2a415c86c6b07c10ba2decc7c9edb21d58f9c01 Mon Sep 17 00:00:00 2001 From: Stefan Popa Date: Wed, 21 Aug 2019 17:16:53 +0300 Subject: [PATCH 12/27] iio: adc: ad7606: Add support for AD7606B ADC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The AD7606B is a 16-bit ADC that supports simultaneous sampling of 8 channels. It is pin compatible to AD7606, but adds extra modes by writing to the register map. The AD7606B can be configured to work in software mode by setting all oversampling pins to high. This mode is selected by default. The oversampling ratio is configured from the OS_MODE register (address 0x08) with the addition of OS=128 and OS=256 that were not available in hardware mode. The device is configured to output data on a single spi channel, but this configuration must be done right after restart. That is why the delay was removed for devices which doesn't require it. Moreover, in software mode, the range gpio has no longer its function. Instead, the scale can be configured individually for each channel from the RANGE_CH registers (address 0x03 to 0x06). Besides the already supported ±10 V and ±5 V ranges, software mode can also accommodate the ±2.5 V range. Signed-off-by: Stefan Popa Co-developed-by: Beniamin Bia Signed-off-by: Beniamin Bia Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ad7606.c | 13 ++++- drivers/iio/adc/ad7606.h | 4 ++ drivers/iio/adc/ad7606_spi.c | 109 ++++++++++++++++++++++++++++++++++- 3 files changed, 123 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c index ed2d08437e5d..f5ba94c03a8d 100644 --- a/drivers/iio/adc/ad7606.c +++ b/drivers/iio/adc/ad7606.c @@ -410,12 +410,19 @@ static const struct ad7606_chip_info ad7606_chip_info_tbl[] = { .oversampling_avail = ad7606_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), }, + [ID_AD7606B] = { + .channels = ad7606_channels, + .num_channels = 9, + .oversampling_avail = ad7606_oversampling_avail, + .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), + }, [ID_AD7616] = { .channels = ad7616_channels, .num_channels = 17, .oversampling_avail = ad7616_oversampling_avail, .oversampling_num = ARRAY_SIZE(ad7616_oversampling_avail), .os_req_reset = true, + .init_delay_ms = 15, }, }; @@ -631,8 +638,10 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); /* AD7616 requires al least 15ms to reconfigure after a reset */ - if (msleep_interruptible(15)) - return -ERESTARTSYS; + if (st->chip_info->init_delay_ms) { + if (msleep_interruptible(st->chip_info->init_delay_ms)) + return -ERESTARTSYS; + } st->write_scale = ad7606_write_scale_hw; st->write_os = ad7606_write_os_hw; diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h index eeaaa8b905db..9350ef1f63b5 100644 --- a/drivers/iio/adc/ad7606.h +++ b/drivers/iio/adc/ad7606.h @@ -46,6 +46,8 @@ * oversampling ratios. * @oversampling_num number of elements stored in oversampling_avail array * @os_req_reset some devices require a reset to update oversampling + * @init_delay_ms required delay in miliseconds for initialization + * after a restart */ struct ad7606_chip_info { const struct iio_chan_spec *channels; @@ -53,6 +55,7 @@ struct ad7606_chip_info { const unsigned int *oversampling_avail; unsigned int oversampling_num; bool os_req_reset; + unsigned long init_delay_ms; }; /** @@ -155,6 +158,7 @@ enum ad7606_supported_device_ids { ID_AD7606_8, ID_AD7606_6, ID_AD7606_4, + ID_AD7606B, ID_AD7616, }; diff --git a/drivers/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c index 98ed52b74507..29945ad07dca 100644 --- a/drivers/iio/adc/ad7606_spi.c +++ b/drivers/iio/adc/ad7606_spi.c @@ -28,9 +28,23 @@ * an offset of 2 for register address. */ #define AD7616_RANGE_CH_ADDR(ch) ((ch) >> 2) -/* The range of the channel is stored on 2 bits*/ +/* The range of the channel is stored in 2 bits */ #define AD7616_RANGE_CH_MSK(ch) (0b11 << (((ch) & 0b11) * 2)) #define AD7616_RANGE_CH_MODE(ch, mode) ((mode) << ((((ch) & 0b11)) * 2)) + +#define AD7606_CONFIGURATION_REGISTER 0x02 +#define AD7606_SINGLE_DOUT 0x00 + +/* + * Range for AD7606B channels are stored in registers starting with address 0x3. + * Each register stores range for 2 channels(4 bits per channel). + */ +#define AD7606_RANGE_CH_MSK(ch) (GENMASK(3, 0) << (4 * ((ch) & 0x1))) +#define AD7606_RANGE_CH_MODE(ch, mode) \ + ((GENMASK(3, 0) & mode) << (4 * ((ch) & 0x1))) +#define AD7606_RANGE_CH_ADDR(ch) (0x03 + ((ch) >> 1)) +#define AD7606_OS_MODE 0x08 + static const struct iio_chan_spec ad7616_sw_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(16), AD7616_CHANNEL(0), @@ -51,6 +65,22 @@ static const struct iio_chan_spec ad7616_sw_channels[] = { AD7616_CHANNEL(15), }; +static const struct iio_chan_spec ad7606b_sw_channels[] = { + IIO_CHAN_SOFT_TIMESTAMP(8), + AD7616_CHANNEL(0), + AD7616_CHANNEL(1), + AD7616_CHANNEL(2), + AD7616_CHANNEL(3), + AD7616_CHANNEL(4), + AD7616_CHANNEL(5), + AD7616_CHANNEL(6), + AD7616_CHANNEL(7), +}; + +static const unsigned int ad7606B_oversampling_avail[9] = { + 1, 2, 4, 8, 16, 32, 64, 128, 256 +}; + static u16 ad7616_spi_rd_wr_cmd(int addr, char isWriteOp) { /* @@ -60,6 +90,16 @@ static u16 ad7616_spi_rd_wr_cmd(int addr, char isWriteOp) return ((addr & 0x7F) << 1) | ((isWriteOp & 0x1) << 7); } +static u16 ad7606B_spi_rd_wr_cmd(int addr, char is_write_op) +{ + /* + * The address of register consists of one bit which + * specifies a read command placed in bit 6, followed by + * 6 bits of address. + */ + return (addr & 0x3F) | (((~is_write_op) & 0x1) << 6); +} + static int ad7606_spi_read_block(struct device *dev, int count, void *buf) { @@ -169,6 +209,23 @@ static int ad7616_write_os_sw(struct iio_dev *indio_dev, int val) AD7616_OS_MASK, val << 2); } +static int ad7606_write_scale_sw(struct iio_dev *indio_dev, int ch, int val) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + return ad7606_spi_write_mask(st, + AD7606_RANGE_CH_ADDR(ch), + AD7606_RANGE_CH_MSK(ch), + AD7606_RANGE_CH_MODE(ch, val)); +} + +static int ad7606_write_os_sw(struct iio_dev *indio_dev, int val) +{ + struct ad7606_state *st = iio_priv(indio_dev); + + return ad7606_spi_reg_write(st, AD7606_OS_MODE, val); +} + static int ad7616_sw_mode_config(struct iio_dev *indio_dev) { struct ad7606_state *st = iio_priv(indio_dev); @@ -189,6 +246,42 @@ static int ad7616_sw_mode_config(struct iio_dev *indio_dev) AD7616_BURST_MODE | AD7616_SEQEN_MODE); } +static int ad7606B_sw_mode_config(struct iio_dev *indio_dev) +{ + struct ad7606_state *st = iio_priv(indio_dev); + unsigned long os[3] = {1}; + + /* + * Software mode is enabled when all three oversampling + * pins are set to high. If oversampling gpios are defined + * in the device tree, then they need to be set to high, + * otherwise, they must be hardwired to VDD + */ + if (st->gpio_os) { + gpiod_set_array_value(ARRAY_SIZE(os), + st->gpio_os->desc, st->gpio_os->info, os); + } + /* OS of 128 and 256 are available only in software mode */ + st->oversampling_avail = ad7606B_oversampling_avail; + st->num_os_ratios = ARRAY_SIZE(ad7606B_oversampling_avail); + + st->write_scale = ad7606_write_scale_sw; + st->write_os = &ad7606_write_os_sw; + + /* Configure device spi to output on a single channel */ + st->bops->reg_write(st, + AD7606_CONFIGURATION_REGISTER, + AD7606_SINGLE_DOUT); + + /* + * Scale can be configured individually for each channel + * in software mode. + */ + indio_dev->channels = ad7606b_sw_channels; + + return 0; +} + static const struct ad7606_bus_ops ad7606_spi_bops = { .read_block = ad7606_spi_read_block, }; @@ -202,6 +295,15 @@ static const struct ad7606_bus_ops ad7616_spi_bops = { .sw_mode_config = ad7616_sw_mode_config, }; +static const struct ad7606_bus_ops ad7606B_spi_bops = { + .read_block = ad7606_spi_read_block, + .reg_read = ad7606_spi_reg_read, + .reg_write = ad7606_spi_reg_write, + .write_mask = ad7606_spi_write_mask, + .rd_wr_cmd = ad7606B_spi_rd_wr_cmd, + .sw_mode_config = ad7606B_sw_mode_config, +}; + static int ad7606_spi_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); @@ -211,6 +313,9 @@ static int ad7606_spi_probe(struct spi_device *spi) case ID_AD7616: bops = &ad7616_spi_bops; break; + case ID_AD7606B: + bops = &ad7606B_spi_bops; + break; default: bops = &ad7606_spi_bops; break; @@ -226,6 +331,7 @@ static const struct spi_device_id ad7606_id_table[] = { { "ad7606-4", ID_AD7606_4 }, { "ad7606-6", ID_AD7606_6 }, { "ad7606-8", ID_AD7606_8 }, + { "ad7606b", ID_AD7606B }, { "ad7616", ID_AD7616 }, {} }; @@ -236,6 +342,7 @@ static const struct of_device_id ad7606_of_match[] = { { .compatible = "adi,ad7606-4" }, { .compatible = "adi,ad7606-6" }, { .compatible = "adi,ad7606-8" }, + { .compatible = "adi,ad7606b" }, { .compatible = "adi,ad7616" }, { }, }; From 75338cc8eb29c90323eb7d54ec09d25e86625515 Mon Sep 17 00:00:00 2001 From: Beniamin Bia Date: Wed, 21 Aug 2019 17:16:54 +0300 Subject: [PATCH 13/27] MAINTAINERS: Add Beniamin Bia for AD7606 driver Add Beniamin Bia as maintainer for AD7606 driver. Signed-off-by: Beniamin Bia Signed-off-by: Jonathan Cameron --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index ac3a5cd6a682..92c2603b71b7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -903,6 +903,7 @@ F: Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml ANALOG DEVICES INC AD7606 DRIVER M: Stefan Popa +M: Beniamin Bia L: linux-iio@vger.kernel.org W: http://ez.analog.com/community/linux-device-drivers S: Supported From 416f882c3b404938ba26622469a956c4cd9f7558 Mon Sep 17 00:00:00 2001 From: Beniamin Bia Date: Wed, 21 Aug 2019 17:16:55 +0300 Subject: [PATCH 14/27] dt-bindings: iio: adc: Migrate AD7606 documentation to yaml The documentation for ad7606 was migrated to yaml. Signed-off-by: Beniamin Bia Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/adc/adi,ad7606.txt | 66 --------- .../bindings/iio/adc/adi,ad7606.yaml | 136 ++++++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 137 insertions(+), 67 deletions(-) delete mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt deleted file mode 100644 index d8652460198e..000000000000 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt +++ /dev/null @@ -1,66 +0,0 @@ -Analog Devices AD7606 Simultaneous Sampling ADC - -Required properties for the AD7606: - -- compatible: Must be one of - * "adi,ad7605-4" - * "adi,ad7606-8" - * "adi,ad7606-6" - * "adi,ad7606-4" - * "adi,ad7616" -- reg: SPI chip select number for the device -- spi-max-frequency: Max SPI frequency to use - see: Documentation/devicetree/bindings/spi/spi-bus.txt -- spi-cpha: See Documentation/devicetree/bindings/spi/spi-bus.txt -- avcc-supply: phandle to the Avcc power supply -- interrupts: IRQ line for the ADC - see: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt -- adi,conversion-start-gpios: must be the device tree identifier of the CONVST pin. - This logic input is used to initiate conversions on the analog - input channels. As the line is active high, it should be marked - GPIO_ACTIVE_HIGH. - -Optional properties: - -- reset-gpios: must be the device tree identifier of the RESET pin. If specified, - it will be asserted during driver probe. As the line is active high, - it should be marked GPIO_ACTIVE_HIGH. -- standby-gpios: must be the device tree identifier of the STBY pin. This pin is used - to place the AD7606 into one of two power-down modes, Standby mode or - Shutdown mode. As the line is active low, it should be marked - GPIO_ACTIVE_LOW. -- adi,first-data-gpios: must be the device tree identifier of the FRSTDATA pin. - The FRSTDATA output indicates when the first channel, V1, is - being read back on either the parallel, byte or serial interface. - As the line is active high, it should be marked GPIO_ACTIVE_HIGH. -- adi,range-gpios: must be the device tree identifier of the RANGE pin. The polarity on - this pin determines the input range of the analog input channels. If - this pin is tied to a logic high, the analog input range is ±10V for - all channels. If this pin is tied to a logic low, the analog input range - is ±5V for all channels. As the line is active high, it should be marked - GPIO_ACTIVE_HIGH. -- adi,oversampling-ratio-gpios: must be the device tree identifier of the over-sampling - mode pins. As the line is active high, it should be marked - GPIO_ACTIVE_HIGH. - -Example: - - adc@0 { - compatible = "adi,ad7606-8"; - reg = <0>; - spi-max-frequency = <1000000>; - spi-cpol; - - avcc-supply = <&adc_vref>; - - interrupts = <25 IRQ_TYPE_EDGE_FALLING>; - interrupt-parent = <&gpio>; - - adi,conversion-start-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>; - reset-gpios = <&gpio 27 GPIO_ACTIVE_HIGH>; - adi,first-data-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>; - adi,oversampling-ratio-gpios = <&gpio 18 GPIO_ACTIVE_HIGH - &gpio 23 GPIO_ACTIVE_HIGH - &gpio 26 GPIO_ACTIVE_HIGH>; - standby-gpios = <&gpio 24 GPIO_ACTIVE_LOW>; - }; diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml new file mode 100644 index 000000000000..3ecdfa780ae3 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml @@ -0,0 +1,136 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/adi,ad7606.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices AD7606 Simultaneous Sampling ADC + +maintainers: + - Beniamin Bia + - Stefan Popa + +description: | + Analog Devices AD7606 Simultaneous Sampling ADC + https://www.analog.com/media/en/technical-documentation/data-sheets/ad7606_7606-6_7606-4.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/AD7616.pdf + +properties: + compatible: + enum: + - adi,ad7605-4 + - adi,ad7606-8 + - adi,ad7606-6 + - adi,ad7606-4 + - adi,ad7616 + + reg: + maxItems: 1 + + spi-cpha: true + + avcc-supply: + description: + Phandle to the Avcc power supply + maxItems: 1 + + interrupts: + maxItems: 1 + + adi,conversion-start-gpios: + description: + Must be the device tree identifier of the CONVST pin. + This logic input is used to initiate conversions on the analog + input channels. As the line is active high, it should be marked + GPIO_ACTIVE_HIGH. + maxItems: 1 + + reset-gpios: + description: + Must be the device tree identifier of the RESET pin. If specified, + it will be asserted during driver probe. As the line is active high, + it should be marked GPIO_ACTIVE_HIGH. + maxItems: 1 + + standby-gpios: + description: + Must be the device tree identifier of the STBY pin. This pin is used + to place the AD7606 into one of two power-down modes, Standby mode or + Shutdown mode. As the line is active low, it should be marked + GPIO_ACTIVE_LOW. + maxItems: 1 + + adi,first-data-gpios: + description: + Must be the device tree identifier of the FRSTDATA pin. + The FRSTDATA output indicates when the first channel, V1, is + being read back on either the parallel, byte or serial interface. + As the line is active high, it should be marked GPIO_ACTIVE_HIGH. + maxItems: 1 + + adi,range-gpios: + description: + Must be the device tree identifier of the RANGE pin. The polarity on + this pin determines the input range of the analog input channels. If + this pin is tied to a logic high, the analog input range is ±10V for + all channels. If this pin is tied to a logic low, the analog input range + is ±5V for all channels. As the line is active high, it should be marked + GPIO_ACTIVE_HIGH. + maxItems: 1 + + adi,oversampling-ratio-gpios: + description: + Must be the device tree identifier of the over-sampling + mode pins. As the line is active high, it should be marked + GPIO_ACTIVE_HIGH. + maxItems: 1 + + adi,sw-mode: + description: + Software mode of operation, so far available only for ad7616. + It is enabled when all three oversampling mode pins are connected to + high level. The device is configured by the corresponding registers. If the + adi,oversampling-ratio-gpios property is defined, then the driver will set the + oversampling gpios to high. Otherwise, it is assumed that the pins are hardwired + to VDD. + type: boolean + +required: + - compatible + - reg + - spi-cpha + - avcc-supply + - interrupts + - adi,conversion-start-gpios + +examples: + - | + #include + #include + spi0 { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "adi,ad7606-8"; + reg = <0>; + spi-max-frequency = <1000000>; + spi-cpol; + spi-cpha; + + avcc-supply = <&adc_vref>; + + interrupts = <25 IRQ_TYPE_EDGE_FALLING>; + interrupt-parent = <&gpio>; + + adi,conversion-start-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio 27 GPIO_ACTIVE_HIGH>; + adi,first-data-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>; + adi,oversampling-ratio-gpios = <&gpio 18 GPIO_ACTIVE_HIGH + &gpio 23 GPIO_ACTIVE_HIGH + &gpio 26 GPIO_ACTIVE_HIGH>; + standby-gpios = <&gpio 24 GPIO_ACTIVE_LOW>; + adi,sw-mode; + }; + }; +... diff --git a/MAINTAINERS b/MAINTAINERS index 92c2603b71b7..f0c03740b9fb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -908,7 +908,7 @@ L: linux-iio@vger.kernel.org W: http://ez.analog.com/community/linux-device-drivers S: Supported F: drivers/iio/adc/ad7606.c -F: Documentation/devicetree/bindings/iio/adc/adi,ad7606.txt +F: Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml ANALOG DEVICES INC AD7768-1 DRIVER M: Stefan Popa From 6b4d6822eef58dc17d35ece72369045247843990 Mon Sep 17 00:00:00 2001 From: Beniamin Bia Date: Wed, 21 Aug 2019 17:16:56 +0300 Subject: [PATCH 15/27] dt-bindings: iio: adc: Add AD7606B ADC documentation Documentation for AD7606B Analog to Digital Converter and software mode was added. Signed-off-by: Beniamin Bia Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml index 3ecdfa780ae3..cc544fdc38be 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml @@ -13,6 +13,7 @@ maintainers: description: | Analog Devices AD7606 Simultaneous Sampling ADC https://www.analog.com/media/en/technical-documentation/data-sheets/ad7606_7606-6_7606-4.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/AD7606B.pdf https://www.analog.com/media/en/technical-documentation/data-sheets/AD7616.pdf properties: @@ -22,6 +23,7 @@ properties: - adi,ad7606-8 - adi,ad7606-6 - adi,ad7606-4 + - adi,ad7606b - adi,ad7616 reg: @@ -87,7 +89,7 @@ properties: adi,sw-mode: description: - Software mode of operation, so far available only for ad7616. + Software mode of operation, so far available only for ad7616 and ad7606b. It is enabled when all three oversampling mode pins are connected to high level. The device is configured by the corresponding registers. If the adi,oversampling-ratio-gpios property is defined, then the driver will set the From 258128e8e953c84bd46e487deedcae2bd6543bd4 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 23 Aug 2019 20:18:52 +0800 Subject: [PATCH 16/27] iio: st_sensors: Fix build error IIO_ST_SENSORS_CORE select IIO_ST_SENSORS_I2C unconditionally, if REGMAP_I2C is not set, build fails drivers/iio/common/st_sensors/st_sensors_i2c.o: In function `st_sensors_i2c_configure': st_sensors_i2c.c:(.text+0x58): undefined reference to `__devm_regmap_init_i2c' This patch selects REGMAP_I2C to fix it. IIO_ST_SENSORS_SPI is similar to SPI issue. Reported-by: Hulk Robot Fixes: 062809ef7733 ("iio: make st_sensors drivers use regmap") Signed-off-by: YueHaibing Signed-off-by: Jonathan Cameron --- drivers/iio/common/st_sensors/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iio/common/st_sensors/Kconfig b/drivers/iio/common/st_sensors/Kconfig index 91b98e152d75..9364ec7a811f 100644 --- a/drivers/iio/common/st_sensors/Kconfig +++ b/drivers/iio/common/st_sensors/Kconfig @@ -5,9 +5,11 @@ config IIO_ST_SENSORS_I2C tristate + select REGMAP_I2C config IIO_ST_SENSORS_SPI tristate + select REGMAP_SPI config IIO_ST_SENSORS_CORE tristate From 4a5e353c16d13168b8906c96013b887896ccf41a Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Mon, 19 Aug 2019 06:48:27 +0200 Subject: [PATCH 17/27] Kconfig: Fix the reference to the RFD77402 ToF sensor in the 'help' section This should be RFD77402, not RFD77420. Signed-off-by: Christophe JAILLET Signed-off-by: Jonathan Cameron --- drivers/iio/proximity/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig index 6b5cce6f1a7b..d53601447da4 100644 --- a/drivers/iio/proximity/Kconfig +++ b/drivers/iio/proximity/Kconfig @@ -62,7 +62,7 @@ config RFD77402 tristate "RFD77402 ToF sensor" depends on I2C help - Say Y to build a driver for the RFD77420 Time-of-Flight (distance) + Say Y to build a driver for the RFD77402 Time-of-Flight (distance) sensor module with I2C interface. To compile this driver as a module, choose M here: the From 88149b520950956f0f786d06693d11df8d6f6da4 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Mon, 19 Aug 2019 16:17:08 +0200 Subject: [PATCH 18/27] dt-bindings: iio: light: isl29501: Rename bindings documentation file Rename the bindings documentation file for Renesas ISL29501 Time-of-flight sensor from isl29501.txt to renesas,isl29501.txt. This is part of an ongoing effort to name bindings documentation files for Renesas IP blocks consistently, in line with the compat strings they document. Signed-off-by: Simon Horman Signed-off-by: Jonathan Cameron --- .../bindings/iio/light/{isl29501.txt => renesas,isl29501.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Documentation/devicetree/bindings/iio/light/{isl29501.txt => renesas,isl29501.txt} (100%) diff --git a/Documentation/devicetree/bindings/iio/light/isl29501.txt b/Documentation/devicetree/bindings/iio/light/renesas,isl29501.txt similarity index 100% rename from Documentation/devicetree/bindings/iio/light/isl29501.txt rename to Documentation/devicetree/bindings/iio/light/renesas,isl29501.txt From 3b72950d5a331686f55a11149b93e2543289b19b Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 21 Aug 2019 15:25:17 +0200 Subject: [PATCH 19/27] iio: imu: st_lsm6dsx: introduce update_fifo function pointer Introduce update_fifo routine pointer in st_lsm6dsx_fifo_ops data structure since we will need a different update FIFO configuration callback adding support for lsm6ds0/lsm9ds1 imu device Signed-off-by: Lorenzo Bianconi Tested-by: Martin Kepplinger Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 4 ++++ .../iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 19 +++++++++++++++---- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 6 ++++++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index 4e8e67ae1632..055e52dec36a 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -75,6 +75,7 @@ struct st_lsm6dsx_reg { u8 mask; }; +struct st_lsm6dsx_sensor; struct st_lsm6dsx_hw; struct st_lsm6dsx_odr { @@ -101,12 +102,14 @@ struct st_lsm6dsx_fs_table_entry { /** * struct st_lsm6dsx_fifo_ops - ST IMU FIFO settings + * @update_fifo: Update FIFO configuration callback. * @read_fifo: Read FIFO callback. * @fifo_th: FIFO threshold register info (addr + mask). * @fifo_diff: FIFO diff status register info (addr + mask). * @th_wl: FIFO threshold word length. */ struct st_lsm6dsx_fifo_ops { + int (*update_fifo)(struct st_lsm6dsx_sensor *sensor, bool enable); int (*read_fifo)(struct st_lsm6dsx_hw *hw); struct { u8 addr; @@ -327,6 +330,7 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw); int st_lsm6dsx_set_watermark(struct iio_dev *iio_dev, unsigned int val); int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor, u16 watermark); +int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable); int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw); int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw, enum st_lsm6dsx_fifo_mode fifo_mode); diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c index 2c03a5b80f80..b0f3da1976e4 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -602,9 +602,8 @@ int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw) return err; } -static int st_lsm6dsx_update_fifo(struct iio_dev *iio_dev, bool enable) +int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable) { - struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); struct st_lsm6dsx_hw *hw = sensor->hw; int err; @@ -676,12 +675,24 @@ static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private) static int st_lsm6dsx_buffer_preenable(struct iio_dev *iio_dev) { - return st_lsm6dsx_update_fifo(iio_dev, true); + struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); + struct st_lsm6dsx_hw *hw = sensor->hw; + + if (!hw->settings->fifo_ops.update_fifo) + return -ENOTSUPP; + + return hw->settings->fifo_ops.update_fifo(sensor, true); } static int st_lsm6dsx_buffer_postdisable(struct iio_dev *iio_dev) { - return st_lsm6dsx_update_fifo(iio_dev, false); + struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); + struct st_lsm6dsx_hw *hw = sensor->hw; + + if (!hw->settings->fifo_ops.update_fifo) + return -ENOTSUPP; + + return hw->settings->fifo_ops.update_fifo(sensor, false); } static const struct iio_buffer_setup_ops st_lsm6dsx_buffer_ops = { diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index 85824d6739ee..0aa93b45d772 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -154,6 +154,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }, .fifo_ops = { + .update_fifo = st_lsm6dsx_update_fifo, .read_fifo = st_lsm6dsx_read_fifo, .fifo_th = { .addr = 0x06, @@ -262,6 +263,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }, .fifo_ops = { + .update_fifo = st_lsm6dsx_update_fifo, .read_fifo = st_lsm6dsx_read_fifo, .fifo_th = { .addr = 0x06, @@ -379,6 +381,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }, .fifo_ops = { + .update_fifo = st_lsm6dsx_update_fifo, .read_fifo = st_lsm6dsx_read_fifo, .fifo_th = { .addr = 0x06, @@ -490,6 +493,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }, .fifo_ops = { + .update_fifo = st_lsm6dsx_update_fifo, .read_fifo = st_lsm6dsx_read_tagged_fifo, .fifo_th = { .addr = 0x07, @@ -616,6 +620,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }, .fifo_ops = { + .update_fifo = st_lsm6dsx_update_fifo, .read_fifo = st_lsm6dsx_read_tagged_fifo, .fifo_th = { .addr = 0x07, @@ -719,6 +724,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, }, .fifo_ops = { + .update_fifo = st_lsm6dsx_update_fifo, .read_fifo = st_lsm6dsx_read_tagged_fifo, .fifo_th = { .addr = 0x07, From 5022c5a43314b4acc0746f1c37293612ca8ebbc9 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Wed, 21 Aug 2019 15:25:18 +0200 Subject: [PATCH 20/27] iio: imu: st_lsm6dsx: move register definitions to sensor_settings struct Move some register definitions to the per-device array of struct st_lsm6dsx_sensor_settings in order to simplify adding new sensor devices to the driver. Also, remove completely unused register definitions. Signed-off-by: Martin Kepplinger Acked-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 6 ++++ drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 31 ++++++++++++++------ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index 055e52dec36a..090b7bd3c5b0 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -203,6 +203,9 @@ struct st_lsm6dsx_ext_dev_settings { /** * struct st_lsm6dsx_settings - ST IMU sensor settings * @wai: Sensor WhoAmI default value. + * @int1_addr: Control Register address for INT1 + * @int2_addr: Control Register address for INT2 + * @reset_addr: register address for reset/reboot * @max_fifo_size: Sensor max fifo length in FIFO words. * @id: List of hw id/device name supported by the driver configuration. * @channels: IIO channels supported by the device. @@ -216,6 +219,9 @@ struct st_lsm6dsx_ext_dev_settings { */ struct st_lsm6dsx_settings { u8 wai; + u8 int1_addr; + u8 int2_addr; + u8 reset_addr; u16 max_fifo_size; struct { enum st_lsm6dsx_hw_id hw_id; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index 0aa93b45d772..1b46d9dc2089 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -49,17 +49,12 @@ #include "st_lsm6dsx.h" -#define ST_LSM6DSX_REG_INT1_ADDR 0x0d -#define ST_LSM6DSX_REG_INT2_ADDR 0x0e #define ST_LSM6DSX_REG_FIFO_FTH_IRQ_MASK BIT(3) #define ST_LSM6DSX_REG_WHOAMI_ADDR 0x0f -#define ST_LSM6DSX_REG_RESET_ADDR 0x12 #define ST_LSM6DSX_REG_RESET_MASK BIT(0) #define ST_LSM6DSX_REG_BOOT_MASK BIT(7) #define ST_LSM6DSX_REG_BDU_ADDR 0x12 #define ST_LSM6DSX_REG_BDU_MASK BIT(6) -#define ST_LSM6DSX_REG_INT2_ON_INT1_ADDR 0x13 -#define ST_LSM6DSX_REG_INT2_ON_INT1_MASK BIT(5) static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = { ST_LSM6DSX_CHANNEL(IIO_ACCEL, 0x28, IIO_MOD_X, 0), @@ -78,6 +73,9 @@ static const struct iio_chan_spec st_lsm6dsx_gyro_channels[] = { static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { { .wai = 0x69, + .int1_addr = 0x0d, + .int2_addr = 0x0e, + .reset_addr = 0x12, .max_fifo_size = 1365, .id = { { @@ -187,6 +185,9 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, { .wai = 0x69, + .int1_addr = 0x0d, + .int2_addr = 0x0e, + .reset_addr = 0x12, .max_fifo_size = 682, .id = { { @@ -296,6 +297,9 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, { .wai = 0x6a, + .int1_addr = 0x0d, + .int2_addr = 0x0e, + .reset_addr = 0x12, .max_fifo_size = 682, .id = { { @@ -414,6 +418,9 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, { .wai = 0x6c, + .int1_addr = 0x0d, + .int2_addr = 0x0e, + .reset_addr = 0x12, .max_fifo_size = 512, .id = { { @@ -544,6 +551,9 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, { .wai = 0x6b, + .int1_addr = 0x0d, + .int2_addr = 0x0e, + .reset_addr = 0x12, .max_fifo_size = 512, .id = { { @@ -645,6 +655,9 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, { .wai = 0x6b, + .int1_addr = 0x0d, + .int2_addr = 0x0e, + .reset_addr = 0x12, .max_fifo_size = 512, .id = { { @@ -1172,10 +1185,10 @@ static int st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw, u8 *drdy_reg) switch (drdy_pin) { case 1: - *drdy_reg = ST_LSM6DSX_REG_INT1_ADDR; + *drdy_reg = hw->settings->int1_addr; break; case 2: - *drdy_reg = ST_LSM6DSX_REG_INT2_ADDR; + *drdy_reg = hw->settings->int2_addr; break; default: dev_err(hw->dev, "unsupported data ready pin\n"); @@ -1275,7 +1288,7 @@ static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw) int err; /* device sw reset */ - err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_RESET_ADDR, + err = regmap_update_bits(hw->regmap, hw->settings->reset_addr, ST_LSM6DSX_REG_RESET_MASK, FIELD_PREP(ST_LSM6DSX_REG_RESET_MASK, 1)); if (err < 0) @@ -1284,7 +1297,7 @@ static int st_lsm6dsx_init_device(struct st_lsm6dsx_hw *hw) msleep(50); /* reload trimming parameter */ - err = regmap_update_bits(hw->regmap, ST_LSM6DSX_REG_RESET_ADDR, + err = regmap_update_bits(hw->regmap, hw->settings->reset_addr, ST_LSM6DSX_REG_BOOT_MASK, FIELD_PREP(ST_LSM6DSX_REG_BOOT_MASK, 1)); if (err < 0) From 52f4b1f1967984b118efeda9d3694c57cf089415 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Wed, 21 Aug 2019 15:25:19 +0200 Subject: [PATCH 21/27] iio: imu: st_lsm6dsx: add support for accel/gyro unit of lsm9ds1 The LSM9DS1's accelerometer / gyroscope unit and it's magnetometer (separately supported in iio/magnetometer/st_magn*) are located on a separate i2c addresses on the bus. For the datasheet, see https://www.st.com/resource/en/datasheet/lsm9ds1.pdf Treat it just like the LSM6* devices and, despite it's name, hook it up to the st_lsm6dsx driver, using it's basic functionality. accelerometer and gyroscope are not independently clocked. It runs at the gyro frequencies if both are enabled, see chapter 7.12 of the datasheet. We could have handled this as a single IIO device but we have split it up to be more consistent with the other more flexible devices. Despite supporting and testing the LSM9DS1, we call the gyro channels iio_chan_spec struct "st_lsm6ds0_gyro_channels" because the register description is equal. This suggests that supporting LSM6DS0 should be trivial to do. Signed-off-by: Martin Kepplinger Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/Kconfig | 2 +- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 2 + drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 87 ++++++++++++++++++++ drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c | 5 ++ drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c | 5 ++ 5 files changed, 100 insertions(+), 1 deletion(-) diff --git a/drivers/iio/imu/st_lsm6dsx/Kconfig b/drivers/iio/imu/st_lsm6dsx/Kconfig index 939058b27746..77aa0e77212d 100644 --- a/drivers/iio/imu/st_lsm6dsx/Kconfig +++ b/drivers/iio/imu/st_lsm6dsx/Kconfig @@ -12,7 +12,7 @@ config IIO_ST_LSM6DSX Say yes here to build support for STMicroelectronics LSM6DSx imu sensor. Supported devices: lsm6ds3, lsm6ds3h, lsm6dsl, lsm6dsm, ism330dlc, lsm6dso, lsm6dsox, asm330lhh, lsm6dsr, lsm6ds3tr-c, - ism330dhcx + ism330dhcx and the accelerometer/gyroscope of lsm9ds1. To compile this driver as a module, choose M here: the module will be called st_lsm6dsx. diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index 090b7bd3c5b0..80e42c7dbcbe 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -24,6 +24,7 @@ #define ST_LSM6DSR_DEV_NAME "lsm6dsr" #define ST_LSM6DS3TRC_DEV_NAME "lsm6ds3tr-c" #define ST_ISM330DHCX_DEV_NAME "ism330dhcx" +#define ST_LSM9DS1_DEV_NAME "lsm9ds1-imu" enum st_lsm6dsx_hw_id { ST_LSM6DS3_ID, @@ -37,6 +38,7 @@ enum st_lsm6dsx_hw_id { ST_LSM6DSR_ID, ST_LSM6DS3TRC_ID, ST_ISM330DHCX_ID, + ST_LSM9DS1_ID, ST_LSM6DSX_MAX_ID, }; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index 1b46d9dc2089..ad839ccf871c 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -10,6 +10,8 @@ * +-125/+-245/+-500/+-1000/+-2000 dps * LSM6DSx series has an integrated First-In-First-Out (FIFO) buffer * allowing dynamic batching of sensor data. + * LSM9DSx series is similar but includes an additional magnetometer, handled + * by a different driver. * * Supported sensors: * - LSM6DS3: @@ -30,6 +32,13 @@ * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 * - FIFO size: 3KB * + * - LSM9DS1: + * - Accelerometer supported ODR [Hz]: 10, 50, 119, 238, 476, 952 + * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 + * - Gyroscope supported ODR [Hz]: 15, 60, 119, 238, 476, 952 + * - Gyroscope supported full-scale [dps]: +-245/+-500/+-2000 + * - FIFO size: 32 + * * Copyright 2016 STMicroelectronics Inc. * * Lorenzo Bianconi @@ -70,7 +79,85 @@ static const struct iio_chan_spec st_lsm6dsx_gyro_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(3), }; +static const struct iio_chan_spec st_lsm6ds0_gyro_channels[] = { + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x18, IIO_MOD_X, 0), + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x1a, IIO_MOD_Y, 1), + ST_LSM6DSX_CHANNEL(IIO_ANGL_VEL, 0x1c, IIO_MOD_Z, 2), + IIO_CHAN_SOFT_TIMESTAMP(3), +}; + static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { + { + .wai = 0x68, + .int1_addr = 0x0c, + .int2_addr = 0x0d, + .reset_addr = 0x22, + .max_fifo_size = 32, + .id = { + { + .hw_id = ST_LSM9DS1_ID, + .name = ST_LSM9DS1_DEV_NAME, + }, + }, + .channels = { + [ST_LSM6DSX_ID_ACC] = { + .chan = st_lsm6dsx_acc_channels, + .len = ARRAY_SIZE(st_lsm6dsx_acc_channels), + }, + [ST_LSM6DSX_ID_GYRO] = { + .chan = st_lsm6ds0_gyro_channels, + .len = ARRAY_SIZE(st_lsm6ds0_gyro_channels), + }, + }, + .odr_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x20, + .mask = GENMASK(7, 5), + }, + .odr_avl[0] = { 10, 0x01 }, + .odr_avl[1] = { 50, 0x02 }, + .odr_avl[2] = { 119, 0x03 }, + .odr_avl[3] = { 238, 0x04 }, + .odr_avl[4] = { 476, 0x05 }, + .odr_avl[5] = { 952, 0x06 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(7, 5), + }, + .odr_avl[0] = { 15, 0x01 }, + .odr_avl[1] = { 60, 0x02 }, + .odr_avl[2] = { 119, 0x03 }, + .odr_avl[3] = { 238, 0x04 }, + .odr_avl[4] = { 476, 0x05 }, + .odr_avl[5] = { 952, 0x06 }, + }, + }, + .fs_table = { + [ST_LSM6DSX_ID_ACC] = { + .reg = { + .addr = 0x20, + .mask = GENMASK(4, 3), + }, + .fs_avl[0] = { 599, 0x0 }, + .fs_avl[1] = { 1197, 0x2 }, + .fs_avl[2] = { 2394, 0x3 }, + .fs_avl[3] = { 4788, 0x1 }, + }, + [ST_LSM6DSX_ID_GYRO] = { + .reg = { + .addr = 0x10, + .mask = GENMASK(4, 3), + }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(245), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(500), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(0), 0x2 }, + .fs_avl[3] = { IIO_DEGREE_TO_RAD(2000), 0x3 }, + }, + }, + }, { .wai = 0x69, .int1_addr = 0x0d, diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c index 15c6aa5b6caa..f52511059545 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c @@ -83,6 +83,10 @@ static const struct of_device_id st_lsm6dsx_i2c_of_match[] = { .compatible = "st,ism330dhcx", .data = (void *)ST_ISM330DHCX_ID, }, + { + .compatible = "st,lsm9ds1-imu", + .data = (void *)ST_LSM9DS1_ID, + }, {}, }; MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match); @@ -99,6 +103,7 @@ static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = { { ST_LSM6DSR_DEV_NAME, ST_LSM6DSR_ID }, { ST_LSM6DS3TRC_DEV_NAME, ST_LSM6DS3TRC_ID }, { ST_ISM330DHCX_DEV_NAME, ST_ISM330DHCX_ID }, + { ST_LSM9DS1_DEV_NAME, ST_LSM9DS1_ID }, {}, }; MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table); diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c index a8430ee11310..344b28dddebb 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c @@ -83,6 +83,10 @@ static const struct of_device_id st_lsm6dsx_spi_of_match[] = { .compatible = "st,ism330dhcx", .data = (void *)ST_ISM330DHCX_ID, }, + { + .compatible = "st,lsm9ds1-imu", + .data = (void *)ST_LSM9DS1_ID, + }, {}, }; MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match); @@ -99,6 +103,7 @@ static const struct spi_device_id st_lsm6dsx_spi_id_table[] = { { ST_LSM6DSR_DEV_NAME, ST_LSM6DSR_ID }, { ST_LSM6DS3TRC_DEV_NAME, ST_LSM6DS3TRC_ID }, { ST_ISM330DHCX_DEV_NAME, ST_ISM330DHCX_ID }, + { ST_LSM9DS1_DEV_NAME, ST_LSM9DS1_ID }, {}, }; MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table); From 050833f1b15d97c6f190ee3ca77ca94c8f2a6648 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Wed, 21 Aug 2019 15:25:20 +0200 Subject: [PATCH 22/27] dt-bindings: iio: imu: st_lsm6dsx: add lsm9ds1 device bindings Note the binding is st,lsm9ds1-imu. This device is effectively two separate devices in the same package. (separate addreses, chip selects etc) The magnetometer is already supported as lsm9ds1-mag. imu may not be the best name but it's the best that anyone has yet come up with for a gyro and accel part. Signed-off-by: Martin Kepplinger Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt b/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt index 87407d110bb7..6d0c050d89fe 100644 --- a/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt +++ b/Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt @@ -13,6 +13,7 @@ Required properties: "st,lsm6dsr" "st,lsm6ds3tr-c" "st,ism330dhcx" + "st,lsm9ds1-imu" - reg: i2c address of the sensor / spi cs line Optional properties: From 70575abeaaca02f2f3f36abcce4ed33f69398ea0 Mon Sep 17 00:00:00 2001 From: mario tesi Date: Thu, 22 Aug 2019 15:22:19 +0200 Subject: [PATCH 23/27] iio: imu: st_lsm6dsx: Fix FIFO diff mask for tagged fifo According to the latest version of datasheet the mask for number of unread sensor data in FIFO_STATUS registers has been extended to 10 bits The devices involved are: - LSM6DSO - LSM6DSOX - ASM330LHH - LSM6DSR - ISM330DHCX Signed-off-by: mario tesi Acked-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index ad839ccf871c..fd152fff0a8c 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -595,7 +595,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, .fifo_diff = { .addr = 0x3a, - .mask = GENMASK(8, 0), + .mask = GENMASK(9, 0), }, .th_wl = 1, }, @@ -725,7 +725,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, .fifo_diff = { .addr = 0x3a, - .mask = GENMASK(8, 0), + .mask = GENMASK(9, 0), }, .th_wl = 1, }, @@ -832,7 +832,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { }, .fifo_diff = { .addr = 0x3a, - .mask = GENMASK(8, 0), + .mask = GENMASK(9, 0), }, .th_wl = 1, }, From b1e18768ef1214c0a8048327918a182cabe09f9d Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 15 Aug 2019 12:58:46 +0100 Subject: [PATCH 24/27] iio: dac: ad5380: fix incorrect assignment to val Currently the pointer val is being incorrectly incremented instead of the value pointed to by val. Fix this by adding in the missing * indirection operator. Addresses-Coverity: ("Unused value") Fixes: c03f2c536818 ("staging:iio:dac: Add AD5380 driver") Signed-off-by: Colin Ian King Reviewed-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- drivers/iio/dac/ad5380.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c index 4335214800d2..2ebe08326048 100644 --- a/drivers/iio/dac/ad5380.c +++ b/drivers/iio/dac/ad5380.c @@ -220,7 +220,7 @@ static int ad5380_read_raw(struct iio_dev *indio_dev, if (ret) return ret; *val >>= chan->scan_type.shift; - val -= (1 << chan->scan_type.realbits) / 2; + *val -= (1 << chan->scan_type.realbits) / 2; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: *val = 2 * st->vref; From 22087c850e8e56c5959640260ab3fa974556ef96 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Mon, 26 Aug 2019 16:02:58 -0700 Subject: [PATCH 25/27] iio: cros_ec: set calibscale for 3d MEMS to unit vector By default, set the calibscale vector to unit vector. When calibrating one axis, the other axis calibrations are sent as well. If left to 0, sensor data from uncalibrated axis are zero'ed out until all axis are calibrated. Fixes: ed1f2e85da79 ("iio: cros_ec: Add calibscale for 3d MEMS ") Signed-off-by: Gwendal Grignou Signed-off-by: Jonathan Cameron --- drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c index fd833295bb17..d44ae126f457 100644 --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c @@ -90,7 +90,7 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent); struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev); u32 ver_mask; - int ret; + int ret, i; platform_set_drvdata(pdev, indio_dev); @@ -136,6 +136,9 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, /* Set sign vector, only used for backward compatibility. */ memset(state->sign, 1, CROS_EC_SENSOR_MAX_AXIS); + for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) + state->calib[i].scale = MOTION_SENSE_DEFAULT_SCALE; + /* 0 is a correct value used to stop the device */ state->frequencies[0] = 0; if (state->msg->version < 3) { From 0f7e17286b451ca6f41497b86c8c15de480e75d7 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 27 Aug 2019 10:26:35 +0200 Subject: [PATCH 26/27] iio: imu: st_lsm6dsx: remove invalid gain value for LSM9DS1 Get rid of invalid sensitivity value for LSM9DS1 gyro sensor Fixes: 52f4b1f19679 ("iio: imu: st_lsm6dsx: add support for accel/gyro unit of lsm9ds1") Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index fd152fff0a8c..c85c8be3a024 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -151,10 +151,9 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x10, .mask = GENMASK(4, 3), }, - .fs_avl[0] = { IIO_DEGREE_TO_RAD(245), 0x0 }, - .fs_avl[1] = { IIO_DEGREE_TO_RAD(500), 0x1 }, - .fs_avl[2] = { IIO_DEGREE_TO_RAD(0), 0x2 }, - .fs_avl[3] = { IIO_DEGREE_TO_RAD(2000), 0x3 }, + .fs_avl[0] = { IIO_DEGREE_TO_RAD(245), 0x0 }, + .fs_avl[1] = { IIO_DEGREE_TO_RAD(500), 0x1 }, + .fs_avl[2] = { IIO_DEGREE_TO_RAD(2000), 0x3 }, }, }, }, @@ -1196,13 +1195,19 @@ static ssize_t st_lsm6dsx_sysfs_scale_avail(struct device *dev, char *buf) { struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev)); + const struct st_lsm6dsx_fs_table_entry *fs_table; enum st_lsm6dsx_sensor_id id = sensor->id; struct st_lsm6dsx_hw *hw = sensor->hw; int i, len = 0; - for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++) + fs_table = &hw->settings->fs_table[id]; + for (i = 0; i < ST_LSM6DSX_FS_LIST_SIZE; i++) { + if (!fs_table->fs_avl[i].gain) + break; + len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ", - hw->settings->fs_table[id].fs_avl[i].gain); + fs_table->fs_avl[i].gain); + } buf[len - 1] = '\n'; return len; From 6fa029486b74c266c39b718b8643ed42d24f977a Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 27 Aug 2019 10:29:06 +0200 Subject: [PATCH 27/27] iio: imu: st_lsm6dsx: rely on IIO_G_TO_M_S_2 for gain definition for LSM9DS1 Rely on IIO_G_TO_M_S_2 macro for LSM9DS1 accelerometer gain definitions Signed-off-by: Lorenzo Bianconi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index c85c8be3a024..2d3495560136 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -141,10 +141,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x20, .mask = GENMASK(4, 3), }, - .fs_avl[0] = { 599, 0x0 }, - .fs_avl[1] = { 1197, 0x2 }, - .fs_avl[2] = { 2394, 0x3 }, - .fs_avl[3] = { 4788, 0x1 }, + .fs_avl[0] = { IIO_G_TO_M_S_2(61), 0x0 }, + .fs_avl[1] = { IIO_G_TO_M_S_2(122), 0x2 }, + .fs_avl[2] = { IIO_G_TO_M_S_2(244), 0x3 }, + .fs_avl[3] = { IIO_G_TO_M_S_2(732), 0x1 }, }, [ST_LSM6DSX_ID_GYRO] = { .reg = {