Commit 821f7ce7 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'iio-for-5.6a' of...

Merge tag 'iio-for-5.6a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next

Jonathan writes:

First set of new device support, features and cleanups for IIO in the 5.6 cycle

New device support

* ad7091r5 ADC
  - New driver with follow up patch adding scale and vref support.
  - DT bindings
* ad7923
  - Support for ad7908, ad7918 and ad7928 added to driver.
* bma180
  - Support the BMA254 accelerometer. Required fairly substantial rework
    to allow for small differences between this an existing parts.
* bma400 accelerometer
  - New driver with follow up patch for regulator support.
  - DT bindings.
* asc dlhl60d
  - New driver support this range of pressure and temperature sensors.
  - DT bindings.
* ltc2496 ADC
  - New driver to support this ADC.
  - Split the existing LTC2497 driver generic component out and reuse.
  - DT bindings.
* parallax ping
  - New driver supporting ultrasonic and laser tof distance sensors.
  - Bindings for these sensors.

New features

* core
  - New char type for read_raw returns, used for thermocouple types.
  - Rename read_first_n callback to read.   The reasons behind the original
    naming are lost to the mists of time.
* ad799x
  - Allow pm_ops to disable device completely allowing regulator power down.
* bma180
  - Enable basic regulator support.
* dmaengine buffer
  - Report platform data alignment requirements via new ABI.
* max31856
  - Add option to set mains filter rejection frequency and document
    new in_temp_filter_notch_center_frequency ABI.
  - Add support for configuring HW averaging (oversampling ratio)
  - Add runtime configuration of thermocouple type and document new ABI.
* maxim-thermocouple
  - Add read only access to thermocouple type using new ABI, includes
    adding more specific compatibles to reflect which variant of the
    chip is being used.
* mpu6050
  - Provide option to support the PMU9150 in package magnetometer directly
    rather than via auxiliary bus.
* stm32_adc
  - Add overrun interrupt checks to detect if this happens.
* st_lsm6dsx
  - Enable the sensor-hub support for lsm6dsm. Includes various reworks to
    allow this.

Cleanups and minor fixes

* Subsystem wide
  - Tidy up indentation in Kconfig and fix alphabetical order of AD7091R5.
  - Drop linux/gpio.h and linux/of_gpio.h from drivers that don't use them.
* ad7266
  - Convert to GPIO descriptors.
* ad7303
  - Avoid a dance with checking if the regulator is supplied by just
    using the optional request interface.
* ad7887
  - Simplify channel specification assignment to enable adding more devices.
* ad7923
  - Drop some unused and largely pointless defines of BOB_N==N variety.
  - Tidy up checkpatch warnings.
  - Add missing of_device_id table.
* adf4350
  - Convert to GPIO descriptors.
* ak8975
  - Convert to GPIO descriptors.
* ADIS library and drivers
  - Expand scope of txrx_lock to cover all state and rename as state_lock
  - Add unlocked read / write to allow grouping of consecutive calls under
    single lock / unlock.
  - Add unlocked check_status, reset to allow grouping under single
    lock / unlock.
  - Remove remaining uses of core mlock for local state protection.
    mlock should never be used directly as it protects tightly defined
    core IIO device management state.
* adis16240
  - Enforce only supported SPI mode on driver load + add DT binding doc.
* atlas-ph-sensor
  - Rename to atlas-sensor given it now covers things beyond ph sensors.
* bma180
  - Use local dev variable to tidy up code.
  - Use c99 style explicity .member assignment to make driver more readable.
* bmp280
  - Drop ACPI support. No evidence this was used and appropriate ID is not
    registered.
  - Allow ACPI to bind device via PRP0001
* dmaengine buffer
  - Use dma_request_chan instead of dma_request_slave_channel_reason as that
    ABI is going away.
  - Add module info to avoid tainting the kernel.
* hts221
  - Avoid magic number defines when only used to fill structure elements
    that are self describing.
* lm3533
  - Drop a stray semicolon.
* max9611
  - Cleanup enum handling to be more resilient to future changes.
* mpu6050
  - Delete MPU9150 from supported SPI devices as doesn't provide SPI.
  - Select I2C_MUX again after kbuild issue fixed elsewhere.
* stm32-timer
  - Drop an unnecessary register update.
* ssp_sensors
  - Convert to GPIO descriptors.
* st_sensors
  - drop !CONFIG_ACPI defines as ACPI_PTR() will stop them being used
    anyway.
  - Make default platform data structures __maybe_unsued.
  - Fill in some missing kernel-doc function parameters.
* st_lsm6dsx
  - white space fixes.
  - Mark some constants that aren't always used as __maybe_unused.
  - Drop of ID table guards as they just pervent use under ACPI.
  - Switch to device properties to allow ACPI usage.
* st_uvis25
  - Drop acpi.h include as no ACPI APIs used.
* ti-ads1015
  - Drop legacy platform data as no one seems to be using it.
  - Use the device property API instead of OF specific.
* ti-ads7950
  - typo fix in error message.

* tag 'iio-for-5.6a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (99 commits)
  iio: accel: bma180: BMA254 support
  iio: pressure: bmp280: Allow device to be enumerated from ACPI
  iio: pressure: bmp280: Drop ACPI support
  dt-bindings: iio: adc: convert sd modulator to json-schema
  iio: buffer: rename 'read_first_n' callback to 'read'
  iio: buffer-dmaengine: Report buffer length requirements
  bindings: iio: pressure: Add documentation for dlh driver
  dt-bindings: Add asc vendor
  iio: pressure: Add driver for DLH pressure sensors
  iio: buffer-dmaengine: Add module information
  iio: accel: bma180: Use explicit member assignment
  iio: accel: bma180: Basic regulator support
  iio: accel: bma180: Add dev helper variable
  iio: imu: st_lsm6dsx: enable sensor-hub support for lsm6dsm
  iio: imu: st_lsm6dsx: rename st_lsm6dsx_shub_read_reg in st_lsm6dsx_shub_read_output
  iio: imu: st_lsm6dsx: check if shub_output reg is located in primary page
  iio: imu: st_lsm6dsx: check if pull_up is located in primary page
  iio: imu: st_lsm6dsx: check if master_enable is located in primary page
  iio: imu: st_lsm6dsx: export max num of slave devices in st_lsm6dsx_shub_settings
  iio: light: remove unneeded semicolon
  ...
parents 0469fc6a c1d1c4a6
...@@ -1726,3 +1726,16 @@ Contact: linux-iio@vger.kernel.org ...@@ -1726,3 +1726,16 @@ Contact: linux-iio@vger.kernel.org
Description: Description:
List of valid periods (in seconds) for which the light intensity List of valid periods (in seconds) for which the light intensity
must be above the threshold level before interrupt is asserted. must be above the threshold level before interrupt is asserted.
What: /sys/bus/iio/devices/iio:deviceX/in_filter_notch_center_frequency
KernelVersion: 5.5
Contact: linux-iio@vger.kernel.org
Description:
Center frequency in Hz for a notch filter. Used i.e. for line
noise suppression.
What: /sys/bus/iio/devices/iio:deviceX/in_temp_thermocouple_type
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/buffer/length_align_bytes
KernelVersion: 5.4
Contact: linux-iio@vger.kernel.org
Description:
DMA buffers tend to have a alignment requirement for the
buffers. If this alignment requirement is not met samples might
be dropped from the buffer.
This property reports the alignment requirements in bytes.
This means that the buffer size in bytes needs to be a integer
multiple of the number reported by this file.
The alignment requirements in number of sample sets will depend
on the enabled channels and the bytes per channel. This means
that the alignment requirement in samples sets might change
depending on which and how many channels are enabled. Whereas
the alignment requirement reported in bytes by this property
will remain static and does not depend on which channels are
enabled.
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/accel/adi,adis16240.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ADIS16240 Programmable Impact Sensor and Recorder driver
maintainers:
- Alexandru Ardelean <alexandru.ardelean@analog.com>
description: |
ADIS16240 Programmable Impact Sensor and Recorder driver that supports
SPI interface.
https://www.analog.com/en/products/adis16240.html
properties:
compatible:
enum:
- adi,adis16240
reg:
maxItems: 1
interrupts:
maxItems: 1
required:
- compatible
- reg
- interrupts
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
spi0 {
#address-cells = <1>;
#size-cells = <0>;
/* Example for a SPI device node */
accelerometer@0 {
compatible = "adi,adis16240";
reg = <0>;
spi-max-frequency = <2500000>;
interrupt-parent = <&gpio0>;
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
};
};
* Bosch BMA180 / BMA250 triaxial acceleration sensor * Bosch BMA180 / BMA25x triaxial acceleration sensor
http://omapworld.com/BMA180_111_1002839.pdf http://omapworld.com/BMA180_111_1002839.pdf
http://ae-bst.resource.bosch.com/media/products/dokumente/bma250/bst-bma250-ds002-05.pdf http://ae-bst.resource.bosch.com/media/products/dokumente/bma250/bst-bma250-ds002-05.pdf
Required properties: Required properties:
- compatible : should be "bosch,bma180" or "bosch,bma250" - compatible : should be one of:
"bosch,bma180"
"bosch,bma250"
"bosch,bma254"
- reg : the I2C address of the sensor - reg : the I2C address of the sensor
Optional properties: Optional properties:
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/accel/bosch,bma400.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Bosch BMA400 triaxial acceleration sensor
maintainers:
- Dan Robertson <dan@dlrobertson.com>
description: |
Acceleration and temperature iio sensors with an i2c interface
Specifications about the sensor can be found at:
https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMA400-DS000.pdf
properties:
compatible:
enum:
- bosch,bma400
reg:
maxItems: 1
vdd-supply:
description: phandle to the regulator that provides power to the accelerometer
vddio-supply:
description: phandle to the regulator that provides power to the sensor's IO
interrupts:
maxItems: 1
required:
- compatible
- reg
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
accelerometer@14 {
compatible = "bosch,bma400";
reg = <0x14>;
vdd-supply = <&vdd>;
vddio-supply = <&vddio>;
interrupt-parent = <&gpio0>;
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
};
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/adi,ad7091r5.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices AD7091R5 4-Channel 12-Bit ADC
maintainers:
- Beniamin Bia <beniamin.bia@analog.com>
description: |
Analog Devices AD7091R5 4-Channel 12-Bit ADC
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7091r-5.pdf
properties:
compatible:
enum:
- adi,ad7091r5
reg:
maxItems: 1
vref-supply:
description:
Phandle to the vref power supply
interrupts:
maxItems: 1
required:
- compatible
- reg
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
adc@2f {
compatible = "adi,ad7091r5";
reg = <0x2f>;
interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
interrupt-parent = <&gpio>;
};
};
...
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/lltc,ltc2496.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Linear Technology / Analog Devices LTC2496 ADC
maintainers:
- Lars-Peter Clausen <lars@metafoo.de>
- Michael Hennerich <Michael.Hennerich@analog.com>
- Stefan Popa <stefan.popa@analog.com>
properties:
compatible:
enum:
- lltc,ltc2496
vref-supply:
description: phandle to an external regulator providing the reference voltage
allOf:
- $ref: /schemas/types.yaml#/definitions/phandle
reg:
description: spi chipselect number according to the usual spi bindings
spi-max-frequency:
description: maximal spi bus frequency supported
required:
- compatible
- vref-supply
- reg
examples:
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
adc@0 {
compatible = "lltc,ltc2496";
reg = <0>;
vref-supply = <&ltc2496_reg>;
spi-max-frequency = <2000000>;
};
};
Device-Tree bindings for sigma delta modulator
Required properties:
- compatible: should be "ads1201", "sd-modulator". "sd-modulator" can be use
as a generic SD modulator if modulator not specified in compatible list.
- #io-channel-cells = <0>: See the IIO bindings section "IIO consumers".
Example node:
ads1202: adc {
compatible = "sd-modulator";
#io-channel-cells = <0>;
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/sigma-delta-modulator.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Device-Tree bindings for sigma delta modulator
maintainers:
- Arnaud Pouliquen <arnaud.pouliquen@st.com>
properties:
compatible:
description: |
"sd-modulator" can be used as a generic SD modulator,
if the modulator is not specified in the compatible list.
enum:
- sd-modulator
- ads1201
'#io-channel-cells':
const: 0
required:
- compatible
- '#io-channel-cells'
additionalProperties: false
examples:
- |
ads1202: adc {
compatible = "sd-modulator";
#io-channel-cells = <0>;
};
...
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/pressure/asc,dlhl60d.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: All Sensors DLH series low voltage digital pressure sensors
maintainers:
- Tomislav Denis <tomislav.denis@avl.com>
description: |
Bindings for the All Sensors DLH series pressure sensors.
Specifications about the sensors can be found at:
http://www.allsensors.com/cad/DS-0355_Rev_B.PDF
properties:
compatible:
enum:
- asc,dlhl60d
- asc,dlhl60g
reg:
description: I2C device address
maxItems: 1
interrupts:
description: interrupt mapping for EOC(data ready) pin
maxItems: 1
required:
- compatible
- reg
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c0 {
#address-cells = <1>;
#size-cells = <0>;
pressure@29 {
compatible = "asc,dlhl60d";
reg = <0x29>;
interrupt-parent = <&gpio0>;
interrupts = <10 IRQ_TYPE_EDGE_RISING>;
};
};
...
# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/proximity/parallax-ping.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Parallax PING))) and LaserPING range finder
maintainers:
- Andreas Klinger <ak@it-klinger.de>
description: |
Bit-banging driver using one GPIO:
- ping-gpios is raised by the driver to start measurement
- direction of ping-gpio is then switched into input with an interrupt
for receiving distance value as PWM signal
Specifications about the devices can be found at:
http://parallax.com/sites/default/files/downloads/28041-LaserPING-2m-Rangefinder-Guide.pdf
http://parallax.com/sites/default/files/downloads/28015-PING-Documentation-v1.6.pdf
properties:
compatible:
enum:
- parallax,ping
- parallax,laserping
ping-gpios:
description:
Definition of the GPIO for the triggering and echo (output and input)
This GPIO is set for about 5 us by the driver to tell the device it
should initiate the measurement cycle. Afterwards the GPIO is switched
to input direction with an interrupt. The device sets it and the
length of the input signal corresponds to the measured distance.
It needs to be an GPIO which is able to deliver an interrupt because
the time between two interrupts is measured in the driver.
See Documentation/devicetree/bindings/gpio/gpio.txt for information
on how to specify a consumer gpio.
maxItems: 1
required:
- compatible
- ping-gpios
examples:
- |
#include <dt-bindings/gpio/gpio.h>
proximity {
compatible = "parallax,laserping";
ping-gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>;
};
...@@ -5,7 +5,10 @@ Maxim thermocouple support ...@@ -5,7 +5,10 @@ Maxim thermocouple support
Required properties: Required properties:
- compatible: must be "maxim,max31855" or "maxim,max6675" - compatible: must be "maxim,max6675" or one of the following:
"maxim,max31855k", "maxim,max31855j", "maxim,max31855n",
"maxim,max31855s", "maxim,max31855t", "maxim,max31855e",
"maxim,max31855r"; the generic "max,max31855" is deprecated.
- reg: SPI chip select number for the device - reg: SPI chip select number for the device
- spi-max-frequency: must be 4300000 - spi-max-frequency: must be 4300000
- spi-cpha: must be defined for max6675 to enable SPI mode 1 - spi-cpha: must be defined for max6675 to enable SPI mode 1
...@@ -15,7 +18,7 @@ Required properties: ...@@ -15,7 +18,7 @@ Required properties:
Example: Example:
max31855@0 { max31855@0 {
compatible = "maxim,max31855"; compatible = "maxim,max31855k";
reg = <0>; reg = <0>;
spi-max-frequency = <4300000>; spi-max-frequency = <4300000>;
}; };
...@@ -109,6 +109,8 @@ patternProperties: ...@@ -109,6 +109,8 @@ patternProperties:
description: Artesyn Embedded Technologies Inc. description: Artesyn Embedded Technologies Inc.
"^asahi-kasei,.*": "^asahi-kasei,.*":
description: Asahi Kasei Corp. description: Asahi Kasei Corp.
"^asc,.*":
description: All Sensors Corporation
"^aspeed,.*": "^aspeed,.*":
description: ASPEED Technology Inc. description: ASPEED Technology Inc.
"^asus,.*": "^asus,.*":
...@@ -717,6 +719,8 @@ patternProperties: ...@@ -717,6 +719,8 @@ patternProperties:
description: Panasonic Corporation description: Panasonic Corporation
"^parade,.*": "^parade,.*":
description: Parade Technologies Inc. description: Parade Technologies Inc.
"^parallax,.*":
description: Parallax Inc.
"^pda,.*": "^pda,.*":
description: Precision Design Associates, Inc. description: Precision Design Associates, Inc.
"^pericom,.*": "^pericom,.*":
......
...@@ -674,6 +674,14 @@ S: Maintained ...@@ -674,6 +674,14 @@ S: Maintained
F: Documentation/i2c/busses/i2c-ali1563.rst F: Documentation/i2c/busses/i2c-ali1563.rst
F: drivers/i2c/busses/i2c-ali1563.c F: drivers/i2c/busses/i2c-ali1563.c
ALL SENSORS DLH SERIES PRESSURE SENSORS DRIVER
M: Tomislav Denis <tomislav.denis@avl.com>
W: http://www.allsensors.com/
S: Maintained
L: linux-iio@vger.kernel.org
F: drivers/iio/pressure/dlhl60d.c
F: Documentation/devicetree/bindings/iio/pressure/asc,dlhl60d.yaml
ALLEGRO DVT VIDEO IP CORE DRIVER ALLEGRO DVT VIDEO IP CORE DRIVER
M: Michael Tretter <m.tretter@pengutronix.de> M: Michael Tretter <m.tretter@pengutronix.de>
R: Pengutronix Kernel Team <kernel@pengutronix.de> R: Pengutronix Kernel Team <kernel@pengutronix.de>
...@@ -898,6 +906,14 @@ S: Supported ...@@ -898,6 +906,14 @@ S: Supported
F: drivers/iio/dac/ad5758.c F: drivers/iio/dac/ad5758.c
F: Documentation/devicetree/bindings/iio/dac/ad5758.txt F: Documentation/devicetree/bindings/iio/dac/ad5758.txt
ANALOG DEVICES INC AD7091R5 DRIVER
M: Beniamin Bia <beniamin.bia@analog.com>
L: linux-iio@vger.kernel.org
W: http://ez.analog.com/community/linux-device-drivers
S: Supported
F: drivers/iio/adc/ad7091r5.c
F: Documentation/devicetree/bindings/iio/adc/adi,ad7091r5.yaml
ANALOG DEVICES INC AD7124 DRIVER ANALOG DEVICES INC AD7124 DRIVER
M: Stefan Popa <stefan.popa@analog.com> M: Stefan Popa <stefan.popa@analog.com>
L: linux-iio@vger.kernel.org L: linux-iio@vger.kernel.org
...@@ -1043,7 +1059,7 @@ S: Supported ...@@ -1043,7 +1059,7 @@ S: Supported
F: Documentation/ABI/testing/sysfs-bus-iio-frequency-ad9523 F: Documentation/ABI/testing/sysfs-bus-iio-frequency-ad9523
F: Documentation/ABI/testing/sysfs-bus-iio-frequency-adf4350 F: Documentation/ABI/testing/sysfs-bus-iio-frequency-adf4350
F: drivers/iio/*/ad* F: drivers/iio/*/ad*
F: drivers/iio/adc/ltc2497* F: drivers/iio/adc/ltc249*
X: drivers/iio/*/adjd* X: drivers/iio/*/adjd*
F: drivers/staging/iio/*/ad* F: drivers/staging/iio/*/ad*
...@@ -3089,6 +3105,13 @@ S: Supported ...@@ -3089,6 +3105,13 @@ S: Supported
F: drivers/net/bonding/ F: drivers/net/bonding/
F: include/uapi/linux/if_bonding.h F: include/uapi/linux/if_bonding.h
BOSCH SENSORTEC BMA400 ACCELEROMETER IIO DRIVER
M: Dan Robertson <dan@dlrobertson.com>
L: linux-iio@vger.kernel.org
S: Maintained
F: drivers/iio/accel/bma400*
F: Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml
BPF (Safe dynamic programs and tools) BPF (Safe dynamic programs and tools)
M: Alexei Starovoitov <ast@kernel.org> M: Alexei Starovoitov <ast@kernel.org>
M: Daniel Borkmann <daniel@iogearbox.net> M: Daniel Borkmann <daniel@iogearbox.net>
...@@ -12443,6 +12466,13 @@ L: platform-driver-x86@vger.kernel.org ...@@ -12443,6 +12466,13 @@ L: platform-driver-x86@vger.kernel.org
S: Maintained S: Maintained
F: drivers/platform/x86/panasonic-laptop.c F: drivers/platform/x86/panasonic-laptop.c
PARALLAX PING IIO SENSOR DRIVER
M: Andreas Klinger <ak@it-klinger.de>
L: linux-iio@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/iio/proximity/parallax-ping.yaml
F: drivers/iio/proximity/ping.c
PARALLEL LCD/KEYPAD PANEL DRIVER PARALLEL LCD/KEYPAD PANEL DRIVER
M: Willy Tarreau <willy@haproxy.com> M: Willy Tarreau <willy@haproxy.com>
M: Ksenija Stanojevic <ksenija.stanojevic@gmail.com> M: Ksenija Stanojevic <ksenija.stanojevic@gmail.com>
......
...@@ -89,13 +89,13 @@ config ADXL372_I2C ...@@ -89,13 +89,13 @@ config ADXL372_I2C
module will be called adxl372_i2c. module will be called adxl372_i2c.
config BMA180 config BMA180
tristate "Bosch BMA180/BMA250 3-Axis Accelerometer Driver" tristate "Bosch BMA180/BMA25x 3-Axis Accelerometer Driver"
depends on I2C depends on I2C
select IIO_BUFFER select IIO_BUFFER
select IIO_TRIGGERED_BUFFER select IIO_TRIGGERED_BUFFER
help help
Say Y here if you want to build a driver for the Bosch BMA180 or Say Y here if you want to build a driver for the Bosch BMA180 or
BMA250 triaxial acceleration sensor. BMA25x triaxial acceleration sensor.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called bma180. module will be called bma180.
...@@ -112,6 +112,22 @@ config BMA220 ...@@ -112,6 +112,22 @@ config BMA220
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called bma220_spi. module will be called bma220_spi.
config BMA400
tristate "Bosch BMA400 3-Axis Accelerometer Driver"
select REGMAP
select BMA400_I2C if I2C
help
Say Y here if you want to build a driver for the Bosch BMA400
triaxial acceleration sensor.
To compile this driver as a module, choose M here: the
module will be called bma400_core and you will also get
bma400_i2c if I2C is enabled.
config BMA400_I2C
tristate
depends on BMA400
config BMC150_ACCEL config BMC150_ACCEL
tristate "Bosch BMC150 Accelerometer Driver" tristate "Bosch BMC150 Accelerometer Driver"
select IIO_BUFFER select IIO_BUFFER
......
...@@ -14,6 +14,8 @@ obj-$(CONFIG_ADXL372_I2C) += adxl372_i2c.o ...@@ -14,6 +14,8 @@ obj-$(CONFIG_ADXL372_I2C) += adxl372_i2c.o
obj-$(CONFIG_ADXL372_SPI) += adxl372_spi.o obj-$(CONFIG_ADXL372_SPI) += adxl372_spi.o
obj-$(CONFIG_BMA180) += bma180.o obj-$(CONFIG_BMA180) += bma180.o
obj-$(CONFIG_BMA220) += bma220_spi.o obj-$(CONFIG_BMA220) += bma220_spi.o
obj-$(CONFIG_BMA400) += bma400_core.o
obj-$(CONFIG_BMA400_I2C) += bma400_i2c.o
obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o
obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Register constants and other forward declarations needed by the bma400
* sources.
*
* Copyright 2019 Dan Robertson <dan@dlrobertson.com>
*/
#ifndef _BMA400_H_
#define _BMA400_H_
#include <linux/bits.h>
#include <linux/regmap.h>
/*
* Read-Only Registers
*/
/* Status and ID registers */
#define BMA400_CHIP_ID_REG 0x00
#define BMA400_ERR_REG 0x02
#define BMA400_STATUS_REG 0x03
/* Acceleration registers */
#define BMA400_X_AXIS_LSB_REG 0x04
#define BMA400_X_AXIS_MSB_REG 0x05
#define BMA400_Y_AXIS_LSB_REG 0x06
#define BMA400_Y_AXIS_MSB_REG 0x07
#define BMA400_Z_AXIS_LSB_REG 0x08
#define BMA400_Z_AXIS_MSB_REG 0x09
/* Sensor time registers */
#define BMA400_SENSOR_TIME0 0x0a
#define BMA400_SENSOR_TIME1 0x0b
#define BMA400_SENSOR_TIME2 0x0c
/* Event and interrupt registers */
#define BMA400_EVENT_REG 0x0d
#define BMA400_INT_STAT0_REG 0x0e
#define BMA400_INT_STAT1_REG 0x0f
#define BMA400_INT_STAT2_REG 0x10
/* Temperature register */
#define BMA400_TEMP_DATA_REG 0x11
/* FIFO length and data registers */
#define BMA400_FIFO_LENGTH0_REG 0x12
#define BMA400_FIFO_LENGTH1_REG 0x13
#define BMA400_FIFO_DATA_REG 0x14
/* Step count registers */
#define BMA400_STEP_CNT0_REG 0x15
#define BMA400_STEP_CNT1_REG 0x16
#define BMA400_STEP_CNT3_REG 0x17
#define BMA400_STEP_STAT_REG 0x18
/*
* Read-write configuration registers
*/
#define BMA400_ACC_CONFIG0_REG 0x19
#define BMA400_ACC_CONFIG1_REG 0x1a
#define BMA400_ACC_CONFIG2_REG 0x1b
#define BMA400_CMD_REG 0x7e
/* Chip ID of BMA 400 devices found in the chip ID register. */
#define BMA400_ID_REG_VAL 0x90
#define BMA400_LP_OSR_SHIFT 5
#define BMA400_NP_OSR_SHIFT 4
#define BMA400_SCALE_SHIFT 6
#define BMA400_TWO_BITS_MASK GENMASK(1, 0)
#define BMA400_LP_OSR_MASK GENMASK(6, 5)
#define BMA400_NP_OSR_MASK GENMASK(5, 4)
#define BMA400_ACC_ODR_MASK GENMASK(3, 0)
#define BMA400_ACC_SCALE_MASK GENMASK(7, 6)
#define BMA400_ACC_ODR_MIN_RAW 0x05
#define BMA400_ACC_ODR_LP_RAW 0x06
#define BMA400_ACC_ODR_MAX_RAW 0x0b
#define BMA400_ACC_ODR_MAX_HZ 800
#define BMA400_ACC_ODR_MIN_WHOLE_HZ 25
#define BMA400_ACC_ODR_MIN_HZ 12
#define BMA400_SCALE_MIN 38357
#define BMA400_SCALE_MAX 306864
#define BMA400_NUM_REGULATORS 2
#define BMA400_VDD_REGULATOR 0
#define BMA400_VDDIO_REGULATOR 1
extern const struct regmap_config bma400_regmap_config;
int bma400_probe(struct device *dev, struct regmap *regmap, const char *name);
int bma400_remove(struct device *dev);
#endif
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0-only
/*
* I2C IIO driver for Bosch BMA400 triaxial acceleration sensor.
*
* Copyright 2019 Dan Robertson <dan@dlrobertson.com>
*
* I2C address is either 0x14 or 0x15 depending on SDO
*/
#include <linux/i2c.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include "bma400.h"
static int bma400_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct regmap *regmap;
regmap = devm_regmap_init_i2c(client, &bma400_regmap_config);
if (IS_ERR(regmap)) {
dev_err(&client->dev, "failed to create regmap\n");
return PTR_ERR(regmap);
}
return bma400_probe(&client->dev, regmap, id->name);
}
static int bma400_i2c_remove(struct i2c_client *client)
{
return bma400_remove(&client->dev);
}
static const struct i2c_device_id bma400_i2c_ids[] = {
{ "bma400", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, bma400_i2c_ids);
static const struct of_device_id bma400_of_i2c_match[] = {
{ .compatible = "bosch,bma400" },
{ }
};
MODULE_DEVICE_TABLE(of, bma400_of_i2c_match);
static struct i2c_driver bma400_i2c_driver = {
.driver = {
.name = "bma400",
.of_match_table = bma400_of_i2c_match,
},
.probe = bma400_i2c_probe,
.remove = bma400_i2c_remove,
.id_table = bma400_i2c_ids,
};
module_i2c_driver(bma400_i2c_driver);
MODULE_AUTHOR("Dan Robertson <dan@dlrobertson.com>");
MODULE_DESCRIPTION("Bosch BMA400 triaxial acceleration sensor (I2C)");
MODULE_LICENSE("GPL");
...@@ -64,7 +64,7 @@ enum st_accel_type { ...@@ -64,7 +64,7 @@ enum st_accel_type {
* struct st_sensors_platform_data - default accel platform data * struct st_sensors_platform_data - default accel platform data
* @drdy_int_pin: default accel DRDY is available on INT1 pin. * @drdy_int_pin: default accel DRDY is available on INT1 pin.
*/ */
static const struct st_sensors_platform_data default_accel_pdata = { static __maybe_unused const struct st_sensors_platform_data default_accel_pdata = {
.drdy_int_pin = 1, .drdy_int_pin = 1,
}; };
......
...@@ -119,8 +119,6 @@ static const struct acpi_device_id st_accel_acpi_match[] = { ...@@ -119,8 +119,6 @@ static const struct acpi_device_id st_accel_acpi_match[] = {
{ }, { },
}; };
MODULE_DEVICE_TABLE(acpi, st_accel_acpi_match); MODULE_DEVICE_TABLE(acpi, st_accel_acpi_match);
#else
#define st_accel_acpi_match NULL
#endif #endif
static const struct i2c_device_id st_accel_id_table[] = { static const struct i2c_device_id st_accel_id_table[] = {
......
...@@ -21,6 +21,13 @@ config AD_SIGMA_DELTA ...@@ -21,6 +21,13 @@ config AD_SIGMA_DELTA
select IIO_BUFFER select IIO_BUFFER
select IIO_TRIGGERED_BUFFER select IIO_TRIGGERED_BUFFER
config AD7091R5
tristate "Analog Devices AD7091R5 ADC Driver"
depends on I2C
select REGMAP_I2C
help
Say yes here to build support for Analog Devices AD7091R-5 ADC.
config AD7124 config AD7124
tristate "Analog Devices AD7124 and similar sigma-delta ADCs driver" tristate "Analog Devices AD7124 and similar sigma-delta ADCs driver"
depends on SPI_MASTER depends on SPI_MASTER
...@@ -523,6 +530,16 @@ config LTC2485 ...@@ -523,6 +530,16 @@ config LTC2485
To compile this driver as a module, choose M here: the module will be To compile this driver as a module, choose M here: the module will be
called ltc2485. called ltc2485.
config LTC2496
tristate "Linear Technology LTC2496 ADC driver"
depends on SPI
help
Say yes here to build support for Linear Technology LTC2496
16-Bit 8-/16-Channel Delta Sigma ADC.
To compile this driver as a module, choose M here: the module will be
called ltc2496.
config LTC2497 config LTC2497
tristate "Linear Technology LTC2497 ADC driver" tristate "Linear Technology LTC2497 ADC driver"
depends on I2C depends on I2C
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
# When adding new entries keep the list in alphabetical order # When adding new entries keep the list in alphabetical order
obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o
obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
obj-$(CONFIG_AD7091R5) += ad7091r5.o ad7091r-base.o
obj-$(CONFIG_AD7124) += ad7124.o obj-$(CONFIG_AD7124) += ad7124.o
obj-$(CONFIG_AD7266) += ad7266.o obj-$(CONFIG_AD7266) += ad7266.o
obj-$(CONFIG_AD7291) += ad7291.o obj-$(CONFIG_AD7291) += ad7291.o
...@@ -50,7 +51,8 @@ obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o ...@@ -50,7 +51,8 @@ obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
obj-$(CONFIG_LTC2471) += ltc2471.o obj-$(CONFIG_LTC2471) += ltc2471.o
obj-$(CONFIG_LTC2485) += ltc2485.o obj-$(CONFIG_LTC2485) += ltc2485.o
obj-$(CONFIG_LTC2497) += ltc2497.o obj-$(CONFIG_LTC2496) += ltc2496.o ltc2497-core.o
obj-$(CONFIG_LTC2497) += ltc2497.o ltc2497-core.o
obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX1027) += max1027.o
obj-$(CONFIG_MAX11100) += max11100.o obj-$(CONFIG_MAX11100) += max11100.o
obj-$(CONFIG_MAX1118) += max1118.o obj-$(CONFIG_MAX1118) += max1118.o
......
// SPDX-License-Identifier: GPL-2.0
/*
* AD7091RX Analog to Digital converter driver
*
* Copyright 2014-2019 Analog Devices Inc.
*/
#include <linux/bitops.h>
#include <linux/iio/events.h>
#include <linux/iio/iio.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include "ad7091r-base.h"
#define AD7091R_REG_RESULT 0
#define AD7091R_REG_CHANNEL 1
#define AD7091R_REG_CONF 2
#define AD7091R_REG_ALERT 3
#define AD7091R_REG_CH_LOW_LIMIT(ch) ((ch) * 3 + 4)
#define AD7091R_REG_CH_HIGH_LIMIT(ch) ((ch) * 3 + 5)
#define AD7091R_REG_CH_HYSTERESIS(ch) ((ch) * 3 + 6)
/* AD7091R_REG_RESULT */
#define AD7091R_REG_RESULT_CH_ID(x) (((x) >> 13) & 0x3)
#define AD7091R_REG_RESULT_CONV_RESULT(x) ((x) & 0xfff)
/* AD7091R_REG_CONF */
#define AD7091R_REG_CONF_AUTO BIT(8)
#define AD7091R_REG_CONF_CMD BIT(10)
#define AD7091R_REG_CONF_MODE_MASK \
(AD7091R_REG_CONF_AUTO | AD7091R_REG_CONF_CMD)
enum ad7091r_mode {
AD7091R_MODE_SAMPLE,
AD7091R_MODE_COMMAND,
AD7091R_MODE_AUTOCYCLE,
};
struct ad7091r_state {
struct device *dev;
struct regmap *map;
struct regulator *vref;
const struct ad7091r_chip_info *chip_info;
enum ad7091r_mode mode;
struct mutex lock; /*lock to prevent concurent reads */
};
static int ad7091r_set_mode(struct ad7091r_state *st, enum ad7091r_mode mode)
{
int ret, conf;
switch (mode) {
case AD7091R_MODE_SAMPLE:
conf = 0;
break;
case AD7091R_MODE_COMMAND:
conf = AD7091R_REG_CONF_CMD;
break;
case AD7091R_MODE_AUTOCYCLE:
conf = AD7091R_REG_CONF_AUTO;
break;
default:
return -EINVAL;
}
ret = regmap_update_bits(st->map, AD7091R_REG_CONF,
AD7091R_REG_CONF_MODE_MASK, conf);
if (ret)
return ret;
st->mode = mode;
return 0;
}
static int ad7091r_set_channel(struct ad7091r_state *st, unsigned int channel)
{
unsigned int dummy;
int ret;
/* AD7091R_REG_CHANNEL specified which channels to be converted */
ret = regmap_write(st->map, AD7091R_REG_CHANNEL,
BIT(channel) | (BIT(channel) << 8));
if (ret)
return ret;
/*
* There is a latency of one conversion before the channel conversion
* sequence is updated
*/
return regmap_read(st->map, AD7091R_REG_RESULT, &dummy);
}
static int ad7091r_read_one(struct iio_dev *iio_dev,
unsigned int channel, unsigned int *read_val)
{
struct ad7091r_state *st = iio_priv(iio_dev);
unsigned int val;
int ret;
ret = ad7091r_set_channel(st, channel);
if (ret)
return ret;
ret = regmap_read(st->map, AD7091R_REG_RESULT, &val);
if (ret)
return ret;
if (AD7091R_REG_RESULT_CH_ID(val) != channel)
return -EIO;
*read_val = AD7091R_REG_RESULT_CONV_RESULT(val);
return 0;
}
static int ad7091r_read_raw(struct iio_dev *iio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long m)
{
struct ad7091r_state *st = iio_priv(iio_dev);
unsigned int read_val;
int ret;
mutex_lock(&st->lock);
switch (m) {
case IIO_CHAN_INFO_RAW:
if (st->mode != AD7091R_MODE_COMMAND) {
ret = -EBUSY;
goto unlock;
}
ret = ad7091r_read_one(iio_dev, chan->channel, &read_val);
if (ret)
goto unlock;
*val = read_val;
ret = IIO_VAL_INT;
break;
case IIO_CHAN_INFO_SCALE:
if (st->vref) {
ret = regulator_get_voltage(st->vref);
if (ret < 0)
goto unlock;
*val = ret / 1000;
} else {
*val = st->chip_info->vref_mV;
}
*val2 = chan->scan_type.realbits;
ret = IIO_VAL_FRACTIONAL_LOG2;
break;
default:
ret = -EINVAL;
break;
}
unlock:
mutex_unlock(&st->lock);
return ret;
}
static const struct iio_info ad7091r_info = {
.read_raw = ad7091r_read_raw,
};
static irqreturn_t ad7091r_event_handler(int irq, void *private)
{
struct ad7091r_state *st = (struct ad7091r_state *) private;
struct iio_dev *iio_dev = dev_get_drvdata(st->dev);
unsigned int i, read_val;
int ret;
s64 timestamp = iio_get_time_ns(iio_dev);
ret = regmap_read(st->map, AD7091R_REG_ALERT, &read_val);
if (ret)
return IRQ_HANDLED;
for (i = 0; i < st->chip_info->num_channels; i++) {
if (read_val & BIT(i * 2))
iio_push_event(iio_dev,
IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING), timestamp);
if (read_val & BIT(i * 2 + 1))
iio_push_event(iio_dev,
IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING), timestamp);
}
return IRQ_HANDLED;
}
static void ad7091r_remove(void *data)
{
struct ad7091r_state *st = data;
regulator_disable(st->vref);
}
int ad7091r_probe(struct device *dev, const char *name,
const struct ad7091r_chip_info *chip_info,
struct regmap *map, int irq)
{
struct iio_dev *iio_dev;
struct ad7091r_state *st;
int ret;
iio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!iio_dev)
return -ENOMEM;
st = iio_priv(iio_dev);
st->dev = dev;
st->chip_info = chip_info;
st->map = map;
iio_dev->dev.parent = dev;
iio_dev->name = name;
iio_dev->info = &ad7091r_info;
iio_dev->modes = INDIO_DIRECT_MODE;
iio_dev->num_channels = chip_info->num_channels;
iio_dev->channels = chip_info->channels;
if (irq) {
ret = devm_request_threaded_irq(dev, irq, NULL,
ad7091r_event_handler,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT, name, st);
if (ret)
return ret;
}
st->vref = devm_regulator_get_optional(dev, "vref");
if (IS_ERR(st->vref)) {
if (PTR_ERR(st->vref) == -EPROBE_DEFER)
return -EPROBE_DEFER;
st->vref = NULL;
} else {
ret = regulator_enable(st->vref);
if (ret)
return ret;
ret = devm_add_action_or_reset(dev, ad7091r_remove, st);
if (ret)
return ret;
}
/* Use command mode by default to convert only desired channels*/
ret = ad7091r_set_mode(st, AD7091R_MODE_COMMAND);
if (ret)
return ret;
return devm_iio_device_register(dev, iio_dev);
}
EXPORT_SYMBOL_GPL(ad7091r_probe);
static bool ad7091r_writeable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case AD7091R_REG_RESULT:
case AD7091R_REG_ALERT:
return false;
default:
return true;
}
}
static bool ad7091r_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case AD7091R_REG_RESULT:
case AD7091R_REG_ALERT:
return true;
default:
return false;
}
}
const struct regmap_config ad7091r_regmap_config = {
.reg_bits = 8,
.val_bits = 16,
.writeable_reg = ad7091r_writeable_reg,
.volatile_reg = ad7091r_volatile_reg,
};
EXPORT_SYMBOL_GPL(ad7091r_regmap_config);
MODULE_AUTHOR("Beniamin Bia <beniamin.bia@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD7091Rx multi-channel converters");
MODULE_LICENSE("GPL v2");
/* SPDX-License-Identifier: GPL-2.0 */
/*
* AD7091RX Analog to Digital converter driver
*
* Copyright 2014-2019 Analog Devices Inc.
*/
#ifndef __DRIVERS_IIO_ADC_AD7091R_BASE_H__
#define __DRIVERS_IIO_ADC_AD7091R_BASE_H__
struct device;
struct ad7091r_state;
struct ad7091r_chip_info {
unsigned int num_channels;
const struct iio_chan_spec *channels;
unsigned int vref_mV;
};
extern const struct regmap_config ad7091r_regmap_config;
int ad7091r_probe(struct device *dev, const char *name,
const struct ad7091r_chip_info *chip_info,
struct regmap *map, int irq);
#endif /* __DRIVERS_IIO_ADC_AD7091R_BASE_H__ */
// SPDX-License-Identifier: GPL-2.0
/*
* AD7091R5 Analog to Digital converter driver
*
* Copyright 2014-2019 Analog Devices Inc.
*/
#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include "ad7091r-base.h"
static const struct iio_event_spec ad7091r5_events[] = {
{
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_RISING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
},
{
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_FALLING,
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
BIT(IIO_EV_INFO_ENABLE),
},
{
.type = IIO_EV_TYPE_THRESH,
.dir = IIO_EV_DIR_EITHER,
.mask_separate = BIT(IIO_EV_INFO_HYSTERESIS),
},
};
#define AD7091R_CHANNEL(idx, bits, ev, num_ev) { \
.type = IIO_VOLTAGE, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.indexed = 1, \
.channel = idx, \
.event_spec = ev, \
.num_event_specs = num_ev, \
.scan_type.storagebits = 16, \
.scan_type.realbits = bits, \
}
static const struct iio_chan_spec ad7091r5_channels_irq[] = {
AD7091R_CHANNEL(0, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)),
AD7091R_CHANNEL(1, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)),
AD7091R_CHANNEL(2, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)),
AD7091R_CHANNEL(3, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)),
};
static const struct iio_chan_spec ad7091r5_channels_noirq[] = {
AD7091R_CHANNEL(0, 12, NULL, 0),
AD7091R_CHANNEL(1, 12, NULL, 0),
AD7091R_CHANNEL(2, 12, NULL, 0),
AD7091R_CHANNEL(3, 12, NULL, 0),
};
static const struct ad7091r_chip_info ad7091r5_chip_info_irq = {
.channels = ad7091r5_channels_irq,
.num_channels = ARRAY_SIZE(ad7091r5_channels_irq),
.vref_mV = 2500,
};
static const struct ad7091r_chip_info ad7091r5_chip_info_noirq = {
.channels = ad7091r5_channels_noirq,
.num_channels = ARRAY_SIZE(ad7091r5_channels_noirq),
.vref_mV = 2500,
};
static int ad7091r5_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
const struct ad7091r_chip_info *chip_info;
struct regmap *map = devm_regmap_init_i2c(i2c, &ad7091r_regmap_config);
if (IS_ERR(map))
return PTR_ERR(map);
if (i2c->irq)
chip_info = &ad7091r5_chip_info_irq;
else
chip_info = &ad7091r5_chip_info_noirq;
return ad7091r_probe(&i2c->dev, id->name, chip_info, map, i2c->irq);
}
static const struct of_device_id ad7091r5_dt_ids[] = {
{ .compatible = "adi,ad7091r5" },
{},
};
MODULE_DEVICE_TABLE(of, ad7091r5_dt_ids);
static const struct i2c_device_id ad7091r5_i2c_ids[] = {
{"ad7091r5", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, ad7091r5_i2c_ids);
static struct i2c_driver ad7091r5_driver = {
.driver = {
.name = "ad7091r5",
.of_match_table = ad7091r5_dt_ids,
},
.probe = ad7091r5_i2c_probe,
.id_table = ad7091r5_i2c_ids,
};
module_i2c_driver(ad7091r5_driver);
MODULE_AUTHOR("Beniamin Bia <beniamin.bia@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD7091R5 multi-channel ADC driver");
MODULE_LICENSE("GPL v2");
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/gpio.h> #include <linux/gpio/consumer.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -34,7 +34,7 @@ struct ad7266_state { ...@@ -34,7 +34,7 @@ struct ad7266_state {
enum ad7266_range range; enum ad7266_range range;
enum ad7266_mode mode; enum ad7266_mode mode;
bool fixed_addr; bool fixed_addr;
struct gpio gpios[3]; struct gpio_desc *gpios[3];
/* /*
* DMA (thus cache coherency maintenance) requires the * DMA (thus cache coherency maintenance) requires the
...@@ -117,7 +117,7 @@ static void ad7266_select_input(struct ad7266_state *st, unsigned int nr) ...@@ -117,7 +117,7 @@ static void ad7266_select_input(struct ad7266_state *st, unsigned int nr)
} }
for (i = 0; i < 3; ++i) for (i = 0; i < 3; ++i)
gpio_set_value(st->gpios[i].gpio, (bool)(nr & BIT(i))); gpiod_set_value(st->gpios[i], (bool)(nr & BIT(i)));
} }
static int ad7266_update_scan_mode(struct iio_dev *indio_dev, static int ad7266_update_scan_mode(struct iio_dev *indio_dev,
...@@ -376,7 +376,7 @@ static void ad7266_init_channels(struct iio_dev *indio_dev) ...@@ -376,7 +376,7 @@ static void ad7266_init_channels(struct iio_dev *indio_dev)
} }
static const char * const ad7266_gpio_labels[] = { static const char * const ad7266_gpio_labels[] = {
"AD0", "AD1", "AD2", "ad0", "ad1", "ad2",
}; };
static int ad7266_probe(struct spi_device *spi) static int ad7266_probe(struct spi_device *spi)
...@@ -419,14 +419,14 @@ static int ad7266_probe(struct spi_device *spi) ...@@ -419,14 +419,14 @@ static int ad7266_probe(struct spi_device *spi)
if (!st->fixed_addr) { if (!st->fixed_addr) {
for (i = 0; i < ARRAY_SIZE(st->gpios); ++i) { for (i = 0; i < ARRAY_SIZE(st->gpios); ++i) {
st->gpios[i].gpio = pdata->addr_gpios[i]; st->gpios[i] = devm_gpiod_get(&spi->dev,
st->gpios[i].flags = GPIOF_OUT_INIT_LOW; ad7266_gpio_labels[i],
st->gpios[i].label = ad7266_gpio_labels[i]; GPIOD_OUT_LOW);
if (IS_ERR(st->gpios[i])) {
ret = PTR_ERR(st->gpios[i]);
goto error_disable_reg;
}
} }
ret = gpio_request_array(st->gpios,
ARRAY_SIZE(st->gpios));
if (ret)
goto error_disable_reg;
} }
} else { } else {
st->fixed_addr = true; st->fixed_addr = true;
...@@ -465,7 +465,7 @@ static int ad7266_probe(struct spi_device *spi) ...@@ -465,7 +465,7 @@ static int ad7266_probe(struct spi_device *spi)
ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
&ad7266_trigger_handler, &iio_triggered_buffer_setup_ops); &ad7266_trigger_handler, &iio_triggered_buffer_setup_ops);
if (ret) if (ret)
goto error_free_gpios; goto error_disable_reg;
ret = iio_device_register(indio_dev); ret = iio_device_register(indio_dev);
if (ret) if (ret)
...@@ -475,9 +475,6 @@ static int ad7266_probe(struct spi_device *spi) ...@@ -475,9 +475,6 @@ static int ad7266_probe(struct spi_device *spi)
error_buffer_cleanup: error_buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev); iio_triggered_buffer_cleanup(indio_dev);
error_free_gpios:
if (!st->fixed_addr)
gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios));
error_disable_reg: error_disable_reg:
if (!IS_ERR(st->reg)) if (!IS_ERR(st->reg))
regulator_disable(st->reg); regulator_disable(st->reg);
...@@ -492,8 +489,6 @@ static int ad7266_remove(struct spi_device *spi) ...@@ -492,8 +489,6 @@ static int ad7266_remove(struct spi_device *spi)
iio_device_unregister(indio_dev); iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev); iio_triggered_buffer_cleanup(indio_dev);
if (!st->fixed_addr)
gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios));
if (!IS_ERR(st->reg)) if (!IS_ERR(st->reg))
regulator_disable(st->reg); regulator_disable(st->reg);
......
...@@ -43,11 +43,17 @@ enum ad7887_channels { ...@@ -43,11 +43,17 @@ enum ad7887_channels {
/** /**
* struct ad7887_chip_info - chip specifc information * struct ad7887_chip_info - chip specifc information
* @int_vref_mv: the internal reference voltage * @int_vref_mv: the internal reference voltage
* @channel: channel specification * @channels: channels specification
* @num_channels: number of channels
* @dual_channels: channels specification in dual mode
* @num_dual_channels: number of channels in dual mode
*/ */
struct ad7887_chip_info { struct ad7887_chip_info {
u16 int_vref_mv; u16 int_vref_mv;
struct iio_chan_spec channel[3]; const struct iio_chan_spec *channels;
unsigned int num_channels;
const struct iio_chan_spec *dual_channels;
unsigned int num_dual_channels;
}; };
struct ad7887_state { struct ad7887_state {
...@@ -183,45 +189,43 @@ static int ad7887_read_raw(struct iio_dev *indio_dev, ...@@ -183,45 +189,43 @@ static int ad7887_read_raw(struct iio_dev *indio_dev,
return -EINVAL; return -EINVAL;
} }
#define AD7887_CHANNEL(x) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = (x), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.address = (x), \
.scan_index = (x), \
.scan_type = { \
.sign = 'u', \
.realbits = 12, \
.storagebits = 16, \
.shift = 0, \
.endianness = IIO_BE, \
}, \
}
static const struct iio_chan_spec ad7887_channels[] = {
AD7887_CHANNEL(0),
IIO_CHAN_SOFT_TIMESTAMP(1),
};
static const struct iio_chan_spec ad7887_dual_channels[] = {
AD7887_CHANNEL(0),
AD7887_CHANNEL(1),
IIO_CHAN_SOFT_TIMESTAMP(2),
};
static const struct ad7887_chip_info ad7887_chip_info_tbl[] = { static const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
/* /*
* More devices added in future * More devices added in future
*/ */
[ID_AD7887] = { [ID_AD7887] = {
.channel[0] = { .channels = ad7887_channels,
.type = IIO_VOLTAGE, .num_channels = ARRAY_SIZE(ad7887_channels),
.indexed = 1, .dual_channels = ad7887_dual_channels,
.channel = 1, .num_dual_channels = ARRAY_SIZE(ad7887_dual_channels),
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
.address = 1,
.scan_index = 1,
.scan_type = {
.sign = 'u',
.realbits = 12,
.storagebits = 16,
.shift = 0,
.endianness = IIO_BE,
},
},
.channel[1] = {
.type = IIO_VOLTAGE,
.indexed = 1,
.channel = 0,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
.address = 0,
.scan_index = 0,
.scan_type = {
.sign = 'u',
.realbits = 12,
.storagebits = 16,
.shift = 0,
.endianness = IIO_BE,
},
},
.channel[2] = IIO_CHAN_SOFT_TIMESTAMP(2),
.int_vref_mv = 2500, .int_vref_mv = 2500,
}, },
}; };
...@@ -306,11 +310,11 @@ static int ad7887_probe(struct spi_device *spi) ...@@ -306,11 +310,11 @@ static int ad7887_probe(struct spi_device *spi)
spi_message_init(&st->msg[AD7887_CH1]); spi_message_init(&st->msg[AD7887_CH1]);
spi_message_add_tail(&st->xfer[3], &st->msg[AD7887_CH1]); spi_message_add_tail(&st->xfer[3], &st->msg[AD7887_CH1]);
indio_dev->channels = st->chip_info->channel; indio_dev->channels = st->chip_info->dual_channels;
indio_dev->num_channels = 3; indio_dev->num_channels = st->chip_info->num_dual_channels;
} else { } else {
indio_dev->channels = &st->chip_info->channel[1]; indio_dev->channels = st->chip_info->channels;
indio_dev->num_channels = 2; indio_dev->num_channels = st->chip_info->num_channels;
} }
ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
......
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* AD7904/AD7914/AD7923/AD7924 SPI ADC driver * AD7904/AD7914/AD7923/AD7924/AD7908/AD7918/AD7928 SPI ADC driver
* *
* Copyright 2011 Analog Devices Inc (from AD7923 Driver) * Copyright 2011 Analog Devices Inc (from AD7923 Driver)
* Copyright 2012 CS Systemes d'Information * Copyright 2012 CS Systemes d'Information
...@@ -29,15 +29,10 @@ ...@@ -29,15 +29,10 @@
#define AD7923_PM_MODE_AS (1) /* auto shutdown */ #define AD7923_PM_MODE_AS (1) /* auto shutdown */
#define AD7923_PM_MODE_FS (2) /* full shutdown */ #define AD7923_PM_MODE_FS (2) /* full shutdown */
#define AD7923_PM_MODE_OPS (3) /* normal operation */ #define AD7923_PM_MODE_OPS (3) /* normal operation */
#define AD7923_CHANNEL_0 (0) /* analog input 0 */
#define AD7923_CHANNEL_1 (1) /* analog input 1 */
#define AD7923_CHANNEL_2 (2) /* analog input 2 */
#define AD7923_CHANNEL_3 (3) /* analog input 3 */
#define AD7923_SEQUENCE_OFF (0) /* no sequence fonction */ #define AD7923_SEQUENCE_OFF (0) /* no sequence fonction */
#define AD7923_SEQUENCE_PROTECT (2) /* no interrupt write cycle */ #define AD7923_SEQUENCE_PROTECT (2) /* no interrupt write cycle */
#define AD7923_SEQUENCE_ON (3) /* continuous sequence */ #define AD7923_SEQUENCE_ON (3) /* continuous sequence */
#define AD7923_MAX_CHAN 4
#define AD7923_PM_MODE_WRITE(mode) ((mode) << 4) /* write mode */ #define AD7923_PM_MODE_WRITE(mode) ((mode) << 4) /* write mode */
#define AD7923_CHANNEL_WRITE(channel) ((channel) << 6) /* write channel */ #define AD7923_CHANNEL_WRITE(channel) ((channel) << 6) /* write channel */
...@@ -78,6 +73,9 @@ enum ad7923_id { ...@@ -78,6 +73,9 @@ enum ad7923_id {
AD7904, AD7904,
AD7914, AD7914,
AD7924, AD7924,
AD7908,
AD7918,
AD7928
}; };
#define AD7923_V_CHAN(index, bits) \ #define AD7923_V_CHAN(index, bits) \
...@@ -106,9 +104,25 @@ const struct iio_chan_spec name ## _channels[] = { \ ...@@ -106,9 +104,25 @@ const struct iio_chan_spec name ## _channels[] = { \
IIO_CHAN_SOFT_TIMESTAMP(4), \ IIO_CHAN_SOFT_TIMESTAMP(4), \
} }
#define DECLARE_AD7908_CHANNELS(name, bits) \
const struct iio_chan_spec name ## _channels[] = { \
AD7923_V_CHAN(0, bits), \
AD7923_V_CHAN(1, bits), \
AD7923_V_CHAN(2, bits), \
AD7923_V_CHAN(3, bits), \
AD7923_V_CHAN(4, bits), \
AD7923_V_CHAN(5, bits), \
AD7923_V_CHAN(6, bits), \
AD7923_V_CHAN(7, bits), \
IIO_CHAN_SOFT_TIMESTAMP(8), \
}
static DECLARE_AD7923_CHANNELS(ad7904, 8); static DECLARE_AD7923_CHANNELS(ad7904, 8);
static DECLARE_AD7923_CHANNELS(ad7914, 10); static DECLARE_AD7923_CHANNELS(ad7914, 10);
static DECLARE_AD7923_CHANNELS(ad7924, 12); static DECLARE_AD7923_CHANNELS(ad7924, 12);
static DECLARE_AD7908_CHANNELS(ad7908, 8);
static DECLARE_AD7908_CHANNELS(ad7918, 10);
static DECLARE_AD7908_CHANNELS(ad7928, 12);
static const struct ad7923_chip_info ad7923_chip_info[] = { static const struct ad7923_chip_info ad7923_chip_info[] = {
[AD7904] = { [AD7904] = {
...@@ -123,6 +137,18 @@ static const struct ad7923_chip_info ad7923_chip_info[] = { ...@@ -123,6 +137,18 @@ static const struct ad7923_chip_info ad7923_chip_info[] = {
.channels = ad7924_channels, .channels = ad7924_channels,
.num_channels = ARRAY_SIZE(ad7924_channels), .num_channels = ARRAY_SIZE(ad7924_channels),
}, },
[AD7908] = {
.channels = ad7908_channels,
.num_channels = ARRAY_SIZE(ad7908_channels),
},
[AD7918] = {
.channels = ad7918_channels,
.num_channels = ARRAY_SIZE(ad7918_channels),
},
[AD7928] = {
.channels = ad7928_channels,
.num_channels = ARRAY_SIZE(ad7928_channels),
},
}; };
/** /**
...@@ -135,7 +161,11 @@ static int ad7923_update_scan_mode(struct iio_dev *indio_dev, ...@@ -135,7 +161,11 @@ static int ad7923_update_scan_mode(struct iio_dev *indio_dev,
int i, cmd, len; int i, cmd, len;
len = 0; len = 0;
for_each_set_bit(i, active_scan_mask, AD7923_MAX_CHAN) { /*
* For this driver the last channel is always the software timestamp so
* skip that one.
*/
for_each_set_bit(i, active_scan_mask, indio_dev->num_channels - 1) {
cmd = AD7923_WRITE_CR | AD7923_CHANNEL_WRITE(i) | cmd = AD7923_WRITE_CR | AD7923_CHANNEL_WRITE(i) |
AD7923_SEQUENCE_WRITE(AD7923_SEQUENCE_OFF) | AD7923_SEQUENCE_WRITE(AD7923_SEQUENCE_OFF) |
st->settings; st->settings;
...@@ -188,7 +218,7 @@ static irqreturn_t ad7923_trigger_handler(int irq, void *p) ...@@ -188,7 +218,7 @@ static irqreturn_t ad7923_trigger_handler(int irq, void *p)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int ad7923_scan_direct(struct ad7923_state *st, unsigned ch) static int ad7923_scan_direct(struct ad7923_state *st, unsigned int ch)
{ {
int ret, cmd; int ret, cmd;
...@@ -348,13 +378,29 @@ static const struct spi_device_id ad7923_id[] = { ...@@ -348,13 +378,29 @@ static const struct spi_device_id ad7923_id[] = {
{"ad7914", AD7914}, {"ad7914", AD7914},
{"ad7923", AD7924}, {"ad7923", AD7924},
{"ad7924", AD7924}, {"ad7924", AD7924},
{"ad7908", AD7908},
{"ad7918", AD7918},
{"ad7928", AD7928},
{} {}
}; };
MODULE_DEVICE_TABLE(spi, ad7923_id); MODULE_DEVICE_TABLE(spi, ad7923_id);
static const struct of_device_id ad7923_of_match[] = {
{ .compatible = "adi,ad7904", },
{ .compatible = "adi,ad7914", },
{ .compatible = "adi,ad7923", },
{ .compatible = "adi,ad7924", },
{ .compatible = "adi,ad7908", },
{ .compatible = "adi,ad7918", },
{ .compatible = "adi,ad7928", },
{ },
};
MODULE_DEVICE_TABLE(of, ad7923_of_match);
static struct spi_driver ad7923_driver = { static struct spi_driver ad7923_driver = {
.driver = { .driver = {
.name = "ad7923", .name = "ad7923",
.of_match_table = ad7923_of_match,
}, },
.probe = ad7923_probe, .probe = ad7923_probe,
.remove = ad7923_remove, .remove = ad7923_remove,
...@@ -364,5 +410,5 @@ module_spi_driver(ad7923_driver); ...@@ -364,5 +410,5 @@ module_spi_driver(ad7923_driver);
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_AUTHOR("Patrick Vasseur <patrick.vasseur@c-s.fr>"); MODULE_AUTHOR("Patrick Vasseur <patrick.vasseur@c-s.fr>");
MODULE_DESCRIPTION("Analog Devices AD7904/AD7914/AD7923/AD7924 ADC"); MODULE_DESCRIPTION("Analog Devices AD7923 and similar ADC");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -167,6 +167,21 @@ static int ad799x_read_config(struct ad799x_state *st) ...@@ -167,6 +167,21 @@ static int ad799x_read_config(struct ad799x_state *st)
} }
} }
static int ad799x_update_config(struct ad799x_state *st, u16 config)
{
int ret;
ret = ad799x_write_config(st, config);
if (ret < 0)
return ret;
ret = ad799x_read_config(st);
if (ret < 0)
return ret;
st->config = ret;
return 0;
}
/** /**
* ad799x_trigger_handler() bh of trigger launched polling to ring buffer * ad799x_trigger_handler() bh of trigger launched polling to ring buffer
* *
...@@ -808,13 +823,9 @@ static int ad799x_probe(struct i2c_client *client, ...@@ -808,13 +823,9 @@ static int ad799x_probe(struct i2c_client *client,
indio_dev->channels = st->chip_config->channel; indio_dev->channels = st->chip_config->channel;
indio_dev->num_channels = chip_info->num_channels; indio_dev->num_channels = chip_info->num_channels;
ret = ad799x_write_config(st, st->chip_config->default_config); ret = ad799x_update_config(st, st->chip_config->default_config);
if (ret < 0) if (ret)
goto error_disable_vref;
ret = ad799x_read_config(st);
if (ret < 0)
goto error_disable_vref; goto error_disable_vref;
st->config = ret;
ret = iio_triggered_buffer_setup(indio_dev, NULL, ret = iio_triggered_buffer_setup(indio_dev, NULL,
&ad799x_trigger_handler, NULL); &ad799x_trigger_handler, NULL);
...@@ -864,6 +875,48 @@ static int ad799x_remove(struct i2c_client *client) ...@@ -864,6 +875,48 @@ static int ad799x_remove(struct i2c_client *client)
return 0; return 0;
} }
static int __maybe_unused ad799x_suspend(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct ad799x_state *st = iio_priv(indio_dev);
regulator_disable(st->vref);
regulator_disable(st->reg);
return 0;
}
static int __maybe_unused ad799x_resume(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct ad799x_state *st = iio_priv(indio_dev);
int ret;
ret = regulator_enable(st->reg);
if (ret) {
dev_err(dev, "Unable to enable vcc regulator\n");
return ret;
}
ret = regulator_enable(st->vref);
if (ret) {
regulator_disable(st->reg);
dev_err(dev, "Unable to enable vref regulator\n");
return ret;
}
/* resync config */
ret = ad799x_update_config(st, st->config);
if (ret) {
regulator_disable(st->vref);
regulator_disable(st->reg);
return ret;
}
return 0;
}
static SIMPLE_DEV_PM_OPS(ad799x_pm_ops, ad799x_suspend, ad799x_resume);
static const struct i2c_device_id ad799x_id[] = { static const struct i2c_device_id ad799x_id[] = {
{ "ad7991", ad7991 }, { "ad7991", ad7991 },
{ "ad7995", ad7995 }, { "ad7995", ad7995 },
...@@ -881,6 +934,7 @@ MODULE_DEVICE_TABLE(i2c, ad799x_id); ...@@ -881,6 +934,7 @@ MODULE_DEVICE_TABLE(i2c, ad799x_id);
static struct i2c_driver ad799x_driver = { static struct i2c_driver ad799x_driver = {
.driver = { .driver = {
.name = "ad799x", .name = "ad799x",
.pm = &ad799x_pm_ops,
}, },
.probe = ad799x_probe, .probe = ad799x_probe,
.remove = ad799x_remove, .remove = ad799x_remove,
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* ltc2496.c - Driver for Analog Devices/Linear Technology LTC2496 ADC
*
* Based on ltc2497.c which has
* Copyright (C) 2017 Analog Devices Inc.
*
* Licensed under the GPL-2.
*
* Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/2496fc.pdf
*/
#include <linux/spi/spi.h>
#include <linux/iio/iio.h>
#include <linux/iio/driver.h>
#include <linux/module.h>
#include <linux/of.h>
#include "ltc2497.h"
struct ltc2496_driverdata {
/* this must be the first member */
struct ltc2497core_driverdata common_ddata;
struct spi_device *spi;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
unsigned char rxbuf[3] ____cacheline_aligned;
unsigned char txbuf[3];
};
static int ltc2496_result_and_measure(struct ltc2497core_driverdata *ddata,
u8 address, int *val)
{
struct ltc2496_driverdata *st =
container_of(ddata, struct ltc2496_driverdata, common_ddata);
struct spi_transfer t = {
.tx_buf = st->txbuf,
.rx_buf = st->rxbuf,
.len = sizeof(st->txbuf),
};
int ret;
st->txbuf[0] = LTC2497_ENABLE | address;
ret = spi_sync_transfer(st->spi, &t, 1);
if (ret < 0) {
dev_err(&st->spi->dev, "spi_sync_transfer failed: %pe\n",
ERR_PTR(ret));
return ret;
}
if (val)
*val = ((st->rxbuf[0] & 0x3f) << 12 |
st->rxbuf[1] << 4 | st->rxbuf[2] >> 4) -
(1 << 17);
return 0;
}
static int ltc2496_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
struct ltc2496_driverdata *st;
struct device *dev = &spi->dev;
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
spi_set_drvdata(spi, indio_dev);
st->spi = spi;
st->common_ddata.result_and_measure = ltc2496_result_and_measure;
return ltc2497core_probe(dev, indio_dev);
}
static int ltc2496_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
ltc2497core_remove(indio_dev);
return 0;
}
static const struct of_device_id ltc2496_of_match[] = {
{ .compatible = "lltc,ltc2496", },
{},
};
MODULE_DEVICE_TABLE(of, ltc2496_of_match);
static struct spi_driver ltc2496_driver = {
.driver = {
.name = "ltc2496",
.of_match_table = of_match_ptr(ltc2496_of_match),
},
.probe = ltc2496_probe,
.remove = ltc2496_remove,
};
module_spi_driver(ltc2496_driver);
MODULE_AUTHOR("Uwe Kleine-König <u.kleine-könig@pengutronix.de>");
MODULE_DESCRIPTION("Linear Technology LTC2496 ADC driver");
MODULE_LICENSE("GPL v2");
// SPDX-License-Identifier: GPL-2.0-only
/*
* ltc2497-core.c - Common code for Analog Devices/Linear Technology
* LTC2496 and LTC2497 ADCs
*
* Copyright (C) 2017 Analog Devices Inc.
*/
#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/iio/driver.h>
#include <linux/module.h>
#include <linux/regulator/consumer.h>
#include "ltc2497.h"
#define LTC2497_SGL BIT(4)
#define LTC2497_DIFF 0
#define LTC2497_SIGN BIT(3)
static int ltc2497core_wait_conv(struct ltc2497core_driverdata *ddata)
{
s64 time_elapsed;
time_elapsed = ktime_ms_delta(ktime_get(), ddata->time_prev);
if (time_elapsed < LTC2497_CONVERSION_TIME_MS) {
/* delay if conversion time not passed
* since last read or write
*/
if (msleep_interruptible(
LTC2497_CONVERSION_TIME_MS - time_elapsed))
return -ERESTARTSYS;
return 0;
}
if (time_elapsed - LTC2497_CONVERSION_TIME_MS <= 0) {
/* We're in automatic mode -
* so the last reading is still not outdated
*/
return 0;
}
return 1;
}
static int ltc2497core_read(struct ltc2497core_driverdata *ddata, u8 address, int *val)
{
int ret;
ret = ltc2497core_wait_conv(ddata);
if (ret < 0)
return ret;
if (ret || ddata->addr_prev != address) {
ret = ddata->result_and_measure(ddata, address, NULL);
if (ret < 0)
return ret;
ddata->addr_prev = address;
if (msleep_interruptible(LTC2497_CONVERSION_TIME_MS))
return -ERESTARTSYS;
}
ret = ddata->result_and_measure(ddata, address, val);
if (ret < 0)
return ret;
ddata->time_prev = ktime_get();
return ret;
}
static int ltc2497core_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct ltc2497core_driverdata *ddata = iio_priv(indio_dev);
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock);
ret = ltc2497core_read(ddata, chan->address, val);
mutex_unlock(&indio_dev->mlock);
if (ret < 0)
return ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
ret = regulator_get_voltage(ddata->ref);
if (ret < 0)
return ret;
*val = ret / 1000;
*val2 = 17;
return IIO_VAL_FRACTIONAL_LOG2;
default:
return -EINVAL;
}
}
#define LTC2497_CHAN(_chan, _addr, _ds_name) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = (_chan), \
.address = (_addr | (_chan / 2) | ((_chan & 1) ? LTC2497_SIGN : 0)), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.datasheet_name = (_ds_name), \
}
#define LTC2497_CHAN_DIFF(_chan, _addr) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 1 : 0), \
.channel2 = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 0 : 1),\
.address = (_addr | _chan), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.differential = 1, \
}
static const struct iio_chan_spec ltc2497core_channel[] = {
LTC2497_CHAN(0, LTC2497_SGL, "CH0"),
LTC2497_CHAN(1, LTC2497_SGL, "CH1"),
LTC2497_CHAN(2, LTC2497_SGL, "CH2"),
LTC2497_CHAN(3, LTC2497_SGL, "CH3"),
LTC2497_CHAN(4, LTC2497_SGL, "CH4"),
LTC2497_CHAN(5, LTC2497_SGL, "CH5"),
LTC2497_CHAN(6, LTC2497_SGL, "CH6"),
LTC2497_CHAN(7, LTC2497_SGL, "CH7"),
LTC2497_CHAN(8, LTC2497_SGL, "CH8"),
LTC2497_CHAN(9, LTC2497_SGL, "CH9"),
LTC2497_CHAN(10, LTC2497_SGL, "CH10"),
LTC2497_CHAN(11, LTC2497_SGL, "CH11"),
LTC2497_CHAN(12, LTC2497_SGL, "CH12"),
LTC2497_CHAN(13, LTC2497_SGL, "CH13"),
LTC2497_CHAN(14, LTC2497_SGL, "CH14"),
LTC2497_CHAN(15, LTC2497_SGL, "CH15"),
LTC2497_CHAN_DIFF(0, LTC2497_DIFF),
LTC2497_CHAN_DIFF(1, LTC2497_DIFF),
LTC2497_CHAN_DIFF(2, LTC2497_DIFF),
LTC2497_CHAN_DIFF(3, LTC2497_DIFF),
LTC2497_CHAN_DIFF(4, LTC2497_DIFF),
LTC2497_CHAN_DIFF(5, LTC2497_DIFF),
LTC2497_CHAN_DIFF(6, LTC2497_DIFF),
LTC2497_CHAN_DIFF(7, LTC2497_DIFF),
LTC2497_CHAN_DIFF(0, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(1, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(2, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(3, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(4, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(5, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(6, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(7, LTC2497_DIFF | LTC2497_SIGN),
};
static const struct iio_info ltc2497core_info = {
.read_raw = ltc2497core_read_raw,
};
int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev)
{
struct ltc2497core_driverdata *ddata = iio_priv(indio_dev);
int ret;
indio_dev->dev.parent = dev;
indio_dev->name = dev_name(dev);
indio_dev->info = &ltc2497core_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = ltc2497core_channel;
indio_dev->num_channels = ARRAY_SIZE(ltc2497core_channel);
ret = ddata->result_and_measure(ddata, LTC2497_CONFIG_DEFAULT, NULL);
if (ret < 0)
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);
}
ret = regulator_enable(ddata->ref);
if (ret < 0) {
dev_err(dev, "Failed to enable vref regulator: %pe\n",
ERR_PTR(ret));
return ret;
}
if (dev->platform_data) {
struct iio_map *plat_data;
plat_data = (struct iio_map *)dev->platform_data;
ret = iio_map_array_register(indio_dev, plat_data);
if (ret) {
dev_err(&indio_dev->dev, "iio map err: %d\n", ret);
goto err_regulator_disable;
}
}
ddata->addr_prev = LTC2497_CONFIG_DEFAULT;
ddata->time_prev = ktime_get();
ret = iio_device_register(indio_dev);
if (ret < 0)
goto err_array_unregister;
return 0;
err_array_unregister:
iio_map_array_unregister(indio_dev);
err_regulator_disable:
regulator_disable(ddata->ref);
return ret;
}
EXPORT_SYMBOL_NS(ltc2497core_probe, LTC2497);
void ltc2497core_remove(struct iio_dev *indio_dev)
{
struct ltc2497core_driverdata *ddata = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
iio_map_array_unregister(indio_dev);
regulator_disable(ddata->ref);
}
EXPORT_SYMBOL_NS(ltc2497core_remove, LTC2497);
MODULE_DESCRIPTION("common code for LTC2496/LTC2497 drivers");
MODULE_LICENSE("GPL v2");
...@@ -7,27 +7,18 @@ ...@@ -7,27 +7,18 @@
* Datasheet: http://cds.linear.com/docs/en/datasheet/2497fd.pdf * Datasheet: http://cds.linear.com/docs/en/datasheet/2497fd.pdf
*/ */
#include <linux/delay.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/driver.h> #include <linux/iio/driver.h>
#include <linux/iio/sysfs.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/regulator/consumer.h>
#define LTC2497_ENABLE 0xA0 #include "ltc2497.h"
#define LTC2497_SGL BIT(4)
#define LTC2497_DIFF 0
#define LTC2497_SIGN BIT(3)
#define LTC2497_CONFIG_DEFAULT LTC2497_ENABLE
#define LTC2497_CONVERSION_TIME_MS 150ULL
struct ltc2497_st { struct ltc2497_driverdata {
/* this must be the first member */
struct ltc2497core_driverdata common_ddata;
struct i2c_client *client; struct i2c_client *client;
struct regulator *ref;
ktime_t time_prev;
u8 addr_prev;
/* /*
* DMA (thus cache coherency maintenance) requires the * DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines. * transfer buffers to live in their own cache lines.
...@@ -35,232 +26,59 @@ struct ltc2497_st { ...@@ -35,232 +26,59 @@ struct ltc2497_st {
__be32 buf ____cacheline_aligned; __be32 buf ____cacheline_aligned;
}; };
static int ltc2497_wait_conv(struct ltc2497_st *st) static int ltc2497_result_and_measure(struct ltc2497core_driverdata *ddata,
u8 address, int *val)
{ {
s64 time_elapsed; struct ltc2497_driverdata *st =
container_of(ddata, struct ltc2497_driverdata, common_ddata);
time_elapsed = ktime_ms_delta(ktime_get(), st->time_prev);
if (time_elapsed < LTC2497_CONVERSION_TIME_MS) {
/* delay if conversion time not passed
* since last read or write
*/
if (msleep_interruptible(
LTC2497_CONVERSION_TIME_MS - time_elapsed))
return -ERESTARTSYS;
return 0;
}
if (time_elapsed - LTC2497_CONVERSION_TIME_MS <= 0) {
/* We're in automatic mode -
* so the last reading is stil not outdated
*/
return 0;
}
return 1;
}
static int ltc2497_read(struct ltc2497_st *st, u8 address, int *val)
{
struct i2c_client *client = st->client;
int ret;
ret = ltc2497_wait_conv(st);
if (ret < 0)
return ret;
if (ret || st->addr_prev != address) {
ret = i2c_smbus_write_byte(st->client,
LTC2497_ENABLE | address);
if (ret < 0)
return ret;
st->addr_prev = address;
if (msleep_interruptible(LTC2497_CONVERSION_TIME_MS))
return -ERESTARTSYS;
}
ret = i2c_master_recv(client, (char *)&st->buf, 3);
if (ret < 0) {
dev_err(&client->dev, "i2c_master_recv failed\n");
return ret;
}
st->time_prev = ktime_get();
/* convert and shift the result,
* and finally convert from offset binary to signed integer
*/
*val = (be32_to_cpu(st->buf) >> 14) - (1 << 17);
return ret;
}
static int ltc2497_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct ltc2497_st *st = iio_priv(indio_dev);
int ret; int ret;
switch (mask) { if (val) {
case IIO_CHAN_INFO_RAW: ret = i2c_master_recv(st->client, (char *)&st->buf, 3);
mutex_lock(&indio_dev->mlock); if (ret < 0) {
ret = ltc2497_read(st, chan->address, val); dev_err(&st->client->dev, "i2c_master_recv failed\n");
mutex_unlock(&indio_dev->mlock);
if (ret < 0)
return ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
ret = regulator_get_voltage(st->ref);
if (ret < 0)
return ret; return ret;
}
*val = ret / 1000; *val = (be32_to_cpu(st->buf) >> 14) - (1 << 17);
*val2 = 17;
return IIO_VAL_FRACTIONAL_LOG2;
default:
return -EINVAL;
} }
}
#define LTC2497_CHAN(_chan, _addr, _ds_name) { \ ret = i2c_smbus_write_byte(st->client,
.type = IIO_VOLTAGE, \ LTC2497_ENABLE | address);
.indexed = 1, \ if (ret)
.channel = (_chan), \ dev_err(&st->client->dev, "i2c transfer failed: %pe\n",
.address = (_addr | (_chan / 2) | ((_chan & 1) ? LTC2497_SIGN : 0)), \ ERR_PTR(ret));
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ return ret;
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.datasheet_name = (_ds_name), \
}
#define LTC2497_CHAN_DIFF(_chan, _addr) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 1 : 0), \
.channel2 = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 0 : 1),\
.address = (_addr | _chan), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.differential = 1, \
} }
static const struct iio_chan_spec ltc2497_channel[] = {
LTC2497_CHAN(0, LTC2497_SGL, "CH0"),
LTC2497_CHAN(1, LTC2497_SGL, "CH1"),
LTC2497_CHAN(2, LTC2497_SGL, "CH2"),
LTC2497_CHAN(3, LTC2497_SGL, "CH3"),
LTC2497_CHAN(4, LTC2497_SGL, "CH4"),
LTC2497_CHAN(5, LTC2497_SGL, "CH5"),
LTC2497_CHAN(6, LTC2497_SGL, "CH6"),
LTC2497_CHAN(7, LTC2497_SGL, "CH7"),
LTC2497_CHAN(8, LTC2497_SGL, "CH8"),
LTC2497_CHAN(9, LTC2497_SGL, "CH9"),
LTC2497_CHAN(10, LTC2497_SGL, "CH10"),
LTC2497_CHAN(11, LTC2497_SGL, "CH11"),
LTC2497_CHAN(12, LTC2497_SGL, "CH12"),
LTC2497_CHAN(13, LTC2497_SGL, "CH13"),
LTC2497_CHAN(14, LTC2497_SGL, "CH14"),
LTC2497_CHAN(15, LTC2497_SGL, "CH15"),
LTC2497_CHAN_DIFF(0, LTC2497_DIFF),
LTC2497_CHAN_DIFF(1, LTC2497_DIFF),
LTC2497_CHAN_DIFF(2, LTC2497_DIFF),
LTC2497_CHAN_DIFF(3, LTC2497_DIFF),
LTC2497_CHAN_DIFF(4, LTC2497_DIFF),
LTC2497_CHAN_DIFF(5, LTC2497_DIFF),
LTC2497_CHAN_DIFF(6, LTC2497_DIFF),
LTC2497_CHAN_DIFF(7, LTC2497_DIFF),
LTC2497_CHAN_DIFF(0, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(1, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(2, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(3, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(4, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(5, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(6, LTC2497_DIFF | LTC2497_SIGN),
LTC2497_CHAN_DIFF(7, LTC2497_DIFF | LTC2497_SIGN),
};
static const struct iio_info ltc2497_info = {
.read_raw = ltc2497_read_raw,
};
static int ltc2497_probe(struct i2c_client *client, static int ltc2497_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
struct ltc2497_st *st; struct ltc2497_driverdata *st;
struct iio_map *plat_data; struct device *dev = &client->dev;
int ret;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
I2C_FUNC_SMBUS_WRITE_BYTE)) I2C_FUNC_SMBUS_WRITE_BYTE))
return -EOPNOTSUPP; return -EOPNOTSUPP;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!indio_dev) if (!indio_dev)
return -ENOMEM; return -ENOMEM;
st = iio_priv(indio_dev); st = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev); i2c_set_clientdata(client, indio_dev);
st->client = client; st->client = client;
st->common_ddata.result_and_measure = ltc2497_result_and_measure;
indio_dev->dev.parent = &client->dev; return ltc2497core_probe(dev, indio_dev);
indio_dev->name = id->name;
indio_dev->info = &ltc2497_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = ltc2497_channel;
indio_dev->num_channels = ARRAY_SIZE(ltc2497_channel);
st->ref = devm_regulator_get(&client->dev, "vref");
if (IS_ERR(st->ref))
return PTR_ERR(st->ref);
ret = regulator_enable(st->ref);
if (ret < 0)
return ret;
if (client->dev.platform_data) {
plat_data = ((struct iio_map *)client->dev.platform_data);
ret = iio_map_array_register(indio_dev, plat_data);
if (ret) {
dev_err(&indio_dev->dev, "iio map err: %d\n", ret);
goto err_regulator_disable;
}
}
ret = i2c_smbus_write_byte(st->client, LTC2497_CONFIG_DEFAULT);
if (ret < 0)
goto err_array_unregister;
st->addr_prev = LTC2497_CONFIG_DEFAULT;
st->time_prev = ktime_get();
ret = iio_device_register(indio_dev);
if (ret < 0)
goto err_array_unregister;
return 0;
err_array_unregister:
iio_map_array_unregister(indio_dev);
err_regulator_disable:
regulator_disable(st->ref);
return ret;
} }
static int ltc2497_remove(struct i2c_client *client) static int ltc2497_remove(struct i2c_client *client)
{ {
struct iio_dev *indio_dev = i2c_get_clientdata(client); struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct ltc2497_st *st = iio_priv(indio_dev);
iio_map_array_unregister(indio_dev); ltc2497core_remove(indio_dev);
iio_device_unregister(indio_dev);
regulator_disable(st->ref);
return 0; return 0;
} }
......
/* SPDX-License-Identifier: GPL-2.0-only */
#define LTC2497_ENABLE 0xA0
#define LTC2497_CONFIG_DEFAULT LTC2497_ENABLE
#define LTC2497_CONVERSION_TIME_MS 150ULL
struct ltc2497core_driverdata {
struct regulator *ref;
ktime_t time_prev;
u8 addr_prev;
int (*result_and_measure)(struct ltc2497core_driverdata *ddata,
u8 address, int *val);
};
int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev);
void ltc2497core_remove(struct iio_dev *indio_dev);
MODULE_IMPORT_NS(LTC2497);
...@@ -115,22 +115,17 @@ enum max9611_conf_ids { ...@@ -115,22 +115,17 @@ enum max9611_conf_ids {
* where data shall be read from * where data shall be read from
*/ */
static const unsigned int max9611_mux_conf[][2] = { static const unsigned int max9611_mux_conf[][2] = {
/* CONF_SENSE_1x */ [CONF_SENSE_1x] = { MAX9611_MUX_SENSE_1x, MAX9611_REG_CSA_DATA },
{ MAX9611_MUX_SENSE_1x, MAX9611_REG_CSA_DATA }, [CONF_SENSE_4x] = { MAX9611_MUX_SENSE_4x, MAX9611_REG_CSA_DATA },
/* CONF_SENSE_4x */ [CONF_SENSE_8x] = { MAX9611_MUX_SENSE_8x, MAX9611_REG_CSA_DATA },
{ MAX9611_MUX_SENSE_4x, MAX9611_REG_CSA_DATA }, [CONF_IN_VOLT] = { MAX9611_INPUT_VOLT, MAX9611_REG_RS_DATA },
/* CONF_SENSE_8x */ [CONF_TEMP] = { MAX9611_MUX_TEMP, MAX9611_REG_TEMP_DATA },
{ MAX9611_MUX_SENSE_8x, MAX9611_REG_CSA_DATA },
/* CONF_IN_VOLT */
{ MAX9611_INPUT_VOLT, MAX9611_REG_RS_DATA },
/* CONF_TEMP */
{ MAX9611_MUX_TEMP, MAX9611_REG_TEMP_DATA },
}; };
enum max9611_csa_gain { enum max9611_csa_gain {
CSA_GAIN_1x, CSA_GAIN_1x = CONF_SENSE_1x,
CSA_GAIN_4x, CSA_GAIN_4x = CONF_SENSE_4x,
CSA_GAIN_8x, CSA_GAIN_8x = CONF_SENSE_8x,
}; };
enum max9611_csa_gain_params { enum max9611_csa_gain_params {
...@@ -148,18 +143,9 @@ enum max9611_csa_gain_params { ...@@ -148,18 +143,9 @@ enum max9611_csa_gain_params {
* value; use this structure to retrieve the correct LSB and offset values. * value; use this structure to retrieve the correct LSB and offset values.
*/ */
static const unsigned int max9611_gain_conf[][2] = { static const unsigned int max9611_gain_conf[][2] = {
{ /* [0] CSA_GAIN_1x */ [CSA_GAIN_1x] = { MAX9611_CSA_1X_LSB_nV, MAX9611_CSA_1X_OFFS_RAW, },
MAX9611_CSA_1X_LSB_nV, [CSA_GAIN_4x] = { MAX9611_CSA_4X_LSB_nV, MAX9611_CSA_4X_OFFS_RAW, },
MAX9611_CSA_1X_OFFS_RAW, [CSA_GAIN_8x] = { MAX9611_CSA_8X_LSB_nV, MAX9611_CSA_8X_OFFS_RAW, },
},
{ /* [1] CSA_GAIN_4x */
MAX9611_CSA_4X_LSB_nV,
MAX9611_CSA_4X_OFFS_RAW,
},
{ /* [2] CSA_GAIN_8x */
MAX9611_CSA_8X_LSB_nV,
MAX9611_CSA_8X_OFFS_RAW,
},
}; };
enum max9611_chan_addrs { enum max9611_chan_addrs {
......
...@@ -280,21 +280,21 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev, ...@@ -280,21 +280,21 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev,
static const struct stm32_adc_common_regs stm32f4_adc_common_regs = { static const struct stm32_adc_common_regs stm32f4_adc_common_regs = {
.csr = STM32F4_ADC_CSR, .csr = STM32F4_ADC_CSR,
.ccr = STM32F4_ADC_CCR, .ccr = STM32F4_ADC_CCR,
.eoc1_msk = STM32F4_EOC1, .eoc1_msk = STM32F4_EOC1 | STM32F4_OVR1,
.eoc2_msk = STM32F4_EOC2, .eoc2_msk = STM32F4_EOC2 | STM32F4_OVR2,
.eoc3_msk = STM32F4_EOC3, .eoc3_msk = STM32F4_EOC3 | STM32F4_OVR3,
.ier = STM32F4_ADC_CR1, .ier = STM32F4_ADC_CR1,
.eocie_msk = STM32F4_EOCIE, .eocie_msk = STM32F4_EOCIE | STM32F4_OVRIE,
}; };
/* STM32H7 common registers definitions */ /* STM32H7 common registers definitions */
static const struct stm32_adc_common_regs stm32h7_adc_common_regs = { static const struct stm32_adc_common_regs stm32h7_adc_common_regs = {
.csr = STM32H7_ADC_CSR, .csr = STM32H7_ADC_CSR,
.ccr = STM32H7_ADC_CCR, .ccr = STM32H7_ADC_CCR,
.eoc1_msk = STM32H7_EOC_MST, .eoc1_msk = STM32H7_EOC_MST | STM32H7_OVR_MST,
.eoc2_msk = STM32H7_EOC_SLV, .eoc2_msk = STM32H7_EOC_SLV | STM32H7_OVR_SLV,
.ier = STM32H7_ADC_IER, .ier = STM32H7_ADC_IER,
.eocie_msk = STM32H7_EOCIE, .eocie_msk = STM32H7_EOCIE | STM32H7_OVRIE,
}; };
static const unsigned int stm32_adc_offset[STM32_ADC_MAX_ADCS] = { static const unsigned int stm32_adc_offset[STM32_ADC_MAX_ADCS] = {
......
...@@ -51,10 +51,12 @@ ...@@ -51,10 +51,12 @@
#define STM32F4_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x04) #define STM32F4_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x04)
/* STM32F4_ADC_SR - bit fields */ /* STM32F4_ADC_SR - bit fields */
#define STM32F4_OVR BIT(5)
#define STM32F4_STRT BIT(4) #define STM32F4_STRT BIT(4)
#define STM32F4_EOC BIT(1) #define STM32F4_EOC BIT(1)
/* STM32F4_ADC_CR1 - bit fields */ /* STM32F4_ADC_CR1 - bit fields */
#define STM32F4_OVRIE BIT(26)
#define STM32F4_RES_SHIFT 24 #define STM32F4_RES_SHIFT 24
#define STM32F4_RES_MASK GENMASK(25, 24) #define STM32F4_RES_MASK GENMASK(25, 24)
#define STM32F4_SCAN BIT(8) #define STM32F4_SCAN BIT(8)
...@@ -72,8 +74,11 @@ ...@@ -72,8 +74,11 @@
#define STM32F4_ADON BIT(0) #define STM32F4_ADON BIT(0)
/* STM32F4_ADC_CSR - bit fields */ /* STM32F4_ADC_CSR - bit fields */
#define STM32F4_OVR3 BIT(21)
#define STM32F4_EOC3 BIT(17) #define STM32F4_EOC3 BIT(17)
#define STM32F4_OVR2 BIT(13)
#define STM32F4_EOC2 BIT(9) #define STM32F4_EOC2 BIT(9)
#define STM32F4_OVR1 BIT(5)
#define STM32F4_EOC1 BIT(1) #define STM32F4_EOC1 BIT(1)
/* STM32F4_ADC_CCR - bit fields */ /* STM32F4_ADC_CCR - bit fields */
...@@ -103,10 +108,12 @@ ...@@ -103,10 +108,12 @@
/* STM32H7_ADC_ISR - bit fields */ /* STM32H7_ADC_ISR - bit fields */
#define STM32MP1_VREGREADY BIT(12) #define STM32MP1_VREGREADY BIT(12)
#define STM32H7_OVR BIT(4)
#define STM32H7_EOC BIT(2) #define STM32H7_EOC BIT(2)
#define STM32H7_ADRDY BIT(0) #define STM32H7_ADRDY BIT(0)
/* STM32H7_ADC_IER - bit fields */ /* STM32H7_ADC_IER - bit fields */
#define STM32H7_OVRIE STM32H7_OVR
#define STM32H7_EOCIE STM32H7_EOC #define STM32H7_EOCIE STM32H7_EOC
/* STM32H7_ADC_CR - bit fields */ /* STM32H7_ADC_CR - bit fields */
...@@ -155,7 +162,9 @@ enum stm32h7_adc_dmngt { ...@@ -155,7 +162,9 @@ enum stm32h7_adc_dmngt {
#define STM32H7_LINCALFACT_MASK GENMASK(29, 0) #define STM32H7_LINCALFACT_MASK GENMASK(29, 0)
/* STM32H7_ADC_CSR - bit fields */ /* STM32H7_ADC_CSR - bit fields */
#define STM32H7_OVR_SLV BIT(20)
#define STM32H7_EOC_SLV BIT(18) #define STM32H7_EOC_SLV BIT(18)
#define STM32H7_OVR_MST BIT(4)
#define STM32H7_EOC_MST BIT(2) #define STM32H7_EOC_MST BIT(2)
/* STM32H7_ADC_CCR - bit fields */ /* STM32H7_ADC_CCR - bit fields */
......
...@@ -117,7 +117,9 @@ struct stm32_adc_regs { ...@@ -117,7 +117,9 @@ struct stm32_adc_regs {
* struct stm32_adc_regspec - stm32 registers definition * struct stm32_adc_regspec - stm32 registers definition
* @dr: data register offset * @dr: data register offset
* @ier_eoc: interrupt enable register & eocie bitfield * @ier_eoc: interrupt enable register & eocie bitfield
* @ier_ovr: interrupt enable register & overrun bitfield
* @isr_eoc: interrupt status register & eoc bitfield * @isr_eoc: interrupt status register & eoc bitfield
* @isr_ovr: interrupt status register & overrun bitfield
* @sqr: reference to sequence registers array * @sqr: reference to sequence registers array
* @exten: trigger control register & bitfield * @exten: trigger control register & bitfield
* @extsel: trigger selection register & bitfield * @extsel: trigger selection register & bitfield
...@@ -128,7 +130,9 @@ struct stm32_adc_regs { ...@@ -128,7 +130,9 @@ struct stm32_adc_regs {
struct stm32_adc_regspec { struct stm32_adc_regspec {
const u32 dr; const u32 dr;
const struct stm32_adc_regs ier_eoc; const struct stm32_adc_regs ier_eoc;
const struct stm32_adc_regs ier_ovr;
const struct stm32_adc_regs isr_eoc; const struct stm32_adc_regs isr_eoc;
const struct stm32_adc_regs isr_ovr;
const struct stm32_adc_regs *sqr; const struct stm32_adc_regs *sqr;
const struct stm32_adc_regs exten; const struct stm32_adc_regs exten;
const struct stm32_adc_regs extsel; const struct stm32_adc_regs extsel;
...@@ -337,7 +341,9 @@ static const unsigned int stm32f4_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = { ...@@ -337,7 +341,9 @@ static const unsigned int stm32f4_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = {
static const struct stm32_adc_regspec stm32f4_adc_regspec = { static const struct stm32_adc_regspec stm32f4_adc_regspec = {
.dr = STM32F4_ADC_DR, .dr = STM32F4_ADC_DR,
.ier_eoc = { STM32F4_ADC_CR1, STM32F4_EOCIE }, .ier_eoc = { STM32F4_ADC_CR1, STM32F4_EOCIE },
.ier_ovr = { STM32F4_ADC_CR1, STM32F4_OVRIE },
.isr_eoc = { STM32F4_ADC_SR, STM32F4_EOC }, .isr_eoc = { STM32F4_ADC_SR, STM32F4_EOC },
.isr_ovr = { STM32F4_ADC_SR, STM32F4_OVR },
.sqr = stm32f4_sq, .sqr = stm32f4_sq,
.exten = { STM32F4_ADC_CR2, STM32F4_EXTEN_MASK, STM32F4_EXTEN_SHIFT }, .exten = { STM32F4_ADC_CR2, STM32F4_EXTEN_MASK, STM32F4_EXTEN_SHIFT },
.extsel = { STM32F4_ADC_CR2, STM32F4_EXTSEL_MASK, .extsel = { STM32F4_ADC_CR2, STM32F4_EXTSEL_MASK,
...@@ -429,7 +435,9 @@ static const unsigned int stm32h7_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = { ...@@ -429,7 +435,9 @@ static const unsigned int stm32h7_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = {
static const struct stm32_adc_regspec stm32h7_adc_regspec = { static const struct stm32_adc_regspec stm32h7_adc_regspec = {
.dr = STM32H7_ADC_DR, .dr = STM32H7_ADC_DR,
.ier_eoc = { STM32H7_ADC_IER, STM32H7_EOCIE }, .ier_eoc = { STM32H7_ADC_IER, STM32H7_EOCIE },
.ier_ovr = { STM32H7_ADC_IER, STM32H7_OVRIE },
.isr_eoc = { STM32H7_ADC_ISR, STM32H7_EOC }, .isr_eoc = { STM32H7_ADC_ISR, STM32H7_EOC },
.isr_ovr = { STM32H7_ADC_ISR, STM32H7_OVR },
.sqr = stm32h7_sq, .sqr = stm32h7_sq,
.exten = { STM32H7_ADC_CFGR, STM32H7_EXTEN_MASK, STM32H7_EXTEN_SHIFT }, .exten = { STM32H7_ADC_CFGR, STM32H7_EXTEN_MASK, STM32H7_EXTEN_SHIFT },
.extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK, .extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK,
...@@ -506,6 +514,18 @@ static void stm32_adc_conv_irq_disable(struct stm32_adc *adc) ...@@ -506,6 +514,18 @@ static void stm32_adc_conv_irq_disable(struct stm32_adc *adc)
adc->cfg->regs->ier_eoc.mask); adc->cfg->regs->ier_eoc.mask);
} }
static void stm32_adc_ovr_irq_enable(struct stm32_adc *adc)
{
stm32_adc_set_bits(adc, adc->cfg->regs->ier_ovr.reg,
adc->cfg->regs->ier_ovr.mask);
}
static void stm32_adc_ovr_irq_disable(struct stm32_adc *adc)
{
stm32_adc_clr_bits(adc, adc->cfg->regs->ier_ovr.reg,
adc->cfg->regs->ier_ovr.mask);
}
static void stm32_adc_set_res(struct stm32_adc *adc) static void stm32_adc_set_res(struct stm32_adc *adc)
{ {
const struct stm32_adc_regs *res = &adc->cfg->regs->res; const struct stm32_adc_regs *res = &adc->cfg->regs->res;
...@@ -1205,6 +1225,19 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev, ...@@ -1205,6 +1225,19 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev,
} }
} }
static irqreturn_t stm32_adc_threaded_isr(int irq, void *data)
{
struct stm32_adc *adc = data;
struct iio_dev *indio_dev = iio_priv_to_dev(adc);
const struct stm32_adc_regspec *regs = adc->cfg->regs;
u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg);
if (status & regs->isr_ovr.mask)
dev_err(&indio_dev->dev, "Overrun, stopping: restart needed\n");
return IRQ_HANDLED;
}
static irqreturn_t stm32_adc_isr(int irq, void *data) static irqreturn_t stm32_adc_isr(int irq, void *data)
{ {
struct stm32_adc *adc = data; struct stm32_adc *adc = data;
...@@ -1212,6 +1245,19 @@ static irqreturn_t stm32_adc_isr(int irq, void *data) ...@@ -1212,6 +1245,19 @@ static irqreturn_t stm32_adc_isr(int irq, void *data)
const struct stm32_adc_regspec *regs = adc->cfg->regs; const struct stm32_adc_regspec *regs = adc->cfg->regs;
u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg); u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg);
if (status & regs->isr_ovr.mask) {
/*
* Overrun occurred on regular conversions: data for wrong
* channel may be read. Unconditionally disable interrupts
* to stop processing data and print error message.
* Restarting the capture can be done by disabling, then
* re-enabling it (e.g. write 0, then 1 to buffer/enable).
*/
stm32_adc_ovr_irq_disable(adc);
stm32_adc_conv_irq_disable(adc);
return IRQ_WAKE_THREAD;
}
if (status & regs->isr_eoc.mask) { if (status & regs->isr_eoc.mask) {
/* Reading DR also clears EOC status flag */ /* Reading DR also clears EOC status flag */
adc->buffer[adc->bufi] = stm32_adc_readw(adc, regs->dr); adc->buffer[adc->bufi] = stm32_adc_readw(adc, regs->dr);
...@@ -1441,6 +1487,8 @@ static int __stm32_adc_buffer_postenable(struct iio_dev *indio_dev) ...@@ -1441,6 +1487,8 @@ static int __stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
/* Reset adc buffer index */ /* Reset adc buffer index */
adc->bufi = 0; adc->bufi = 0;
stm32_adc_ovr_irq_enable(adc);
if (!adc->dma_chan) if (!adc->dma_chan)
stm32_adc_conv_irq_enable(adc); stm32_adc_conv_irq_enable(adc);
...@@ -1481,6 +1529,8 @@ static void __stm32_adc_buffer_predisable(struct iio_dev *indio_dev) ...@@ -1481,6 +1529,8 @@ static void __stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
if (!adc->dma_chan) if (!adc->dma_chan)
stm32_adc_conv_irq_disable(adc); stm32_adc_conv_irq_disable(adc);
stm32_adc_ovr_irq_disable(adc);
if (adc->dma_chan) if (adc->dma_chan)
dmaengine_terminate_sync(adc->dma_chan); dmaengine_terminate_sync(adc->dma_chan);
...@@ -1818,8 +1868,9 @@ static int stm32_adc_probe(struct platform_device *pdev) ...@@ -1818,8 +1868,9 @@ static int stm32_adc_probe(struct platform_device *pdev)
if (adc->irq < 0) if (adc->irq < 0)
return adc->irq; return adc->irq;
ret = devm_request_irq(&pdev->dev, adc->irq, stm32_adc_isr, ret = devm_request_threaded_irq(&pdev->dev, adc->irq, stm32_adc_isr,
0, pdev->name, adc); stm32_adc_threaded_isr,
0, pdev->name, adc);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to request IRQ\n"); dev_err(&pdev->dev, "failed to request IRQ\n");
return ret; return ret;
......
...@@ -12,17 +12,15 @@ ...@@ -12,17 +12,15 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_device.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/property.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/platform_data/ads1015.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/types.h> #include <linux/iio/types.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
...@@ -33,6 +31,8 @@ ...@@ -33,6 +31,8 @@
#define ADS1015_DRV_NAME "ads1015" #define ADS1015_DRV_NAME "ads1015"
#define ADS1015_CHANNELS 8
#define ADS1015_CONV_REG 0x00 #define ADS1015_CONV_REG 0x00
#define ADS1015_CFG_REG 0x01 #define ADS1015_CFG_REG 0x01
#define ADS1015_LO_THRESH_REG 0x02 #define ADS1015_LO_THRESH_REG 0x02
...@@ -77,6 +77,7 @@ ...@@ -77,6 +77,7 @@
#define ADS1015_DEFAULT_CHAN 0 #define ADS1015_DEFAULT_CHAN 0
enum chip_ids { enum chip_ids {
ADSXXXX = 0,
ADS1015, ADS1015,
ADS1115, ADS1115,
}; };
...@@ -219,6 +220,12 @@ static const struct iio_event_spec ads1015_events[] = { ...@@ -219,6 +220,12 @@ static const struct iio_event_spec ads1015_events[] = {
.datasheet_name = "AIN"#_chan"-AIN"#_chan2, \ .datasheet_name = "AIN"#_chan"-AIN"#_chan2, \
} }
struct ads1015_channel_data {
bool enabled;
unsigned int pga;
unsigned int data_rate;
};
struct ads1015_thresh_data { struct ads1015_thresh_data {
unsigned int comp_queue; unsigned int comp_queue;
int high_thresh; int high_thresh;
...@@ -837,65 +844,58 @@ static const struct iio_info ads1115_info = { ...@@ -837,65 +844,58 @@ static const struct iio_info ads1115_info = {
.attrs = &ads1115_attribute_group, .attrs = &ads1115_attribute_group,
}; };
#ifdef CONFIG_OF static int ads1015_client_get_channels_config(struct i2c_client *client)
static int ads1015_get_channels_config_of(struct i2c_client *client)
{ {
struct iio_dev *indio_dev = i2c_get_clientdata(client); struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct ads1015_data *data = iio_priv(indio_dev); struct ads1015_data *data = iio_priv(indio_dev);
struct device_node *node; struct device *dev = &client->dev;
struct fwnode_handle *node;
int i = -1;
if (!client->dev.of_node || device_for_each_child_node(dev, node) {
!of_get_next_child(client->dev.of_node, NULL))
return -EINVAL;
for_each_child_of_node(client->dev.of_node, node) {
u32 pval; u32 pval;
unsigned int channel; unsigned int channel;
unsigned int pga = ADS1015_DEFAULT_PGA; unsigned int pga = ADS1015_DEFAULT_PGA;
unsigned int data_rate = ADS1015_DEFAULT_DATA_RATE; unsigned int data_rate = ADS1015_DEFAULT_DATA_RATE;
if (of_property_read_u32(node, "reg", &pval)) { if (fwnode_property_read_u32(node, "reg", &pval)) {
dev_err(&client->dev, "invalid reg on %pOF\n", dev_err(dev, "invalid reg on %pfw\n", node);
node);
continue; continue;
} }
channel = pval; channel = pval;
if (channel >= ADS1015_CHANNELS) { if (channel >= ADS1015_CHANNELS) {
dev_err(&client->dev, dev_err(dev, "invalid channel index %d on %pfw\n",
"invalid channel index %d on %pOF\n",
channel, node); channel, node);
continue; continue;
} }
if (!of_property_read_u32(node, "ti,gain", &pval)) { if (!fwnode_property_read_u32(node, "ti,gain", &pval)) {
pga = pval; pga = pval;
if (pga > 6) { if (pga > 6) {
dev_err(&client->dev, "invalid gain on %pOF\n", dev_err(dev, "invalid gain on %pfw\n", node);
node); fwnode_handle_put(node);
of_node_put(node);
return -EINVAL; return -EINVAL;
} }
} }
if (!of_property_read_u32(node, "ti,datarate", &pval)) { if (!fwnode_property_read_u32(node, "ti,datarate", &pval)) {
data_rate = pval; data_rate = pval;
if (data_rate > 7) { if (data_rate > 7) {
dev_err(&client->dev, dev_err(dev, "invalid data_rate on %pfw\n", node);
"invalid data_rate on %pOF\n", fwnode_handle_put(node);
node);
of_node_put(node);
return -EINVAL; return -EINVAL;
} }
} }
data->channel_data[channel].pga = pga; data->channel_data[channel].pga = pga;
data->channel_data[channel].data_rate = data_rate; data->channel_data[channel].data_rate = data_rate;
i++;
} }
return 0; return i < 0 ? -EINVAL : 0;
} }
#endif
static void ads1015_get_channels_config(struct i2c_client *client) static void ads1015_get_channels_config(struct i2c_client *client)
{ {
...@@ -903,19 +903,10 @@ static void ads1015_get_channels_config(struct i2c_client *client) ...@@ -903,19 +903,10 @@ static void ads1015_get_channels_config(struct i2c_client *client)
struct iio_dev *indio_dev = i2c_get_clientdata(client); struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct ads1015_data *data = iio_priv(indio_dev); struct ads1015_data *data = iio_priv(indio_dev);
struct ads1015_platform_data *pdata = dev_get_platdata(&client->dev);
/* prefer platform data */ if (!ads1015_client_get_channels_config(client))
if (pdata) {
memcpy(data->channel_data, pdata->channel_data,
sizeof(data->channel_data));
return; return;
}
#ifdef CONFIG_OF
if (!ads1015_get_channels_config_of(client))
return;
#endif
/* fallback on default configuration */ /* fallback on default configuration */
for (k = 0; k < ADS1015_CHANNELS; ++k) { for (k = 0; k < ADS1015_CHANNELS; ++k) {
data->channel_data[k].pga = ADS1015_DEFAULT_PGA; data->channel_data[k].pga = ADS1015_DEFAULT_PGA;
...@@ -953,9 +944,8 @@ static int ads1015_probe(struct i2c_client *client, ...@@ -953,9 +944,8 @@ static int ads1015_probe(struct i2c_client *client,
indio_dev->name = ADS1015_DRV_NAME; indio_dev->name = ADS1015_DRV_NAME;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
if (client->dev.of_node) chip = (enum chip_ids)device_get_match_data(&client->dev);
chip = (enum chip_ids)of_device_get_match_data(&client->dev); if (chip == ADSXXXX)
else
chip = id->driver_data; chip = id->driver_data;
switch (chip) { switch (chip) {
case ADS1015: case ADS1015:
...@@ -970,6 +960,9 @@ static int ads1015_probe(struct i2c_client *client, ...@@ -970,6 +960,9 @@ static int ads1015_probe(struct i2c_client *client,
indio_dev->info = &ads1115_info; indio_dev->info = &ads1115_info;
data->data_rate = (unsigned int *) &ads1115_data_rate; data->data_rate = (unsigned int *) &ads1115_data_rate;
break; break;
default:
dev_err(&client->dev, "Unknown chip %d\n", chip);
return -EINVAL;
} }
data->event_channel = ADS1015_CHANNELS; data->event_channel = ADS1015_CHANNELS;
......
...@@ -602,7 +602,7 @@ static int ti_ads7950_probe(struct spi_device *spi) ...@@ -602,7 +602,7 @@ static int ti_ads7950_probe(struct spi_device *spi)
st->reg = devm_regulator_get(&spi->dev, "vref"); st->reg = devm_regulator_get(&spi->dev, "vref");
if (IS_ERR(st->reg)) { if (IS_ERR(st->reg)) {
dev_err(&spi->dev, "Failed get get regulator \"vref\"\n"); dev_err(&spi->dev, "Failed to get regulator \"vref\"\n");
ret = PTR_ERR(st->reg); ret = PTR_ERR(st->reg);
goto error_destroy_mutex; goto error_destroy_mutex;
} }
......
...@@ -476,7 +476,7 @@ static struct iio_dma_buffer_block *iio_dma_buffer_dequeue( ...@@ -476,7 +476,7 @@ static struct iio_dma_buffer_block *iio_dma_buffer_dequeue(
* @n: Number of bytes to read * @n: Number of bytes to read
* @user_buffer: Userspace buffer to copy the data to * @user_buffer: Userspace buffer to copy the data to
* *
* Should be used as the read_first_n callback for iio_buffer_access_ops * Should be used as the read callback for iio_buffer_access_ops
* struct for DMA buffers. * struct for DMA buffers.
*/ */
int iio_dma_buffer_read(struct iio_buffer *buffer, size_t n, int iio_dma_buffer_read(struct iio_buffer *buffer, size_t n,
......
...@@ -10,8 +10,10 @@ ...@@ -10,8 +10,10 @@
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/module.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h> #include <linux/iio/buffer.h>
#include <linux/iio/buffer_impl.h> #include <linux/iio/buffer_impl.h>
#include <linux/iio/buffer-dma.h> #include <linux/iio/buffer-dma.h>
...@@ -107,7 +109,7 @@ static void iio_dmaengine_buffer_release(struct iio_buffer *buf) ...@@ -107,7 +109,7 @@ static void iio_dmaengine_buffer_release(struct iio_buffer *buf)
} }
static const struct iio_buffer_access_funcs iio_dmaengine_buffer_ops = { static const struct iio_buffer_access_funcs iio_dmaengine_buffer_ops = {
.read_first_n = iio_dma_buffer_read, .read = iio_dma_buffer_read,
.set_bytes_per_datum = iio_dma_buffer_set_bytes_per_datum, .set_bytes_per_datum = iio_dma_buffer_set_bytes_per_datum,
.set_length = iio_dma_buffer_set_length, .set_length = iio_dma_buffer_set_length,
.request_update = iio_dma_buffer_request_update, .request_update = iio_dma_buffer_request_update,
...@@ -125,6 +127,24 @@ static const struct iio_dma_buffer_ops iio_dmaengine_default_ops = { ...@@ -125,6 +127,24 @@ static const struct iio_dma_buffer_ops iio_dmaengine_default_ops = {
.abort = iio_dmaengine_buffer_abort, .abort = iio_dmaengine_buffer_abort,
}; };
static ssize_t iio_dmaengine_buffer_get_length_align(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct dmaengine_buffer *dmaengine_buffer =
iio_buffer_to_dmaengine_buffer(indio_dev->buffer);
return sprintf(buf, "%u\n", dmaengine_buffer->align);
}
static IIO_DEVICE_ATTR(length_align_bytes, 0444,
iio_dmaengine_buffer_get_length_align, NULL, 0);
static const struct attribute *iio_dmaengine_buffer_attrs[] = {
&iio_dev_attr_length_align_bytes.dev_attr.attr,
NULL,
};
/** /**
* iio_dmaengine_buffer_alloc() - Allocate new buffer which uses DMAengine * iio_dmaengine_buffer_alloc() - Allocate new buffer which uses DMAengine
* @dev: Parent device for the buffer * @dev: Parent device for the buffer
...@@ -150,7 +170,7 @@ struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev, ...@@ -150,7 +170,7 @@ struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev,
if (!dmaengine_buffer) if (!dmaengine_buffer)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
chan = dma_request_slave_channel_reason(dev, channel); chan = dma_request_chan(dev, channel);
if (IS_ERR(chan)) { if (IS_ERR(chan)) {
ret = PTR_ERR(chan); ret = PTR_ERR(chan);
goto err_free; goto err_free;
...@@ -178,6 +198,8 @@ struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev, ...@@ -178,6 +198,8 @@ struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev,
iio_dma_buffer_init(&dmaengine_buffer->queue, chan->device->dev, iio_dma_buffer_init(&dmaengine_buffer->queue, chan->device->dev,
&iio_dmaengine_default_ops); &iio_dmaengine_default_ops);
iio_buffer_set_attrs(&dmaengine_buffer->queue.buffer,
iio_dmaengine_buffer_attrs);
dmaengine_buffer->queue.buffer.access = &iio_dmaengine_buffer_ops; dmaengine_buffer->queue.buffer.access = &iio_dmaengine_buffer_ops;
...@@ -206,3 +228,7 @@ void iio_dmaengine_buffer_free(struct iio_buffer *buffer) ...@@ -206,3 +228,7 @@ void iio_dmaengine_buffer_free(struct iio_buffer *buffer)
iio_buffer_put(buffer); iio_buffer_put(buffer);
} }
EXPORT_SYMBOL_GPL(iio_dmaengine_buffer_free); EXPORT_SYMBOL_GPL(iio_dmaengine_buffer_free);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("DMA buffer for the IIO framework");
MODULE_LICENSE("GPL");
...@@ -98,8 +98,7 @@ static int iio_store_to_kfifo(struct iio_buffer *r, ...@@ -98,8 +98,7 @@ static int iio_store_to_kfifo(struct iio_buffer *r,
return 0; return 0;
} }
static int iio_read_first_n_kfifo(struct iio_buffer *r, static int iio_read_kfifo(struct iio_buffer *r, size_t n, char __user *buf)
size_t n, char __user *buf)
{ {
int ret, copied; int ret, copied;
struct iio_kfifo *kf = iio_to_kfifo(r); struct iio_kfifo *kf = iio_to_kfifo(r);
...@@ -141,7 +140,7 @@ static void iio_kfifo_buffer_release(struct iio_buffer *buffer) ...@@ -141,7 +140,7 @@ static void iio_kfifo_buffer_release(struct iio_buffer *buffer)
static const struct iio_buffer_access_funcs kfifo_access_funcs = { static const struct iio_buffer_access_funcs kfifo_access_funcs = {
.store_to = &iio_store_to_kfifo, .store_to = &iio_store_to_kfifo,
.read_first_n = &iio_read_first_n_kfifo, .read = &iio_read_kfifo,
.data_available = iio_kfifo_buf_data_available, .data_available = iio_kfifo_buf_data_available,
.request_update = &iio_request_update_kfifo, .request_update = &iio_request_update_kfifo,
.set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo, .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo,
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# #
# When adding new entries keep the list in alphabetical order # When adding new entries keep the list in alphabetical order
obj-$(CONFIG_ATLAS_PH_SENSOR) += atlas-ph-sensor.o obj-$(CONFIG_ATLAS_PH_SENSOR) += atlas-sensor.o
obj-$(CONFIG_BME680) += bme680_core.o obj-$(CONFIG_BME680) += bme680_core.o
obj-$(CONFIG_BME680_I2C) += bme680_i2c.o obj-$(CONFIG_BME680_I2C) += bme680_i2c.o
obj-$(CONFIG_BME680_SPI) += bme680_spi.o obj-$(CONFIG_BME680_SPI) += bme680_spi.o
......
// SPDX-License-Identifier: GPL-2.0+ // SPDX-License-Identifier: GPL-2.0+
/* /*
* atlas-ph-sensor.c - Support for Atlas Scientific OEM pH-SM sensor * atlas-sensor.c - Support for Atlas Scientific OEM SM sensors
* *
* Copyright (C) 2015-2018 Matt Ranostay * Copyright (C) 2015-2019 Konsulko Group
* Author: Matt Ranostay <matt.ranostay@konsulko.com> * Author: Matt Ranostay <matt.ranostay@konsulko.com>
*/ */
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/irq_work.h> #include <linux/irq_work.h>
#include <linux/gpio.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/regmap.h> #include <linux/regmap.h>
...@@ -25,8 +24,8 @@ ...@@ -25,8 +24,8 @@
#include <linux/iio/triggered_buffer.h> #include <linux/iio/triggered_buffer.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#define ATLAS_REGMAP_NAME "atlas_ph_regmap" #define ATLAS_REGMAP_NAME "atlas_regmap"
#define ATLAS_DRV_NAME "atlas_ph" #define ATLAS_DRV_NAME "atlas"
#define ATLAS_REG_DEV_TYPE 0x00 #define ATLAS_REG_DEV_TYPE 0x00
#define ATLAS_REG_DEV_VERSION 0x01 #define ATLAS_REG_DEV_VERSION 0x01
...@@ -681,5 +680,5 @@ static struct i2c_driver atlas_driver = { ...@@ -681,5 +680,5 @@ static struct i2c_driver atlas_driver = {
module_i2c_driver(atlas_driver); module_i2c_driver(atlas_driver);
MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>"); MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>");
MODULE_DESCRIPTION("Atlas Scientific pH-SM sensor"); MODULE_DESCRIPTION("Atlas Scientific SM sensors");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#define __SSP_SENSORHUB_H__ #define __SSP_SENSORHUB_H__
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio.h> #include <linux/gpio/consumer.h>
#include <linux/iio/common/ssp_sensors.h> #include <linux/iio/common/ssp_sensors.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
...@@ -168,9 +168,9 @@ struct ssp_sensorhub_info { ...@@ -168,9 +168,9 @@ struct ssp_sensorhub_info {
* @fw_dl_state: firmware download state * @fw_dl_state: firmware download state
* @comm_lock: lock protecting the handshake * @comm_lock: lock protecting the handshake
* @pending_lock: lock protecting pending list and completion * @pending_lock: lock protecting pending list and completion
* @mcu_reset_gpio: mcu reset line * @mcu_reset_gpiod: mcu reset line
* @ap_mcu_gpio: ap to mcu gpio line * @ap_mcu_gpiod: ap to mcu gpio line
* @mcu_ap_gpio: mcu to ap gpio line * @mcu_ap_gpiod: mcu to ap gpio line
* @pending_list: pending list for messages queued to be sent/read * @pending_list: pending list for messages queued to be sent/read
* @sensor_devs: registered IIO devices table * @sensor_devs: registered IIO devices table
* @enable_refcount: enable reference count for wdt (watchdog timer) * @enable_refcount: enable reference count for wdt (watchdog timer)
...@@ -212,9 +212,9 @@ struct ssp_data { ...@@ -212,9 +212,9 @@ struct ssp_data {
struct mutex comm_lock; struct mutex comm_lock;
struct mutex pending_lock; struct mutex pending_lock;
int mcu_reset_gpio; struct gpio_desc *mcu_reset_gpiod;
int ap_mcu_gpio; struct gpio_desc *ap_mcu_gpiod;
int mcu_ap_gpio; struct gpio_desc *mcu_ap_gpiod;
struct list_head pending_list; struct list_head pending_list;
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include "ssp.h" #include "ssp.h"
...@@ -61,9 +60,9 @@ static const struct mfd_cell sensorhub_sensor_devs[] = { ...@@ -61,9 +60,9 @@ static const struct mfd_cell sensorhub_sensor_devs[] = {
static void ssp_toggle_mcu_reset_gpio(struct ssp_data *data) static void ssp_toggle_mcu_reset_gpio(struct ssp_data *data)
{ {
gpio_set_value(data->mcu_reset_gpio, 0); gpiod_set_value(data->mcu_reset_gpiod, 0);
usleep_range(1000, 1200); usleep_range(1000, 1200);
gpio_set_value(data->mcu_reset_gpio, 1); gpiod_set_value(data->mcu_reset_gpiod, 1);
msleep(50); msleep(50);
} }
...@@ -441,7 +440,6 @@ MODULE_DEVICE_TABLE(of, ssp_of_match); ...@@ -441,7 +440,6 @@ MODULE_DEVICE_TABLE(of, ssp_of_match);
static struct ssp_data *ssp_parse_dt(struct device *dev) static struct ssp_data *ssp_parse_dt(struct device *dev)
{ {
int ret;
struct ssp_data *data; struct ssp_data *data;
struct device_node *node = dev->of_node; struct device_node *node = dev->of_node;
const struct of_device_id *match; const struct of_device_id *match;
...@@ -450,26 +448,17 @@ static struct ssp_data *ssp_parse_dt(struct device *dev) ...@@ -450,26 +448,17 @@ static struct ssp_data *ssp_parse_dt(struct device *dev)
if (!data) if (!data)
return NULL; return NULL;
data->mcu_ap_gpio = of_get_named_gpio(node, "mcu-ap-gpios", 0); data->mcu_ap_gpiod = devm_gpiod_get(dev, "mcu-ap", GPIOD_IN);
if (data->mcu_ap_gpio < 0) if (IS_ERR(data->mcu_ap_gpiod))
return NULL;
data->ap_mcu_gpio = of_get_named_gpio(node, "ap-mcu-gpios", 0);
if (data->ap_mcu_gpio < 0)
return NULL;
data->mcu_reset_gpio = of_get_named_gpio(node, "mcu-reset-gpios", 0);
if (data->mcu_reset_gpio < 0)
return NULL; return NULL;
ret = devm_gpio_request_one(dev, data->ap_mcu_gpio, GPIOF_OUT_INIT_HIGH, data->ap_mcu_gpiod = devm_gpiod_get(dev, "ap-mcu", GPIOD_OUT_HIGH);
"ap-mcu-gpios"); if (IS_ERR(data->ap_mcu_gpiod))
if (ret)
return NULL; return NULL;
ret = devm_gpio_request_one(dev, data->mcu_reset_gpio, data->mcu_reset_gpiod = devm_gpiod_get(dev, "mcu-reset",
GPIOF_OUT_INIT_HIGH, "mcu-reset-gpios"); GPIOD_OUT_HIGH);
if (ret) if (IS_ERR(data->mcu_reset_gpiod))
return NULL; return NULL;
match = of_match_node(ssp_of_match, node); match = of_match_node(ssp_of_match, node);
......
...@@ -155,9 +155,9 @@ static int ssp_check_lines(struct ssp_data *data, bool state) ...@@ -155,9 +155,9 @@ static int ssp_check_lines(struct ssp_data *data, bool state)
{ {
int delay_cnt = 0; int delay_cnt = 0;
gpio_set_value_cansleep(data->ap_mcu_gpio, state); gpiod_set_value_cansleep(data->ap_mcu_gpiod, state);
while (gpio_get_value_cansleep(data->mcu_ap_gpio) != state) { while (gpiod_get_value_cansleep(data->mcu_ap_gpiod) != state) {
usleep_range(3000, 3500); usleep_range(3000, 3500);
if (data->shut_down || delay_cnt++ > 500) { if (data->shut_down || delay_cnt++ > 500) {
...@@ -165,7 +165,7 @@ static int ssp_check_lines(struct ssp_data *data, bool state) ...@@ -165,7 +165,7 @@ static int ssp_check_lines(struct ssp_data *data, bool state)
__func__, state); __func__, state);
if (!state) if (!state)
gpio_set_value_cansleep(data->ap_mcu_gpio, 1); gpiod_set_value_cansleep(data->ap_mcu_gpiod, 1);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
...@@ -197,7 +197,7 @@ static int ssp_do_transfer(struct ssp_data *data, struct ssp_msg *msg, ...@@ -197,7 +197,7 @@ static int ssp_do_transfer(struct ssp_data *data, struct ssp_msg *msg,
status = spi_write(data->spi, msg->buffer, SSP_HEADER_SIZE); status = spi_write(data->spi, msg->buffer, SSP_HEADER_SIZE);
if (status < 0) { if (status < 0) {
gpio_set_value_cansleep(data->ap_mcu_gpio, 1); gpiod_set_value_cansleep(data->ap_mcu_gpiod, 1);
dev_err(SSP_DEV, "%s spi_write fail\n", __func__); dev_err(SSP_DEV, "%s spi_write fail\n", __func__);
goto _error_locked; goto _error_locked;
} }
......
...@@ -19,6 +19,9 @@ ...@@ -19,6 +19,9 @@
/** /**
* st_sensors_new_samples_available() - check if more samples came in * st_sensors_new_samples_available() - check if more samples came in
* @indio_dev: IIO device reference.
* @sdata: Sensor data.
*
* returns: * returns:
* 0 - no new samples available * 0 - no new samples available
* 1 - new samples available * 1 - new samples available
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h> #include <linux/gpio/driver.h>
#include <linux/gpio.h>
#include <linux/property.h> #include <linux/property.h>
#include <dt-bindings/iio/adi,ad5592r.h> #include <dt-bindings/iio/adi,ad5592r.h>
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/sysfs.h> #include <linux/sysfs.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/of.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
...@@ -202,7 +201,6 @@ static int ad7303_probe(struct spi_device *spi) ...@@ -202,7 +201,6 @@ static int ad7303_probe(struct spi_device *spi)
const struct spi_device_id *id = spi_get_device_id(spi); const struct spi_device_id *id = spi_get_device_id(spi);
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
struct ad7303_state *st; struct ad7303_state *st;
bool ext_ref;
int ret; int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
...@@ -224,24 +222,15 @@ static int ad7303_probe(struct spi_device *spi) ...@@ -224,24 +222,15 @@ static int ad7303_probe(struct spi_device *spi)
if (ret) if (ret)
return ret; return ret;
if (spi->dev.of_node) { st->vref_reg = devm_regulator_get_optional(&spi->dev, "REF");
ext_ref = of_property_read_bool(spi->dev.of_node, if (IS_ERR(st->vref_reg)) {
"REF-supply"); ret = PTR_ERR(st->vref_reg);
} else { if (ret != -ENODEV)
struct ad7303_platform_data *pdata = spi->dev.platform_data;
if (pdata && pdata->use_external_ref)
ext_ref = true;
else
ext_ref = false;
}
if (ext_ref) {
st->vref_reg = devm_regulator_get(&spi->dev, "REF");
if (IS_ERR(st->vref_reg)) {
ret = PTR_ERR(st->vref_reg);
goto err_disable_vdd_reg; goto err_disable_vdd_reg;
} st->vref_reg = NULL;
}
if (st->vref_reg) {
ret = regulator_enable(st->vref_reg); ret = regulator_enable(st->vref_reg);
if (ret) if (ret)
goto err_disable_vdd_reg; goto err_disable_vdd_reg;
......
...@@ -14,11 +14,10 @@ ...@@ -14,11 +14,10 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/gcd.h> #include <linux/gcd.h>
#include <linux/gpio.h> #include <linux/gpio/consumer.h>
#include <asm/div64.h> #include <asm/div64.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
...@@ -34,6 +33,7 @@ enum { ...@@ -34,6 +33,7 @@ enum {
struct adf4350_state { struct adf4350_state {
struct spi_device *spi; struct spi_device *spi;
struct regulator *reg; struct regulator *reg;
struct gpio_desc *lock_detect_gpiod;
struct adf4350_platform_data *pdata; struct adf4350_platform_data *pdata;
struct clk *clk; struct clk *clk;
unsigned long clkin; unsigned long clkin;
...@@ -61,7 +61,6 @@ static struct adf4350_platform_data default_pdata = { ...@@ -61,7 +61,6 @@ static struct adf4350_platform_data default_pdata = {
.r3_user_settings = ADF4350_REG3_12BIT_CLKDIV_MODE(0), .r3_user_settings = ADF4350_REG3_12BIT_CLKDIV_MODE(0),
.r4_user_settings = ADF4350_REG4_OUTPUT_PWR(3) | .r4_user_settings = ADF4350_REG4_OUTPUT_PWR(3) |
ADF4350_REG4_MUTE_TILL_LOCK_EN, ADF4350_REG4_MUTE_TILL_LOCK_EN,
.gpio_lock_detect = -1,
}; };
static int adf4350_sync_config(struct adf4350_state *st) static int adf4350_sync_config(struct adf4350_state *st)
...@@ -317,8 +316,8 @@ static ssize_t adf4350_read(struct iio_dev *indio_dev, ...@@ -317,8 +316,8 @@ static ssize_t adf4350_read(struct iio_dev *indio_dev,
(u64)st->fpfd; (u64)st->fpfd;
do_div(val, st->r1_mod * (1 << st->r4_rf_div_sel)); do_div(val, st->r1_mod * (1 << st->r4_rf_div_sel));
/* PLL unlocked? return error */ /* PLL unlocked? return error */
if (gpio_is_valid(st->pdata->gpio_lock_detect)) if (st->lock_detect_gpiod)
if (!gpio_get_value(st->pdata->gpio_lock_detect)) { if (!gpiod_get_value(st->lock_detect_gpiod)) {
dev_dbg(&st->spi->dev, "PLL un-locked\n"); dev_dbg(&st->spi->dev, "PLL un-locked\n");
ret = -EBUSY; ret = -EBUSY;
} }
...@@ -381,7 +380,6 @@ static struct adf4350_platform_data *adf4350_parse_dt(struct device *dev) ...@@ -381,7 +380,6 @@ static struct adf4350_platform_data *adf4350_parse_dt(struct device *dev)
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct adf4350_platform_data *pdata; struct adf4350_platform_data *pdata;
unsigned int tmp; unsigned int tmp;
int ret;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) if (!pdata)
...@@ -401,12 +399,6 @@ static struct adf4350_platform_data *adf4350_parse_dt(struct device *dev) ...@@ -401,12 +399,6 @@ static struct adf4350_platform_data *adf4350_parse_dt(struct device *dev)
of_property_read_u32(np, "adi,reference-div-factor", &tmp); of_property_read_u32(np, "adi,reference-div-factor", &tmp);
pdata->ref_div_factor = tmp; pdata->ref_div_factor = tmp;
ret = of_get_gpio(np, 0);
if (ret < 0)
pdata->gpio_lock_detect = -1;
else
pdata->gpio_lock_detect = ret;
pdata->ref_doubler_en = of_property_read_bool(np, pdata->ref_doubler_en = of_property_read_bool(np,
"adi,reference-doubler-enable"); "adi,reference-doubler-enable");
pdata->ref_div2_en = of_property_read_bool(np, pdata->ref_div2_en = of_property_read_bool(np,
...@@ -561,16 +553,10 @@ static int adf4350_probe(struct spi_device *spi) ...@@ -561,16 +553,10 @@ static int adf4350_probe(struct spi_device *spi)
memset(st->regs_hw, 0xFF, sizeof(st->regs_hw)); memset(st->regs_hw, 0xFF, sizeof(st->regs_hw));
if (gpio_is_valid(pdata->gpio_lock_detect)) { st->lock_detect_gpiod = devm_gpiod_get_optional(&spi->dev, NULL,
ret = devm_gpio_request(&spi->dev, pdata->gpio_lock_detect, GPIOD_IN);
indio_dev->name); if (IS_ERR(st->lock_detect_gpiod))
if (ret) { return PTR_ERR(st->lock_detect_gpiod);
dev_err(&spi->dev, "fail to request lock detect GPIO-%d",
pdata->gpio_lock_detect);
goto error_disable_reg;
}
gpio_direction_input(pdata->gpio_lock_detect);
}
if (pdata->power_up_frequency) { if (pdata->power_up_frequency) {
ret = adf4350_set_freq(st, pdata->power_up_frequency); ret = adf4350_set_freq(st, pdata->power_up_frequency);
......
...@@ -75,26 +75,26 @@ config BMG160_SPI ...@@ -75,26 +75,26 @@ config BMG160_SPI
select REGMAP_SPI select REGMAP_SPI
config FXAS21002C config FXAS21002C
tristate "NXP FXAS21002C Gyro Sensor" tristate "NXP FXAS21002C Gyro Sensor"
select IIO_BUFFER select IIO_BUFFER
select IIO_TRIGGERED_BUFFER select IIO_TRIGGERED_BUFFER
select FXAS21002C_I2C if (I2C) select FXAS21002C_I2C if (I2C)
select FXAS21002C_SPI if (SPI) select FXAS21002C_SPI if (SPI)
depends on (I2C || SPI_MASTER) depends on (I2C || SPI_MASTER)
help help
Say yes here to build support for NXP FXAS21002C Tri-axis Gyro Say yes here to build support for NXP FXAS21002C Tri-axis Gyro
Sensor driver connected via I2C or SPI. Sensor driver connected via I2C or SPI.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called fxas21002c_i2c or fxas21002c_spi. will be called fxas21002c_i2c or fxas21002c_spi.
config FXAS21002C_I2C config FXAS21002C_I2C
tristate tristate
select REGMAP_I2C select REGMAP_I2C
config FXAS21002C_SPI config FXAS21002C_SPI
tristate tristate
select REGMAP_SPI select REGMAP_SPI
config HID_SENSOR_GYRO_3D config HID_SENSOR_GYRO_3D
depends on HID_SENSOR_HUB depends on HID_SENSOR_HUB
......
...@@ -185,12 +185,12 @@ static int adis16136_set_freq(struct adis16136 *adis16136, unsigned int freq) ...@@ -185,12 +185,12 @@ static int adis16136_set_freq(struct adis16136 *adis16136, unsigned int freq)
return adis_write_reg_16(&adis16136->adis, ADIS16136_REG_SMPL_PRD, t); return adis_write_reg_16(&adis16136->adis, ADIS16136_REG_SMPL_PRD, t);
} }
static int adis16136_get_freq(struct adis16136 *adis16136, unsigned int *freq) static int __adis16136_get_freq(struct adis16136 *adis16136, unsigned int *freq)
{ {
uint16_t t; uint16_t t;
int ret; int ret;
ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_SMPL_PRD, &t); ret = __adis_read_reg_16(&adis16136->adis, ADIS16136_REG_SMPL_PRD, &t);
if (ret) if (ret)
return ret; return ret;
...@@ -224,10 +224,13 @@ static ssize_t adis16136_read_frequency(struct device *dev, ...@@ -224,10 +224,13 @@ static ssize_t adis16136_read_frequency(struct device *dev,
{ {
struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct adis16136 *adis16136 = iio_priv(indio_dev); struct adis16136 *adis16136 = iio_priv(indio_dev);
struct mutex *slock = &adis16136->adis.state_lock;
unsigned int freq; unsigned int freq;
int ret; int ret;
ret = adis16136_get_freq(adis16136, &freq); mutex_lock(slock);
ret = __adis16136_get_freq(adis16136, &freq);
mutex_unlock(slock);
if (ret) if (ret)
return ret; return ret;
...@@ -252,42 +255,50 @@ static const unsigned adis16136_3db_divisors[] = { ...@@ -252,42 +255,50 @@ static const unsigned adis16136_3db_divisors[] = {
static int adis16136_set_filter(struct iio_dev *indio_dev, int val) static int adis16136_set_filter(struct iio_dev *indio_dev, int val)
{ {
struct adis16136 *adis16136 = iio_priv(indio_dev); struct adis16136 *adis16136 = iio_priv(indio_dev);
struct mutex *slock = &adis16136->adis.state_lock;
unsigned int freq; unsigned int freq;
int i, ret; int i, ret;
ret = adis16136_get_freq(adis16136, &freq); mutex_lock(slock);
ret = __adis16136_get_freq(adis16136, &freq);
if (ret) if (ret)
return ret; goto out_unlock;
for (i = ARRAY_SIZE(adis16136_3db_divisors) - 1; i >= 1; i--) { for (i = ARRAY_SIZE(adis16136_3db_divisors) - 1; i >= 1; i--) {
if (freq / adis16136_3db_divisors[i] >= val) if (freq / adis16136_3db_divisors[i] >= val)
break; break;
} }
return adis_write_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, i); ret = __adis_write_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, i);
out_unlock:
mutex_unlock(slock);
return ret;
} }
static int adis16136_get_filter(struct iio_dev *indio_dev, int *val) static int adis16136_get_filter(struct iio_dev *indio_dev, int *val)
{ {
struct adis16136 *adis16136 = iio_priv(indio_dev); struct adis16136 *adis16136 = iio_priv(indio_dev);
struct mutex *slock = &adis16136->adis.state_lock;
unsigned int freq; unsigned int freq;
uint16_t val16; uint16_t val16;
int ret; int ret;
mutex_lock(&indio_dev->mlock); mutex_lock(slock);
ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, &val16); ret = __adis_read_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT,
&val16);
if (ret) if (ret)
goto err_unlock; goto err_unlock;
ret = adis16136_get_freq(adis16136, &freq); ret = __adis16136_get_freq(adis16136, &freq);
if (ret) if (ret)
goto err_unlock; goto err_unlock;
*val = freq / adis16136_3db_divisors[val16 & 0x07]; *val = freq / adis16136_3db_divisors[val16 & 0x07];
err_unlock: err_unlock:
mutex_unlock(&indio_dev->mlock); mutex_unlock(slock);
return ret ? ret : IIO_VAL_INT; return ret ? ret : IIO_VAL_INT;
} }
......
...@@ -293,7 +293,7 @@ static int adis16260_write_raw(struct iio_dev *indio_dev, ...@@ -293,7 +293,7 @@ static int adis16260_write_raw(struct iio_dev *indio_dev,
addr = adis16260_addresses[chan->scan_index][1]; addr = adis16260_addresses[chan->scan_index][1];
return adis_write_reg_16(adis, addr, val); return adis_write_reg_16(adis, addr, val);
case IIO_CHAN_INFO_SAMP_FREQ: case IIO_CHAN_INFO_SAMP_FREQ:
mutex_lock(&indio_dev->mlock); mutex_lock(&adis->state_lock);
if (spi_get_device_id(adis->spi)->driver_data) if (spi_get_device_id(adis->spi)->driver_data)
t = 256 / val; t = 256 / val;
else else
...@@ -308,9 +308,9 @@ static int adis16260_write_raw(struct iio_dev *indio_dev, ...@@ -308,9 +308,9 @@ static int adis16260_write_raw(struct iio_dev *indio_dev,
adis->spi->max_speed_hz = ADIS16260_SPI_SLOW; adis->spi->max_speed_hz = ADIS16260_SPI_SLOW;
else else
adis->spi->max_speed_hz = ADIS16260_SPI_FAST; adis->spi->max_speed_hz = ADIS16260_SPI_FAST;
ret = adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t); ret = __adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t);
mutex_unlock(&indio_dev->mlock); mutex_unlock(&adis->state_lock);
return ret; return ret;
} }
return -EINVAL; return -EINVAL;
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/module.h> #include <linux/module.h>
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
* struct st_sensors_platform_data - gyro platform data * struct st_sensors_platform_data - gyro platform data
* @drdy_int_pin: DRDY on gyros is available only on INT2 pin. * @drdy_int_pin: DRDY on gyros is available only on INT2 pin.
*/ */
static const struct st_sensors_platform_data gyro_pdata = { static __maybe_unused const struct st_sensors_platform_data gyro_pdata = {
.drdy_int_pin = 2, .drdy_int_pin = 2,
}; };
......
...@@ -24,13 +24,6 @@ ...@@ -24,13 +24,6 @@
#define HTS221_REG_CNTRL1_ADDR 0x20 #define HTS221_REG_CNTRL1_ADDR 0x20
#define HTS221_REG_CNTRL2_ADDR 0x21 #define HTS221_REG_CNTRL2_ADDR 0x21
#define HTS221_REG_AVG_ADDR 0x10
#define HTS221_REG_H_OUT_L 0x28
#define HTS221_REG_T_OUT_L 0x2a
#define HTS221_HUMIDITY_AVG_MASK 0x07
#define HTS221_TEMP_AVG_MASK 0x38
#define HTS221_ODR_MASK 0x03 #define HTS221_ODR_MASK 0x03
#define HTS221_BDU_MASK BIT(2) #define HTS221_BDU_MASK BIT(2)
#define HTS221_ENABLE_MASK BIT(7) #define HTS221_ENABLE_MASK BIT(7)
...@@ -66,8 +59,8 @@ static const struct hts221_odr hts221_odr_table[] = { ...@@ -66,8 +59,8 @@ static const struct hts221_odr hts221_odr_table[] = {
static const struct hts221_avg hts221_avg_list[] = { static const struct hts221_avg hts221_avg_list[] = {
{ {
.addr = HTS221_REG_AVG_ADDR, .addr = 0x10,
.mask = HTS221_HUMIDITY_AVG_MASK, .mask = 0x07,
.avg_avl = { .avg_avl = {
4, /* 0.4 %RH */ 4, /* 0.4 %RH */
8, /* 0.3 %RH */ 8, /* 0.3 %RH */
...@@ -80,8 +73,8 @@ static const struct hts221_avg hts221_avg_list[] = { ...@@ -80,8 +73,8 @@ static const struct hts221_avg hts221_avg_list[] = {
}, },
}, },
{ {
.addr = HTS221_REG_AVG_ADDR, .addr = 0x10,
.mask = HTS221_TEMP_AVG_MASK, .mask = 0x38,
.avg_avl = { .avg_avl = {
2, /* 0.08 degC */ 2, /* 0.08 degC */
4, /* 0.05 degC */ 4, /* 0.05 degC */
...@@ -98,7 +91,7 @@ static const struct hts221_avg hts221_avg_list[] = { ...@@ -98,7 +91,7 @@ static const struct hts221_avg hts221_avg_list[] = {
static const struct iio_chan_spec hts221_channels[] = { static const struct iio_chan_spec hts221_channels[] = {
{ {
.type = IIO_HUMIDITYRELATIVE, .type = IIO_HUMIDITYRELATIVE,
.address = HTS221_REG_H_OUT_L, .address = 0x28,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_OFFSET) |
BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SCALE) |
...@@ -114,7 +107,7 @@ static const struct iio_chan_spec hts221_channels[] = { ...@@ -114,7 +107,7 @@ static const struct iio_chan_spec hts221_channels[] = {
}, },
{ {
.type = IIO_TEMP, .type = IIO_TEMP,
.address = HTS221_REG_T_OUT_L, .address = 0x2a,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_OFFSET) |
BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SCALE) |
......
...@@ -42,14 +42,14 @@ struct poll_table_struct; ...@@ -42,14 +42,14 @@ struct poll_table_struct;
__poll_t iio_buffer_poll(struct file *filp, __poll_t iio_buffer_poll(struct file *filp,
struct poll_table_struct *wait); struct poll_table_struct *wait);
ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, ssize_t iio_buffer_read_outer(struct file *filp, char __user *buf,
size_t n, loff_t *f_ps); size_t n, loff_t *f_ps);
int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev); int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev);
void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev); void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev);
#define iio_buffer_poll_addr (&iio_buffer_poll) #define iio_buffer_poll_addr (&iio_buffer_poll)
#define iio_buffer_read_first_n_outer_addr (&iio_buffer_read_first_n_outer) #define iio_buffer_read_outer_addr (&iio_buffer_read_outer)
void iio_disable_all_buffers(struct iio_dev *indio_dev); void iio_disable_all_buffers(struct iio_dev *indio_dev);
void iio_buffer_wakeup_poll(struct iio_dev *indio_dev); void iio_buffer_wakeup_poll(struct iio_dev *indio_dev);
...@@ -57,7 +57,7 @@ void iio_buffer_wakeup_poll(struct iio_dev *indio_dev); ...@@ -57,7 +57,7 @@ void iio_buffer_wakeup_poll(struct iio_dev *indio_dev);
#else #else
#define iio_buffer_poll_addr NULL #define iio_buffer_poll_addr NULL
#define iio_buffer_read_first_n_outer_addr NULL #define iio_buffer_read_outer_addr NULL
static inline int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) static inline int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
{ {
......
...@@ -26,7 +26,14 @@ ...@@ -26,7 +26,14 @@
#define ADIS_MSC_CTRL_DATA_RDY_DIO2 BIT(0) #define ADIS_MSC_CTRL_DATA_RDY_DIO2 BIT(0)
#define ADIS_GLOB_CMD_SW_RESET BIT(7) #define ADIS_GLOB_CMD_SW_RESET BIT(7)
int adis_write_reg(struct adis *adis, unsigned int reg, /**
* __adis_write_reg() - write N bytes to register (unlocked version)
* @adis: The adis device
* @reg: The address of the lower of the two registers
* @value: The value to write to device (up to 4 bytes)
* @size: The size of the @value (in bytes)
*/
int __adis_write_reg(struct adis *adis, unsigned int reg,
unsigned int value, unsigned int size) unsigned int value, unsigned int size)
{ {
unsigned int page = reg / ADIS_PAGE_SIZE; unsigned int page = reg / ADIS_PAGE_SIZE;
...@@ -70,8 +77,6 @@ int adis_write_reg(struct adis *adis, unsigned int reg, ...@@ -70,8 +77,6 @@ int adis_write_reg(struct adis *adis, unsigned int reg,
}, },
}; };
mutex_lock(&adis->txrx_lock);
spi_message_init(&msg); spi_message_init(&msg);
if (adis->current_page != page) { if (adis->current_page != page) {
...@@ -96,8 +101,7 @@ int adis_write_reg(struct adis *adis, unsigned int reg, ...@@ -96,8 +101,7 @@ int adis_write_reg(struct adis *adis, unsigned int reg,
adis->tx[3] = value & 0xff; adis->tx[3] = value & 0xff;
break; break;
default: default:
ret = -EINVAL; return -EINVAL;
goto out_unlock;
} }
xfers[size].cs_change = 0; xfers[size].cs_change = 0;
...@@ -113,20 +117,18 @@ int adis_write_reg(struct adis *adis, unsigned int reg, ...@@ -113,20 +117,18 @@ int adis_write_reg(struct adis *adis, unsigned int reg,
adis->current_page = page; adis->current_page = page;
} }
out_unlock:
mutex_unlock(&adis->txrx_lock);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(adis_write_reg); EXPORT_SYMBOL_GPL(__adis_write_reg);
/** /**
* adis_read_reg() - read 2 bytes from a 16-bit register * __adis_read_reg() - read N bytes from register (unlocked version)
* @adis: The adis device * @adis: The adis device
* @reg: The address of the lower of the two registers * @reg: The address of the lower of the two registers
* @val: The value read back from the device * @val: The value read back from the device
* @size: The size of the @val buffer
*/ */
int adis_read_reg(struct adis *adis, unsigned int reg, int __adis_read_reg(struct adis *adis, unsigned int reg,
unsigned int *val, unsigned int size) unsigned int *val, unsigned int size)
{ {
unsigned int page = reg / ADIS_PAGE_SIZE; unsigned int page = reg / ADIS_PAGE_SIZE;
...@@ -166,7 +168,6 @@ int adis_read_reg(struct adis *adis, unsigned int reg, ...@@ -166,7 +168,6 @@ int adis_read_reg(struct adis *adis, unsigned int reg,
}, },
}; };
mutex_lock(&adis->txrx_lock);
spi_message_init(&msg); spi_message_init(&msg);
if (adis->current_page != page) { if (adis->current_page != page) {
...@@ -188,15 +189,14 @@ int adis_read_reg(struct adis *adis, unsigned int reg, ...@@ -188,15 +189,14 @@ int adis_read_reg(struct adis *adis, unsigned int reg,
spi_message_add_tail(&xfers[3], &msg); spi_message_add_tail(&xfers[3], &msg);
break; break;
default: default:
ret = -EINVAL; return -EINVAL;
goto out_unlock;
} }
ret = spi_sync(adis->spi, &msg); ret = spi_sync(adis->spi, &msg);
if (ret) { if (ret) {
dev_err(&adis->spi->dev, "Failed to read register 0x%02X: %d\n", dev_err(&adis->spi->dev, "Failed to read register 0x%02X: %d\n",
reg, ret); reg, ret);
goto out_unlock; return ret;
} else { } else {
adis->current_page = page; adis->current_page = page;
} }
...@@ -210,12 +210,9 @@ int adis_read_reg(struct adis *adis, unsigned int reg, ...@@ -210,12 +210,9 @@ int adis_read_reg(struct adis *adis, unsigned int reg,
break; break;
} }
out_unlock:
mutex_unlock(&adis->txrx_lock);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(adis_read_reg); EXPORT_SYMBOL_GPL(__adis_read_reg);
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
...@@ -253,12 +250,16 @@ int adis_enable_irq(struct adis *adis, bool enable) ...@@ -253,12 +250,16 @@ int adis_enable_irq(struct adis *adis, bool enable)
int ret = 0; int ret = 0;
uint16_t msc; uint16_t msc;
if (adis->data->enable_irq) mutex_lock(&adis->state_lock);
return adis->data->enable_irq(adis, enable);
if (adis->data->enable_irq) {
ret = adis->data->enable_irq(adis, enable);
goto out_unlock;
}
ret = adis_read_reg_16(adis, adis->data->msc_ctrl_reg, &msc); ret = __adis_read_reg_16(adis, adis->data->msc_ctrl_reg, &msc);
if (ret) if (ret)
goto error_ret; goto out_unlock;
msc |= ADIS_MSC_CTRL_DATA_RDY_POL_HIGH; msc |= ADIS_MSC_CTRL_DATA_RDY_POL_HIGH;
msc &= ~ADIS_MSC_CTRL_DATA_RDY_DIO2; msc &= ~ADIS_MSC_CTRL_DATA_RDY_DIO2;
...@@ -267,26 +268,27 @@ int adis_enable_irq(struct adis *adis, bool enable) ...@@ -267,26 +268,27 @@ int adis_enable_irq(struct adis *adis, bool enable)
else else
msc &= ~ADIS_MSC_CTRL_DATA_RDY_EN; msc &= ~ADIS_MSC_CTRL_DATA_RDY_EN;
ret = adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc); ret = __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc);
error_ret: out_unlock:
mutex_unlock(&adis->state_lock);
return ret; return ret;
} }
EXPORT_SYMBOL(adis_enable_irq); EXPORT_SYMBOL(adis_enable_irq);
/** /**
* adis_check_status() - Check the device for error conditions * __adis_check_status() - Check the device for error conditions (unlocked)
* @adis: The adis device * @adis: The adis device
* *
* Returns 0 on success, a negative error code otherwise * Returns 0 on success, a negative error code otherwise
*/ */
int adis_check_status(struct adis *adis) int __adis_check_status(struct adis *adis)
{ {
uint16_t status; uint16_t status;
int ret; int ret;
int i; int i;
ret = adis_read_reg_16(adis, adis->data->diag_stat_reg, &status); ret = __adis_read_reg_16(adis, adis->data->diag_stat_reg, &status);
if (ret) if (ret)
return ret; return ret;
...@@ -304,32 +306,32 @@ int adis_check_status(struct adis *adis) ...@@ -304,32 +306,32 @@ int adis_check_status(struct adis *adis)
return -EIO; return -EIO;
} }
EXPORT_SYMBOL_GPL(adis_check_status); EXPORT_SYMBOL_GPL(__adis_check_status);
/** /**
* adis_reset() - Reset the device * __adis_reset() - Reset the device (unlocked version)
* @adis: The adis device * @adis: The adis device
* *
* Returns 0 on success, a negative error code otherwise * Returns 0 on success, a negative error code otherwise
*/ */
int adis_reset(struct adis *adis) int __adis_reset(struct adis *adis)
{ {
int ret; int ret;
ret = adis_write_reg_8(adis, adis->data->glob_cmd_reg, ret = __adis_write_reg_8(adis, adis->data->glob_cmd_reg,
ADIS_GLOB_CMD_SW_RESET); ADIS_GLOB_CMD_SW_RESET);
if (ret) if (ret)
dev_err(&adis->spi->dev, "Failed to reset device: %d\n", ret); dev_err(&adis->spi->dev, "Failed to reset device: %d\n", ret);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(adis_reset); EXPORT_SYMBOL_GPL(__adis_reset);
static int adis_self_test(struct adis *adis) static int adis_self_test(struct adis *adis)
{ {
int ret; int ret;
ret = adis_write_reg_16(adis, adis->data->msc_ctrl_reg, ret = __adis_write_reg_16(adis, adis->data->msc_ctrl_reg,
adis->data->self_test_mask); adis->data->self_test_mask);
if (ret) { if (ret) {
dev_err(&adis->spi->dev, "Failed to initiate self test: %d\n", dev_err(&adis->spi->dev, "Failed to initiate self test: %d\n",
...@@ -339,10 +341,10 @@ static int adis_self_test(struct adis *adis) ...@@ -339,10 +341,10 @@ static int adis_self_test(struct adis *adis)
msleep(adis->data->startup_delay); msleep(adis->data->startup_delay);
ret = adis_check_status(adis); ret = __adis_check_status(adis);
if (adis->data->self_test_no_autoclear) if (adis->data->self_test_no_autoclear)
adis_write_reg_16(adis, adis->data->msc_ctrl_reg, 0x00); __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, 0x00);
return ret; return ret;
} }
...@@ -360,19 +362,23 @@ int adis_initial_startup(struct adis *adis) ...@@ -360,19 +362,23 @@ int adis_initial_startup(struct adis *adis)
{ {
int ret; int ret;
mutex_lock(&adis->state_lock);
ret = adis_self_test(adis); ret = adis_self_test(adis);
if (ret) { if (ret) {
dev_err(&adis->spi->dev, "Self-test failed, trying reset.\n"); dev_err(&adis->spi->dev, "Self-test failed, trying reset.\n");
adis_reset(adis); __adis_reset(adis);
msleep(adis->data->startup_delay); msleep(adis->data->startup_delay);
ret = adis_self_test(adis); ret = adis_self_test(adis);
if (ret) { if (ret) {
dev_err(&adis->spi->dev, "Second self-test failed, giving up.\n"); dev_err(&adis->spi->dev, "Second self-test failed, giving up.\n");
return ret; goto out_unlock;
} }
} }
return 0; out_unlock:
mutex_unlock(&adis->state_lock);
return ret;
} }
EXPORT_SYMBOL_GPL(adis_initial_startup); EXPORT_SYMBOL_GPL(adis_initial_startup);
...@@ -398,15 +404,15 @@ int adis_single_conversion(struct iio_dev *indio_dev, ...@@ -398,15 +404,15 @@ int adis_single_conversion(struct iio_dev *indio_dev,
unsigned int uval; unsigned int uval;
int ret; int ret;
mutex_lock(&indio_dev->mlock); mutex_lock(&adis->state_lock);
ret = adis_read_reg(adis, chan->address, &uval, ret = __adis_read_reg(adis, chan->address, &uval,
chan->scan_type.storagebits / 8); chan->scan_type.storagebits / 8);
if (ret) if (ret)
goto err_unlock; goto err_unlock;
if (uval & error_mask) { if (uval & error_mask) {
ret = adis_check_status(adis); ret = __adis_check_status(adis);
if (ret) if (ret)
goto err_unlock; goto err_unlock;
} }
...@@ -418,7 +424,7 @@ int adis_single_conversion(struct iio_dev *indio_dev, ...@@ -418,7 +424,7 @@ int adis_single_conversion(struct iio_dev *indio_dev,
ret = IIO_VAL_INT; ret = IIO_VAL_INT;
err_unlock: err_unlock:
mutex_unlock(&indio_dev->mlock); mutex_unlock(&adis->state_lock);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(adis_single_conversion); EXPORT_SYMBOL_GPL(adis_single_conversion);
...@@ -438,7 +444,7 @@ EXPORT_SYMBOL_GPL(adis_single_conversion); ...@@ -438,7 +444,7 @@ EXPORT_SYMBOL_GPL(adis_single_conversion);
int adis_init(struct adis *adis, struct iio_dev *indio_dev, int adis_init(struct adis *adis, struct iio_dev *indio_dev,
struct spi_device *spi, const struct adis_data *data) struct spi_device *spi, const struct adis_data *data)
{ {
mutex_init(&adis->txrx_lock); mutex_init(&adis->state_lock);
adis->spi = spi; adis->spi = spi;
adis->data = data; adis->data = data;
iio_device_set_drvdata(indio_dev, adis); iio_device_set_drvdata(indio_dev, adis);
......
...@@ -162,6 +162,7 @@ struct adis16400_chip_info { ...@@ -162,6 +162,7 @@ struct adis16400_chip_info {
unsigned int accel_scale_micro; unsigned int accel_scale_micro;
int temp_scale_nano; int temp_scale_nano;
int temp_offset; int temp_offset;
/* set_freq() & get_freq() need to avoid using ADIS lib's state lock */
int (*set_freq)(struct adis16400_state *st, unsigned int freq); int (*set_freq)(struct adis16400_state *st, unsigned int freq);
int (*get_freq)(struct adis16400_state *st); int (*get_freq)(struct adis16400_state *st);
}; };
...@@ -326,7 +327,7 @@ static int adis16334_get_freq(struct adis16400_state *st) ...@@ -326,7 +327,7 @@ static int adis16334_get_freq(struct adis16400_state *st)
int ret; int ret;
uint16_t t; uint16_t t;
ret = adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t); ret = __adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t);
if (ret) if (ret)
return ret; return ret;
...@@ -350,7 +351,7 @@ static int adis16334_set_freq(struct adis16400_state *st, unsigned int freq) ...@@ -350,7 +351,7 @@ static int adis16334_set_freq(struct adis16400_state *st, unsigned int freq)
t <<= ADIS16334_RATE_DIV_SHIFT; t <<= ADIS16334_RATE_DIV_SHIFT;
t |= ADIS16334_RATE_INT_CLK; t |= ADIS16334_RATE_INT_CLK;
return adis_write_reg_16(&st->adis, ADIS16400_SMPL_PRD, t); return __adis_write_reg_16(&st->adis, ADIS16400_SMPL_PRD, t);
} }
static int adis16400_get_freq(struct adis16400_state *st) static int adis16400_get_freq(struct adis16400_state *st)
...@@ -358,7 +359,7 @@ static int adis16400_get_freq(struct adis16400_state *st) ...@@ -358,7 +359,7 @@ static int adis16400_get_freq(struct adis16400_state *st)
int sps, ret; int sps, ret;
uint16_t t; uint16_t t;
ret = adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t); ret = __adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t);
if (ret) if (ret)
return ret; return ret;
...@@ -390,7 +391,7 @@ static int adis16400_set_freq(struct adis16400_state *st, unsigned int freq) ...@@ -390,7 +391,7 @@ static int adis16400_set_freq(struct adis16400_state *st, unsigned int freq)
else else
st->adis.spi->max_speed_hz = ADIS16400_SPI_FAST; st->adis.spi->max_speed_hz = ADIS16400_SPI_FAST;
return adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, val); return __adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, val);
} }
static const unsigned int adis16400_3db_divisors[] = { static const unsigned int adis16400_3db_divisors[] = {
...@@ -404,7 +405,7 @@ static const unsigned int adis16400_3db_divisors[] = { ...@@ -404,7 +405,7 @@ static const unsigned int adis16400_3db_divisors[] = {
[7] = 200, /* Not a valid setting */ [7] = 200, /* Not a valid setting */
}; };
static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val) static int __adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val)
{ {
struct adis16400_state *st = iio_priv(indio_dev); struct adis16400_state *st = iio_priv(indio_dev);
uint16_t val16; uint16_t val16;
...@@ -415,11 +416,11 @@ static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val) ...@@ -415,11 +416,11 @@ static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val)
break; break;
} }
ret = adis_read_reg_16(&st->adis, ADIS16400_SENS_AVG, &val16); ret = __adis_read_reg_16(&st->adis, ADIS16400_SENS_AVG, &val16);
if (ret) if (ret)
return ret; return ret;
ret = adis_write_reg_16(&st->adis, ADIS16400_SENS_AVG, ret = __adis_write_reg_16(&st->adis, ADIS16400_SENS_AVG,
(val16 & ~0x07) | i); (val16 & ~0x07) | i);
return ret; return ret;
} }
...@@ -507,32 +508,31 @@ static int adis16400_write_raw(struct iio_dev *indio_dev, ...@@ -507,32 +508,31 @@ static int adis16400_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int val, int val2, long info) struct iio_chan_spec const *chan, int val, int val2, long info)
{ {
struct adis16400_state *st = iio_priv(indio_dev); struct adis16400_state *st = iio_priv(indio_dev);
struct mutex *slock = &st->adis.state_lock;
int ret, sps; int ret, sps;
switch (info) { switch (info) {
case IIO_CHAN_INFO_CALIBBIAS: case IIO_CHAN_INFO_CALIBBIAS:
mutex_lock(&indio_dev->mlock);
ret = adis_write_reg_16(&st->adis, ret = adis_write_reg_16(&st->adis,
adis16400_addresses[chan->scan_index], val); adis16400_addresses[chan->scan_index], val);
mutex_unlock(&indio_dev->mlock);
return ret; return ret;
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
/* /*
* Need to cache values so we can update if the frequency * Need to cache values so we can update if the frequency
* changes. * changes.
*/ */
mutex_lock(&indio_dev->mlock); mutex_lock(slock);
st->filt_int = val; st->filt_int = val;
/* Work out update to current value */ /* Work out update to current value */
sps = st->variant->get_freq(st); sps = st->variant->get_freq(st);
if (sps < 0) { if (sps < 0) {
mutex_unlock(&indio_dev->mlock); mutex_unlock(slock);
return sps; return sps;
} }
ret = adis16400_set_filter(indio_dev, sps, ret = __adis16400_set_filter(indio_dev, sps,
val * 1000 + val2 / 1000); val * 1000 + val2 / 1000);
mutex_unlock(&indio_dev->mlock); mutex_unlock(slock);
return ret; return ret;
case IIO_CHAN_INFO_SAMP_FREQ: case IIO_CHAN_INFO_SAMP_FREQ:
sps = val * 1000 + val2 / 1000; sps = val * 1000 + val2 / 1000;
...@@ -540,9 +540,9 @@ static int adis16400_write_raw(struct iio_dev *indio_dev, ...@@ -540,9 +540,9 @@ static int adis16400_write_raw(struct iio_dev *indio_dev,
if (sps <= 0) if (sps <= 0)
return -EINVAL; return -EINVAL;
mutex_lock(&indio_dev->mlock); mutex_lock(slock);
ret = st->variant->set_freq(st, sps); ret = st->variant->set_freq(st, sps);
mutex_unlock(&indio_dev->mlock); mutex_unlock(slock);
return ret; return ret;
default: default:
return -EINVAL; return -EINVAL;
...@@ -553,6 +553,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, ...@@ -553,6 +553,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val, int *val2, long info) struct iio_chan_spec const *chan, int *val, int *val2, long info)
{ {
struct adis16400_state *st = iio_priv(indio_dev); struct adis16400_state *st = iio_priv(indio_dev);
struct mutex *slock = &st->adis.state_lock;
int16_t val16; int16_t val16;
int ret; int ret;
...@@ -596,10 +597,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, ...@@ -596,10 +597,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
return -EINVAL; return -EINVAL;
} }
case IIO_CHAN_INFO_CALIBBIAS: case IIO_CHAN_INFO_CALIBBIAS:
mutex_lock(&indio_dev->mlock);
ret = adis_read_reg_16(&st->adis, ret = adis_read_reg_16(&st->adis,
adis16400_addresses[chan->scan_index], &val16); adis16400_addresses[chan->scan_index], &val16);
mutex_unlock(&indio_dev->mlock);
if (ret) if (ret)
return ret; return ret;
val16 = sign_extend32(val16, 11); val16 = sign_extend32(val16, 11);
...@@ -610,27 +609,27 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, ...@@ -610,27 +609,27 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
*val = st->variant->temp_offset; *val = st->variant->temp_offset;
return IIO_VAL_INT; return IIO_VAL_INT;
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
mutex_lock(&indio_dev->mlock); mutex_lock(slock);
/* Need both the number of taps and the sampling frequency */ /* Need both the number of taps and the sampling frequency */
ret = adis_read_reg_16(&st->adis, ret = __adis_read_reg_16(&st->adis,
ADIS16400_SENS_AVG, ADIS16400_SENS_AVG,
&val16); &val16);
if (ret) { if (ret) {
mutex_unlock(&indio_dev->mlock); mutex_unlock(slock);
return ret; return ret;
} }
ret = st->variant->get_freq(st); ret = st->variant->get_freq(st);
if (ret >= 0) { mutex_unlock(slock);
ret /= adis16400_3db_divisors[val16 & 0x07];
*val = ret / 1000;
*val2 = (ret % 1000) * 1000;
}
mutex_unlock(&indio_dev->mlock);
if (ret) if (ret)
return ret; return ret;
ret /= adis16400_3db_divisors[val16 & 0x07];
*val = ret / 1000;
*val2 = (ret % 1000) * 1000;
return IIO_VAL_INT_PLUS_MICRO; return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SAMP_FREQ: case IIO_CHAN_INFO_SAMP_FREQ:
mutex_lock(slock);
ret = st->variant->get_freq(st); ret = st->variant->get_freq(st);
mutex_unlock(slock);
if (ret) if (ret)
return ret; return ret;
*val = ret / 1000; *val = ret / 1000;
......
This diff is collapsed.
...@@ -129,7 +129,7 @@ static irqreturn_t adis_trigger_handler(int irq, void *p) ...@@ -129,7 +129,7 @@ static irqreturn_t adis_trigger_handler(int irq, void *p)
return -ENOMEM; return -ENOMEM;
if (adis->data->has_paging) { if (adis->data->has_paging) {
mutex_lock(&adis->txrx_lock); mutex_lock(&adis->state_lock);
if (adis->current_page != 0) { if (adis->current_page != 0) {
adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID);
adis->tx[1] = 0; adis->tx[1] = 0;
...@@ -144,7 +144,7 @@ static irqreturn_t adis_trigger_handler(int irq, void *p) ...@@ -144,7 +144,7 @@ static irqreturn_t adis_trigger_handler(int irq, void *p)
if (adis->data->has_paging) { if (adis->data->has_paging) {
adis->current_page = 0; adis->current_page = 0;
mutex_unlock(&adis->txrx_lock); mutex_unlock(&adis->state_lock);
} }
iio_push_to_buffers_with_timestamp(indio_dev, adis->buffer, iio_push_to_buffers_with_timestamp(indio_dev, adis->buffer,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -74,7 +74,6 @@ static int inv_mpu_probe(struct spi_device *spi) ...@@ -74,7 +74,6 @@ static int inv_mpu_probe(struct spi_device *spi)
static const struct spi_device_id inv_mpu_id[] = { static const struct spi_device_id inv_mpu_id[] = {
{"mpu6000", INV_MPU6000}, {"mpu6000", INV_MPU6000},
{"mpu6500", INV_MPU6500}, {"mpu6500", INV_MPU6500},
{"mpu9150", INV_MPU9150},
{"mpu9250", INV_MPU9250}, {"mpu9250", INV_MPU9250},
{"mpu9255", INV_MPU9255}, {"mpu9255", INV_MPU9255},
{"icm20608", INV_ICM20608}, {"icm20608", INV_ICM20608},
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment