summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-bus-iio45
-rw-r--r--Documentation/ABI/testing/sysfs-bus-iio-adc-mcp356453
-rw-r--r--Documentation/devicetree/bindings/iio/accel/kionix,kx022a.yaml12
-rw-r--r--Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml20
-rw-r--r--Documentation/devicetree/bindings/iio/adc/microchip,mcp3564.yaml205
-rw-r--r--Documentation/devicetree/bindings/iio/adc/microchip,mcp3911.yaml6
-rw-r--r--Documentation/devicetree/bindings/iio/adc/ti,ads1015.yaml3
-rw-r--r--Documentation/devicetree/bindings/iio/adc/ti,twl6030-gpadc.yaml43
-rw-r--r--Documentation/devicetree/bindings/iio/amplifiers/adi,hmc425a.yaml12
-rw-r--r--Documentation/devicetree/bindings/iio/magnetometer/asahi-kasei,ak8975.yaml7
-rw-r--r--MAINTAINERS7
-rw-r--r--drivers/iio/accel/Kconfig10
-rw-r--r--drivers/iio/accel/adxl345.h21
-rw-r--r--drivers/iio/accel/adxl345_core.c47
-rw-r--r--drivers/iio/accel/adxl345_i2c.c20
-rw-r--r--drivers/iio/accel/adxl345_spi.c20
-rw-r--r--drivers/iio/accel/bma180.c27
-rw-r--r--drivers/iio/accel/fxls8962af.h1
-rw-r--r--drivers/iio/accel/hid-sensor-accel-3d.c6
-rw-r--r--drivers/iio/accel/kionix-kx022a-i2c.c20
-rw-r--r--drivers/iio/accel/kionix-kx022a-spi.c15
-rw-r--r--drivers/iio/accel/kionix-kx022a.c317
-rw-r--r--drivers/iio/accel/kionix-kx022a.h112
-rw-r--r--drivers/iio/accel/mma8452.c28
-rw-r--r--drivers/iio/accel/msa311.c2
-rw-r--r--drivers/iio/adc/Kconfig29
-rw-r--r--drivers/iio/adc/Makefile2
-rw-r--r--drivers/iio/adc/ab8500-gpadc.c6
-rw-r--r--drivers/iio/adc/ad4130.c15
-rw-r--r--drivers/iio/adc/at91-sama5d2_adc.c6
-rw-r--r--drivers/iio/adc/at91_adc.c114
-rw-r--r--drivers/iio/adc/axp20x_adc.c6
-rw-r--r--drivers/iio/adc/bcm_iproc_adc.c6
-rw-r--r--drivers/iio/adc/dln2-adc.c5
-rw-r--r--drivers/iio/adc/ep93xx_adc.c6
-rw-r--r--drivers/iio/adc/exynos_adc.c6
-rw-r--r--drivers/iio/adc/fsl-imx25-gcq.c6
-rw-r--r--drivers/iio/adc/hx711.c6
-rw-r--r--drivers/iio/adc/imx8qxp-adc.c6
-rw-r--r--drivers/iio/adc/imx93_adc.c6
-rw-r--r--drivers/iio/adc/ltc2309.c246
-rw-r--r--drivers/iio/adc/ltc2497.c5
-rw-r--r--drivers/iio/adc/max1363.c87
-rw-r--r--drivers/iio/adc/mcp3564.c1516
-rw-r--r--drivers/iio/adc/mcp3911.c562
-rw-r--r--drivers/iio/adc/meson_saradc.c6
-rw-r--r--drivers/iio/adc/mp2629_adc.c6
-rw-r--r--drivers/iio/adc/mt6577_auxadc.c73
-rw-r--r--drivers/iio/adc/mxs-lradc-adc.c6
-rw-r--r--drivers/iio/adc/npcm_adc.c6
-rw-r--r--drivers/iio/adc/palmas_gpadc.c2
-rw-r--r--drivers/iio/adc/qcom-pm8xxx-xoadc.c6
-rw-r--r--drivers/iio/adc/rcar-gyroadc.c6
-rw-r--r--drivers/iio/adc/spear_adc.c64
-rw-r--r--drivers/iio/adc/stm32-adc-core.c15
-rw-r--r--drivers/iio/adc/stm32-adc.c6
-rw-r--r--drivers/iio/adc/stm32-dfsdm-adc.c6
-rw-r--r--drivers/iio/adc/stm32-dfsdm-core.c6
-rw-r--r--drivers/iio/adc/sun4i-gpadc-iio.c8
-rw-r--r--drivers/iio/adc/ti-adc081c.c12
-rw-r--r--drivers/iio/adc/ti-ads1015.c7
-rw-r--r--drivers/iio/adc/ti_am335x_adc.c6
-rw-r--r--drivers/iio/adc/twl4030-madc.c6
-rw-r--r--drivers/iio/adc/twl6030-gpadc.c6
-rw-r--r--drivers/iio/adc/vf610_adc.c6
-rw-r--r--drivers/iio/addac/Kconfig1
-rw-r--r--drivers/iio/addac/ad74413r.c24
-rw-r--r--drivers/iio/addac/stx104.c61
-rw-r--r--drivers/iio/amplifiers/hmc425a.c17
-rw-r--r--drivers/iio/chemical/atlas-ezo-sensor.c6
-rw-r--r--drivers/iio/chemical/atlas-sensor.c32
-rw-r--r--drivers/iio/chemical/sgp30.c24
-rw-r--r--drivers/iio/chemical/vz89x.c16
-rw-r--r--drivers/iio/dac/dpot-dac.c6
-rw-r--r--drivers/iio/dac/lpc18xx_dac.c6
-rw-r--r--drivers/iio/dac/mcp4725.c42
-rw-r--r--drivers/iio/dac/stm32-dac-core.c6
-rw-r--r--drivers/iio/dac/stm32-dac.c9
-rw-r--r--drivers/iio/dac/ti-dac5571.c48
-rw-r--r--drivers/iio/dac/vf610_dac.c6
-rw-r--r--drivers/iio/frequency/adf4350.c75
-rw-r--r--drivers/iio/gyro/hid-sensor-gyro-3d.c6
-rw-r--r--drivers/iio/humidity/hid-sensor-humidity.c6
-rw-r--r--drivers/iio/iio_core.h3
-rw-r--r--drivers/iio/imu/adis16475.c165
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h1
-rw-r--r--drivers/iio/industrialio-core.c2
-rw-r--r--drivers/iio/light/cm3605.c6
-rw-r--r--drivers/iio/light/hid-sensor-als.c6
-rw-r--r--drivers/iio/light/hid-sensor-prox.c6
-rw-r--r--drivers/iio/light/lm3533-als.c6
-rw-r--r--drivers/iio/light/opt4001.c2
-rw-r--r--drivers/iio/magnetometer/ak8975.c86
-rw-r--r--drivers/iio/magnetometer/hid-sensor-magn-3d.c6
-rw-r--r--drivers/iio/magnetometer/yamaha-yas530.c4
-rw-r--r--drivers/iio/orientation/hid-sensor-incl-3d.c6
-rw-r--r--drivers/iio/orientation/hid-sensor-rotation.c6
-rw-r--r--drivers/iio/position/hid-sensor-custom-intel-hinge.c6
-rw-r--r--drivers/iio/potentiometer/ad5110.c21
-rw-r--r--drivers/iio/potentiometer/ds1803.c13
-rw-r--r--drivers/iio/pressure/hid-sensor-press.c6
-rw-r--r--drivers/iio/pressure/ms5637.c6
-rw-r--r--drivers/iio/proximity/cros_ec_mkbp_proximity.c6
-rw-r--r--drivers/iio/proximity/srf04.c6
-rw-r--r--drivers/iio/proximity/sx9310.c46
-rw-r--r--drivers/iio/temperature/hid-sensor-temperature.c6
-rw-r--r--drivers/iio/temperature/mlx90614.c2
-rw-r--r--drivers/iio/temperature/tmp117.c94
-rw-r--r--drivers/iio/trigger/iio-trig-interrupt.c6
-rw-r--r--drivers/iio/trigger/stm32-timer-trigger.c6
-rw-r--r--drivers/staging/iio/frequency/ad9832.c15
-rw-r--r--drivers/staging/iio/frequency/ad9834.c21
-rw-r--r--drivers/staging/iio/impedance-analyzer/ad5933.c22
-rw-r--r--include/linux/iio/sw_device.h3
-rw-r--r--include/linux/iio/sw_trigger.h3
-rw-r--r--include/uapi/linux/iio/types.h2
-rw-r--r--tools/iio/iio_event_monitor.c4
117 files changed, 3846 insertions, 1103 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index 0c9389ad3709..8e13642bbe23 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -279,6 +279,35 @@ Description:
but should match other such assignments on device).
Units after application of scale and offset are m/s^2.
+What: /sys/bus/iio/devices/iio:deviceX/in_deltaangl_x_raw
+What: /sys/bus/iio/devices/iio:deviceX/in_deltaangl_y_raw
+What: /sys/bus/iio/devices/iio:deviceX/in_deltaangl_z_raw
+KernelVersion: 6.5
+Contact: linux-iio@vger.kernel.org
+Description:
+ Angular displacement between two consecutive samples on x, y or
+ z (may be arbitrarily assigned but should match other such
+ assignments on device).
+ In order to compute the total angular displacement during a
+ desired period of time, the application should sum-up the delta
+ angle samples acquired during that time.
+ Units after application of scale and offset are radians.
+
+What: /sys/bus/iio/devices/iio:deviceX/in_deltavelocity_x_raw
+What: /sys/bus/iio/devices/iio:deviceX/in_deltavelocity_y_raw
+What: /sys/bus/iio/devices/iio:deviceX/in_deltavelocity_z_raw
+KernelVersion: 6.5
+Contact: linux-iio@vger.kernel.org
+Description:
+ The linear velocity change between two consecutive samples on x,
+ y or z (may be arbitrarily assigned but should match other such
+ assignments on device).
+ In order to compute the total linear velocity change during a
+ desired period of time, the application should sum-up the delta
+ velocity samples acquired during that time.
+ Units after application of scale and offset are meters per
+ second.
+
What: /sys/bus/iio/devices/iio:deviceX/in_angl_raw
What: /sys/bus/iio/devices/iio:deviceX/in_anglY_raw
KernelVersion: 4.17
@@ -461,6 +490,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_humidityrelative_scale
What: /sys/bus/iio/devices/iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_scale
What: /sys/bus/iio/devices/iio:deviceX/in_illuminance_scale
What: /sys/bus/iio/devices/iio:deviceX/in_countY_scale
+What: /sys/bus/iio/devices/iio:deviceX/in_deltaangl_scale
+What: /sys/bus/iio/devices/iio:deviceX/in_deltavelocity_scale
What: /sys/bus/iio/devices/iio:deviceX/in_angl_scale
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_x_scale
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_y_scale
@@ -1332,6 +1363,12 @@ Description:
What: /sys/.../iio:deviceX/bufferY/in_accel_x_en
What: /sys/.../iio:deviceX/bufferY/in_accel_y_en
What: /sys/.../iio:deviceX/bufferY/in_accel_z_en
+What: /sys/.../iio:deviceX/bufferY/in_deltaangl_x_en
+What: /sys/.../iio:deviceX/bufferY/in_deltaangl_y_en
+What: /sys/.../iio:deviceX/bufferY/in_deltaangl_z_en
+What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_x_en
+What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_y_en
+What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_z_en
What: /sys/.../iio:deviceX/bufferY/in_anglvel_x_en
What: /sys/.../iio:deviceX/bufferY/in_anglvel_y_en
What: /sys/.../iio:deviceX/bufferY/in_anglvel_z_en
@@ -1362,6 +1399,8 @@ Description:
Scan element control for triggered data capture.
What: /sys/.../iio:deviceX/bufferY/in_accel_type
+What: /sys/.../iio:deviceX/bufferY/in_deltaangl_type
+What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_type
What: /sys/.../iio:deviceX/bufferY/in_anglvel_type
What: /sys/.../iio:deviceX/bufferY/in_magn_type
What: /sys/.../iio:deviceX/bufferY/in_incli_type
@@ -1416,6 +1455,12 @@ What: /sys/.../iio:deviceX/bufferY/in_voltage_q_index
What: /sys/.../iio:deviceX/bufferY/in_accel_x_index
What: /sys/.../iio:deviceX/bufferY/in_accel_y_index
What: /sys/.../iio:deviceX/bufferY/in_accel_z_index
+What: /sys/.../iio:deviceX/bufferY/in_deltaangl_x_index
+What: /sys/.../iio:deviceX/bufferY/in_deltaangl_y_index
+What: /sys/.../iio:deviceX/bufferY/in_deltaangl_z_index
+What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_x_index
+What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_y_index
+What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_z_index
What: /sys/.../iio:deviceX/bufferY/in_anglvel_x_index
What: /sys/.../iio:deviceX/bufferY/in_anglvel_y_index
What: /sys/.../iio:deviceX/bufferY/in_anglvel_z_index
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-adc-mcp3564 b/Documentation/ABI/testing/sysfs-bus-iio-adc-mcp3564
new file mode 100644
index 000000000000..b168aa44b233
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-iio-adc-mcp3564
@@ -0,0 +1,53 @@
+What: /sys/bus/iio/devices/iio:deviceX/boost_current_gain
+KernelVersion: 6.4
+Contact: linux-iio@vger.kernel.org
+Description:
+ This attribute is used to set the gain of the biasing current
+ circuit of the Delta-Sigma modulator. The different BOOST
+ settings are applied to the entire modulator circuit, including
+ the voltage reference buffers.
+
+What: /sys/bus/iio/devices/iio:deviceX/boost_current_gain_available
+KernelVersion: 6.4
+Contact: linux-iio@vger.kernel.org
+Description:
+ Reading returns a list with the possible gain values for
+ the current biasing circuit of the Delta-Sigma modulator.
+
+What: /sys/bus/iio/devices/iio:deviceX/auto_zeroing_mux_enable
+KernelVersion: 6.4
+Contact: linux-iio@vger.kernel.org
+Description:
+ This attribute is used to enable the analog input multiplexer
+ auto-zeroing algorithm (the input multiplexer and the ADC
+ include an offset cancellation algorithm that cancels the offset
+ contribution of the ADC). When the offset cancellation algorithm
+ is enabled, ADC takes two conversions, one with the differential
+ input as VIN+/VIN-, one with VIN+/VIN- inverted. In this case the
+ conversion time is multiplied by two compared to the default
+ case where the algorithm is disabled. This technique allows the
+ cancellation of the ADC offset error and the achievement of
+ ultra-low offset without any digital calibration. The resulting
+ offset is the residue of the difference between the two
+ conversions, which is on the order of magnitude of the noise
+ floor. This offset is effectively canceled at every conversion,
+ so the residual offset error temperature drift is extremely low.
+ Write '1' to enable it, write '0' to disable it.
+
+What: /sys/bus/iio/devices/iio:deviceX/auto_zeroing_ref_enable
+KernelVersion: 6.4
+Contact: linux-iio@vger.kernel.org
+Description:
+ This attribute is used to enable the chopping algorithm for the
+ internal voltage reference buffer. This setting has no effect
+ when external voltage reference is selected.
+ Internal voltage reference buffer injects a certain quantity of
+ 1/f noise into the system that can be modulated with the
+ incoming input signals and can limit the SNR performance at
+ higher Oversampling Ratio values (over 256). To overcome this
+ limitation, the buffer includes an auto-zeroing algorithm that
+ greatly reduces (cancels out) the 1/f noise and cancels the
+ offset value of the reference buffer. As a result, the SNR of
+ the system is not affected by this 1/f noise component of the
+ reference buffer, even at maximum oversampling ratio values.
+ Write '1' to enable it, write '0' to disable it.
diff --git a/Documentation/devicetree/bindings/iio/accel/kionix,kx022a.yaml b/Documentation/devicetree/bindings/iio/accel/kionix,kx022a.yaml
index 986df1a6ff0a..034b69614416 100644
--- a/Documentation/devicetree/bindings/iio/accel/kionix,kx022a.yaml
+++ b/Documentation/devicetree/bindings/iio/accel/kionix,kx022a.yaml
@@ -4,19 +4,21 @@
$id: http://devicetree.org/schemas/iio/accel/kionix,kx022a.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: ROHM/Kionix KX022A Accelerometer
+title: ROHM/Kionix KX022A and KX132-1211 Accelerometers
maintainers:
- Matti Vaittinen <mazziesaccount@gmail.com>
description: |
- KX022A is a 3-axis accelerometer supporting +/- 2G, 4G, 8G and 16G ranges,
- output data-rates from 0.78Hz to 1600Hz and a hardware-fifo buffering.
- KX022A can be accessed either via I2C or SPI.
+ KX022A and KX132-1211 are 3-axis accelerometers supporting +/- 2G, 4G, 8G and
+ 16G ranges, variable output data-rates and a hardware-fifo buffering.
+ KX022A and KX132-1211 can be accessed either via I2C or SPI.
properties:
compatible:
- const: kionix,kx022a
+ enum:
+ - kionix,kx022a
+ - kionix,kx132-1211
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml b/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml
index 875f394576c2..5cc6a9684077 100644
--- a/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml
@@ -4,21 +4,31 @@
$id: http://devicetree.org/schemas/iio/adc/lltc,ltc2497.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Linear Technology / Analog Devices LTC2497 ADC
+title: Linear Technology / Analog Devices LTC2497 and LTC2309 ADC
maintainers:
- Michael Hennerich <michael.hennerich@analog.com>
+ - Liam Beguin <liambeguin@gmail.com>
description: |
- 16bit ADC supporting up to 16 single ended or 8 differential inputs.
- I2C interface.
+ LTC2309:
+ low noise, low power, 8-channel, 12-bit successive approximation ADC with an
+ I2C compatible serial interface.
- https://www.analog.com/media/en/technical-documentation/data-sheets/2497fb.pdf
- https://www.analog.com/media/en/technical-documentation/data-sheets/2499fe.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/2309fd.pdf
+
+ LTC2497:
+ LTC2499:
+ 16bit ADC supporting up to 16 single ended or 8 differential inputs.
+ I2C interface.
+
+ https://www.analog.com/media/en/technical-documentation/data-sheets/2497fb.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/2499fe.pdf
properties:
compatible:
enum:
+ - lltc,ltc2309
- lltc,ltc2497
- lltc,ltc2499
diff --git a/Documentation/devicetree/bindings/iio/adc/microchip,mcp3564.yaml b/Documentation/devicetree/bindings/iio/adc/microchip,mcp3564.yaml
new file mode 100644
index 000000000000..675319276197
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/microchip,mcp3564.yaml
@@ -0,0 +1,205 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/microchip,mcp3564.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip MCP346X and MCP356X ADC Family
+
+maintainers:
+ - Marius Cristea <marius.cristea@microchip.com>
+
+description: |
+ Bindings for the Microchip family of 153.6 ksps, Low-Noise 16/24-Bit
+ Delta-Sigma ADCs with an SPI interface. Datasheet can be found here:
+ Datasheet for MCP3561, MCP3562, MCP3564 can be found here:
+ https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/MCP3561-2-4-Family-Data-Sheet-DS20006181C.pdf
+ Datasheet for MCP3561R, MCP3562R, MCP3564R can be found here:
+ https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/MCP3561_2_4R-Data-Sheet-DS200006391C.pdf
+ Datasheet for MCP3461, MCP3462, MCP3464 can be found here:
+ https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/MCP3461-2-4-Two-Four-Eight-Channel-153.6-ksps-Low-Noise-16-Bit-Delta-Sigma-ADC-Data-Sheet-20006180D.pdf
+ Datasheet for MCP3461R, MCP3462R, MCP3464R can be found here:
+ https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/MCP3461-2-4R-Family-Data-Sheet-DS20006404C.pdf
+
+properties:
+ compatible:
+ enum:
+ - microchip,mcp3461
+ - microchip,mcp3462
+ - microchip,mcp3464
+ - microchip,mcp3461r
+ - microchip,mcp3462r
+ - microchip,mcp3464r
+ - microchip,mcp3561
+ - microchip,mcp3562
+ - microchip,mcp3564
+ - microchip,mcp3561r
+ - microchip,mcp3562r
+ - microchip,mcp3564r
+
+ reg:
+ maxItems: 1
+
+ spi-max-frequency:
+ maximum: 20000000
+
+ spi-cpha: true
+
+ spi-cpol: true
+
+ vdd-supply: true
+
+ avdd-supply: true
+
+ clocks:
+ description:
+ Phandle and clock identifier for external sampling clock.
+ If not specified, the internal crystal oscillator will be used.
+ maxItems: 1
+
+ interrupts:
+ description: IRQ line of the ADC
+ maxItems: 1
+
+ drive-open-drain:
+ description:
+ Whether to drive the IRQ signal as push-pull (default) or open-drain. Note
+ that the device requires this pin to become "high", otherwise it will stop
+ converting.
+ type: boolean
+
+ vref-supply:
+ description:
+ Some devices have a specific reference voltage supplied on a different
+ pin to the other supplies. Needed to be able to establish channel scaling
+ unless there is also an internal reference available (e.g. mcp3564r). In
+ case of "r" devices (e. g. mcp3564r), if it does not exists the internal
+ reference will be used.
+
+ microchip,hw-device-address:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 3
+ description:
+ The address is set on a per-device basis by fuses in the factory,
+ configured on request. If not requested, the fuses are set for 0x1.
+ The device address is part of the device markings to avoid
+ potential confusion. This address is coded on two bits, so four possible
+ addresses are available when multiple devices are present on the same
+ SPI bus with only one Chip Select line for all devices.
+ Each device communication starts by a CS falling edge, followed by the
+ clocking of the device address (BITS[7:6] - top two bits of COMMAND BYTE
+ which is first one on the wire).
+
+ "#io-channel-cells":
+ const: 1
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+patternProperties:
+ "^channel@([0-9]|([1-7][0-9]))$":
+ $ref: adc.yaml
+ type: object
+ unevaluatedProperties: false
+ description: Represents the external channels which are connected to the ADC.
+
+ properties:
+ reg:
+ description: The channel number in single-ended and differential mode.
+ minimum: 0
+ maximum: 79
+
+ required:
+ - reg
+
+dependencies:
+ spi-cpol: [ spi-cpha ]
+ spi-cpha: [ spi-cpol ]
+
+required:
+ - compatible
+ - reg
+ - microchip,hw-device-address
+ - spi-max-frequency
+
+allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+ - # External vref, no internal reference
+ if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - microchip,mcp3461
+ - microchip,mcp3462
+ - microchip,mcp3464
+ - microchip,mcp3561
+ - microchip,mcp3562
+ - microchip,mcp3564
+ then:
+ required:
+ - vref-supply
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ adc@0 {
+ compatible = "microchip,mcp3564r";
+ reg = <0>;
+ vref-supply = <&vref_reg>;
+ spi-cpha;
+ spi-cpol;
+ spi-max-frequency = <10000000>;
+ microchip,hw-device-address = <1>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ channel@0 {
+ /* CH0 to AGND */
+ reg = <0>;
+ label = "CH0";
+ };
+
+ channel@1 {
+ /* CH1 to AGND */
+ reg = <1>;
+ label = "CH1";
+ };
+
+ /* diff-channels */
+ channel@11 {
+ reg = <11>;
+
+ /* CN0, CN1 */
+ diff-channels = <0 1>;
+ label = "CH0_CH1";
+ };
+
+ channel@22 {
+ reg = <0x22>;
+
+ /* CN1, CN2 */
+ diff-channels = <1 2>;
+ label = "CH1_CH3";
+ };
+
+ channel@23 {
+ reg = <0x23>;
+
+ /* CN1, CN3 */
+ diff-channels = <1 3>;
+ label = "CH1_CH3";
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/adc/microchip,mcp3911.yaml b/Documentation/devicetree/bindings/iio/adc/microchip,mcp3911.yaml
index f7b3fde4115a..06951ec5f5da 100644
--- a/Documentation/devicetree/bindings/iio/adc/microchip,mcp3911.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/microchip,mcp3911.yaml
@@ -18,7 +18,13 @@ description: |
properties:
compatible:
enum:
+ - microchip,mcp3910
- microchip,mcp3911
+ - microchip,mcp3912
+ - microchip,mcp3913
+ - microchip,mcp3914
+ - microchip,mcp3918
+ - microchip,mcp3919
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/iio/adc/ti,ads1015.yaml b/Documentation/devicetree/bindings/iio/adc/ti,ads1015.yaml
index e004659099c1..d605999ffe28 100644
--- a/Documentation/devicetree/bindings/iio/adc/ti,ads1015.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/ti,ads1015.yaml
@@ -23,6 +23,9 @@ properties:
reg:
maxItems: 1
+ interrupts:
+ maxItems: 1
+
"#address-cells":
const: 1
diff --git a/Documentation/devicetree/bindings/iio/adc/ti,twl6030-gpadc.yaml b/Documentation/devicetree/bindings/iio/adc/ti,twl6030-gpadc.yaml
new file mode 100644
index 000000000000..e779a8986e0b
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/ti,twl6030-gpadc.yaml
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/ti,twl6030-gpadc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: GPADC subsystem in the TWL6030 power module
+
+maintainers:
+ - Andreas Kemnade <andreas@kemnade.info>
+
+description:
+ The GPADC subsystem in the TWL603X consists of a 10-bit ADC
+ combined with a 15-input analog multiplexer in the TWL6030 resp. a
+ 19-input analog muliplexer in the TWL6032.
+
+properties:
+ compatible:
+ enum:
+ - ti,twl6030-gpadc
+ - ti,twl6032-gpadc
+
+ interrupts:
+ maxItems: 1
+
+ "#io-channel-cells":
+ const: 1
+
+required:
+ - compatible
+ - interrupts
+ - "#io-channel-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ gpadc {
+ compatible = "ti,twl6030-gpadc";
+ interrupts = <3>;
+ #io-channel-cells = <1>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/amplifiers/adi,hmc425a.yaml b/Documentation/devicetree/bindings/iio/amplifiers/adi,hmc425a.yaml
index 9fda56fa49c3..2ee6080deac7 100644
--- a/Documentation/devicetree/bindings/iio/amplifiers/adi,hmc425a.yaml
+++ b/Documentation/devicetree/bindings/iio/amplifiers/adi,hmc425a.yaml
@@ -4,20 +4,26 @@
$id: http://devicetree.org/schemas/iio/amplifiers/adi,hmc425a.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: HMC425A 6-bit Digital Step Attenuator
+title: Analog Devices HMC425A and similar Digital Step Attenuators
maintainers:
- Michael Hennerich <michael.hennerich@analog.com>
description: |
- Digital Step Attenuator IIO device with gpio interface.
+ Digital Step Attenuator IIO devices with gpio interface.
+ Offer various frequency and attenuation ranges.
HMC425A 0.5 dB LSB GaAs MMIC 6-BIT DIGITAL POSITIVE CONTROL ATTENUATOR, 2.2 - 8.0 GHz
- https://www.analog.com/media/en/technical-documentation/data-sheets/hmc425A.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/hmc425A.pdf
+
+ HMC540S 1 dB LSB Silicon MMIC 4-Bit Digital Positive Control Attenuator, 0.1 - 8 GHz
+ https://www.analog.com/media/en/technical-documentation/data-sheets/hmc540s.pdf
+
properties:
compatible:
enum:
- adi,hmc425a
+ - adi,hmc540s
vcc-supply: true
diff --git a/Documentation/devicetree/bindings/iio/magnetometer/asahi-kasei,ak8975.yaml b/Documentation/devicetree/bindings/iio/magnetometer/asahi-kasei,ak8975.yaml
index 9790f75fc669..ee77558e9800 100644
--- a/Documentation/devicetree/bindings/iio/magnetometer/asahi-kasei,ak8975.yaml
+++ b/Documentation/devicetree/bindings/iio/magnetometer/asahi-kasei,ak8975.yaml
@@ -18,13 +18,6 @@ properties:
- asahi-kasei,ak09911
- asahi-kasei,ak09912
- asahi-kasei,ak09916
- - enum:
- - ak8975
- - ak8963
- - ak09911
- - ak09912
- - ak09916
- deprecated: true
reg:
maxItems: 1
diff --git a/MAINTAINERS b/MAINTAINERS
index 90f13281d297..337a4244ee30 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14019,6 +14019,13 @@ S: Supported
F: Documentation/devicetree/bindings/regulator/mcp16502-regulator.txt
F: drivers/regulator/mcp16502.c
+MICROCHIP MCP3564 ADC DRIVER
+M: Marius Cristea <marius.cristea@microchip.com>
+L: linux-iio@vger.kernel.org
+S: Supported
+F: Documentation/devicetree/bindings/iio/adc/microchip,mcp3564.yaml
+F: drivers/iio/adc/mcp3564.c
+
MICROCHIP MCP3911 ADC DRIVER
M: Marcus Folkesson <marcus.folkesson@gmail.com>
M: Kent Gustavsson <kent@minoris.se>
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index b6b45d359f28..373257d64a7e 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -418,8 +418,9 @@ config IIO_KX022A_SPI
select IIO_KX022A
select REGMAP_SPI
help
- Enable support for the Kionix KX022A digital tri-axis
- accelerometer connected to I2C interface.
+ Enable support for the Kionix digital tri-axis accelerometers
+ connected to SPI interface. Supported devices are:
+ KX022A, KX132-1211
config IIO_KX022A_I2C
tristate "Kionix KX022A tri-axis digital accelerometer I2C interface"
@@ -427,8 +428,9 @@ config IIO_KX022A_I2C
select IIO_KX022A
select REGMAP_I2C
help
- Enable support for the Kionix KX022A digital tri-axis
- accelerometer connected to I2C interface.
+ Enable support for the Kionix digital tri-axis accelerometers
+ connected to I2C interface. Supported devices are:
+ KX022A, KX132-1211
config KXSD9
tristate "Kionix KXSD9 Accelerometer Driver"
diff --git a/drivers/iio/accel/adxl345.h b/drivers/iio/accel/adxl345.h
index d7e67cb08538..284bd387ce69 100644
--- a/drivers/iio/accel/adxl345.h
+++ b/drivers/iio/accel/adxl345.h
@@ -8,9 +8,24 @@
#ifndef _ADXL345_H_
#define _ADXL345_H_
-enum adxl345_device_type {
- ADXL345 = 1,
- ADXL375 = 2,
+/*
+ * In full-resolution mode, scale factor is maintained at ~4 mg/LSB
+ * in all g ranges.
+ *
+ * At +/- 16g with 13-bit resolution, scale is computed as:
+ * (16 + 16) * 9.81 / (2^13 - 1) = 0.0383
+ */
+#define ADXL345_USCALE 38300
+
+/*
+ * The Datasheet lists a resolution of Resolution is ~49 mg per LSB. That's
+ * ~480mm/s**2 per LSB.
+ */
+#define ADXL375_USCALE 480000
+
+struct adxl345_chip_info {
+ const char *name;
+ int uscale;
};
int adxl345_core_probe(struct device *dev, struct regmap *regmap);
diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c
index 1919e0089c11..8bd30a23ed3b 100644
--- a/drivers/iio/accel/adxl345_core.c
+++ b/drivers/iio/accel/adxl345_core.c
@@ -45,25 +45,10 @@
#define ADXL345_DEVID 0xE5
-/*
- * In full-resolution mode, scale factor is maintained at ~4 mg/LSB
- * in all g ranges.
- *
- * At +/- 16g with 13-bit resolution, scale is computed as:
- * (16 + 16) * 9.81 / (2^13 - 1) = 0.0383
- */
-static const int adxl345_uscale = 38300;
-
-/*
- * The Datasheet lists a resolution of Resolution is ~49 mg per LSB. That's
- * ~480mm/s**2 per LSB.
- */
-static const int adxl375_uscale = 480000;
-
struct adxl345_data {
+ const struct adxl345_chip_info *info;
struct regmap *regmap;
u8 data_range;
- enum adxl345_device_type type;
};
#define ADXL345_CHANNEL(index, axis) { \
@@ -110,15 +95,7 @@ static int adxl345_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 0;
- switch (data->type) {
- case ADXL345:
- *val2 = adxl345_uscale;
- break;
- case ADXL375:
- *val2 = adxl375_uscale;
- break;
- }
-
+ *val2 = data->info->uscale;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_CALIBBIAS:
ret = regmap_read(data->regmap,
@@ -222,25 +199,11 @@ static void adxl345_powerdown(void *regmap)
int adxl345_core_probe(struct device *dev, struct regmap *regmap)
{
- enum adxl345_device_type type;
struct adxl345_data *data;
struct iio_dev *indio_dev;
- const char *name;
u32 regval;
int ret;
- type = (uintptr_t)device_get_match_data(dev);
- switch (type) {
- case ADXL345:
- name = "adxl345";
- break;
- case ADXL375:
- name = "adxl375";
- break;
- default:
- return -EINVAL;
- }
-
ret = regmap_read(regmap, ADXL345_REG_DEVID, &regval);
if (ret < 0)
return dev_err_probe(dev, ret, "Error reading device ID\n");
@@ -255,16 +218,18 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap)
data = iio_priv(indio_dev);
data->regmap = regmap;
- data->type = type;
/* Enable full-resolution mode */
data->data_range = ADXL345_DATA_FORMAT_FULL_RES;
+ data->info = device_get_match_data(dev);
+ if (!data->info)
+ return -ENODEV;
ret = regmap_write(data->regmap, ADXL345_REG_DATA_FORMAT,
data->data_range);
if (ret < 0)
return dev_err_probe(dev, ret, "Failed to set data range\n");
- indio_dev->name = name;
+ indio_dev->name = data->info->name;
indio_dev->info = &adxl345_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = adxl345_channels;
diff --git a/drivers/iio/accel/adxl345_i2c.c b/drivers/iio/accel/adxl345_i2c.c
index e47d12f19602..a3084b0a8f78 100644
--- a/drivers/iio/accel/adxl345_i2c.c
+++ b/drivers/iio/accel/adxl345_i2c.c
@@ -30,22 +30,32 @@ static int adxl345_i2c_probe(struct i2c_client *client)
return adxl345_core_probe(&client->dev, regmap);
}
+static const struct adxl345_chip_info adxl345_i2c_info = {
+ .name = "adxl345",
+ .uscale = ADXL345_USCALE,
+};
+
+static const struct adxl345_chip_info adxl375_i2c_info = {
+ .name = "adxl375",
+ .uscale = ADXL375_USCALE,
+};
+
static const struct i2c_device_id adxl345_i2c_id[] = {
- { "adxl345", ADXL345 },
- { "adxl375", ADXL375 },
+ { "adxl345", (kernel_ulong_t)&adxl345_i2c_info },
+ { "adxl375", (kernel_ulong_t)&adxl375_i2c_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, adxl345_i2c_id);
static const struct of_device_id adxl345_of_match[] = {
- { .compatible = "adi,adxl345", .data = (const void *)ADXL345 },
- { .compatible = "adi,adxl375", .data = (const void *)ADXL375 },
+ { .compatible = "adi,adxl345", .data = &adxl345_i2c_info },
+ { .compatible = "adi,adxl375", .data = &adxl375_i2c_info },
{ }
};
MODULE_DEVICE_TABLE(of, adxl345_of_match);
static const struct acpi_device_id adxl345_acpi_match[] = {
- { "ADS0345", ADXL345 },
+ { "ADS0345", (kernel_ulong_t)&adxl345_i2c_info },
{ }
};
MODULE_DEVICE_TABLE(acpi, adxl345_acpi_match);
diff --git a/drivers/iio/accel/adxl345_spi.c b/drivers/iio/accel/adxl345_spi.c
index aaade5808657..93ca349f1780 100644
--- a/drivers/iio/accel/adxl345_spi.c
+++ b/drivers/iio/accel/adxl345_spi.c
@@ -36,22 +36,32 @@ static int adxl345_spi_probe(struct spi_device *spi)
return adxl345_core_probe(&spi->dev, regmap);
}
+static const struct adxl345_chip_info adxl345_spi_info = {
+ .name = "adxl345",
+ .uscale = ADXL345_USCALE,
+};
+
+static const struct adxl345_chip_info adxl375_spi_info = {
+ .name = "adxl375",
+ .uscale = ADXL375_USCALE,
+};
+
static const struct spi_device_id adxl345_spi_id[] = {
- { "adxl345", ADXL345 },
- { "adxl375", ADXL375 },
+ { "adxl345", (kernel_ulong_t)&adxl345_spi_info },
+ { "adxl375", (kernel_ulong_t)&adxl375_spi_info },
{ }
};
MODULE_DEVICE_TABLE(spi, adxl345_spi_id);
static const struct of_device_id adxl345_of_match[] = {
- { .compatible = "adi,adxl345", .data = (const void *)ADXL345 },
- { .compatible = "adi,adxl375", .data = (const void *)ADXL375 },
+ { .compatible = "adi,adxl345", .data = &adxl345_spi_info },
+ { .compatible = "adi,adxl375", .data = &adxl375_spi_info },
{ }
};
MODULE_DEVICE_TABLE(of, adxl345_of_match);
static const struct acpi_device_id adxl345_acpi_match[] = {
- { "ADS0345", ADXL345 },
+ { "ADS0345", (kernel_ulong_t)&adxl345_spi_info },
{ }
};
MODULE_DEVICE_TABLE(acpi, adxl345_acpi_match);
diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c
index 13439f52d26d..ab4fccb24b6c 100644
--- a/drivers/iio/accel/bma180.c
+++ b/drivers/iio/accel/bma180.c
@@ -926,7 +926,6 @@ static int bma180_probe(struct i2c_client *client)
struct device *dev = &client->dev;
struct bma180_data *data;
struct iio_dev *indio_dev;
- enum chip_ids chip;
int ret;
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
@@ -936,11 +935,7 @@ static int bma180_probe(struct i2c_client *client)
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
- if (client->dev.of_node)
- chip = (uintptr_t)of_device_get_match_data(dev);
- else
- chip = id->driver_data;
- data->part_info = &bma180_part_info[chip];
+ data->part_info = i2c_get_match_data(client);
ret = iio_read_mount_matrix(dev, &data->orientation);
if (ret)
@@ -1092,11 +1087,11 @@ static int bma180_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(bma180_pm_ops, bma180_suspend, bma180_resume);
static const struct i2c_device_id bma180_ids[] = {
- { "bma023", BMA023 },
- { "bma150", BMA150 },
- { "bma180", BMA180 },
- { "bma250", BMA250 },
- { "smb380", BMA150 },
+ { "bma023", (kernel_ulong_t)&bma180_part_info[BMA023] },
+ { "bma150", (kernel_ulong_t)&bma180_part_info[BMA150] },
+ { "bma180", (kernel_ulong_t)&bma180_part_info[BMA180] },
+ { "bma250", (kernel_ulong_t)&bma180_part_info[BMA250] },
+ { "smb380", (kernel_ulong_t)&bma180_part_info[BMA150] },
{ }
};
@@ -1105,23 +1100,23 @@ MODULE_DEVICE_TABLE(i2c, bma180_ids);
static const struct of_device_id bma180_of_match[] = {
{
.compatible = "bosch,bma023",
- .data = (void *)BMA023
+ .data = &bma180_part_info[BMA023]
},
{
.compatible = "bosch,bma150",
- .data = (void *)BMA150
+ .data = &bma180_part_info[BMA150]
},
{
.compatible = "bosch,bma180",
- .data = (void *)BMA180
+ .data = &bma180_part_info[BMA180]
},
{
.compatible = "bosch,bma250",
- .data = (void *)BMA250
+ .data = &bma180_part_info[BMA250]
},
{
.compatible = "bosch,smb380",
- .data = (void *)BMA150
+ .data = &bma180_part_info[BMA150]
},
{ }
};
diff --git a/drivers/iio/accel/fxls8962af.h b/drivers/iio/accel/fxls8962af.h
index 9cbe98c3ba9a..6eaa2803b26f 100644
--- a/drivers/iio/accel/fxls8962af.h
+++ b/drivers/iio/accel/fxls8962af.h
@@ -14,7 +14,6 @@ enum {
};
int fxls8962af_core_probe(struct device *dev, struct regmap *regmap, int irq);
-int fxls8962af_core_remove(struct device *dev);
extern const struct dev_pm_ops fxls8962af_pm_ops;
extern const struct regmap_config fxls8962af_i2c_regmap_conf;
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index 5eac7ea19993..9b7a73a4c48a 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -422,7 +422,7 @@ error_remove_trigger:
}
/* Function to deinitialize the processing for usage id */
-static int hid_accel_3d_remove(struct platform_device *pdev)
+static void hid_accel_3d_remove(struct platform_device *pdev)
{
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@@ -431,8 +431,6 @@ static int hid_accel_3d_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, hsdev->usage);
iio_device_unregister(indio_dev);
hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes);
-
- return 0;
}
static const struct platform_device_id hid_accel_3d_ids[] = {
@@ -454,7 +452,7 @@ static struct platform_driver hid_accel_3d_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_accel_3d_probe,
- .remove = hid_accel_3d_remove,
+ .remove_new = hid_accel_3d_remove,
};
module_platform_driver(hid_accel_3d_platform_driver);
diff --git a/drivers/iio/accel/kionix-kx022a-i2c.c b/drivers/iio/accel/kionix-kx022a-i2c.c
index b0ac78e85dad..fc53e527cae0 100644
--- a/drivers/iio/accel/kionix-kx022a-i2c.c
+++ b/drivers/iio/accel/kionix-kx022a-i2c.c
@@ -15,6 +15,7 @@
static int kx022a_i2c_probe(struct i2c_client *i2c)
{
struct device *dev = &i2c->dev;
+ const struct kx022a_chip_info *chip_info;
struct regmap *regmap;
if (!i2c->irq) {
@@ -22,16 +23,28 @@ static int kx022a_i2c_probe(struct i2c_client *i2c)
return -EINVAL;
}
- regmap = devm_regmap_init_i2c(i2c, &kx022a_regmap);
+ chip_info = i2c_get_match_data(i2c);
+ if (!chip_info)
+ return -EINVAL;
+
+ regmap = devm_regmap_init_i2c(i2c, chip_info->regmap_config);
if (IS_ERR(regmap))
return dev_err_probe(dev, PTR_ERR(regmap),
"Failed to initialize Regmap\n");
- return kx022a_probe_internal(dev);
+ return kx022a_probe_internal(dev, chip_info);
}
+static const struct i2c_device_id kx022a_i2c_id[] = {
+ { .name = "kx022a", .driver_data = (kernel_ulong_t)&kx022a_chip_info },
+ { .name = "kx132-1211", .driver_data = (kernel_ulong_t)&kx132_chip_info },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, kx022a_i2c_id);
+
static const struct of_device_id kx022a_of_match[] = {
- { .compatible = "kionix,kx022a", },
+ { .compatible = "kionix,kx022a", .data = &kx022a_chip_info },
+ { .compatible = "kionix,kx132-1211", .data = &kx132_chip_info },
{ }
};
MODULE_DEVICE_TABLE(of, kx022a_of_match);
@@ -43,6 +56,7 @@ static struct i2c_driver kx022a_i2c_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.probe = kx022a_i2c_probe,
+ .id_table = kx022a_i2c_id,
};
module_i2c_driver(kx022a_i2c_driver);
diff --git a/drivers/iio/accel/kionix-kx022a-spi.c b/drivers/iio/accel/kionix-kx022a-spi.c
index f45a46899a5f..e7878ba67827 100644
--- a/drivers/iio/accel/kionix-kx022a-spi.c
+++ b/drivers/iio/accel/kionix-kx022a-spi.c
@@ -15,6 +15,7 @@
static int kx022a_spi_probe(struct spi_device *spi)
{
struct device *dev = &spi->dev;
+ const struct kx022a_chip_info *chip_info;
struct regmap *regmap;
if (!spi->irq) {
@@ -22,22 +23,28 @@ static int kx022a_spi_probe(struct spi_device *spi)
return -EINVAL;
}
- regmap = devm_regmap_init_spi(spi, &kx022a_regmap);
+ chip_info = spi_get_device_match_data(spi);
+ if (!chip_info)
+ return -EINVAL;
+
+ regmap = devm_regmap_init_spi(spi, chip_info->regmap_config);
if (IS_ERR(regmap))
return dev_err_probe(dev, PTR_ERR(regmap),
"Failed to initialize Regmap\n");
- return kx022a_probe_internal(dev);
+ return kx022a_probe_internal(dev, chip_info);
}
static const struct spi_device_id kx022a_id[] = {
- { "kx022a" },
+ { .name = "kx022a", .driver_data = (kernel_ulong_t)&kx022a_chip_info },
+ { .name = "kx132-1211", .driver_data = (kernel_ulong_t)&kx132_chip_info },
{ }
};
MODULE_DEVICE_TABLE(spi, kx022a_id);
static const struct of_device_id kx022a_of_match[] = {
- { .compatible = "kionix,kx022a", },
+ { .compatible = "kionix,kx022a", .data = &kx022a_chip_info },
+ { .compatible = "kionix,kx132-1211", .data = &kx132_chip_info },
{ }
};
MODULE_DEVICE_TABLE(of, kx022a_of_match);
diff --git a/drivers/iio/accel/kionix-kx022a.c b/drivers/iio/accel/kionix-kx022a.c
index 4ea3c6718ed4..c5b555094e60 100644
--- a/drivers/iio/accel/kionix-kx022a.c
+++ b/drivers/iio/accel/kionix-kx022a.c
@@ -15,7 +15,7 @@
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
-#include <linux/string_helpers.h>
+#include <linux/string_choices.h>
#include <linux/units.h>
#include <linux/iio/iio.h>
@@ -48,7 +48,7 @@ enum {
KX022A_STATE_FIFO,
};
-/* Regmap configs */
+/* kx022a Regmap configs */
static const struct regmap_range kx022a_volatile_ranges[] = {
{
.range_min = KX022A_REG_XHP_L,
@@ -138,7 +138,7 @@ static const struct regmap_access_table kx022a_nir_regs = {
.n_yes_ranges = ARRAY_SIZE(kx022a_noinc_read_ranges),
};
-const struct regmap_config kx022a_regmap = {
+static const struct regmap_config kx022a_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.volatile_table = &kx022a_volatile_regs,
@@ -149,10 +149,121 @@ const struct regmap_config kx022a_regmap = {
.max_register = KX022A_MAX_REGISTER,
.cache_type = REGCACHE_RBTREE,
};
-EXPORT_SYMBOL_NS_GPL(kx022a_regmap, IIO_KX022A);
+
+/* Regmap configs kx132 */
+static const struct regmap_range kx132_volatile_ranges[] = {
+ {
+ .range_min = KX132_REG_XADP_L,
+ .range_max = KX132_REG_COTR,
+ }, {
+ .range_min = KX132_REG_TSCP,
+ .range_max = KX132_REG_INT_REL,
+ }, {
+ /* The reset bit will be cleared by sensor */
+ .range_min = KX132_REG_CNTL2,
+ .range_max = KX132_REG_CNTL2,
+ }, {
+ .range_min = KX132_REG_CNTL5,
+ .range_max = KX132_REG_CNTL5,
+ }, {
+ .range_min = KX132_REG_BUF_STATUS_1,
+ .range_max = KX132_REG_BUF_READ,
+ },
+};
+
+static const struct regmap_access_table kx132_volatile_regs = {
+ .yes_ranges = &kx132_volatile_ranges[0],
+ .n_yes_ranges = ARRAY_SIZE(kx132_volatile_ranges),
+};
+
+static const struct regmap_range kx132_precious_ranges[] = {
+ {
+ .range_min = KX132_REG_INT_REL,
+ .range_max = KX132_REG_INT_REL,
+ },
+};
+
+static const struct regmap_access_table kx132_precious_regs = {
+ .yes_ranges = &kx132_precious_ranges[0],
+ .n_yes_ranges = ARRAY_SIZE(kx132_precious_ranges),
+};
+
+static const struct regmap_range kx132_read_only_ranges[] = {
+ {
+ .range_min = KX132_REG_XADP_L,
+ .range_max = KX132_REG_INT_REL,
+ }, {
+ .range_min = KX132_REG_BUF_STATUS_1,
+ .range_max = KX132_REG_BUF_STATUS_2,
+ }, {
+ .range_min = KX132_REG_BUF_READ,
+ .range_max = KX132_REG_BUF_READ,
+ }, {
+ /* Kionix reserved registers: should not be written */
+ .range_min = 0x28,
+ .range_max = 0x28,
+ }, {
+ .range_min = 0x35,
+ .range_max = 0x36,
+ }, {
+ .range_min = 0x3c,
+ .range_max = 0x48,
+ }, {
+ .range_min = 0x4e,
+ .range_max = 0x5c,
+ }, {
+ .range_min = 0x77,
+ .range_max = 0x7f,
+ },
+};
+
+static const struct regmap_access_table kx132_ro_regs = {
+ .no_ranges = &kx132_read_only_ranges[0],
+ .n_no_ranges = ARRAY_SIZE(kx132_read_only_ranges),
+};
+
+static const struct regmap_range kx132_write_only_ranges[] = {
+ {
+ .range_min = KX132_REG_SELF_TEST,
+ .range_max = KX132_REG_SELF_TEST,
+ }, {
+ .range_min = KX132_REG_BUF_CLEAR,
+ .range_max = KX132_REG_BUF_CLEAR,
+ },
+};
+
+static const struct regmap_access_table kx132_wo_regs = {
+ .no_ranges = &kx132_write_only_ranges[0],
+ .n_no_ranges = ARRAY_SIZE(kx132_write_only_ranges),
+};
+
+static const struct regmap_range kx132_noinc_read_ranges[] = {
+ {
+ .range_min = KX132_REG_BUF_READ,
+ .range_max = KX132_REG_BUF_READ,
+ },
+};
+
+static const struct regmap_access_table kx132_nir_regs = {
+ .yes_ranges = &kx132_noinc_read_ranges[0],
+ .n_yes_ranges = ARRAY_SIZE(kx132_noinc_read_ranges),
+};
+
+static const struct regmap_config kx132_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .volatile_table = &kx132_volatile_regs,
+ .rd_table = &kx132_wo_regs,
+ .wr_table = &kx132_ro_regs,
+ .rd_noinc_table = &kx132_nir_regs,
+ .precious_table = &kx132_precious_regs,
+ .max_register = KX132_MAX_REGISTER,
+ .cache_type = REGCACHE_RBTREE,
+};
struct kx022a_data {
struct regmap *regmap;
+ const struct kx022a_chip_info *chip_info;
struct iio_trigger *trig;
struct device *dev;
struct iio_mount_matrix orientation;
@@ -175,6 +286,8 @@ struct kx022a_data {
struct mutex mutex;
u8 watermark;
+ __le16 *fifo_buffer;
+
/* 3 x 16bit accel data + timestamp */
__le16 buffer[8] __aligned(IIO_DMA_MINALIGN);
struct {
@@ -208,7 +321,7 @@ static const struct iio_chan_spec_ext_info kx022a_ext_info[] = {
{ }
};
-#define KX022A_ACCEL_CHAN(axis, index) \
+#define KX022A_ACCEL_CHAN(axis, reg, index) \
{ \
.type = IIO_ACCEL, \
.modified = 1, \
@@ -220,7 +333,7 @@ static const struct iio_chan_spec_ext_info kx022a_ext_info[] = {
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.ext_info = kx022a_ext_info, \
- .address = KX022A_REG_##axis##OUT_L, \
+ .address = reg, \
.scan_index = index, \
.scan_type = { \
.sign = 's', \
@@ -231,9 +344,16 @@ static const struct iio_chan_spec_ext_info kx022a_ext_info[] = {
}
static const struct iio_chan_spec kx022a_channels[] = {
- KX022A_ACCEL_CHAN(X, 0),
- KX022A_ACCEL_CHAN(Y, 1),
- KX022A_ACCEL_CHAN(Z, 2),
+ KX022A_ACCEL_CHAN(X, KX022A_REG_XOUT_L, 0),
+ KX022A_ACCEL_CHAN(Y, KX022A_REG_YOUT_L, 1),
+ KX022A_ACCEL_CHAN(Z, KX022A_REG_ZOUT_L, 2),
+ IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+static const struct iio_chan_spec kx132_channels[] = {
+ KX022A_ACCEL_CHAN(X, KX132_REG_XOUT_L, 0),
+ KX022A_ACCEL_CHAN(Y, KX132_REG_YOUT_L, 1),
+ KX022A_ACCEL_CHAN(Z, KX132_REG_ZOUT_L, 2),
IIO_CHAN_SOFT_TIMESTAMP(3),
};
@@ -332,16 +452,15 @@ static int kx022a_turn_on_off_unlocked(struct kx022a_data *data, bool on)
int ret;
if (on)
- ret = regmap_set_bits(data->regmap, KX022A_REG_CNTL,
+ ret = regmap_set_bits(data->regmap, data->chip_info->cntl,
KX022A_MASK_PC1);
else
- ret = regmap_clear_bits(data->regmap, KX022A_REG_CNTL,
+ ret = regmap_clear_bits(data->regmap, data->chip_info->cntl,
KX022A_MASK_PC1);
if (ret)
dev_err(data->dev, "Turn %s fail %d\n", str_on_off(on), ret);
return ret;
-
}
static int kx022a_turn_off_lock(struct kx022a_data *data)
@@ -403,7 +522,7 @@ static int kx022a_write_raw(struct iio_dev *idev,
break;
ret = regmap_update_bits(data->regmap,
- KX022A_REG_ODCNTL,
+ data->chip_info->odcntl,
KX022A_MASK_ODR, n);
data->odr_ns = kx022a_odrs[n];
kx022a_turn_on_unlock(data);
@@ -424,7 +543,7 @@ static int kx022a_write_raw(struct iio_dev *idev,
if (ret)
break;
- ret = regmap_update_bits(data->regmap, KX022A_REG_CNTL,
+ ret = regmap_update_bits(data->regmap, data->chip_info->cntl,
KX022A_MASK_GSEL,
n << KX022A_GSEL_SHIFT);
kx022a_turn_on_unlock(data);
@@ -446,7 +565,7 @@ static int kx022a_fifo_set_wmi(struct kx022a_data *data)
threshold = data->watermark;
- return regmap_update_bits(data->regmap, KX022A_REG_BUF_CNTL1,
+ return regmap_update_bits(data->regmap, data->chip_info->buf_cntl1,
KX022A_MASK_WM_TH, threshold);
}
@@ -489,7 +608,7 @@ static int kx022a_read_raw(struct iio_dev *idev,
return ret;
case IIO_CHAN_INFO_SAMP_FREQ:
- ret = regmap_read(data->regmap, KX022A_REG_ODCNTL, &regval);
+ ret = regmap_read(data->regmap, data->chip_info->odcntl, &regval);
if (ret)
return ret;
@@ -504,7 +623,7 @@ static int kx022a_read_raw(struct iio_dev *idev,
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SCALE:
- ret = regmap_read(data->regmap, KX022A_REG_CNTL, &regval);
+ ret = regmap_read(data->regmap, data->chip_info->cntl, &regval);
if (ret < 0)
return ret;
@@ -520,8 +639,7 @@ static int kx022a_set_watermark(struct iio_dev *idev, unsigned int val)
{
struct kx022a_data *data = iio_priv(idev);
- if (val > KX022A_FIFO_LENGTH)
- val = KX022A_FIFO_LENGTH;
+ val = min(data->chip_info->fifo_length, val);
mutex_lock(&data->mutex);
data->watermark = val;
@@ -582,30 +700,56 @@ static int kx022a_drop_fifo_contents(struct kx022a_data *data)
*/
data->timestamp = 0;
- return regmap_write(data->regmap, KX022A_REG_BUF_CLEAR, 0x0);
+ return regmap_write(data->regmap, data->chip_info->buf_clear, 0x0);
+}
+
+static int kx022a_get_fifo_bytes_available(struct kx022a_data *data)
+{
+ int ret, fifo_bytes;
+
+ ret = regmap_read(data->regmap, KX022A_REG_BUF_STATUS_1, &fifo_bytes);
+ if (ret) {
+ dev_err(data->dev, "Error reading buffer status\n");
+ return ret;
+ }
+
+ if (fifo_bytes == KX022A_FIFO_FULL_VALUE)
+ return KX022A_FIFO_MAX_BYTES;
+
+ return fifo_bytes;
+}
+
+static int kx132_get_fifo_bytes_available(struct kx022a_data *data)
+{
+ __le16 buf_status;
+ int ret, fifo_bytes;
+
+ ret = regmap_bulk_read(data->regmap, data->chip_info->buf_status1,
+ &buf_status, sizeof(buf_status));
+ if (ret) {
+ dev_err(data->dev, "Error reading buffer status\n");
+ return ret;
+ }
+
+ fifo_bytes = le16_to_cpu(buf_status);
+ fifo_bytes &= data->chip_info->buf_smp_lvl_mask;
+ fifo_bytes = min((unsigned int)fifo_bytes, data->chip_info->fifo_length *
+ KX022A_FIFO_SAMPLES_SIZE_BYTES);
+
+ return fifo_bytes;
}
static int __kx022a_fifo_flush(struct iio_dev *idev, unsigned int samples,
bool irq)
{
struct kx022a_data *data = iio_priv(idev);
- struct device *dev = regmap_get_device(data->regmap);
- __le16 buffer[KX022A_FIFO_LENGTH * 3];
uint64_t sample_period;
int count, fifo_bytes;
bool renable = false;
int64_t tstamp;
int ret, i;
- ret = regmap_read(data->regmap, KX022A_REG_BUF_STATUS_1, &fifo_bytes);
- if (ret) {
- dev_err(dev, "Error reading buffer status\n");
- return ret;
- }
-
- /* Let's not overflow if we for some reason get bogus value from i2c */
- if (fifo_bytes == KX022A_FIFO_FULL_VALUE)
- fifo_bytes = KX022A_FIFO_MAX_BYTES;
+ fifo_bytes = data->chip_info->get_fifo_bytes_available(data);
if (fifo_bytes % KX022A_FIFO_SAMPLES_SIZE_BYTES)
dev_warn(data->dev, "Bad FIFO alignment. Data may be corrupt\n");
@@ -669,13 +813,13 @@ static int __kx022a_fifo_flush(struct iio_dev *idev, unsigned int samples,
}
fifo_bytes = count * KX022A_FIFO_SAMPLES_SIZE_BYTES;
- ret = regmap_noinc_read(data->regmap, KX022A_REG_BUF_READ,
- &buffer[0], fifo_bytes);
+ ret = regmap_noinc_read(data->regmap, data->chip_info->buf_read,
+ data->fifo_buffer, fifo_bytes);
if (ret)
goto renable_out;
for (i = 0; i < count; i++) {
- __le16 *sam = &buffer[i * 3];
+ __le16 *sam = &data->fifo_buffer[i * 3];
__le16 *chs;
int bit;
@@ -722,10 +866,10 @@ static const struct iio_info kx022a_info = {
static int kx022a_set_drdy_irq(struct kx022a_data *data, bool en)
{
if (en)
- return regmap_set_bits(data->regmap, KX022A_REG_CNTL,
+ return regmap_set_bits(data->regmap, data->chip_info->cntl,
KX022A_MASK_DRDY);
- return regmap_clear_bits(data->regmap, KX022A_REG_CNTL,
+ return regmap_clear_bits(data->regmap, data->chip_info->cntl,
KX022A_MASK_DRDY);
}
@@ -760,7 +904,7 @@ static int kx022a_fifo_disable(struct kx022a_data *data)
if (ret)
goto unlock_out;
- ret = regmap_clear_bits(data->regmap, KX022A_REG_BUF_CNTL2,
+ ret = regmap_clear_bits(data->regmap, data->chip_info->buf_cntl2,
KX022A_MASK_BUF_EN);
if (ret)
goto unlock_out;
@@ -769,6 +913,8 @@ static int kx022a_fifo_disable(struct kx022a_data *data)
kx022a_drop_fifo_contents(data);
+ kfree(data->fifo_buffer);
+
return kx022a_turn_on_unlock(data);
unlock_out:
@@ -791,6 +937,12 @@ static int kx022a_fifo_enable(struct kx022a_data *data)
{
int ret;
+ data->fifo_buffer = kmalloc_array(data->chip_info->fifo_length,
+ KX022A_FIFO_SAMPLES_SIZE_BYTES,
+ GFP_KERNEL);
+ if (!data->fifo_buffer)
+ return -ENOMEM;
+
ret = kx022a_turn_off_lock(data);
if (ret)
return ret;
@@ -801,7 +953,7 @@ static int kx022a_fifo_enable(struct kx022a_data *data)
goto unlock_out;
/* Enable buffer */
- ret = regmap_set_bits(data->regmap, KX022A_REG_BUF_CNTL2,
+ ret = regmap_set_bits(data->regmap, data->chip_info->buf_cntl2,
KX022A_MASK_BUF_EN);
if (ret)
goto unlock_out;
@@ -847,7 +999,7 @@ static irqreturn_t kx022a_trigger_handler(int irq, void *p)
struct kx022a_data *data = iio_priv(idev);
int ret;
- ret = regmap_bulk_read(data->regmap, KX022A_REG_XOUT_L, data->buffer,
+ ret = regmap_bulk_read(data->regmap, data->chip_info->xout_l, data->buffer,
KX022A_FIFO_SAMPLES_SIZE_BYTES);
if (ret < 0)
goto err_read;
@@ -895,7 +1047,7 @@ static irqreturn_t kx022a_irq_thread_handler(int irq, void *private)
if (data->state & KX022A_STATE_FIFO) {
int ok;
- ok = __kx022a_fifo_flush(idev, KX022A_FIFO_LENGTH, true);
+ ok = __kx022a_fifo_flush(idev, data->chip_info->fifo_length, true);
if (ok > 0)
ret = IRQ_HANDLED;
}
@@ -948,7 +1100,7 @@ static int kx022a_chip_init(struct kx022a_data *data)
int ret, val;
/* Reset the senor */
- ret = regmap_write(data->regmap, KX022A_REG_CNTL2, KX022A_MASK_SRST);
+ ret = regmap_write(data->regmap, data->chip_info->cntl2, KX022A_MASK_SRST);
if (ret)
return ret;
@@ -958,7 +1110,7 @@ static int kx022a_chip_init(struct kx022a_data *data)
*/
msleep(1);
- ret = regmap_read_poll_timeout(data->regmap, KX022A_REG_CNTL2, val,
+ ret = regmap_read_poll_timeout(data->regmap, data->chip_info->cntl2, val,
!(val & KX022A_MASK_SRST),
KX022A_SOFT_RESET_WAIT_TIME_US,
KX022A_SOFT_RESET_TOTAL_WAIT_TIME_US);
@@ -968,14 +1120,14 @@ static int kx022a_chip_init(struct kx022a_data *data)
return ret;
}
- ret = regmap_reinit_cache(data->regmap, &kx022a_regmap);
+ ret = regmap_reinit_cache(data->regmap, data->chip_info->regmap_config);
if (ret) {
dev_err(data->dev, "Failed to reinit reg cache\n");
return ret;
}
/* set data res 16bit */
- ret = regmap_set_bits(data->regmap, KX022A_REG_BUF_CNTL2,
+ ret = regmap_set_bits(data->regmap, data->chip_info->buf_cntl2,
KX022A_MASK_BRES16);
if (ret) {
dev_err(data->dev, "Failed to set data resolution\n");
@@ -985,7 +1137,58 @@ static int kx022a_chip_init(struct kx022a_data *data)
return kx022a_prepare_irq_pin(data);
}
-int kx022a_probe_internal(struct device *dev)
+const struct kx022a_chip_info kx022a_chip_info = {
+ .name = "kx022-accel",
+ .regmap_config = &kx022a_regmap_config,
+ .channels = kx022a_channels,
+ .num_channels = ARRAY_SIZE(kx022a_channels),
+ .fifo_length = KX022A_FIFO_LENGTH,
+ .who = KX022A_REG_WHO,
+ .id = KX022A_ID,
+ .cntl = KX022A_REG_CNTL,
+ .cntl2 = KX022A_REG_CNTL2,
+ .odcntl = KX022A_REG_ODCNTL,
+ .buf_cntl1 = KX022A_REG_BUF_CNTL1,
+ .buf_cntl2 = KX022A_REG_BUF_CNTL2,
+ .buf_clear = KX022A_REG_BUF_CLEAR,
+ .buf_status1 = KX022A_REG_BUF_STATUS_1,
+ .buf_read = KX022A_REG_BUF_READ,
+ .inc1 = KX022A_REG_INC1,
+ .inc4 = KX022A_REG_INC4,
+ .inc5 = KX022A_REG_INC5,
+ .inc6 = KX022A_REG_INC6,
+ .xout_l = KX022A_REG_XOUT_L,
+ .get_fifo_bytes_available = kx022a_get_fifo_bytes_available,
+};
+EXPORT_SYMBOL_NS_GPL(kx022a_chip_info, IIO_KX022A);
+
+const struct kx022a_chip_info kx132_chip_info = {
+ .name = "kx132-1211",
+ .regmap_config = &kx132_regmap_config,
+ .channels = kx132_channels,
+ .num_channels = ARRAY_SIZE(kx132_channels),
+ .fifo_length = KX132_FIFO_LENGTH,
+ .who = KX132_REG_WHO,
+ .id = KX132_ID,
+ .cntl = KX132_REG_CNTL,
+ .cntl2 = KX132_REG_CNTL2,
+ .odcntl = KX132_REG_ODCNTL,
+ .buf_cntl1 = KX132_REG_BUF_CNTL1,
+ .buf_cntl2 = KX132_REG_BUF_CNTL2,
+ .buf_clear = KX132_REG_BUF_CLEAR,
+ .buf_status1 = KX132_REG_BUF_STATUS_1,
+ .buf_smp_lvl_mask = KX132_MASK_BUF_SMP_LVL,
+ .buf_read = KX132_REG_BUF_READ,
+ .inc1 = KX132_REG_INC1,
+ .inc4 = KX132_REG_INC4,
+ .inc5 = KX132_REG_INC5,
+ .inc6 = KX132_REG_INC6,
+ .xout_l = KX132_REG_XOUT_L,
+ .get_fifo_bytes_available = kx132_get_fifo_bytes_available,
+};
+EXPORT_SYMBOL_NS_GPL(kx132_chip_info, IIO_KX022A);
+
+int kx022a_probe_internal(struct device *dev, const struct kx022a_chip_info *chip_info)
{
static const char * const regulator_names[] = {"io-vdd", "vdd"};
struct iio_trigger *indio_trig;
@@ -1012,6 +1215,7 @@ int kx022a_probe_internal(struct device *dev)
return -ENOMEM;
data = iio_priv(idev);
+ data->chip_info = chip_info;
/*
* VDD is the analog and digital domain voltage supply and
@@ -1022,26 +1226,24 @@ int kx022a_probe_internal(struct device *dev)
if (ret && ret != -ENODEV)
return dev_err_probe(dev, ret, "failed to enable regulator\n");
- ret = regmap_read(regmap, KX022A_REG_WHO, &chip_id);
+ ret = regmap_read(regmap, chip_info->who, &chip_id);
if (ret)
return dev_err_probe(dev, ret, "Failed to access sensor\n");
- if (chip_id != KX022A_ID) {
- dev_err(dev, "unsupported device 0x%x\n", chip_id);
- return -EINVAL;
- }
+ if (chip_id != chip_info->id)
+ dev_warn(dev, "unknown device 0x%x\n", chip_id);
irq = fwnode_irq_get_byname(fwnode, "INT1");
if (irq > 0) {
- data->inc_reg = KX022A_REG_INC1;
- data->ien_reg = KX022A_REG_INC4;
+ data->inc_reg = chip_info->inc1;
+ data->ien_reg = chip_info->inc4;
} else {
irq = fwnode_irq_get_byname(fwnode, "INT2");
if (irq < 0)
return dev_err_probe(dev, irq, "No suitable IRQ\n");
- data->inc_reg = KX022A_REG_INC5;
- data->ien_reg = KX022A_REG_INC6;
+ data->inc_reg = chip_info->inc5;
+ data->ien_reg = chip_info->inc6;
}
data->regmap = regmap;
@@ -1050,9 +1252,9 @@ int kx022a_probe_internal(struct device *dev)
data->odr_ns = KX022A_DEFAULT_PERIOD_NS;
mutex_init(&data->mutex);
- idev->channels = kx022a_channels;
- idev->num_channels = ARRAY_SIZE(kx022a_channels);
- idev->name = "kx022-accel";
+ idev->channels = chip_info->channels;
+ idev->num_channels = chip_info->num_channels;
+ idev->name = chip_info->name;
idev->info = &kx022a_info;
idev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
idev->available_scan_masks = kx022a_scan_masks;
@@ -1110,7 +1312,6 @@ int kx022a_probe_internal(struct device *dev)
if (ret)
return dev_err_probe(data->dev, ret, "Could not request IRQ\n");
-
ret = devm_iio_trigger_register(dev, indio_trig);
if (ret)
return dev_err_probe(data->dev, ret,
diff --git a/drivers/iio/accel/kionix-kx022a.h b/drivers/iio/accel/kionix-kx022a.h
index 12424649d438..35c548ae7eff 100644
--- a/drivers/iio/accel/kionix-kx022a.h
+++ b/drivers/iio/accel/kionix-kx022a.h
@@ -74,9 +74,117 @@
#define KX022A_REG_SELF_TEST 0x60
#define KX022A_MAX_REGISTER 0x60
+#define KX132_REG_WHO 0x13
+#define KX132_ID 0x3d
+
+#define KX132_FIFO_LENGTH 86
+
+#define KX132_REG_CNTL 0x1b
+#define KX132_REG_CNTL2 0x1c
+#define KX132_REG_CNTL5 0x1f
+#define KX132_MASK_RES BIT(6)
+#define KX132_GSEL_2 0x0
+#define KX132_GSEL_4 BIT(3)
+#define KX132_GSEL_8 BIT(4)
+#define KX132_GSEL_16 GENMASK(4, 3)
+
+#define KX132_REG_INS2 0x17
+#define KX132_MASK_INS2_WMI BIT(5)
+
+#define KX132_REG_XADP_L 0x02
+#define KX132_REG_XOUT_L 0x08
+#define KX132_REG_YOUT_L 0x0a
+#define KX132_REG_ZOUT_L 0x0c
+#define KX132_REG_COTR 0x12
+#define KX132_REG_TSCP 0x14
+#define KX132_REG_INT_REL 0x1a
+
+#define KX132_REG_ODCNTL 0x21
+
+#define KX132_REG_BTS_WUF_TH 0x4a
+
+#define KX132_REG_BUF_CNTL1 0x5e
+#define KX132_REG_BUF_CNTL2 0x5f
+#define KX132_REG_BUF_STATUS_1 0x60
+#define KX132_REG_BUF_STATUS_2 0x61
+#define KX132_MASK_BUF_SMP_LVL GENMASK(9, 0)
+#define KX132_REG_BUF_CLEAR 0x62
+#define KX132_REG_BUF_READ 0x63
+#define KX132_ODR_SHIFT 3
+#define KX132_FIFO_MAX_WMI_TH 86
+
+#define KX132_REG_INC1 0x22
+#define KX132_REG_INC5 0x26
+#define KX132_REG_INC6 0x27
+#define KX132_IPOL_LOW 0
+#define KX132_IPOL_HIGH KX022A_MASK_IPOL
+#define KX132_ITYP_PULSE KX022A_MASK_ITYP
+
+#define KX132_REG_INC4 0x25
+
+#define KX132_REG_SELF_TEST 0x5d
+#define KX132_MAX_REGISTER 0x76
+
struct device;
-int kx022a_probe_internal(struct device *dev);
-extern const struct regmap_config kx022a_regmap;
+struct kx022a_data;
+
+/**
+ * struct kx022a_chip_info - Kionix accelerometer chip specific information
+ *
+ * @name: name of the device
+ * @regmap_config: pointer to register map configuration
+ * @channels: pointer to iio_chan_spec array
+ * @num_channels: number of iio_chan_spec channels
+ * @fifo_length: number of 16-bit samples in a full buffer
+ * @buf_smp_lvl_mask: buffer sample level mask
+ * @who: WHO_AM_I register
+ * @id: WHO_AM_I register value
+ * @cntl: control register 1
+ * @cntl2: control register 2
+ * @odcntl: output data control register
+ * @buf_cntl1: buffer control register 1
+ * @buf_cntl2: buffer control register 2
+ * @buf_clear: buffer clear register
+ * @buf_status1: buffer status register 1
+ * @buf_read: buffer read register
+ * @inc1: interrupt control register 1
+ * @inc4: interrupt control register 4
+ * @inc5: interrupt control register 5
+ * @inc6: interrupt control register 6
+ * @xout_l: x-axis output least significant byte
+ * @get_fifo_bytes_available: function pointer to get amount of acceleration
+ * data bytes currently stored in the sensor's FIFO
+ * buffer
+ */
+struct kx022a_chip_info {
+ const char *name;
+ const struct regmap_config *regmap_config;
+ const struct iio_chan_spec *channels;
+ unsigned int num_channels;
+ unsigned int fifo_length;
+ u16 buf_smp_lvl_mask;
+ u8 who;
+ u8 id;
+ u8 cntl;
+ u8 cntl2;
+ u8 odcntl;
+ u8 buf_cntl1;
+ u8 buf_cntl2;
+ u8 buf_clear;
+ u8 buf_status1;
+ u8 buf_read;
+ u8 inc1;
+ u8 inc4;
+ u8 inc5;
+ u8 inc6;
+ u8 xout_l;
+ int (*get_fifo_bytes_available)(struct kx022a_data *);
+};
+
+int kx022a_probe_internal(struct device *dev, const struct kx022a_chip_info *chip_info);
+
+extern const struct kx022a_chip_info kx022a_chip_info;
+extern const struct kx022a_chip_info kx132_chip_info;
#endif
diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c
index f42a88711486..d3fd0318e47b 100644
--- a/drivers/iio/accel/mma8452.c
+++ b/drivers/iio/accel/mma8452.c
@@ -1535,19 +1535,18 @@ static int mma8452_reset(struct i2c_client *client)
}
static const struct of_device_id mma8452_dt_ids[] = {
+ { .compatible = "fsl,fxls8471", .data = &mma_chip_info_table[fxls8471] },
{ .compatible = "fsl,mma8451", .data = &mma_chip_info_table[mma8451] },
{ .compatible = "fsl,mma8452", .data = &mma_chip_info_table[mma8452] },
{ .compatible = "fsl,mma8453", .data = &mma_chip_info_table[mma8453] },
{ .compatible = "fsl,mma8652", .data = &mma_chip_info_table[mma8652] },
{ .compatible = "fsl,mma8653", .data = &mma_chip_info_table[mma8653] },
- { .compatible = "fsl,fxls8471", .data = &mma_chip_info_table[fxls8471] },
{ }
};
MODULE_DEVICE_TABLE(of, mma8452_dt_ids);
static int mma8452_probe(struct i2c_client *client)
{
- const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct mma8452_data *data;
struct iio_dev *indio_dev;
int ret;
@@ -1560,15 +1559,10 @@ static int mma8452_probe(struct i2c_client *client)
data->client = client;
mutex_init(&data->lock);
- data->chip_info = device_get_match_data(&client->dev);
- if (!data->chip_info) {
- if (id) {
- data->chip_info = &mma_chip_info_table[id->driver_data];
- } else {
- dev_err(&client->dev, "unknown device model\n");
- return -ENODEV;
- }
- }
+ data->chip_info = i2c_get_match_data(client);
+ if (!data->chip_info)
+ return dev_err_probe(&client->dev, -ENODEV,
+ "unknown device model\n");
ret = iio_read_mount_matrix(&client->dev, &data->orientation);
if (ret)
@@ -1830,12 +1824,12 @@ static const struct dev_pm_ops mma8452_pm_ops = {
};
static const struct i2c_device_id mma8452_id[] = {
- { "mma8451", mma8451 },
- { "mma8452", mma8452 },
- { "mma8453", mma8453 },
- { "mma8652", mma8652 },
- { "mma8653", mma8653 },
- { "fxls8471", fxls8471 },
+ { "fxls8471", (kernel_ulong_t)&mma_chip_info_table[fxls8471] },
+ { "mma8451", (kernel_ulong_t)&mma_chip_info_table[mma8451] },
+ { "mma8452", (kernel_ulong_t)&mma_chip_info_table[mma8452] },
+ { "mma8453", (kernel_ulong_t)&mma_chip_info_table[mma8453] },
+ { "mma8652", (kernel_ulong_t)&mma_chip_info_table[mma8652] },
+ { "mma8653", (kernel_ulong_t)&mma_chip_info_table[mma8653] },
{ }
};
MODULE_DEVICE_TABLE(i2c, mma8452_id);
diff --git a/drivers/iio/accel/msa311.c b/drivers/iio/accel/msa311.c
index 6ddcc3c2f840..b8ddbfd98f11 100644
--- a/drivers/iio/accel/msa311.c
+++ b/drivers/iio/accel/msa311.c
@@ -33,7 +33,7 @@
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
-#include <linux/string_helpers.h>
+#include <linux/string_choices.h>
#include <linux/units.h>
#include <linux/iio/buffer.h>
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 517b3db114b8..35f9867da12c 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -607,6 +607,16 @@ config LPC32XX_ADC
activate only one via device tree selection. Provides direct access
via sysfs.
+config LTC2309
+ tristate "Linear Technology LTC2309 ADC driver"
+ depends on I2C
+ help
+ Say yes here to build support for Linear Technology LTC2309, a low
+ noise, low power, 8-channel, 12-bit SAR ADC
+
+ This driver can also be built as a module. If so, the module will
+ be called ltc2309.
+
config LTC2471
tristate "Linear Technology LTC2471 and LTC2473 ADC driver"
depends on I2C
@@ -779,14 +789,29 @@ config MCP3422
This driver can also be built as a module. If so, the module will be
called mcp3422.
+config MCP3564
+ tristate "Microchip Technology MCP3461/2/4/R, MCP3561/2/4/R driver"
+ depends on SPI
+ depends on IIO
+ help
+ Say yes here to build support for Microchip Technology's MCP3461,
+ MCP3462, MCP3464, MCP3461R, MCP3462R, MCP3464R, MCP3561, MCP3562,
+ MCP3564, MCP3561R, MCP3562R and MCP3564R analog to digital
+ converters.
+
+ This driver can also be built as a module. If so, the module will be
+ called mcp3564.
+
config MCP3911
tristate "Microchip Technology MCP3911 driver"
depends on SPI
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
- Say yes here to build support for Microchip Technology's MCP3911
- analog to digital converter.
+ Say yes here to build support for one of the following
+ Microchip Technology's analog to digital converters:
+ MCP3910, MCP3911, MCP3912, MCP3913, MCP3914,
+ MCP3918 and MCP3919.
This driver can also be built as a module. If so, the module will be
called mcp3911.
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 2facf979327d..bee11d442af4 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_INTEL_MRFLD_ADC) += intel_mrfld_adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
+obj-$(CONFIG_LTC2309) += ltc2309.o
obj-$(CONFIG_LTC2471) += ltc2471.o
obj-$(CONFIG_LTC2485) += ltc2485.o
obj-$(CONFIG_LTC2496) += ltc2496.o ltc2497-core.o
@@ -71,6 +72,7 @@ obj-$(CONFIG_MAX77541_ADC) += max77541-adc.o
obj-$(CONFIG_MAX9611) += max9611.o
obj-$(CONFIG_MCP320X) += mcp320x.o
obj-$(CONFIG_MCP3422) += mcp3422.o
+obj-$(CONFIG_MCP3564) += mcp3564.o
obj-$(CONFIG_MCP3911) += mcp3911.o
obj-$(CONFIG_MEDIATEK_MT6360_ADC) += mt6360-adc.o
obj-$(CONFIG_MEDIATEK_MT6370_ADC) += mt6370-adc.o
diff --git a/drivers/iio/adc/ab8500-gpadc.c b/drivers/iio/adc/ab8500-gpadc.c
index 3b1bdd0b531d..80645fee79a4 100644
--- a/drivers/iio/adc/ab8500-gpadc.c
+++ b/drivers/iio/adc/ab8500-gpadc.c
@@ -1179,7 +1179,7 @@ out_dis_pm:
return ret;
}
-static int ab8500_gpadc_remove(struct platform_device *pdev)
+static void ab8500_gpadc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct ab8500_gpadc *gpadc = iio_priv(indio_dev);
@@ -1188,8 +1188,6 @@ static int ab8500_gpadc_remove(struct platform_device *pdev)
pm_runtime_put_noidle(gpadc->dev);
pm_runtime_disable(gpadc->dev);
regulator_disable(gpadc->vddadc);
-
- return 0;
}
static DEFINE_RUNTIME_DEV_PM_OPS(ab8500_gpadc_pm_ops,
@@ -1198,7 +1196,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(ab8500_gpadc_pm_ops,
static struct platform_driver ab8500_gpadc_driver = {
.probe = ab8500_gpadc_probe,
- .remove = ab8500_gpadc_remove,
+ .remove_new = ab8500_gpadc_remove,
.driver = {
.name = "ab8500-gpadc",
.pm = pm_ptr(&ab8500_gpadc_pm_ops),
diff --git a/drivers/iio/adc/ad4130.c b/drivers/iio/adc/ad4130.c
index 5a5dd5e87ffc..feb86fe6c422 100644
--- a/drivers/iio/adc/ad4130.c
+++ b/drivers/iio/adc/ad4130.c
@@ -1817,18 +1817,12 @@ static const struct clk_ops ad4130_int_clk_ops = {
.unprepare = ad4130_int_clk_unprepare,
};
-static void ad4130_clk_del_provider(void *of_node)
-{
- of_clk_del_provider(of_node);
-}
-
static int ad4130_setup_int_clk(struct ad4130_state *st)
{
struct device *dev = &st->spi->dev;
struct device_node *of_node = dev_of_node(dev);
struct clk_init_data init;
const char *clk_name;
- struct clk *clk;
int ret;
if (st->int_pin_sel == AD4130_INT_PIN_CLK ||
@@ -1845,15 +1839,12 @@ static int ad4130_setup_int_clk(struct ad4130_state *st)
init.ops = &ad4130_int_clk_ops;
st->int_clk_hw.init = &init;
- clk = devm_clk_register(dev, &st->int_clk_hw);
- if (IS_ERR(clk))
- return PTR_ERR(clk);
-
- ret = of_clk_add_provider(of_node, of_clk_src_simple_get, clk);
+ ret = devm_clk_hw_register(dev, &st->int_clk_hw);
if (ret)
return ret;
- return devm_add_action_or_reset(dev, ad4130_clk_del_provider, of_node);
+ return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
+ &st->int_clk_hw);
}
static int ad4130_setup(struct iio_dev *indio_dev)
diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index df67b63ccf69..d7fd21e7c6e2 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -2486,7 +2486,7 @@ reg_disable:
return ret;
}
-static int at91_adc_remove(struct platform_device *pdev)
+static void at91_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct at91_adc_state *st = iio_priv(indio_dev);
@@ -2501,8 +2501,6 @@ static int at91_adc_remove(struct platform_device *pdev)
regulator_disable(st->vref);
regulator_disable(st->reg);
-
- return 0;
}
static int at91_adc_suspend(struct device *dev)
@@ -2627,7 +2625,7 @@ MODULE_DEVICE_TABLE(of, at91_adc_dt_match);
static struct platform_driver at91_adc_driver = {
.probe = at91_adc_probe,
- .remove = at91_adc_remove,
+ .remove_new = at91_adc_remove,
.driver = {
.name = "at91-sama5d2_adc",
.of_match_table = at91_adc_dt_match,
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index de6650f9c4b1..eb501e3c86a5 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -1013,28 +1013,25 @@ static int at91_adc_probe(struct platform_device *pdev)
st->use_external = of_property_read_bool(node, "atmel,adc-use-external-triggers");
- if (of_property_read_u32(node, "atmel,adc-channels-used", &prop)) {
- dev_err(&idev->dev, "Missing adc-channels-used property in the DT.\n");
- return -EINVAL;
- }
+ if (of_property_read_u32(node, "atmel,adc-channels-used", &prop))
+ return dev_err_probe(&idev->dev, -EINVAL,
+ "Missing adc-channels-used property in the DT.\n");
st->channels_mask = prop;
st->sleep_mode = of_property_read_bool(node, "atmel,adc-sleep-mode");
- if (of_property_read_u32(node, "atmel,adc-startup-time", &prop)) {
- dev_err(&idev->dev, "Missing adc-startup-time property in the DT.\n");
- return -EINVAL;
- }
+ if (of_property_read_u32(node, "atmel,adc-startup-time", &prop))
+ return dev_err_probe(&idev->dev, -EINVAL,
+ "Missing adc-startup-time property in the DT.\n");
st->startup_time = prop;
prop = 0;
of_property_read_u32(node, "atmel,adc-sample-hold-time", &prop);
st->sample_hold_time = prop;
- if (of_property_read_u32(node, "atmel,adc-vref", &prop)) {
- dev_err(&idev->dev, "Missing adc-vref property in the DT.\n");
- return -EINVAL;
- }
+ if (of_property_read_u32(node, "atmel,adc-vref", &prop))
+ return dev_err_probe(&idev->dev, -EINVAL,
+ "Missing adc-vref property in the DT.\n");
st->vref_mv = prop;
st->res = st->caps->high_res_bits;
@@ -1069,7 +1066,6 @@ static int at91_adc_probe(struct platform_device *pdev)
if (IS_ERR(st->reg_base))
return PTR_ERR(st->reg_base);
-
/*
* Disable all IRQs before setting up the handler
*/
@@ -1077,43 +1073,26 @@ static int at91_adc_probe(struct platform_device *pdev)
at91_adc_writel(st, AT91_ADC_IDR, 0xFFFFFFFF);
if (st->caps->has_tsmr)
- ret = request_irq(st->irq, at91_adc_9x5_interrupt, 0,
- pdev->dev.driver->name, idev);
+ ret = devm_request_irq(&pdev->dev, st->irq,
+ at91_adc_9x5_interrupt, 0,
+ pdev->dev.driver->name, idev);
else
- ret = request_irq(st->irq, at91_adc_rl_interrupt, 0,
- pdev->dev.driver->name, idev);
- if (ret) {
- dev_err(&pdev->dev, "Failed to allocate IRQ.\n");
- return ret;
- }
-
- st->clk = devm_clk_get(&pdev->dev, "adc_clk");
- if (IS_ERR(st->clk)) {
- dev_err(&pdev->dev, "Failed to get the clock.\n");
- ret = PTR_ERR(st->clk);
- goto error_free_irq;
- }
-
- ret = clk_prepare_enable(st->clk);
- if (ret) {
- dev_err(&pdev->dev,
- "Could not prepare or enable the clock.\n");
- goto error_free_irq;
- }
+ ret = devm_request_irq(&pdev->dev, st->irq,
+ at91_adc_rl_interrupt, 0,
+ pdev->dev.driver->name, idev);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to allocate IRQ.\n");
- st->adc_clk = devm_clk_get(&pdev->dev, "adc_op_clk");
- if (IS_ERR(st->adc_clk)) {
- dev_err(&pdev->dev, "Failed to get the ADC clock.\n");
- ret = PTR_ERR(st->adc_clk);
- goto error_disable_clk;
- }
+ st->clk = devm_clk_get_enabled(&pdev->dev, "adc_clk");
+ if (IS_ERR(st->clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(st->clk),
+ "Could not prepare or enable the clock.\n");
- ret = clk_prepare_enable(st->adc_clk);
- if (ret) {
- dev_err(&pdev->dev,
- "Could not prepare or enable the ADC clock.\n");
- goto error_disable_clk;
- }
+ st->adc_clk = devm_clk_get_enabled(&pdev->dev, "adc_op_clk");
+ if (IS_ERR(st->adc_clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(st->adc_clk),
+ "Could not prepare or enable the ADC clock.\n");
/*
* Prescaler rate computation using the formula from the Atmel's
@@ -1129,11 +1108,9 @@ static int at91_adc_probe(struct platform_device *pdev)
prsc = (mstrclk / (2 * adc_clk)) - 1;
- if (!st->startup_time) {
- dev_err(&pdev->dev, "No startup time available.\n");
- ret = -EINVAL;
- goto error_disable_adc_clk;
- }
+ if (!st->startup_time)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "No startup time available.\n");
ticks = (*st->caps->calc_startup_ticks)(st->startup_time, adc_clk_khz);
/*
@@ -1158,10 +1135,9 @@ static int at91_adc_probe(struct platform_device *pdev)
/* Setup the ADC channels available on the board */
ret = at91_adc_channel_init(idev);
- if (ret < 0) {
- dev_err(&pdev->dev, "Couldn't initialize the channels.\n");
- goto error_disable_adc_clk;
- }
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret,
+ "Couldn't initialize the channels.\n");
init_waitqueue_head(&st->wq_data_avail);
mutex_init(&st->lock);
@@ -1173,21 +1149,20 @@ static int at91_adc_probe(struct platform_device *pdev)
*/
if (!st->touchscreen_type) {
ret = at91_adc_buffer_init(idev);
- if (ret < 0) {
- dev_err(&pdev->dev, "Couldn't initialize the buffer.\n");
- goto error_disable_adc_clk;
- }
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret,
+ "Couldn't initialize the buffer.\n");
ret = at91_adc_trigger_init(idev);
if (ret < 0) {
dev_err(&pdev->dev, "Couldn't setup the triggers.\n");
at91_adc_buffer_remove(idev);
- goto error_disable_adc_clk;
+ return ret;
}
} else {
ret = at91_ts_register(idev, pdev);
if (ret)
- goto error_disable_adc_clk;
+ return ret;
at91_ts_hw_init(idev, adc_clk_khz);
}
@@ -1207,16 +1182,10 @@ error_iio_device_register:
} else {
at91_ts_unregister(st);
}
-error_disable_adc_clk:
- clk_disable_unprepare(st->adc_clk);
-error_disable_clk:
- clk_disable_unprepare(st->clk);
-error_free_irq:
- free_irq(st->irq, idev);
return ret;
}
-static int at91_adc_remove(struct platform_device *pdev)
+static void at91_adc_remove(struct platform_device *pdev)
{
struct iio_dev *idev = platform_get_drvdata(pdev);
struct at91_adc_state *st = iio_priv(idev);
@@ -1228,11 +1197,6 @@ static int at91_adc_remove(struct platform_device *pdev)
} else {
at91_ts_unregister(st);
}
- clk_disable_unprepare(st->adc_clk);
- clk_disable_unprepare(st->clk);
- free_irq(st->irq, idev);
-
- return 0;
}
static int at91_adc_suspend(struct device *dev)
@@ -1382,7 +1346,7 @@ MODULE_DEVICE_TABLE(of, at91_adc_dt_ids);
static struct platform_driver at91_adc_driver = {
.probe = at91_adc_probe,
- .remove = at91_adc_remove,
+ .remove_new = at91_adc_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = at91_adc_dt_ids,
diff --git a/drivers/iio/adc/axp20x_adc.c b/drivers/iio/adc/axp20x_adc.c
index 75bda94dbce1..d6c51b0f48e3 100644
--- a/drivers/iio/adc/axp20x_adc.c
+++ b/drivers/iio/adc/axp20x_adc.c
@@ -745,7 +745,7 @@ fail_map:
return ret;
}
-static int axp20x_remove(struct platform_device *pdev)
+static void axp20x_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct axp20x_adc_iio *info = iio_priv(indio_dev);
@@ -757,8 +757,6 @@ static int axp20x_remove(struct platform_device *pdev)
if (info->data->adc_en2_mask)
regmap_write(info->regmap, AXP20X_ADC_EN2, 0);
-
- return 0;
}
static struct platform_driver axp20x_adc_driver = {
@@ -768,7 +766,7 @@ static struct platform_driver axp20x_adc_driver = {
},
.id_table = axp20x_adc_id_match,
.probe = axp20x_probe,
- .remove = axp20x_remove,
+ .remove_new = axp20x_remove,
};
module_platform_driver(axp20x_adc_driver);
diff --git a/drivers/iio/adc/bcm_iproc_adc.c b/drivers/iio/adc/bcm_iproc_adc.c
index 0d6885413a7e..5bc514bd5ebc 100644
--- a/drivers/iio/adc/bcm_iproc_adc.c
+++ b/drivers/iio/adc/bcm_iproc_adc.c
@@ -594,7 +594,7 @@ err_adc_enable:
return ret;
}
-static int iproc_adc_remove(struct platform_device *pdev)
+static void iproc_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct iproc_adc_priv *adc_priv = iio_priv(indio_dev);
@@ -602,8 +602,6 @@ static int iproc_adc_remove(struct platform_device *pdev)
iio_device_unregister(indio_dev);
iproc_adc_disable(indio_dev);
clk_disable_unprepare(adc_priv->adc_clk);
-
- return 0;
}
static const struct of_device_id iproc_adc_of_match[] = {
@@ -614,7 +612,7 @@ MODULE_DEVICE_TABLE(of, iproc_adc_of_match);
static struct platform_driver iproc_adc_driver = {
.probe = iproc_adc_probe,
- .remove = iproc_adc_remove,
+ .remove_new = iproc_adc_remove,
.driver = {
.name = "iproc-static-adc",
.of_match_table = iproc_adc_of_match,
diff --git a/drivers/iio/adc/dln2-adc.c b/drivers/iio/adc/dln2-adc.c
index 97d162a3cba4..06cfbbabaf8d 100644
--- a/drivers/iio/adc/dln2-adc.c
+++ b/drivers/iio/adc/dln2-adc.c
@@ -691,19 +691,18 @@ unregister_event:
return ret;
}
-static int dln2_adc_remove(struct platform_device *pdev)
+static void dln2_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
iio_device_unregister(indio_dev);
dln2_unregister_event_cb(pdev, DLN2_ADC_CONDITION_MET_EV);
- return 0;
}
static struct platform_driver dln2_adc_driver = {
.driver.name = DLN2_ADC_MOD_NAME,
.probe = dln2_adc_probe,
- .remove = dln2_adc_remove,
+ .remove_new = dln2_adc_remove,
};
module_platform_driver(dln2_adc_driver);
diff --git a/drivers/iio/adc/ep93xx_adc.c b/drivers/iio/adc/ep93xx_adc.c
index a35e6cead67d..971942ce4c66 100644
--- a/drivers/iio/adc/ep93xx_adc.c
+++ b/drivers/iio/adc/ep93xx_adc.c
@@ -217,15 +217,13 @@ static int ep93xx_adc_probe(struct platform_device *pdev)
return ret;
}
-static int ep93xx_adc_remove(struct platform_device *pdev)
+static void ep93xx_adc_remove(struct platform_device *pdev)
{
struct iio_dev *iiodev = platform_get_drvdata(pdev);
struct ep93xx_adc_priv *priv = iio_priv(iiodev);
iio_device_unregister(iiodev);
clk_disable_unprepare(priv->clk);
-
- return 0;
}
static const struct of_device_id ep93xx_adc_of_ids[] = {
@@ -240,7 +238,7 @@ static struct platform_driver ep93xx_adc_driver = {
.of_match_table = ep93xx_adc_of_ids,
},
.probe = ep93xx_adc_probe,
- .remove = ep93xx_adc_remove,
+ .remove_new = ep93xx_adc_remove,
};
module_platform_driver(ep93xx_adc_driver);
diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
index cff1ba57fb16..eb7a2dd59517 100644
--- a/drivers/iio/adc/exynos_adc.c
+++ b/drivers/iio/adc/exynos_adc.c
@@ -946,7 +946,7 @@ err_disable_reg:
return ret;
}
-static int exynos_adc_remove(struct platform_device *pdev)
+static void exynos_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct exynos_adc *info = iio_priv(indio_dev);
@@ -964,8 +964,6 @@ static int exynos_adc_remove(struct platform_device *pdev)
exynos_adc_disable_clk(info);
exynos_adc_unprepare_clk(info);
regulator_disable(info->vdd);
-
- return 0;
}
static int exynos_adc_suspend(struct device *dev)
@@ -1006,7 +1004,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(exynos_adc_pm_ops, exynos_adc_suspend,
static struct platform_driver exynos_adc_driver = {
.probe = exynos_adc_probe,
- .remove = exynos_adc_remove,
+ .remove_new = exynos_adc_remove,
.driver = {
.name = "exynos-adc",
.of_match_table = exynos_adc_match,
diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c
index 551e83ae573c..68c813de0605 100644
--- a/drivers/iio/adc/fsl-imx25-gcq.c
+++ b/drivers/iio/adc/fsl-imx25-gcq.c
@@ -384,7 +384,7 @@ err_regulator_disable:
return ret;
}
-static int mx25_gcq_remove(struct platform_device *pdev)
+static void mx25_gcq_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct mx25_gcq_priv *priv = iio_priv(indio_dev);
@@ -397,8 +397,6 @@ static int mx25_gcq_remove(struct platform_device *pdev)
if (priv->vref[i])
regulator_disable(priv->vref[i]);
}
-
- return 0;
}
static const struct of_device_id mx25_gcq_ids[] = {
@@ -413,7 +411,7 @@ static struct platform_driver mx25_gcq_driver = {
.of_match_table = mx25_gcq_ids,
},
.probe = mx25_gcq_probe,
- .remove = mx25_gcq_remove,
+ .remove_new = mx25_gcq_remove,
};
module_platform_driver(mx25_gcq_driver);
diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
index f7ee856a6b8b..c80c55fb8c6c 100644
--- a/drivers/iio/adc/hx711.c
+++ b/drivers/iio/adc/hx711.c
@@ -580,7 +580,7 @@ error_regulator:
return ret;
}
-static int hx711_remove(struct platform_device *pdev)
+static void hx711_remove(struct platform_device *pdev)
{
struct hx711_data *hx711_data;
struct iio_dev *indio_dev;
@@ -593,8 +593,6 @@ static int hx711_remove(struct platform_device *pdev)
iio_triggered_buffer_cleanup(indio_dev);
regulator_disable(hx711_data->reg_avdd);
-
- return 0;
}
static const struct of_device_id of_hx711_match[] = {
@@ -606,7 +604,7 @@ MODULE_DEVICE_TABLE(of, of_hx711_match);
static struct platform_driver hx711_driver = {
.probe = hx711_probe,
- .remove = hx711_remove,
+ .remove_new = hx711_remove,
.driver = {
.name = "hx711-gpio",
.of_match_table = of_hx711_match,
diff --git a/drivers/iio/adc/imx8qxp-adc.c b/drivers/iio/adc/imx8qxp-adc.c
index f5a0fc9e64c5..a180c6974d5b 100644
--- a/drivers/iio/adc/imx8qxp-adc.c
+++ b/drivers/iio/adc/imx8qxp-adc.c
@@ -404,7 +404,7 @@ error_regulator_disable:
return ret;
}
-static int imx8qxp_adc_remove(struct platform_device *pdev)
+static void imx8qxp_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct imx8qxp_adc *adc = iio_priv(indio_dev);
@@ -422,8 +422,6 @@ static int imx8qxp_adc_remove(struct platform_device *pdev)
pm_runtime_disable(dev);
pm_runtime_put_noidle(dev);
-
- return 0;
}
static int imx8qxp_adc_runtime_suspend(struct device *dev)
@@ -489,7 +487,7 @@ MODULE_DEVICE_TABLE(of, imx8qxp_adc_match);
static struct platform_driver imx8qxp_adc_driver = {
.probe = imx8qxp_adc_probe,
- .remove = imx8qxp_adc_remove,
+ .remove_new = imx8qxp_adc_remove,
.driver = {
.name = ADC_DRIVER_NAME,
.of_match_table = imx8qxp_adc_match,
diff --git a/drivers/iio/adc/imx93_adc.c b/drivers/iio/adc/imx93_adc.c
index dce9ec91e4a7..9bb1e4ba1aee 100644
--- a/drivers/iio/adc/imx93_adc.c
+++ b/drivers/iio/adc/imx93_adc.c
@@ -392,7 +392,7 @@ error_regulator_disable:
return ret;
}
-static int imx93_adc_remove(struct platform_device *pdev)
+static void imx93_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct imx93_adc *adc = iio_priv(indio_dev);
@@ -410,8 +410,6 @@ static int imx93_adc_remove(struct platform_device *pdev)
free_irq(adc->irq, adc);
clk_disable_unprepare(adc->ipg_clk);
regulator_disable(adc->vref);
-
- return 0;
}
static int imx93_adc_runtime_suspend(struct device *dev)
@@ -468,7 +466,7 @@ MODULE_DEVICE_TABLE(of, imx93_adc_match);
static struct platform_driver imx93_adc_driver = {
.probe = imx93_adc_probe,
- .remove = imx93_adc_remove,
+ .remove_new = imx93_adc_remove,
.driver = {
.name = IMX93_ADC_DRIVER_NAME,
.of_match_table = imx93_adc_match,
diff --git a/drivers/iio/adc/ltc2309.c b/drivers/iio/adc/ltc2309.c
new file mode 100644
index 000000000000..8b3a89c1b840
--- /dev/null
+++ b/drivers/iio/adc/ltc2309.c
@@ -0,0 +1,246 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * The LTC2309 is an 8-Channel, 12-Bit SAR ADC with an I2C Interface.
+ *
+ * Datasheet:
+ * https://www.analog.com/media/en/technical-documentation/data-sheets/2309fd.pdf
+ *
+ * Copyright (c) 2023, Liam Beguin <liambeguin@gmail.com>
+ */
+#include <linux/bitfield.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
+
+#define LTC2309_ADC_RESOLUTION 12
+
+#define LTC2309_DIN_CH_MASK GENMASK(7, 4)
+#define LTC2309_DIN_SDN BIT(7)
+#define LTC2309_DIN_OSN BIT(6)
+#define LTC2309_DIN_S1 BIT(5)
+#define LTC2309_DIN_S0 BIT(4)
+#define LTC2309_DIN_UNI BIT(3)
+#define LTC2309_DIN_SLEEP BIT(2)
+
+/**
+ * struct ltc2309 - internal device data structure
+ * @dev: Device reference
+ * @client: I2C reference
+ * @vref: External reference source
+ * @lock: Lock to serialize data access
+ * @vref_mv: Internal voltage reference
+ */
+struct ltc2309 {
+ struct device *dev;
+ struct i2c_client *client;
+ struct regulator *vref;
+ struct mutex lock; /* serialize data access */
+ int vref_mv;
+};
+
+/* Order matches expected channel address, See datasheet Table 1. */
+enum ltc2309_channels {
+ LTC2309_CH0_CH1 = 0,
+ LTC2309_CH2_CH3,
+ LTC2309_CH4_CH5,
+ LTC2309_CH6_CH7,
+ LTC2309_CH1_CH0,
+ LTC2309_CH3_CH2,
+ LTC2309_CH5_CH4,
+ LTC2309_CH7_CH6,
+ LTC2309_CH0,
+ LTC2309_CH2,
+ LTC2309_CH4,
+ LTC2309_CH6,
+ LTC2309_CH1,
+ LTC2309_CH3,
+ LTC2309_CH5,
+ LTC2309_CH7,
+};
+
+#define LTC2309_CHAN(_chan, _addr) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .address = _addr, \
+ .channel = _chan, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+}
+
+#define LTC2309_DIFF_CHAN(_chan, _chan2, _addr) { \
+ .type = IIO_VOLTAGE, \
+ .differential = 1, \
+ .indexed = 1, \
+ .address = _addr, \
+ .channel = _chan, \
+ .channel2 = _chan2, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+}
+
+static const struct iio_chan_spec ltc2309_channels[] = {
+ LTC2309_CHAN(0, LTC2309_CH0),
+ LTC2309_CHAN(1, LTC2309_CH1),
+ LTC2309_CHAN(2, LTC2309_CH2),
+ LTC2309_CHAN(3, LTC2309_CH3),
+ LTC2309_CHAN(4, LTC2309_CH4),
+ LTC2309_CHAN(5, LTC2309_CH5),
+ LTC2309_CHAN(6, LTC2309_CH6),
+ LTC2309_CHAN(7, LTC2309_CH7),
+ LTC2309_DIFF_CHAN(0, 1, LTC2309_CH0_CH1),
+ LTC2309_DIFF_CHAN(2, 3, LTC2309_CH2_CH3),
+ LTC2309_DIFF_CHAN(4, 5, LTC2309_CH4_CH5),
+ LTC2309_DIFF_CHAN(6, 7, LTC2309_CH6_CH7),
+ LTC2309_DIFF_CHAN(1, 0, LTC2309_CH1_CH0),
+ LTC2309_DIFF_CHAN(3, 2, LTC2309_CH3_CH2),
+ LTC2309_DIFF_CHAN(5, 4, LTC2309_CH5_CH4),
+ LTC2309_DIFF_CHAN(7, 6, LTC2309_CH7_CH6),
+};
+
+static int ltc2309_read_raw_channel(struct ltc2309 *ltc2309,
+ unsigned long address, int *val)
+{
+ int ret;
+ u16 buf;
+ u8 din;
+
+ din = FIELD_PREP(LTC2309_DIN_CH_MASK, address & 0x0f) |
+ FIELD_PREP(LTC2309_DIN_UNI, 1) |
+ FIELD_PREP(LTC2309_DIN_SLEEP, 0);
+
+ ret = i2c_smbus_write_byte(ltc2309->client, din);
+ if (ret < 0) {
+ dev_err(ltc2309->dev, "i2c command failed: %pe\n",
+ ERR_PTR(ret));
+ return ret;
+ }
+
+ ret = i2c_master_recv(ltc2309->client, (char *)&buf, 2);
+ if (ret < 0) {
+ dev_err(ltc2309->dev, "i2c read failed: %pe\n", ERR_PTR(ret));
+ return ret;
+ }
+
+ *val = be16_to_cpu(buf) >> 4;
+
+ return ret;
+}
+
+static int ltc2309_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ struct ltc2309 *ltc2309 = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ mutex_lock(&ltc2309->lock);
+ ret = ltc2309_read_raw_channel(ltc2309, chan->address, val);
+ mutex_unlock(&ltc2309->lock);
+ if (ret < 0)
+ return -EINVAL;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = ltc2309->vref_mv;
+ *val2 = LTC2309_ADC_RESOLUTION;
+ return IIO_VAL_FRACTIONAL_LOG2;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info ltc2309_info = {
+ .read_raw = ltc2309_read_raw,
+};
+
+static void ltc2309_regulator_disable(void *regulator)
+{
+ regulator_disable(regulator);
+}
+
+static int ltc2309_probe(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev;
+ struct ltc2309 *ltc2309;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*ltc2309));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ ltc2309 = iio_priv(indio_dev);
+ ltc2309->dev = &indio_dev->dev;
+ ltc2309->client = client;
+ ltc2309->vref_mv = 4096; /* Default to the internal ref */
+
+ indio_dev->name = "ltc2309";
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = ltc2309_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ltc2309_channels);
+ indio_dev->info = &ltc2309_info;
+
+ ltc2309->vref = devm_regulator_get_optional(&client->dev, "vref");
+ if (IS_ERR(ltc2309->vref)) {
+ ret = PTR_ERR(ltc2309->vref);
+ if (ret == -ENODEV)
+ ltc2309->vref = NULL;
+ else
+ return ret;
+ }
+
+ if (ltc2309->vref) {
+ ret = regulator_enable(ltc2309->vref);
+ if (ret)
+ return dev_err_probe(ltc2309->dev, ret,
+ "failed to enable vref\n");
+
+ ret = devm_add_action_or_reset(ltc2309->dev,
+ ltc2309_regulator_disable,
+ ltc2309->vref);
+ if (ret) {
+ return dev_err_probe(ltc2309->dev, ret,
+ "failed to add regulator_disable action: %d\n",
+ ret);
+ }
+
+ ret = regulator_get_voltage(ltc2309->vref);
+ if (ret < 0)
+ return ret;
+
+ ltc2309->vref_mv = ret / 1000;
+ }
+
+ mutex_init(&ltc2309->lock);
+
+ return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct of_device_id ltc2309_of_match[] = {
+ { .compatible = "lltc,ltc2309" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ltc2309_of_match);
+
+static const struct i2c_device_id ltc2309_id[] = {
+ { "ltc2309" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ltc2309_id);
+
+static struct i2c_driver ltc2309_driver = {
+ .driver = {
+ .name = "ltc2309",
+ .of_match_table = ltc2309_of_match,
+ },
+ .probe = ltc2309_probe,
+ .id_table = ltc2309_id,
+};
+module_i2c_driver(ltc2309_driver);
+
+MODULE_AUTHOR("Liam Beguin <liambeguin@gmail.com>");
+MODULE_DESCRIPTION("Linear Technology LTC2309 ADC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/ltc2497.c b/drivers/iio/adc/ltc2497.c
index 5bdd40729611..6401a7727c31 100644
--- a/drivers/iio/adc/ltc2497.c
+++ b/drivers/iio/adc/ltc2497.c
@@ -95,7 +95,6 @@ static int ltc2497_result_and_measure(struct ltc2497core_driverdata *ddata,
static int ltc2497_probe(struct i2c_client *client)
{
- const struct i2c_device_id *id = i2c_client_get_device_id(client);
const struct ltc2497_chip_info *chip_info;
struct iio_dev *indio_dev;
struct ltc2497_driverdata *st;
@@ -115,9 +114,7 @@ static int ltc2497_probe(struct i2c_client *client)
st->client = client;
st->common_ddata.result_and_measure = ltc2497_result_and_measure;
- chip_info = device_get_match_data(dev);
- if (!chip_info)
- chip_info = (const struct ltc2497_chip_info *)id->driver_data;
+ chip_info = i2c_get_match_data(client);
st->common_ddata.chip_info = chip_info;
resolution = chip_info->resolution;
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c
index b31581616ce3..7c2a98b8c3a9 100644
--- a/drivers/iio/adc/max1363.c
+++ b/drivers/iio/adc/max1363.c
@@ -1599,9 +1599,7 @@ static int max1363_probe(struct i2c_client *client)
if (ret)
return ret;
- st->chip_info = device_get_match_data(&client->dev);
- if (!st->chip_info)
- st->chip_info = &max1363_chip_info_tbl[id->driver_data];
+ st->chip_info = i2c_get_match_data(client);
st->client = client;
st->vref_uv = st->chip_info->int_vref_mv * 1000;
@@ -1669,46 +1667,51 @@ static int max1363_probe(struct i2c_client *client)
return devm_iio_device_register(&client->dev, indio_dev);
}
+#define MAX1363_ID_TABLE(_name, cfg) { \
+ .name = _name, \
+ .driver_data = (kernel_ulong_t)&max1363_chip_info_tbl[cfg], \
+}
+
static const struct i2c_device_id max1363_id[] = {
- { "max1361", max1361 },
- { "max1362", max1362 },
- { "max1363", max1363 },
- { "max1364", max1364 },
- { "max1036", max1036 },
- { "max1037", max1037 },
- { "max1038", max1038 },
- { "max1039", max1039 },
- { "max1136", max1136 },
- { "max1137", max1137 },
- { "max1138", max1138 },
- { "max1139", max1139 },
- { "max1236", max1236 },
- { "max1237", max1237 },
- { "max1238", max1238 },
- { "max1239", max1239 },
- { "max11600", max11600 },
- { "max11601", max11601 },
- { "max11602", max11602 },
- { "max11603", max11603 },
- { "max11604", max11604 },
- { "max11605", max11605 },
- { "max11606", max11606 },
- { "max11607", max11607 },
- { "max11608", max11608 },
- { "max11609", max11609 },
- { "max11610", max11610 },
- { "max11611", max11611 },
- { "max11612", max11612 },
- { "max11613", max11613 },
- { "max11614", max11614 },
- { "max11615", max11615 },
- { "max11616", max11616 },
- { "max11617", max11617 },
- { "max11644", max11644 },
- { "max11645", max11645 },
- { "max11646", max11646 },
- { "max11647", max11647 },
- {}
+ MAX1363_ID_TABLE("max1361", max1361),
+ MAX1363_ID_TABLE("max1362", max1362),
+ MAX1363_ID_TABLE("max1363", max1363),
+ MAX1363_ID_TABLE("max1364", max1364),
+ MAX1363_ID_TABLE("max1036", max1036),
+ MAX1363_ID_TABLE("max1037", max1037),
+ MAX1363_ID_TABLE("max1038", max1038),
+ MAX1363_ID_TABLE("max1039", max1039),
+ MAX1363_ID_TABLE("max1136", max1136),
+ MAX1363_ID_TABLE("max1137", max1137),
+ MAX1363_ID_TABLE("max1138", max1138),
+ MAX1363_ID_TABLE("max1139", max1139),
+ MAX1363_ID_TABLE("max1236", max1236),
+ MAX1363_ID_TABLE("max1237", max1237),
+ MAX1363_ID_TABLE("max1238", max1238),
+ MAX1363_ID_TABLE("max1239", max1239),
+ MAX1363_ID_TABLE("max11600", max11600),
+ MAX1363_ID_TABLE("max11601", max11601),
+ MAX1363_ID_TABLE("max11602", max11602),
+ MAX1363_ID_TABLE("max11603", max11603),
+ MAX1363_ID_TABLE("max11604", max11604),
+ MAX1363_ID_TABLE("max11605", max11605),
+ MAX1363_ID_TABLE("max11606", max11606),
+ MAX1363_ID_TABLE("max11607", max11607),
+ MAX1363_ID_TABLE("max11608", max11608),
+ MAX1363_ID_TABLE("max11609", max11609),
+ MAX1363_ID_TABLE("max11610", max11610),
+ MAX1363_ID_TABLE("max11611", max11611),
+ MAX1363_ID_TABLE("max11612", max11612),
+ MAX1363_ID_TABLE("max11613", max11613),
+ MAX1363_ID_TABLE("max11614", max11614),
+ MAX1363_ID_TABLE("max11615", max11615),
+ MAX1363_ID_TABLE("max11616", max11616),
+ MAX1363_ID_TABLE("max11617", max11617),
+ MAX1363_ID_TABLE("max11644", max11644),
+ MAX1363_ID_TABLE("max11645", max11645),
+ MAX1363_ID_TABLE("max11646", max11646),
+ MAX1363_ID_TABLE("max11647", max11647),
+ { /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, max1363_id);
diff --git a/drivers/iio/adc/mcp3564.c b/drivers/iio/adc/mcp3564.c
new file mode 100644
index 000000000000..64145f4ae55c
--- /dev/null
+++ b/drivers/iio/adc/mcp3564.c
@@ -0,0 +1,1516 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * IIO driver for MCP356X/MCP356XR and MCP346X/MCP346XR series ADC chip family
+ *
+ * Copyright (C) 2022-2023 Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Marius Cristea <marius.cristea@microchip.com>
+ *
+ * Datasheet for MCP3561, MCP3562, MCP3564 can be found here:
+ * https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/MCP3561-2-4-Family-Data-Sheet-DS20006181C.pdf
+ * Datasheet for MCP3561R, MCP3562R, MCP3564R can be found here:
+ * https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/MCP3561_2_4R-Data-Sheet-DS200006391C.pdf
+ * Datasheet for MCP3461, MCP3462, MCP3464 can be found here:
+ * https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/MCP3461-2-4-Two-Four-Eight-Channel-153.6-ksps-Low-Noise-16-Bit-Delta-Sigma-ADC-Data-Sheet-20006180D.pdf
+ * Datasheet for MCP3461R, MCP3462R, MCP3464R can be found here:
+ * https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/MCP3461-2-4R-Family-Data-Sheet-DS20006404C.pdf
+ */
+
+#include <linux/bitfield.h>
+#include <linux/iopoll.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+#include <linux/units.h>
+#include <linux/util_macros.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define MCP3564_ADCDATA_REG 0x00
+
+#define MCP3564_CONFIG0_REG 0x01
+#define MCP3564_CONFIG0_ADC_MODE_MASK GENMASK(1, 0)
+/* Current Source/Sink Selection Bits for Sensor Bias */
+#define MCP3564_CONFIG0_CS_SEL_MASK GENMASK(3, 2)
+/* Internal clock is selected and AMCLK is present on the analog master clock output pin */
+#define MCP3564_CONFIG0_USE_INT_CLK_OUTPUT_EN 0x03
+/* Internal clock is selected and no clock output is present on the CLK pin */
+#define MCP3564_CONFIG0_USE_INT_CLK 0x02
+/* External digital clock */
+#define MCP3564_CONFIG0_USE_EXT_CLK 0x01
+/* External digital clock (default) */
+#define MCP3564_CONFIG0_USE_EXT_CLK_DEFAULT 0x00
+#define MCP3564_CONFIG0_CLK_SEL_MASK GENMASK(5, 4)
+#define MCP3456_CONFIG0_BIT6_DEFAULT BIT(6)
+#define MCP3456_CONFIG0_VREF_MASK BIT(7)
+
+#define MCP3564_CONFIG1_REG 0x02
+#define MCP3564_CONFIG1_OVERSPL_RATIO_MASK GENMASK(5, 2)
+
+#define MCP3564_CONFIG2_REG 0x03
+#define MCP3564_CONFIG2_AZ_REF_MASK BIT(1)
+#define MCP3564_CONFIG2_AZ_MUX_MASK BIT(2)
+
+#define MCP3564_CONFIG2_HARDWARE_GAIN_MASK GENMASK(5, 3)
+#define MCP3564_DEFAULT_HARDWARE_GAIN 0x01
+#define MCP3564_CONFIG2_BOOST_CURRENT_MASK GENMASK(7, 6)
+
+#define MCP3564_CONFIG3_REG 0x04
+#define MCP3464_CONFIG3_EN_GAINCAL_MASK BIT(0)
+#define MCP3464_CONFIG3_EN_OFFCAL_MASK BIT(1)
+#define MCP3464_CONFIG3_EN_CRCCOM_MASK BIT(2)
+#define MCP3464_CONFIG3_CRC_FORMAT_MASK BIT(3)
+/*
+ * ADC Output Data Format 32-bit (25-bit right justified data + Channel ID):
+ * CHID[3:0] + SGN extension (4 bits) + 24-bit ADC data.
+ * It allows overrange with the SGN extension.
+ */
+#define MCP3464_CONFIG3_DATA_FMT_32B_WITH_CH_ID 3
+/*
+ * ADC Output Data Format 32-bit (25-bit right justified data):
+ * SGN extension (8-bit) + 24-bit ADC data.
+ * It allows overrange with the SGN extension.
+ */
+#define MCP3464_CONFIG3_DATA_FMT_32B_SGN_EXT 2
+/*
+ * ADC Output Data Format 32-bit (24-bit left justified data):
+ * 24-bit ADC data + 0x00 (8-bit).
+ * It does not allow overrange (ADC code locked to 0xFFFFFF or 0x800000).
+ */
+#define MCP3464_CONFIG3_DATA_FMT_32B_LEFT_JUSTIFIED 1
+/*
+ * ADC Output Data Format 24-bit (default ADC coding):
+ * 24-bit ADC data.
+ * It does not allow overrange (ADC code locked to 0xFFFFFF or 0x800000).
+ */
+#define MCP3464_CONFIG3_DATA_FMT_24B 0
+#define MCP3464_CONFIG3_DATA_FORMAT_MASK GENMASK(5, 4)
+
+/* Continuous Conversion mode or continuous conversion cycle in SCAN mode. */
+#define MCP3464_CONFIG3_CONV_MODE_CONTINUOUS 3
+/*
+ * One-shot conversion or one-shot cycle in SCAN mode. It sets ADC_MODE[1:0] to ‘10’
+ * (standby) at the end of the conversion or at the end of the conversion cycle in SCAN mode.
+ */
+#define MCP3464_CONFIG3_CONV_MODE_ONE_SHOT_STANDBY 2
+/*
+ * One-shot conversion or one-shot cycle in SCAN mode. It sets ADC_MODE[1:0] to ‘0x’ (ADC
+ * Shutdown) at the end of the conversion or at the end of the conversion cycle in SCAN
+ * mode (default).
+ */
+#define MCP3464_CONFIG3_CONV_MODE_ONE_SHOT_SHUTDOWN 0
+#define MCP3464_CONFIG3_CONV_MODE_MASK GENMASK(7, 6)
+
+#define MCP3564_IRQ_REG 0x05
+#define MCP3464_EN_STP_MASK BIT(0)
+#define MCP3464_EN_FASTCMD_MASK BIT(1)
+#define MCP3464_IRQ_MODE_0_MASK BIT(2)
+#define MCP3464_IRQ_MODE_1_MASK BIT(3)
+#define MCP3564_POR_STATUS_MASK BIT(4)
+#define MCP3564_CRCCFG_STATUS_MASK BIT(5)
+#define MCP3564_DATA_READY_MASK BIT(6)
+
+#define MCP3564_MUX_REG 0x06
+#define MCP3564_MUX_VIN_P_MASK GENMASK(7, 4)
+#define MCP3564_MUX_VIN_N_MASK GENMASK(3, 0)
+#define MCP3564_MUX_SET(x, y) (FIELD_PREP(MCP3564_MUX_VIN_P_MASK, (x)) | \
+ FIELD_PREP(MCP3564_MUX_VIN_N_MASK, (y)))
+
+#define MCP3564_SCAN_REG 0x07
+#define MCP3564_SCAN_CH_SEL_MASK GENMASK(15, 0)
+#define MCP3564_SCAN_CH_SEL_SET(x) FIELD_PREP(MCP3564_SCAN_CH_SEL_MASK, (x))
+#define MCP3564_SCAN_DELAY_TIME_MASK GENMASK(23, 21)
+#define MCP3564_SCAN_DELAY_TIME_SET(x) FIELD_PREP(MCP3564_SCAN_DELAY_TIME_MASK, (x))
+#define MCP3564_SCAN_DEFAULT_VALUE 0
+
+#define MCP3564_TIMER_REG 0x08
+#define MCP3564_TIMER_DEFAULT_VALUE 0
+
+#define MCP3564_OFFSETCAL_REG 0x09
+#define MCP3564_DEFAULT_OFFSETCAL 0
+
+#define MCP3564_GAINCAL_REG 0x0A
+#define MCP3564_DEFAULT_GAINCAL 0x00800000
+
+#define MCP3564_RESERVED_B_REG 0x0B
+
+#define MCP3564_RESERVED_C_REG 0x0C
+#define MCP3564_C_REG_DEFAULT 0x50
+#define MCP3564R_C_REG_DEFAULT 0x30
+
+#define MCP3564_LOCK_REG 0x0D
+#define MCP3564_LOCK_WRITE_ACCESS_PASSWORD 0xA5
+#define MCP3564_RESERVED_E_REG 0x0E
+#define MCP3564_CRCCFG_REG 0x0F
+
+#define MCP3564_CMD_HW_ADDR_MASK GENMASK(7, 6)
+#define MCP3564_CMD_ADDR_MASK GENMASK(5, 2)
+
+#define MCP3564_HW_ADDR_MASK GENMASK(1, 0)
+
+#define MCP3564_FASTCMD_START 0x0A
+#define MCP3564_FASTCMD_RESET 0x0E
+
+#define MCP3461_HW_ID 0x0008
+#define MCP3462_HW_ID 0x0009
+#define MCP3464_HW_ID 0x000B
+
+#define MCP3561_HW_ID 0x000C
+#define MCP3562_HW_ID 0x000D
+#define MCP3564_HW_ID 0x000F
+#define MCP3564_HW_ID_MASK GENMASK(3, 0)
+
+#define MCP3564R_INT_VREF_MV 2400
+
+#define MCP3564_DATA_READY_TIMEOUT_MS 2000
+
+#define MCP3564_MAX_PGA 8
+#define MCP3564_MAX_BURNOUT_IDX 4
+#define MCP3564_MAX_CHANNELS 66
+
+enum mcp3564_ids {
+ mcp3461,
+ mcp3462,
+ mcp3464,
+ mcp3561,
+ mcp3562,
+ mcp3564,
+ mcp3461r,
+ mcp3462r,
+ mcp3464r,
+ mcp3561r,
+ mcp3562r,
+ mcp3564r,
+};
+
+enum mcp3564_delay_time {
+ MCP3564_NO_DELAY,
+ MCP3564_DELAY_8_DMCLK,
+ MCP3564_DELAY_16_DMCLK,
+ MCP3564_DELAY_32_DMCLK,
+ MCP3564_DELAY_64_DMCLK,
+ MCP3564_DELAY_128_DMCLK,
+ MCP3564_DELAY_256_DMCLK,
+ MCP3564_DELAY_512_DMCLK
+};
+
+enum mcp3564_adc_conversion_mode {
+ MCP3564_ADC_MODE_DEFAULT,
+ MCP3564_ADC_MODE_SHUTDOWN,
+ MCP3564_ADC_MODE_STANDBY,
+ MCP3564_ADC_MODE_CONVERSION
+};
+
+enum mcp3564_adc_bias_current {
+ MCP3564_BOOST_CURRENT_x0_50,
+ MCP3564_BOOST_CURRENT_x0_66,
+ MCP3564_BOOST_CURRENT_x1_00,
+ MCP3564_BOOST_CURRENT_x2_00
+};
+
+enum mcp3564_burnout {
+ MCP3564_CONFIG0_CS_SEL_0_0_uA,
+ MCP3564_CONFIG0_CS_SEL_0_9_uA,
+ MCP3564_CONFIG0_CS_SEL_3_7_uA,
+ MCP3564_CONFIG0_CS_SEL_15_uA
+};
+
+enum mcp3564_channel_names {
+ MCP3564_CH0,
+ MCP3564_CH1,
+ MCP3564_CH2,
+ MCP3564_CH3,
+ MCP3564_CH4,
+ MCP3564_CH5,
+ MCP3564_CH6,
+ MCP3564_CH7,
+ MCP3564_AGND,
+ MCP3564_AVDD,
+ MCP3564_RESERVED, /* do not use */
+ MCP3564_REFIN_POZ,
+ MCP3564_REFIN_NEG,
+ MCP3564_TEMP_DIODE_P,
+ MCP3564_TEMP_DIODE_M,
+ MCP3564_INTERNAL_VCM,
+};
+
+enum mcp3564_oversampling {
+ MCP3564_OVERSAMPLING_RATIO_32,
+ MCP3564_OVERSAMPLING_RATIO_64,
+ MCP3564_OVERSAMPLING_RATIO_128,
+ MCP3564_OVERSAMPLING_RATIO_256,
+ MCP3564_OVERSAMPLING_RATIO_512,
+ MCP3564_OVERSAMPLING_RATIO_1024,
+ MCP3564_OVERSAMPLING_RATIO_2048,
+ MCP3564_OVERSAMPLING_RATIO_4096,
+ MCP3564_OVERSAMPLING_RATIO_8192,
+ MCP3564_OVERSAMPLING_RATIO_16384,
+ MCP3564_OVERSAMPLING_RATIO_20480,
+ MCP3564_OVERSAMPLING_RATIO_24576,
+ MCP3564_OVERSAMPLING_RATIO_40960,
+ MCP3564_OVERSAMPLING_RATIO_49152,
+ MCP3564_OVERSAMPLING_RATIO_81920,
+ MCP3564_OVERSAMPLING_RATIO_98304
+};
+
+static const unsigned int mcp3564_oversampling_avail[] = {
+ [MCP3564_OVERSAMPLING_RATIO_32] = 32,
+ [MCP3564_OVERSAMPLING_RATIO_64] = 64,
+ [MCP3564_OVERSAMPLING_RATIO_128] = 128,
+ [MCP3564_OVERSAMPLING_RATIO_256] = 256,
+ [MCP3564_OVERSAMPLING_RATIO_512] = 512,
+ [MCP3564_OVERSAMPLING_RATIO_1024] = 1024,
+ [MCP3564_OVERSAMPLING_RATIO_2048] = 2048,
+ [MCP3564_OVERSAMPLING_RATIO_4096] = 4096,
+ [MCP3564_OVERSAMPLING_RATIO_8192] = 8192,
+ [MCP3564_OVERSAMPLING_RATIO_16384] = 16384,
+ [MCP3564_OVERSAMPLING_RATIO_20480] = 20480,
+ [MCP3564_OVERSAMPLING_RATIO_24576] = 24576,
+ [MCP3564_OVERSAMPLING_RATIO_40960] = 40960,
+ [MCP3564_OVERSAMPLING_RATIO_49152] = 49152,
+ [MCP3564_OVERSAMPLING_RATIO_81920] = 81920,
+ [MCP3564_OVERSAMPLING_RATIO_98304] = 98304
+};
+
+/*
+ * Current Source/Sink Selection Bits for Sensor Bias (source on VIN+/sink on VIN-)
+ */
+static const int mcp3564_burnout_avail[][2] = {
+ [MCP3564_CONFIG0_CS_SEL_0_0_uA] = { 0, 0 },
+ [MCP3564_CONFIG0_CS_SEL_0_9_uA] = { 0, 900 },
+ [MCP3564_CONFIG0_CS_SEL_3_7_uA] = { 0, 3700 },
+ [MCP3564_CONFIG0_CS_SEL_15_uA] = { 0, 15000 }
+};
+
+/*
+ * BOOST[1:0]: ADC Bias Current Selection
+ */
+static const char * const mcp3564_boost_current_avail[] = {
+ [MCP3564_BOOST_CURRENT_x0_50] = "0.5",
+ [MCP3564_BOOST_CURRENT_x0_66] = "0.66",
+ [MCP3564_BOOST_CURRENT_x1_00] = "1",
+ [MCP3564_BOOST_CURRENT_x2_00] = "2",
+};
+
+/*
+ * Calibration bias values
+ */
+static const int mcp3564_calib_bias[] = {
+ -8388608, /* min: -2^23 */
+ 1, /* step: 1 */
+ 8388607 /* max: 2^23 - 1 */
+};
+
+/*
+ * Calibration scale values
+ * The Gain Error Calibration register (GAINCAL) is an
+ * unsigned 24-bit register that holds the digital gain error
+ * calibration value, GAINCAL which could be calculated by
+ * GAINCAL (V/V) = (GAINCAL[23:0])/8388608
+ * The gain error calibration value range in equivalent voltage is [0; 2-2^(-23)]
+ */
+static const unsigned int mcp3564_calib_scale[] = {
+ 0, /* min: 0 */
+ 1, /* step: 1/8388608 */
+ 16777215 /* max: 2 - 2^(-23) */
+};
+
+/* Programmable hardware gain x1/3, x1, x2, x4, x8, x16, x32, x64 */
+static const int mcp3564_hwgain_frac[] = {
+ 3, 10,
+ 1, 1,
+ 2, 1,
+ 4, 1,
+ 8, 1,
+ 16, 1,
+ 32, 1,
+ 64, 1
+};
+
+static const char *mcp3564_channel_labels[2] = {
+ "burnout_current", "temperature",
+};
+
+/**
+ * struct mcp3564_chip_info - chip specific data
+ * @name: device name
+ * @num_channels: number of channels
+ * @resolution: ADC resolution
+ * @have_vref: does the hardware have an internal voltage reference?
+ */
+struct mcp3564_chip_info {
+ const char *name;
+ unsigned int num_channels;
+ unsigned int resolution;
+ bool have_vref;
+};
+
+/**
+ * struct mcp3564_state - working data for a ADC device
+ * @chip_info: chip specific data
+ * @spi: SPI device structure
+ * @vref: the regulator device used as a voltage reference in case
+ * external voltage reference is used
+ * @vref_mv: voltage reference value in miliVolts
+ * @lock: synchronize access to driver's state members
+ * @dev_addr: hardware device address
+ * @oversampling: the index inside oversampling list of the ADC
+ * @hwgain: the index inside hardware gain list of the ADC
+ * @scale_tbls: table with precalculated scale
+ * @calib_bias: calibration bias value
+ * @calib_scale: calibration scale value
+ * @current_boost_mode: the index inside current boost list of the ADC
+ * @burnout_mode: the index inside current bias list of the ADC
+ * @auto_zeroing_mux: set if ADC auto-zeroing algorithm is enabled
+ * @auto_zeroing_ref: set if ADC auto-Zeroing Reference Buffer Setting is enabled
+ * @have_vref: does the ADC have an internal voltage reference?
+ * @labels: table with channels labels
+ */
+struct mcp3564_state {
+ const struct mcp3564_chip_info *chip_info;
+ struct spi_device *spi;
+ struct regulator *vref;
+ unsigned short vref_mv;
+ struct mutex lock; /* Synchronize access to driver's state members */
+ u8 dev_addr;
+ enum mcp3564_oversampling oversampling;
+ unsigned int hwgain;
+ unsigned int scale_tbls[MCP3564_MAX_PGA][2];
+ int calib_bias;
+ int calib_scale;
+ unsigned int current_boost_mode;
+ enum mcp3564_burnout burnout_mode;
+ bool auto_zeroing_mux;
+ bool auto_zeroing_ref;
+ bool have_vref;
+ const char *labels[MCP3564_MAX_CHANNELS];
+};
+
+static inline u8 mcp3564_cmd_write(u8 chip_addr, u8 reg)
+{
+ return FIELD_PREP(MCP3564_CMD_HW_ADDR_MASK, chip_addr) |
+ FIELD_PREP(MCP3564_CMD_ADDR_MASK, reg) |
+ BIT(1);
+}
+
+static inline u8 mcp3564_cmd_read(u8 chip_addr, u8 reg)
+{
+ return FIELD_PREP(MCP3564_CMD_HW_ADDR_MASK, chip_addr) |
+ FIELD_PREP(MCP3564_CMD_ADDR_MASK, reg) |
+ BIT(0);
+}
+
+static int mcp3564_read_8bits(struct mcp3564_state *adc, u8 reg, u8 *val)
+{
+ int ret;
+ u8 tx_buf;
+ u8 rx_buf;
+
+ tx_buf = mcp3564_cmd_read(adc->dev_addr, reg);
+
+ ret = spi_write_then_read(adc->spi, &tx_buf, sizeof(tx_buf),
+ &rx_buf, sizeof(rx_buf));
+ *val = rx_buf;
+
+ return ret;
+}
+
+static int mcp3564_read_16bits(struct mcp3564_state *adc, u8 reg, u16 *val)
+{
+ int ret;
+ u8 tx_buf;
+ __be16 rx_buf;
+
+ tx_buf = mcp3564_cmd_read(adc->dev_addr, reg);
+
+ ret = spi_write_then_read(adc->spi, &tx_buf, sizeof(tx_buf),
+ &rx_buf, sizeof(rx_buf));
+ *val = be16_to_cpu(rx_buf);
+
+ return ret;
+}
+
+static int mcp3564_read_32bits(struct mcp3564_state *adc, u8 reg, u32 *val)
+{
+ int ret;
+ u8 tx_buf;
+ __be32 rx_buf;
+
+ tx_buf = mcp3564_cmd_read(adc->dev_addr, reg);
+
+ ret = spi_write_then_read(adc->spi, &tx_buf, sizeof(tx_buf),
+ &rx_buf, sizeof(rx_buf));
+ *val = be32_to_cpu(rx_buf);
+
+ return ret;
+}
+
+static int mcp3564_write_8bits(struct mcp3564_state *adc, u8 reg, u8 val)
+{
+ u8 tx_buf[2];
+
+ tx_buf[0] = mcp3564_cmd_write(adc->dev_addr, reg);
+ tx_buf[1] = val;
+
+ return spi_write_then_read(adc->spi, tx_buf, sizeof(tx_buf), NULL, 0);
+}
+
+static int mcp3564_write_24bits(struct mcp3564_state *adc, u8 reg, u32 val)
+{
+ __be32 val_be;
+
+ val |= (mcp3564_cmd_write(adc->dev_addr, reg) << 24);
+ val_be = cpu_to_be32(val);
+
+ return spi_write_then_read(adc->spi, &val_be, sizeof(val_be), NULL, 0);
+}
+
+static int mcp3564_fast_cmd(struct mcp3564_state *adc, u8 fast_cmd)
+{
+ u8 val;
+
+ val = FIELD_PREP(MCP3564_CMD_HW_ADDR_MASK, adc->dev_addr) |
+ FIELD_PREP(MCP3564_CMD_ADDR_MASK, fast_cmd);
+
+ return spi_write_then_read(adc->spi, &val, 1, NULL, 0);
+}
+
+static int mcp3564_update_8bits(struct mcp3564_state *adc, u8 reg, u32 mask, u8 val)
+{
+ u8 tmp;
+ int ret;
+
+ val &= mask;
+
+ ret = mcp3564_read_8bits(adc, reg, &tmp);
+ if (ret < 0)
+ return ret;
+
+ tmp &= ~mask;
+ tmp |= val;
+
+ return mcp3564_write_8bits(adc, reg, tmp);
+}
+
+static int mcp3564_set_current_boost_mode(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ unsigned int mode)
+{
+ struct mcp3564_state *adc = iio_priv(indio_dev);
+ int ret;
+
+ dev_dbg(&indio_dev->dev, "%s: %d\n", __func__, mode);
+
+ mutex_lock(&adc->lock);
+ ret = mcp3564_update_8bits(adc, MCP3564_CONFIG2_REG, MCP3564_CONFIG2_BOOST_CURRENT_MASK,
+ FIELD_PREP(MCP3564_CONFIG2_BOOST_CURRENT_MASK, mode));
+
+ if (ret)
+ dev_err(&indio_dev->dev, "Failed to configure CONFIG2 register\n");
+ else
+ adc->current_boost_mode = mode;
+
+ mutex_unlock(&adc->lock);
+
+ return ret;
+}
+
+static int mcp3564_get_current_boost_mode(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan)
+{
+ struct mcp3564_state *adc = iio_priv(indio_dev);
+
+ return adc->current_boost_mode;
+}
+
+static const struct iio_enum mcp3564_current_boost_mode_enum = {
+ .items = mcp3564_boost_current_avail,
+ .num_items = ARRAY_SIZE(mcp3564_boost_current_avail),
+ .set = mcp3564_set_current_boost_mode,
+ .get = mcp3564_get_current_boost_mode,
+};
+
+static const struct iio_chan_spec_ext_info mcp3564_ext_info[] = {
+ IIO_ENUM("boost_current_gain", IIO_SHARED_BY_ALL, &mcp3564_current_boost_mode_enum),
+ {
+ .name = "boost_current_gain_available",
+ .shared = IIO_SHARED_BY_ALL,
+ .read = iio_enum_available_read,
+ .private = (uintptr_t)&mcp3564_current_boost_mode_enum,
+ },
+ { }
+};
+
+static ssize_t mcp3564_auto_zeroing_mux_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct mcp3564_state *adc = iio_priv(indio_dev);
+
+ return sysfs_emit(buf, "%d\n", adc->auto_zeroing_mux);
+}
+
+static ssize_t mcp3564_auto_zeroing_mux_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct mcp3564_state *adc = iio_priv(indio_dev);
+ bool auto_zero;
+ int ret;
+
+ ret = kstrtobool(buf, &auto_zero);
+ if (ret)
+ return ret;
+
+ mutex_lock(&adc->lock);
+ ret = mcp3564_update_8bits(adc, MCP3564_CONFIG2_REG, MCP3564_CONFIG2_AZ_MUX_MASK,
+ FIELD_PREP(MCP3564_CONFIG2_AZ_MUX_MASK, auto_zero));
+
+ if (ret)
+ dev_err(&indio_dev->dev, "Failed to update CONFIG2 register\n");
+ else
+ adc->auto_zeroing_mux = auto_zero;
+
+ mutex_unlock(&adc->lock);
+
+ return ret ? ret : len;
+}
+
+static ssize_t mcp3564_auto_zeroing_ref_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct mcp3564_state *adc = iio_priv(indio_dev);
+
+ return sysfs_emit(buf, "%d\n", adc->auto_zeroing_ref);
+}
+
+static ssize_t mcp3564_auto_zeroing_ref_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct mcp3564_state *adc = iio_priv(indio_dev);
+ bool auto_zero;
+ int ret;
+
+ ret = kstrtobool(buf, &auto_zero);
+ if (ret)
+ return ret;
+
+ mutex_lock(&adc->lock);
+ ret = mcp3564_update_8bits(adc, MCP3564_CONFIG2_REG, MCP3564_CONFIG2_AZ_REF_MASK,
+ FIELD_PREP(MCP3564_CONFIG2_AZ_REF_MASK, auto_zero));
+
+ if (ret)
+ dev_err(&indio_dev->dev, "Failed to update CONFIG2 register\n");
+ else
+ adc->auto_zeroing_ref = auto_zero;
+
+ mutex_unlock(&adc->lock);
+
+ return ret ? ret : len;
+}
+
+static const struct iio_chan_spec mcp3564_channel_template = {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .differential = 1,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_CALIBSCALE) |
+ BIT(IIO_CHAN_INFO_CALIBBIAS) |
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_CALIBSCALE) |
+ BIT(IIO_CHAN_INFO_CALIBBIAS) |
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .ext_info = mcp3564_ext_info,
+};
+
+static const struct iio_chan_spec mcp3564_temp_channel_template = {
+ .type = IIO_TEMP,
+ .channel = 0,
+ .address = ((MCP3564_TEMP_DIODE_P << 4) | MCP3564_TEMP_DIODE_M),
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_CALIBSCALE) |
+ BIT(IIO_CHAN_INFO_CALIBBIAS) |
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_CALIBSCALE) |
+ BIT(IIO_CHAN_INFO_CALIBBIAS) |
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+};
+
+static const struct iio_chan_spec mcp3564_burnout_channel_template = {
+ .type = IIO_CURRENT,
+ .output = true,
+ .channel = 0,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW),
+};
+
+/*
+ * Number of channels could be calculated:
+ * num_channels = single_ended_input + differential_input + temperature + burnout
+ * Eg. for MCP3561 (only 2 channels available: CH0 and CH1)
+ * single_ended_input = (CH0 - GND), (CH1 - GND) = 2
+ * differential_input = (CH0 - CH1), (CH0 - CH0) = 2
+ * num_channels = 2 + 2 + 2
+ * Generic formula is:
+ * num_channels = P^R(Number_of_single_ended_channels, 2) + 2 (temperature + burnout channels)
+ * P^R(Number_of_single_ended_channels, 2) is Permutations with Replacement of
+ * Number_of_single_ended_channels taken by 2
+ */
+static const struct mcp3564_chip_info mcp3564_chip_infos_tbl[] = {
+ [mcp3461] = {
+ .name = "mcp3461",
+ .num_channels = 6,
+ .resolution = 16,
+ .have_vref = false,
+ },
+ [mcp3462] = {
+ .name = "mcp3462",
+ .num_channels = 18,
+ .resolution = 16,
+ .have_vref = false,
+ },
+ [mcp3464] = {
+ .name = "mcp3464",
+ .num_channels = 66,
+ .resolution = 16,
+ .have_vref = false,
+ },
+ [mcp3561] = {
+ .name = "mcp3561",
+ .num_channels = 6,
+ .resolution = 24,
+ .have_vref = false,
+ },
+ [mcp3562] = {
+ .name = "mcp3562",
+ .num_channels = 18,
+ .resolution = 24,
+ .have_vref = false,
+ },
+ [mcp3564] = {
+ .name = "mcp3564",
+ .num_channels = 66,
+ .resolution = 24,
+ .have_vref = false,
+ },
+ [mcp3461r] = {
+ .name = "mcp3461r",
+ .num_channels = 6,
+ .resolution = 16,
+ .have_vref = false,
+ },
+ [mcp3462r] = {
+ .name = "mcp3462r",
+ .num_channels = 18,
+ .resolution = 16,
+ .have_vref = true,
+ },
+ [mcp3464r] = {
+ .name = "mcp3464r",
+ .num_channels = 66,
+ .resolution = 16,
+ .have_vref = true,
+ },
+ [mcp3561r] = {
+ .name = "mcp3561r",
+ .num_channels = 6,
+ .resolution = 24,
+ .have_vref = true,
+ },
+ [mcp3562r] = {
+ .name = "mcp3562r",
+ .num_channels = 18,
+ .resolution = 24,
+ .have_vref = true,
+ },
+ [mcp3564r] = {
+ .name = "mcp3564r",
+ .num_channels = 66,
+ .resolution = 24,
+ .have_vref = true,
+ },
+};
+
+static int mcp3564_read_single_value(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *channel,
+ int *val)
+{
+ struct mcp3564_state *adc = iio_priv(indio_dev);
+ int ret;
+ u8 tmp;
+ int ret_read = 0;
+
+ ret = mcp3564_write_8bits(adc, MCP3564_MUX_REG, channel->address);
+ if (ret)
+ return ret;
+
+ /* Start ADC Conversion using fast command (overwrites ADC_MODE[1:0] = 11) */
+ ret = mcp3564_fast_cmd(adc, MCP3564_FASTCMD_START);
+ if (ret)
+ return ret;
+
+ /*
+ * Check if the conversion is ready. If not, wait a little bit, and
+ * in case of timeout exit with an error.
+ */
+ ret = read_poll_timeout(mcp3564_read_8bits, ret_read,
+ ret_read || !(tmp & MCP3564_DATA_READY_MASK),
+ 20000, MCP3564_DATA_READY_TIMEOUT_MS * 1000, true,
+ adc, MCP3564_IRQ_REG, &tmp);
+
+ /* failed to read status register */
+ if (ret_read)
+ return ret_read;
+
+ if (ret)
+ return ret;
+
+ if (tmp & MCP3564_DATA_READY_MASK)
+ /* failing to finish conversion */
+ return -EBUSY;
+
+ return mcp3564_read_32bits(adc, MCP3564_ADCDATA_REG, val);
+}
+
+static int mcp3564_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *channel,
+ const int **vals, int *type,
+ int *length, long mask)
+{
+ struct mcp3564_state *adc = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ if (!channel->output)
+ return -EINVAL;
+
+ *vals = mcp3564_burnout_avail[0];
+ *length = ARRAY_SIZE(mcp3564_burnout_avail) * 2;
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ return IIO_AVAIL_LIST;
+ case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+ *vals = mcp3564_oversampling_avail;
+ *length = ARRAY_SIZE(mcp3564_oversampling_avail);
+ *type = IIO_VAL_INT;
+ return IIO_AVAIL_LIST;
+ case IIO_CHAN_INFO_SCALE:
+ *vals = (int *)adc->scale_tbls;
+ *length = ARRAY_SIZE(adc->scale_tbls) * 2;
+ *type = IIO_VAL_INT_PLUS_NANO;
+ return IIO_AVAIL_LIST;
+ case IIO_CHAN_INFO_CALIBBIAS:
+ *vals = mcp3564_calib_bias;
+ *type = IIO_VAL_INT;
+ return IIO_AVAIL_RANGE;
+ case IIO_CHAN_INFO_CALIBSCALE:
+ *vals = mcp3564_calib_scale;
+ *type = IIO_VAL_INT;
+ return IIO_AVAIL_RANGE;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int mcp3564_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *channel,
+ int *val, int *val2, long mask)
+{
+ struct mcp3564_state *adc = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ if (channel->output) {
+ mutex_lock(&adc->lock);
+ *val = mcp3564_burnout_avail[adc->burnout_mode][0];
+ *val2 = mcp3564_burnout_avail[adc->burnout_mode][1];
+ mutex_unlock(&adc->lock);
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+
+ ret = mcp3564_read_single_value(indio_dev, channel, val);
+ if (ret)
+ return -EINVAL;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ mutex_lock(&adc->lock);
+ *val = adc->scale_tbls[adc->hwgain][0];
+ *val2 = adc->scale_tbls[adc->hwgain][1];
+ mutex_unlock(&adc->lock);
+ return IIO_VAL_INT_PLUS_NANO;
+ case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+ *val = mcp3564_oversampling_avail[adc->oversampling];
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_CALIBBIAS:
+ *val = adc->calib_bias;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_CALIBSCALE:
+ *val = adc->calib_scale;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int mcp3564_write_raw_get_fmt(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ long info)
+{
+ switch (info) {
+ case IIO_CHAN_INFO_RAW:
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_CALIBBIAS:
+ case IIO_CHAN_INFO_CALIBSCALE:
+ case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ return IIO_VAL_INT_PLUS_NANO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int mcp3564_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *channel, int val,
+ int val2, long mask)
+{
+ struct mcp3564_state *adc = iio_priv(indio_dev);
+ int tmp;
+ unsigned int hwgain;
+ enum mcp3564_burnout burnout;
+ int ret = 0;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ if (!channel->output)
+ return -EINVAL;
+
+ for (burnout = 0; burnout < MCP3564_MAX_BURNOUT_IDX; burnout++)
+ if (val == mcp3564_burnout_avail[burnout][0] &&
+ val2 == mcp3564_burnout_avail[burnout][1])
+ break;
+
+ if (burnout == MCP3564_MAX_BURNOUT_IDX)
+ return -EINVAL;
+
+ if (burnout == adc->burnout_mode)
+ return ret;
+
+ mutex_lock(&adc->lock);
+ ret = mcp3564_update_8bits(adc, MCP3564_CONFIG0_REG,
+ MCP3564_CONFIG0_CS_SEL_MASK,
+ FIELD_PREP(MCP3564_CONFIG0_CS_SEL_MASK, burnout));
+
+ if (ret)
+ dev_err(&indio_dev->dev, "Failed to configure burnout current\n");
+ else
+ adc->burnout_mode = burnout;
+ mutex_unlock(&adc->lock);
+ return ret;
+ case IIO_CHAN_INFO_CALIBBIAS:
+ if (val < mcp3564_calib_bias[0] && val > mcp3564_calib_bias[2])
+ return -EINVAL;
+
+ mutex_lock(&adc->lock);
+ ret = mcp3564_write_24bits(adc, MCP3564_OFFSETCAL_REG, val);
+ if (!ret)
+ adc->calib_bias = val;
+ mutex_unlock(&adc->lock);
+ return ret;
+ case IIO_CHAN_INFO_CALIBSCALE:
+ if (val < mcp3564_calib_scale[0] && val > mcp3564_calib_scale[2])
+ return -EINVAL;
+
+ if (adc->calib_scale == val)
+ return ret;
+
+ mutex_lock(&adc->lock);
+ ret = mcp3564_write_24bits(adc, MCP3564_GAINCAL_REG, val);
+ if (!ret)
+ adc->calib_scale = val;
+ mutex_unlock(&adc->lock);
+ return ret;
+ case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+ if (val < 0)
+ return -EINVAL;
+
+ tmp = find_closest(val, mcp3564_oversampling_avail,
+ ARRAY_SIZE(mcp3564_oversampling_avail));
+
+ if (adc->oversampling == tmp)
+ return ret;
+
+ mutex_lock(&adc->lock);
+ ret = mcp3564_update_8bits(adc, MCP3564_CONFIG1_REG,
+ MCP3564_CONFIG1_OVERSPL_RATIO_MASK,
+ FIELD_PREP(MCP3564_CONFIG1_OVERSPL_RATIO_MASK,
+ adc->oversampling));
+ if (!ret)
+ adc->oversampling = tmp;
+ mutex_unlock(&adc->lock);
+ return ret;
+ case IIO_CHAN_INFO_SCALE:
+ for (hwgain = 0; hwgain < MCP3564_MAX_PGA; hwgain++)
+ if (val == adc->scale_tbls[hwgain][0] &&
+ val2 == adc->scale_tbls[hwgain][1])
+ break;
+
+ if (hwgain == MCP3564_MAX_PGA)
+ return -EINVAL;
+
+ if (hwgain == adc->hwgain)
+ return ret;
+
+ mutex_lock(&adc->lock);
+ ret = mcp3564_update_8bits(adc, MCP3564_CONFIG2_REG,
+ MCP3564_CONFIG2_HARDWARE_GAIN_MASK,
+ FIELD_PREP(MCP3564_CONFIG2_HARDWARE_GAIN_MASK, hwgain));
+ if (!ret)
+ adc->hwgain = hwgain;
+
+ mutex_unlock(&adc->lock);
+ return ret;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int mcp3564_read_label(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, char *label)
+{
+ struct mcp3564_state *adc = iio_priv(indio_dev);
+
+ return sprintf(label, "%s\n", adc->labels[chan->scan_index]);
+}
+
+static int mcp3564_parse_fw_children(struct iio_dev *indio_dev)
+{
+ struct mcp3564_state *adc = iio_priv(indio_dev);
+ struct device *dev = &adc->spi->dev;
+ struct iio_chan_spec *channels;
+ struct fwnode_handle *child;
+ struct iio_chan_spec chanspec = mcp3564_channel_template;
+ struct iio_chan_spec temp_chanspec = mcp3564_temp_channel_template;
+ struct iio_chan_spec burnout_chanspec = mcp3564_burnout_channel_template;
+ int chan_idx = 0;
+ unsigned int num_ch;
+ u32 inputs[2];
+ const char *node_name;
+ const char *label;
+ int ret;
+
+ num_ch = device_get_child_node_count(dev);
+ if (num_ch == 0)
+ return dev_err_probe(&indio_dev->dev, -ENODEV,
+ "FW has no channels defined\n");
+
+ /* Reserve space for burnout and temperature channel */
+ num_ch += 2;
+
+ if (num_ch > adc->chip_info->num_channels)
+ return dev_err_probe(dev, -EINVAL, "Too many channels %d > %d\n",
+ num_ch, adc->chip_info->num_channels);
+
+ channels = devm_kcalloc(dev, num_ch, sizeof(*channels), GFP_KERNEL);
+ if (!channels)
+ return dev_err_probe(dev, -ENOMEM, "Can't allocate memory\n");
+
+ device_for_each_child_node(dev, child) {
+ node_name = fwnode_get_name(child);
+
+ if (fwnode_property_present(child, "diff-channels")) {
+ ret = fwnode_property_read_u32_array(child,
+ "diff-channels",
+ inputs,
+ ARRAY_SIZE(inputs));
+ chanspec.differential = 1;
+ } else {
+ ret = fwnode_property_read_u32(child, "reg", &inputs[0]);
+
+ chanspec.differential = 0;
+ inputs[1] = MCP3564_AGND;
+ }
+ if (ret) {
+ fwnode_handle_put(child);
+ return ret;
+ }
+
+ if (inputs[0] > MCP3564_INTERNAL_VCM ||
+ inputs[1] > MCP3564_INTERNAL_VCM) {
+ fwnode_handle_put(child);
+ return dev_err_probe(&indio_dev->dev, -EINVAL,
+ "Channel index > %d, for %s\n",
+ MCP3564_INTERNAL_VCM + 1,
+ node_name);
+ }
+
+ chanspec.address = (inputs[0] << 4) | inputs[1];
+ chanspec.channel = inputs[0];
+ chanspec.channel2 = inputs[1];
+ chanspec.scan_index = chan_idx;
+
+ if (fwnode_property_present(child, "label")) {
+ fwnode_property_read_string(child, "label", &label);
+ adc->labels[chan_idx] = label;
+ }
+
+ channels[chan_idx] = chanspec;
+ chan_idx++;
+ }
+
+ /* Add burnout current channel */
+ burnout_chanspec.scan_index = chan_idx;
+ channels[chan_idx] = burnout_chanspec;
+ adc->labels[chan_idx] = mcp3564_channel_labels[0];
+ chanspec.scan_index = chan_idx;
+ chan_idx++;
+
+ /* Add temperature channel */
+ temp_chanspec.scan_index = chan_idx;
+ channels[chan_idx] = temp_chanspec;
+ adc->labels[chan_idx] = mcp3564_channel_labels[1];
+ chan_idx++;
+
+ indio_dev->num_channels = chan_idx;
+ indio_dev->channels = channels;
+
+ return 0;
+}
+
+static void mcp3564_disable_reg(void *reg)
+{
+ regulator_disable(reg);
+}
+
+static void mcp3564_fill_scale_tbls(struct mcp3564_state *adc)
+{
+ unsigned int pow = adc->chip_info->resolution - 1;
+ int ref;
+ unsigned int i;
+ int tmp0;
+ u64 tmp1;
+
+ for (i = 0; i < MCP3564_MAX_PGA; i++) {
+ ref = adc->vref_mv;
+ tmp1 = shift_right((u64)ref * NANO, pow);
+ div_u64_rem(tmp1, NANO, &tmp0);
+
+ tmp1 = tmp1 * mcp3564_hwgain_frac[(2 * i) + 1];
+ tmp0 = (int)div_u64(tmp1, mcp3564_hwgain_frac[2 * i]);
+
+ adc->scale_tbls[i][1] = tmp0;
+ }
+}
+
+static int mcp3564_config(struct iio_dev *indio_dev)
+{
+ struct mcp3564_state *adc = iio_priv(indio_dev);
+ struct device *dev = &adc->spi->dev;
+ const struct spi_device_id *dev_id;
+ u8 tmp_reg;
+ u16 tmp_u16;
+ enum mcp3564_ids ids;
+ int ret = 0;
+ unsigned int tmp = 0x01;
+ bool err = true;
+
+ /*
+ * The address is set on a per-device basis by fuses in the factory,
+ * configured on request. If not requested, the fuses are set for 0x1.
+ * The device address is part of the device markings to avoid
+ * potential confusion. This address is coded on two bits, so four possible
+ * addresses are available when multiple devices are present on the same
+ * SPI bus with only one Chip Select line for all devices.
+ */
+ device_property_read_u32(dev, "microchip,hw-device-address", &tmp);
+
+ if (tmp > 3) {
+ dev_err_probe(dev, tmp,
+ "invalid device address. Must be in range 0-3.\n");
+ return -EINVAL;
+ }
+
+ adc->dev_addr = FIELD_GET(MCP3564_HW_ADDR_MASK, tmp);
+
+ dev_dbg(dev, "use HW device address %i\n", adc->dev_addr);
+
+ ret = mcp3564_read_8bits(adc, MCP3564_RESERVED_C_REG, &tmp_reg);
+ if (ret < 0)
+ return ret;
+
+ switch (tmp_reg) {
+ case MCP3564_C_REG_DEFAULT:
+ adc->have_vref = false;
+ break;
+ case MCP3564R_C_REG_DEFAULT:
+ adc->have_vref = true;
+ break;
+ default:
+ dev_info(dev, "Unknown chip found: %d\n", tmp_reg);
+ err = true;
+ }
+
+ if (!err) {
+ ret = mcp3564_read_16bits(adc, MCP3564_RESERVED_E_REG, &tmp_u16);
+ if (ret < 0)
+ return ret;
+
+ switch (tmp_u16 & MCP3564_HW_ID_MASK) {
+ case MCP3461_HW_ID:
+ if (adc->have_vref)
+ ids = mcp3461r;
+ else
+ ids = mcp3461;
+ break;
+ case MCP3462_HW_ID:
+ if (adc->have_vref)
+ ids = mcp3462r;
+ else
+ ids = mcp3462;
+ break;
+ case MCP3464_HW_ID:
+ if (adc->have_vref)
+ ids = mcp3464r;
+ else
+ ids = mcp3464;
+ break;
+ case MCP3561_HW_ID:
+ if (adc->have_vref)
+ ids = mcp3561r;
+ else
+ ids = mcp3561;
+ break;
+ case MCP3562_HW_ID:
+ if (adc->have_vref)
+ ids = mcp3562r;
+ else
+ ids = mcp3562;
+ break;
+ case MCP3564_HW_ID:
+ if (adc->have_vref)
+ ids = mcp3564r;
+ else
+ ids = mcp3564;
+ break;
+ default:
+ dev_info(dev, "Unknown chip found: %d\n", tmp_u16);
+ err = true;
+ }
+ }
+
+ if (err) {
+ /*
+ * If failed to identify the hardware based on internal registers,
+ * try using fallback compatible in device tree to deal with some newer part number.
+ */
+ adc->chip_info = spi_get_device_match_data(adc->spi);
+ if (!adc->chip_info) {
+ dev_id = spi_get_device_id(adc->spi);
+ adc->chip_info = (const struct mcp3564_chip_info *)dev_id->driver_data;
+ }
+
+ adc->have_vref = adc->chip_info->have_vref;
+ } else {
+ adc->chip_info = &mcp3564_chip_infos_tbl[ids];
+ }
+
+ dev_dbg(dev, "Found %s chip\n", adc->chip_info->name);
+
+ adc->vref = devm_regulator_get_optional(dev, "vref");
+ if (IS_ERR(adc->vref)) {
+ if (PTR_ERR(adc->vref) != -ENODEV)
+ return dev_err_probe(dev, PTR_ERR(adc->vref),
+ "failed to get regulator\n");
+
+ /* Check if chip has internal vref */
+ if (!adc->have_vref)
+ return dev_err_probe(dev, PTR_ERR(adc->vref),
+ "Unknown Vref\n");
+ adc->vref = NULL;
+ dev_dbg(dev, "%s: Using internal Vref\n", __func__);
+ } else {
+ ret = regulator_enable(adc->vref);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(dev, mcp3564_disable_reg,
+ adc->vref);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "%s: Using External Vref\n", __func__);
+
+ ret = regulator_get_voltage(adc->vref);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "Failed to read vref regulator\n");
+
+ adc->vref_mv = ret / MILLI;
+ }
+
+ ret = mcp3564_parse_fw_children(indio_dev);
+ if (ret)
+ return ret;
+
+ /*
+ * Command sequence that ensures a recovery with the desired settings
+ * in any cases of loss-of-power scenario (Full Chip Reset):
+ * - Write LOCK register to 0xA5
+ * - Write IRQ register to 0x03
+ * - Send "Device Full Reset" fast command
+ * - Wait 1ms for "Full Reset" to complete
+ */
+ ret = mcp3564_write_8bits(adc, MCP3564_LOCK_REG, MCP3564_LOCK_WRITE_ACCESS_PASSWORD);
+ if (ret)
+ return ret;
+
+ ret = mcp3564_write_8bits(adc, MCP3564_IRQ_REG, 0x03);
+ if (ret)
+ return ret;
+
+ ret = mcp3564_fast_cmd(adc, MCP3564_FASTCMD_RESET);
+ if (ret)
+ return ret;
+
+ /*
+ * After Full reset wait some time to be able to fully reset the part and place
+ * it back in a default configuration.
+ * From datasheet: POR (Power On Reset Time) is ~1us
+ * 1ms should be enough.
+ */
+ mdelay(1);
+
+ /* set a gain of 1x for GAINCAL */
+ ret = mcp3564_write_24bits(adc, MCP3564_GAINCAL_REG, MCP3564_DEFAULT_GAINCAL);
+ if (ret)
+ return ret;
+
+ adc->calib_scale = MCP3564_DEFAULT_GAINCAL;
+
+ ret = mcp3564_write_24bits(adc, MCP3564_OFFSETCAL_REG, MCP3564_DEFAULT_OFFSETCAL);
+ if (ret)
+ return ret;
+
+ ret = mcp3564_write_24bits(adc, MCP3564_TIMER_REG, MCP3564_TIMER_DEFAULT_VALUE);
+ if (ret)
+ return ret;
+
+ ret = mcp3564_write_24bits(adc, MCP3564_SCAN_REG,
+ MCP3564_SCAN_DELAY_TIME_SET(MCP3564_NO_DELAY) |
+ MCP3564_SCAN_CH_SEL_SET(MCP3564_SCAN_DEFAULT_VALUE));
+ if (ret)
+ return ret;
+
+ ret = mcp3564_write_8bits(adc, MCP3564_MUX_REG, MCP3564_MUX_SET(MCP3564_CH0, MCP3564_CH1));
+ if (ret)
+ return ret;
+
+ ret = mcp3564_write_8bits(adc, MCP3564_IRQ_REG,
+ FIELD_PREP(MCP3464_EN_FASTCMD_MASK, 1) |
+ FIELD_PREP(MCP3464_EN_STP_MASK, 1));
+ if (ret)
+ return ret;
+
+ tmp_reg = FIELD_PREP(MCP3464_CONFIG3_CONV_MODE_MASK,
+ MCP3464_CONFIG3_CONV_MODE_ONE_SHOT_STANDBY);
+ tmp_reg |= FIELD_PREP(MCP3464_CONFIG3_DATA_FORMAT_MASK,
+ MCP3464_CONFIG3_DATA_FMT_32B_SGN_EXT);
+ tmp_reg |= MCP3464_CONFIG3_EN_OFFCAL_MASK;
+ tmp_reg |= MCP3464_CONFIG3_EN_GAINCAL_MASK;
+
+ ret = mcp3564_write_8bits(adc, MCP3564_CONFIG3_REG, tmp_reg);
+ if (ret)
+ return ret;
+
+ tmp_reg = FIELD_PREP(MCP3564_CONFIG2_BOOST_CURRENT_MASK, MCP3564_BOOST_CURRENT_x1_00);
+ tmp_reg |= FIELD_PREP(MCP3564_CONFIG2_HARDWARE_GAIN_MASK, 0x01);
+ tmp_reg |= FIELD_PREP(MCP3564_CONFIG2_AZ_MUX_MASK, 1);
+
+ ret = mcp3564_write_8bits(adc, MCP3564_CONFIG2_REG, tmp_reg);
+ if (ret)
+ return ret;
+
+ adc->hwgain = 0x01;
+ adc->auto_zeroing_mux = true;
+ adc->auto_zeroing_ref = false;
+ adc->current_boost_mode = MCP3564_BOOST_CURRENT_x1_00;
+
+ tmp_reg = FIELD_PREP(MCP3564_CONFIG1_OVERSPL_RATIO_MASK, MCP3564_OVERSAMPLING_RATIO_98304);
+
+ ret = mcp3564_write_8bits(adc, MCP3564_CONFIG1_REG, tmp_reg);
+ if (ret)
+ return ret;
+
+ adc->oversampling = MCP3564_OVERSAMPLING_RATIO_98304;
+
+ tmp_reg = FIELD_PREP(MCP3564_CONFIG0_ADC_MODE_MASK, MCP3564_ADC_MODE_STANDBY);
+ tmp_reg |= FIELD_PREP(MCP3564_CONFIG0_CS_SEL_MASK, MCP3564_CONFIG0_CS_SEL_0_0_uA);
+ tmp_reg |= FIELD_PREP(MCP3564_CONFIG0_CLK_SEL_MASK, MCP3564_CONFIG0_USE_INT_CLK);
+ tmp_reg |= MCP3456_CONFIG0_BIT6_DEFAULT;
+
+ if (!adc->vref) {
+ tmp_reg |= FIELD_PREP(MCP3456_CONFIG0_VREF_MASK, 1);
+ adc->vref_mv = MCP3564R_INT_VREF_MV;
+ }
+
+ ret = mcp3564_write_8bits(adc, MCP3564_CONFIG0_REG, tmp_reg);
+
+ adc->burnout_mode = MCP3564_CONFIG0_CS_SEL_0_0_uA;
+
+ return ret;
+}
+
+static IIO_DEVICE_ATTR(auto_zeroing_ref_enable, 0644,
+ mcp3564_auto_zeroing_ref_show,
+ mcp3564_auto_zeroing_ref_store, 0);
+
+static IIO_DEVICE_ATTR(auto_zeroing_mux_enable, 0644,
+ mcp3564_auto_zeroing_mux_show,
+ mcp3564_auto_zeroing_mux_store, 0);
+
+static struct attribute *mcp3564_attributes[] = {
+ &iio_dev_attr_auto_zeroing_mux_enable.dev_attr.attr,
+ NULL
+};
+
+static struct attribute *mcp3564r_attributes[] = {
+ &iio_dev_attr_auto_zeroing_mux_enable.dev_attr.attr,
+ &iio_dev_attr_auto_zeroing_ref_enable.dev_attr.attr,
+ NULL
+};
+
+static struct attribute_group mcp3564_attribute_group = {
+ .attrs = mcp3564_attributes,
+};
+
+static struct attribute_group mcp3564r_attribute_group = {
+ .attrs = mcp3564r_attributes,
+};
+
+static const struct iio_info mcp3564_info = {
+ .read_raw = mcp3564_read_raw,
+ .read_avail = mcp3564_read_avail,
+ .write_raw = mcp3564_write_raw,
+ .write_raw_get_fmt = mcp3564_write_raw_get_fmt,
+ .read_label = mcp3564_read_label,
+ .attrs = &mcp3564_attribute_group,
+};
+
+static const struct iio_info mcp3564r_info = {
+ .read_raw = mcp3564_read_raw,
+ .read_avail = mcp3564_read_avail,
+ .write_raw = mcp3564_write_raw,
+ .write_raw_get_fmt = mcp3564_write_raw_get_fmt,
+ .read_label = mcp3564_read_label,
+ .attrs = &mcp3564r_attribute_group,
+};
+
+static int mcp3564_probe(struct spi_device *spi)
+{
+ int ret;
+ struct iio_dev *indio_dev;
+ struct mcp3564_state *adc;
+
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc));
+ if (!indio_dev) {
+ dev_err_probe(&indio_dev->dev, PTR_ERR(indio_dev),
+ "Can't allocate iio device\n");
+ return -ENOMEM;
+ }
+
+ adc = iio_priv(indio_dev);
+ adc->spi = spi;
+
+ dev_dbg(&spi->dev, "%s: probe(spi = 0x%p)\n", __func__, spi);
+
+ /*
+ * Do any chip specific initialization, e.g:
+ * read/write some registers
+ * enable/disable certain channels
+ * change the sampling rate to the requested value
+ */
+ ret = mcp3564_config(indio_dev);
+ if (ret)
+ return dev_err_probe(&spi->dev, ret,
+ "Can't configure MCP356X device\n");
+
+ dev_dbg(&spi->dev, "%s: Vref (mV): %d\n", __func__, adc->vref_mv);
+
+ mcp3564_fill_scale_tbls(adc);
+
+ indio_dev->name = adc->chip_info->name;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ if (!adc->vref)
+ indio_dev->info = &mcp3564r_info;
+ else
+ indio_dev->info = &mcp3564_info;
+
+ mutex_init(&adc->lock);
+
+ ret = devm_iio_device_register(&spi->dev, indio_dev);
+ if (ret)
+ return dev_err_probe(&spi->dev, ret,
+ "Can't register IIO device\n");
+
+ return 0;
+}
+
+static const struct of_device_id mcp3564_dt_ids[] = {
+ { .compatible = "microchip,mcp3461", .data = &mcp3564_chip_infos_tbl[mcp3461] },
+ { .compatible = "microchip,mcp3462", .data = &mcp3564_chip_infos_tbl[mcp3462] },
+ { .compatible = "microchip,mcp3464", .data = &mcp3564_chip_infos_tbl[mcp3464] },
+ { .compatible = "microchip,mcp3561", .data = &mcp3564_chip_infos_tbl[mcp3561] },
+ { .compatible = "microchip,mcp3562", .data = &mcp3564_chip_infos_tbl[mcp3562] },
+ { .compatible = "microchip,mcp3564", .data = &mcp3564_chip_infos_tbl[mcp3564] },
+ { .compatible = "microchip,mcp3461r", .data = &mcp3564_chip_infos_tbl[mcp3461r] },
+ { .compatible = "microchip,mcp3462r", .data = &mcp3564_chip_infos_tbl[mcp3462r] },
+ { .compatible = "microchip,mcp3464r", .data = &mcp3564_chip_infos_tbl[mcp3464r] },
+ { .compatible = "microchip,mcp3561r", .data = &mcp3564_chip_infos_tbl[mcp3561r] },
+ { .compatible = "microchip,mcp3562r", .data = &mcp3564_chip_infos_tbl[mcp3562r] },
+ { .compatible = "microchip,mcp3564r", .data = &mcp3564_chip_infos_tbl[mcp3564r] },
+ { }
+};
+MODULE_DEVICE_TABLE(of, mcp3564_dt_ids);
+
+static const struct spi_device_id mcp3564_id[] = {
+ { "mcp3461", (kernel_ulong_t)&mcp3564_chip_infos_tbl[mcp3461] },
+ { "mcp3462", (kernel_ulong_t)&mcp3564_chip_infos_tbl[mcp3462] },
+ { "mcp3464", (kernel_ulong_t)&mcp3564_chip_infos_tbl[mcp3464] },
+ { "mcp3561", (kernel_ulong_t)&mcp3564_chip_infos_tbl[mcp3561] },
+ { "mcp3562", (kernel_ulong_t)&mcp3564_chip_infos_tbl[mcp3562] },
+ { "mcp3564", (kernel_ulong_t)&mcp3564_chip_infos_tbl[mcp3564] },
+ { "mcp3461r", (kernel_ulong_t)&mcp3564_chip_infos_tbl[mcp3461r] },
+ { "mcp3462r", (kernel_ulong_t)&mcp3564_chip_infos_tbl[mcp3462r] },
+ { "mcp3464r", (kernel_ulong_t)&mcp3564_chip_infos_tbl[mcp3464r] },
+ { "mcp3561r", (kernel_ulong_t)&mcp3564_chip_infos_tbl[mcp3561r] },
+ { "mcp3562r", (kernel_ulong_t)&mcp3564_chip_infos_tbl[mcp3562r] },
+ { "mcp3564r", (kernel_ulong_t)&mcp3564_chip_infos_tbl[mcp3564r] },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, mcp3564_id);
+
+static struct spi_driver mcp3564_driver = {
+ .driver = {
+ .name = "mcp3564",
+ .of_match_table = mcp3564_dt_ids,
+ },
+ .probe = mcp3564_probe,
+ .id_table = mcp3564_id,
+};
+
+module_spi_driver(mcp3564_driver);
+
+MODULE_AUTHOR("Marius Cristea <marius.cristea@microchip.com>");
+MODULE_DESCRIPTION("Microchip MCP346x/MCP346xR and MCP356x/MCP346xR ADCs");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/mcp3911.c b/drivers/iio/adc/mcp3911.c
index 974c5bd923a6..d864558bc087 100644
--- a/drivers/iio/adc/mcp3911.c
+++ b/drivers/iio/adc/mcp3911.c
@@ -29,11 +29,11 @@
#define MCP3911_REG_MOD 0x06
#define MCP3911_REG_PHASE 0x07
#define MCP3911_REG_GAIN 0x09
-#define MCP3911_GAIN_MASK(ch) (GENMASK(2, 0) << 3 * ch)
-#define MCP3911_GAIN_VAL(ch, val) ((val << 3 * ch) & MCP3911_GAIN_MASK(ch))
+#define MCP3911_GAIN_MASK(ch) (GENMASK(2, 0) << 3 * (ch))
+#define MCP3911_GAIN_VAL(ch, val) ((val << 3 * (ch)) & MCP3911_GAIN_MASK(ch))
#define MCP3911_REG_STATUSCOM 0x0a
-#define MCP3911_STATUSCOM_DRHIZ BIT(12)
+#define MCP3911_STATUSCOM_DRHIZ BIT(12)
#define MCP3911_STATUSCOM_READ GENMASK(7, 6)
#define MCP3911_STATUSCOM_CH1_24WIDTH BIT(4)
#define MCP3911_STATUSCOM_CH0_24WIDTH BIT(3)
@@ -51,8 +51,8 @@
#define MCP3911_REG_GAINCAL_CH1 0x17
#define MCP3911_REG_VREFCAL 0x1a
-#define MCP3911_CHANNEL(x) (MCP3911_REG_CHANNEL0 + x * 3)
-#define MCP3911_OFFCAL(x) (MCP3911_REG_OFFCAL_CH0 + x * 6)
+#define MCP3911_CHANNEL(ch) (MCP3911_REG_CHANNEL0 + (ch) * 3)
+#define MCP3911_OFFCAL(ch) (MCP3911_REG_OFFCAL_CH0 + (ch) * 6)
/* Internal voltage reference in mV */
#define MCP3911_INT_VREF_MV 1200
@@ -61,12 +61,56 @@
#define MCP3911_REG_WRITE(reg, id) ((((reg) << 1) | ((id) << 6) | (0 << 0)) & 0xff)
#define MCP3911_REG_MASK GENMASK(4, 1)
-#define MCP3911_NUM_CHANNELS 2
#define MCP3911_NUM_SCALES 6
+/* Registers compatible with MCP3910 */
+#define MCP3910_REG_STATUSCOM 0x0c
+#define MCP3910_STATUSCOM_READ GENMASK(23, 22)
+#define MCP3910_STATUSCOM_DRHIZ BIT(20)
+
+#define MCP3910_REG_GAIN 0x0b
+
+#define MCP3910_REG_CONFIG0 0x0d
+#define MCP3910_CONFIG0_EN_OFFCAL BIT(23)
+#define MCP3910_CONFIG0_OSR GENMASK(15, 13)
+
+#define MCP3910_REG_CONFIG1 0x0e
+#define MCP3910_CONFIG1_CLKEXT BIT(6)
+#define MCP3910_CONFIG1_VREFEXT BIT(7)
+
+#define MCP3910_REG_OFFCAL_CH0 0x0f
+#define MCP3910_OFFCAL(ch) (MCP3910_REG_OFFCAL_CH0 + (ch) * 6)
+
+/* Maximal number of channels used by the MCP39XX family */
+#define MCP39XX_MAX_NUM_CHANNELS 8
+
static const int mcp3911_osr_table[] = { 32, 64, 128, 256, 512, 1024, 2048, 4096 };
static u32 mcp3911_scale_table[MCP3911_NUM_SCALES][2];
+enum mcp3911_id {
+ MCP3910,
+ MCP3911,
+ MCP3912,
+ MCP3913,
+ MCP3914,
+ MCP3918,
+ MCP3919,
+};
+
+struct mcp3911;
+struct mcp3911_chip_info {
+ const struct iio_chan_spec *channels;
+ unsigned int num_channels;
+
+ int (*config)(struct mcp3911 *adc);
+ int (*get_osr)(struct mcp3911 *adc, u32 *val);
+ int (*set_osr)(struct mcp3911 *adc, u32 val);
+ int (*enable_offset)(struct mcp3911 *adc, bool enable);
+ int (*get_offset)(struct mcp3911 *adc, int channel, int *val);
+ int (*set_offset)(struct mcp3911 *adc, int channel, int val);
+ int (*set_scale)(struct mcp3911 *adc, int channel, u32 val);
+};
+
struct mcp3911 {
struct spi_device *spi;
struct mutex lock;
@@ -74,14 +118,15 @@ struct mcp3911 {
struct clk *clki;
u32 dev_addr;
struct iio_trigger *trig;
- u32 gain[MCP3911_NUM_CHANNELS];
+ u32 gain[MCP39XX_MAX_NUM_CHANNELS];
+ const struct mcp3911_chip_info *chip;
struct {
- u32 channels[MCP3911_NUM_CHANNELS];
+ u32 channels[MCP39XX_MAX_NUM_CHANNELS];
s64 ts __aligned(8);
} scan;
u8 tx_buf __aligned(IIO_DMA_MINALIGN);
- u8 rx_buf[MCP3911_NUM_CHANNELS * 3];
+ u8 rx_buf[MCP39XX_MAX_NUM_CHANNELS * 3];
};
static int mcp3911_read(struct mcp3911 *adc, u8 reg, u32 *val, u8 len)
@@ -111,8 +156,7 @@ static int mcp3911_write(struct mcp3911 *adc, u8 reg, u32 val, u8 len)
return spi_write(adc->spi, &val, len + 1);
}
-static int mcp3911_update(struct mcp3911 *adc, u8 reg, u32 mask,
- u32 val, u8 len)
+static int mcp3911_update(struct mcp3911 *adc, u8 reg, u32 mask, u32 val, u8 len)
{
u32 tmp;
int ret;
@@ -126,9 +170,115 @@ static int mcp3911_update(struct mcp3911 *adc, u8 reg, u32 mask,
return mcp3911_write(adc, reg, val, len);
}
+static int mcp3910_enable_offset(struct mcp3911 *adc, bool enable)
+{
+ unsigned int mask = MCP3910_CONFIG0_EN_OFFCAL;
+ unsigned int value = enable ? mask : 0;
+
+ return mcp3911_update(adc, MCP3910_REG_CONFIG0, mask, value, 3);
+}
+
+static int mcp3910_get_offset(struct mcp3911 *adc, int channel, int *val)
+{
+ return mcp3911_read(adc, MCP3910_OFFCAL(channel), val, 3);
+}
+
+static int mcp3910_set_offset(struct mcp3911 *adc, int channel, int val)
+{
+ int ret;
+
+ ret = mcp3911_write(adc, MCP3910_OFFCAL(channel), val, 3);
+ if (ret)
+ return ret;
+
+ return adc->chip->enable_offset(adc, 1);
+}
+
+static int mcp3911_enable_offset(struct mcp3911 *adc, bool enable)
+{
+ unsigned int mask = MCP3911_STATUSCOM_EN_OFFCAL;
+ unsigned int value = enable ? mask : 0;
+
+ return mcp3911_update(adc, MCP3911_REG_STATUSCOM, mask, value, 2);
+}
+
+static int mcp3911_get_offset(struct mcp3911 *adc, int channel, int *val)
+{
+ return mcp3911_read(adc, MCP3911_OFFCAL(channel), val, 3);
+}
+
+static int mcp3911_set_offset(struct mcp3911 *adc, int channel, int val)
+{
+ int ret;
+
+ ret = mcp3911_write(adc, MCP3911_OFFCAL(channel), val, 3);
+ if (ret)
+ return ret;
+
+ return adc->chip->enable_offset(adc, 1);
+}
+
+static int mcp3910_get_osr(struct mcp3911 *adc, u32 *val)
+{
+ int ret;
+ unsigned int osr;
+
+ ret = mcp3911_read(adc, MCP3910_REG_CONFIG0, val, 3);
+ if (ret)
+ return ret;
+
+ osr = FIELD_GET(MCP3910_CONFIG0_OSR, *val);
+ *val = 32 << osr;
+ return 0;
+}
+
+static int mcp3910_set_osr(struct mcp3911 *adc, u32 val)
+{
+ unsigned int osr = FIELD_PREP(MCP3910_CONFIG0_OSR, val);
+ unsigned int mask = MCP3910_CONFIG0_OSR;
+
+ return mcp3911_update(adc, MCP3910_REG_CONFIG0, mask, osr, 3);
+}
+
+static int mcp3911_set_osr(struct mcp3911 *adc, u32 val)
+{
+ unsigned int osr = FIELD_PREP(MCP3911_CONFIG_OSR, val);
+ unsigned int mask = MCP3911_CONFIG_OSR;
+
+ return mcp3911_update(adc, MCP3911_REG_CONFIG, mask, osr, 2);
+}
+
+static int mcp3911_get_osr(struct mcp3911 *adc, u32 *val)
+{
+ int ret;
+ unsigned int osr;
+
+ ret = mcp3911_read(adc, MCP3911_REG_CONFIG, val, 2);
+ if (ret)
+ return ret;
+
+ osr = FIELD_GET(MCP3911_CONFIG_OSR, *val);
+ *val = 32 << osr;
+ return ret;
+}
+
+static int mcp3910_set_scale(struct mcp3911 *adc, int channel, u32 val)
+{
+ return mcp3911_update(adc, MCP3910_REG_GAIN,
+ MCP3911_GAIN_MASK(channel),
+ MCP3911_GAIN_VAL(channel, val), 3);
+}
+
+static int mcp3911_set_scale(struct mcp3911 *adc, int channel, u32 val)
+{
+ return mcp3911_update(adc, MCP3911_REG_GAIN,
+ MCP3911_GAIN_MASK(channel),
+ MCP3911_GAIN_VAL(channel, val), 1);
+}
+
static int mcp3911_write_raw_get_fmt(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- long mask)
+ struct iio_chan_spec const *chan,
+ long mask)
{
switch (mask) {
case IIO_CHAN_INFO_SCALE:
@@ -141,9 +291,9 @@ static int mcp3911_write_raw_get_fmt(struct iio_dev *indio_dev,
}
static int mcp3911_read_avail(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- const int **vals, int *type, int *length,
- long info)
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long info)
{
switch (info) {
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
@@ -182,20 +332,18 @@ static int mcp3911_read_raw(struct iio_dev *indio_dev,
break;
case IIO_CHAN_INFO_OFFSET:
- ret = mcp3911_read(adc,
- MCP3911_OFFCAL(channel->channel), val, 3);
+
+ ret = adc->chip->get_offset(adc, channel->channel, val);
if (ret)
goto out;
ret = IIO_VAL_INT;
break;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
- ret = mcp3911_read(adc, MCP3911_REG_CONFIG, val, 2);
+ ret = adc->chip->get_osr(adc, val);
if (ret)
goto out;
- *val = FIELD_GET(MCP3911_CONFIG_OSR, *val);
- *val = 32 << *val;
ret = IIO_VAL_INT;
break;
@@ -212,8 +360,8 @@ out:
}
static int mcp3911_write_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *channel, int val,
- int val2, long mask)
+ struct iio_chan_spec const *channel, int val,
+ int val2, long mask)
{
struct mcp3911 *adc = iio_priv(indio_dev);
int ret = -EINVAL;
@@ -223,12 +371,10 @@ static int mcp3911_write_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
for (int i = 0; i < MCP3911_NUM_SCALES; i++) {
if (val == mcp3911_scale_table[i][0] &&
- val2 == mcp3911_scale_table[i][1]) {
+ val2 == mcp3911_scale_table[i][1]) {
adc->gain[channel->channel] = BIT(i);
- ret = mcp3911_update(adc, MCP3911_REG_GAIN,
- MCP3911_GAIN_MASK(channel->channel),
- MCP3911_GAIN_VAL(channel->channel, i), 1);
+ ret = adc->chip->set_scale(adc, channel->channel, i);
}
}
break;
@@ -238,24 +384,13 @@ static int mcp3911_write_raw(struct iio_dev *indio_dev,
goto out;
}
- /* Write offset */
- ret = mcp3911_write(adc, MCP3911_OFFCAL(channel->channel), val,
- 3);
- if (ret)
- goto out;
-
- /* Enable offset*/
- ret = mcp3911_update(adc, MCP3911_REG_STATUSCOM,
- MCP3911_STATUSCOM_EN_OFFCAL,
- MCP3911_STATUSCOM_EN_OFFCAL, 2);
+ ret = adc->chip->set_offset(adc, channel->channel, val);
break;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
for (int i = 0; i < ARRAY_SIZE(mcp3911_osr_table); i++) {
if (val == mcp3911_osr_table[i]) {
- val = FIELD_PREP(MCP3911_CONFIG_OSR, i);
- ret = mcp3911_update(adc, MCP3911_REG_CONFIG, MCP3911_CONFIG_OSR,
- val, 2);
+ ret = adc->chip->set_osr(adc, i);
break;
}
}
@@ -269,6 +404,7 @@ out:
static int mcp3911_calc_scale_table(struct mcp3911 *adc)
{
+ struct device *dev = &adc->spi->dev;
u32 ref = MCP3911_INT_VREF_MV;
u32 div;
int ret;
@@ -277,10 +413,7 @@ static int mcp3911_calc_scale_table(struct mcp3911 *adc)
if (adc->vref) {
ret = regulator_get_voltage(adc->vref);
if (ret < 0) {
- dev_err(&adc->spi->dev,
- "failed to get vref voltage: %d\n",
- ret);
- return ret;
+ return dev_err_probe(dev, ret, "failed to get vref voltage\n");
}
ref = ret / 1000;
@@ -326,24 +459,73 @@ static int mcp3911_calc_scale_table(struct mcp3911 *adc)
}, \
}
+static const struct iio_chan_spec mcp3910_channels[] = {
+ MCP3911_CHAN(0),
+ MCP3911_CHAN(1),
+ IIO_CHAN_SOFT_TIMESTAMP(2),
+};
+
static const struct iio_chan_spec mcp3911_channels[] = {
MCP3911_CHAN(0),
MCP3911_CHAN(1),
IIO_CHAN_SOFT_TIMESTAMP(2),
};
+static const struct iio_chan_spec mcp3912_channels[] = {
+ MCP3911_CHAN(0),
+ MCP3911_CHAN(1),
+ MCP3911_CHAN(2),
+ MCP3911_CHAN(3),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
+static const struct iio_chan_spec mcp3913_channels[] = {
+ MCP3911_CHAN(0),
+ MCP3911_CHAN(1),
+ MCP3911_CHAN(2),
+ MCP3911_CHAN(3),
+ MCP3911_CHAN(4),
+ MCP3911_CHAN(5),
+ IIO_CHAN_SOFT_TIMESTAMP(6),
+};
+
+static const struct iio_chan_spec mcp3914_channels[] = {
+ MCP3911_CHAN(0),
+ MCP3911_CHAN(1),
+ MCP3911_CHAN(2),
+ MCP3911_CHAN(3),
+ MCP3911_CHAN(4),
+ MCP3911_CHAN(5),
+ MCP3911_CHAN(6),
+ MCP3911_CHAN(7),
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+};
+
+static const struct iio_chan_spec mcp3918_channels[] = {
+ MCP3911_CHAN(0),
+ IIO_CHAN_SOFT_TIMESTAMP(1),
+};
+
+static const struct iio_chan_spec mcp3919_channels[] = {
+ MCP3911_CHAN(0),
+ MCP3911_CHAN(1),
+ MCP3911_CHAN(2),
+ IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
static irqreturn_t mcp3911_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct mcp3911 *adc = iio_priv(indio_dev);
+ struct device *dev = &adc->spi->dev;
struct spi_transfer xfer[] = {
{
.tx_buf = &adc->tx_buf,
.len = 1,
}, {
.rx_buf = adc->rx_buf,
- .len = sizeof(adc->rx_buf),
+ .len = (adc->chip->num_channels - 1) * 3,
},
};
int scan_index;
@@ -354,8 +536,7 @@ static irqreturn_t mcp3911_trigger_handler(int irq, void *p)
adc->tx_buf = MCP3911_REG_READ(MCP3911_CHANNEL(0), adc->dev_addr);
ret = spi_sync_transfer(adc->spi, xfer, ARRAY_SIZE(xfer));
if (ret < 0) {
- dev_warn(&adc->spi->dev,
- "failed to get conversion data\n");
+ dev_warn(dev, "failed to get conversion data\n");
goto out;
}
@@ -387,43 +568,25 @@ static int mcp3911_config(struct mcp3911 *adc)
u32 regval;
int ret;
- ret = device_property_read_u32(dev, "microchip,device-addr", &adc->dev_addr);
-
- /*
- * Fallback to "device-addr" due to historical mismatch between
- * dt-bindings and implementation
- */
- if (ret)
- device_property_read_u32(dev, "device-addr", &adc->dev_addr);
- if (adc->dev_addr > 3) {
- dev_err(&adc->spi->dev,
- "invalid device address (%i). Must be in range 0-3.\n",
- adc->dev_addr);
- return -EINVAL;
- }
- dev_dbg(&adc->spi->dev, "use device address %i\n", adc->dev_addr);
-
ret = mcp3911_read(adc, MCP3911_REG_CONFIG, &regval, 2);
if (ret)
return ret;
regval &= ~MCP3911_CONFIG_VREFEXT;
if (adc->vref) {
- dev_dbg(&adc->spi->dev, "use external voltage reference\n");
+ dev_dbg(dev, "use external voltage reference\n");
regval |= FIELD_PREP(MCP3911_CONFIG_VREFEXT, 1);
} else {
- dev_dbg(&adc->spi->dev,
- "use internal voltage reference (1.2V)\n");
+ dev_dbg(dev, "use internal voltage reference (1.2V)\n");
regval |= FIELD_PREP(MCP3911_CONFIG_VREFEXT, 0);
}
regval &= ~MCP3911_CONFIG_CLKEXT;
if (adc->clki) {
- dev_dbg(&adc->spi->dev, "use external clock as clocksource\n");
+ dev_dbg(dev, "use external clock as clocksource\n");
regval |= FIELD_PREP(MCP3911_CONFIG_CLKEXT, 1);
} else {
- dev_dbg(&adc->spi->dev,
- "use crystal oscillator as clocksource\n");
+ dev_dbg(dev, "use crystal oscillator as clocksource\n");
regval |= FIELD_PREP(MCP3911_CONFIG_CLKEXT, 0);
}
@@ -439,7 +602,97 @@ static int mcp3911_config(struct mcp3911 *adc)
regval &= ~MCP3911_STATUSCOM_READ;
regval |= FIELD_PREP(MCP3911_STATUSCOM_READ, 0x02);
- return mcp3911_write(adc, MCP3911_REG_STATUSCOM, regval, 2);
+ regval &= ~MCP3911_STATUSCOM_DRHIZ;
+ if (device_property_read_bool(dev, "microchip,data-ready-hiz"))
+ regval |= FIELD_PREP(MCP3911_STATUSCOM_DRHIZ, 0);
+ else
+ regval |= FIELD_PREP(MCP3911_STATUSCOM_DRHIZ, 1);
+
+ /* Disable offset to ignore any old values in offset register */
+ regval &= ~MCP3911_STATUSCOM_EN_OFFCAL;
+
+ ret = mcp3911_write(adc, MCP3911_REG_STATUSCOM, regval, 2);
+ if (ret)
+ return ret;
+
+ /* Set gain to 1 for all channels */
+ ret = mcp3911_read(adc, MCP3911_REG_GAIN, &regval, 1);
+ if (ret)
+ return ret;
+
+ for (int i = 0; i < adc->chip->num_channels - 1; i++) {
+ adc->gain[i] = 1;
+ regval &= ~MCP3911_GAIN_MASK(i);
+ }
+
+ return mcp3911_write(adc, MCP3911_REG_GAIN, regval, 1);
+}
+
+static int mcp3910_config(struct mcp3911 *adc)
+{
+ struct device *dev = &adc->spi->dev;
+ u32 regval;
+ int ret;
+
+ ret = mcp3911_read(adc, MCP3910_REG_CONFIG1, &regval, 3);
+ if (ret)
+ return ret;
+
+ regval &= ~MCP3910_CONFIG1_VREFEXT;
+ if (adc->vref) {
+ dev_dbg(dev, "use external voltage reference\n");
+ regval |= FIELD_PREP(MCP3910_CONFIG1_VREFEXT, 1);
+ } else {
+ dev_dbg(dev, "use internal voltage reference (1.2V)\n");
+ regval |= FIELD_PREP(MCP3910_CONFIG1_VREFEXT, 0);
+ }
+
+ regval &= ~MCP3910_CONFIG1_CLKEXT;
+ if (adc->clki) {
+ dev_dbg(dev, "use external clock as clocksource\n");
+ regval |= FIELD_PREP(MCP3910_CONFIG1_CLKEXT, 1);
+ } else {
+ dev_dbg(dev, "use crystal oscillator as clocksource\n");
+ regval |= FIELD_PREP(MCP3910_CONFIG1_CLKEXT, 0);
+ }
+
+ ret = mcp3911_write(adc, MCP3910_REG_CONFIG1, regval, 3);
+ if (ret)
+ return ret;
+
+ ret = mcp3911_read(adc, MCP3910_REG_STATUSCOM, &regval, 3);
+ if (ret)
+ return ret;
+
+ /* Address counter incremented, cycle through register types */
+ regval &= ~MCP3910_STATUSCOM_READ;
+ regval |= FIELD_PREP(MCP3910_STATUSCOM_READ, 0x02);
+
+ regval &= ~MCP3910_STATUSCOM_DRHIZ;
+ if (device_property_read_bool(dev, "microchip,data-ready-hiz"))
+ regval |= FIELD_PREP(MCP3910_STATUSCOM_DRHIZ, 0);
+ else
+ regval |= FIELD_PREP(MCP3910_STATUSCOM_DRHIZ, 1);
+
+ ret = mcp3911_write(adc, MCP3910_REG_STATUSCOM, regval, 3);
+ if (ret)
+ return ret;
+
+ /* Set gain to 1 for all channels */
+ ret = mcp3911_read(adc, MCP3910_REG_GAIN, &regval, 3);
+ if (ret)
+ return ret;
+
+ for (int i = 0; i < adc->chip->num_channels - 1; i++) {
+ adc->gain[i] = 1;
+ regval &= ~MCP3911_GAIN_MASK(i);
+ }
+ ret = mcp3911_write(adc, MCP3910_REG_GAIN, regval, 3);
+ if (ret)
+ return ret;
+
+ /* Disable offset to ignore any old values in offset register */
+ return adc->chip->enable_offset(adc, 0);
}
static void mcp3911_cleanup_regulator(void *vref)
@@ -466,26 +719,25 @@ static const struct iio_trigger_ops mcp3911_trigger_ops = {
static int mcp3911_probe(struct spi_device *spi)
{
+ struct device *dev = &spi->dev;
struct iio_dev *indio_dev;
struct mcp3911 *adc;
int ret;
- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*adc));
if (!indio_dev)
return -ENOMEM;
adc = iio_priv(indio_dev);
adc->spi = spi;
+ adc->chip = spi_get_device_match_data(spi);
- adc->vref = devm_regulator_get_optional(&adc->spi->dev, "vref");
+ adc->vref = devm_regulator_get_optional(dev, "vref");
if (IS_ERR(adc->vref)) {
if (PTR_ERR(adc->vref) == -ENODEV) {
adc->vref = NULL;
} else {
- dev_err(&adc->spi->dev,
- "failed to get regulator (%ld)\n",
- PTR_ERR(adc->vref));
- return PTR_ERR(adc->vref);
+ return dev_err_probe(dev, PTR_ERR(adc->vref), "failed to get regulator\n");
}
} else {
@@ -493,34 +745,35 @@ static int mcp3911_probe(struct spi_device *spi)
if (ret)
return ret;
- ret = devm_add_action_or_reset(&spi->dev,
- mcp3911_cleanup_regulator, adc->vref);
+ ret = devm_add_action_or_reset(dev, mcp3911_cleanup_regulator, adc->vref);
if (ret)
return ret;
}
- adc->clki = devm_clk_get_enabled(&adc->spi->dev, NULL);
+ adc->clki = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(adc->clki)) {
if (PTR_ERR(adc->clki) == -ENOENT) {
adc->clki = NULL;
} else {
- dev_err(&adc->spi->dev,
- "failed to get adc clk (%ld)\n",
- PTR_ERR(adc->clki));
- return PTR_ERR(adc->clki);
+ return dev_err_probe(dev, PTR_ERR(adc->clki), "failed to get adc clk\n");
}
}
- ret = mcp3911_config(adc);
+ /*
+ * Fallback to "device-addr" due to historical mismatch between
+ * dt-bindings and implementation.
+ */
+ ret = device_property_read_u32(dev, "microchip,device-addr", &adc->dev_addr);
if (ret)
- return ret;
+ device_property_read_u32(dev, "device-addr", &adc->dev_addr);
+ if (adc->dev_addr > 3) {
+ return dev_err_probe(dev, -EINVAL,
+ "invalid device address (%i). Must be in range 0-3.\n",
+ adc->dev_addr);
+ }
+ dev_dbg(dev, "use device address %i\n", adc->dev_addr);
- if (device_property_read_bool(&adc->spi->dev, "microchip,data-ready-hiz"))
- ret = mcp3911_update(adc, MCP3911_REG_STATUSCOM, MCP3911_STATUSCOM_DRHIZ,
- 0, 2);
- else
- ret = mcp3911_update(adc, MCP3911_REG_STATUSCOM, MCP3911_STATUSCOM_DRHIZ,
- MCP3911_STATUSCOM_DRHIZ, 2);
+ ret = adc->chip->config(adc);
if (ret)
return ret;
@@ -528,12 +781,12 @@ static int mcp3911_probe(struct spi_device *spi)
if (ret)
return ret;
- /* Set gain to 1 for all channels */
- for (int i = 0; i < MCP3911_NUM_CHANNELS; i++) {
+ /* Set gain to 1 for all channels */
+ for (int i = 0; i < adc->chip->num_channels - 1; i++) {
adc->gain[i] = 1;
ret = mcp3911_update(adc, MCP3911_REG_GAIN,
- MCP3911_GAIN_MASK(i),
- MCP3911_GAIN_VAL(i, 0), 1);
+ MCP3911_GAIN_MASK(i),
+ MCP3911_GAIN_VAL(i, 0), 1);
if (ret)
return ret;
}
@@ -543,21 +796,20 @@ static int mcp3911_probe(struct spi_device *spi)
indio_dev->info = &mcp3911_info;
spi_set_drvdata(spi, indio_dev);
- indio_dev->channels = mcp3911_channels;
- indio_dev->num_channels = ARRAY_SIZE(mcp3911_channels);
+ indio_dev->channels = adc->chip->channels;
+ indio_dev->num_channels = adc->chip->num_channels;
mutex_init(&adc->lock);
if (spi->irq > 0) {
- adc->trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d",
- indio_dev->name,
- iio_device_id(indio_dev));
+ adc->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name,
+ iio_device_id(indio_dev));
if (!adc->trig)
return -ENOMEM;
adc->trig->ops = &mcp3911_trigger_ops;
iio_trigger_set_drvdata(adc->trig, adc);
- ret = devm_iio_trigger_register(&spi->dev, adc->trig);
+ ret = devm_iio_trigger_register(dev, adc->trig);
if (ret)
return ret;
@@ -566,30 +818,120 @@ static int mcp3911_probe(struct spi_device *spi)
* Some platforms might not allow the option to power it down so
* don't enable the interrupt to avoid extra load on the system.
*/
- ret = devm_request_irq(&spi->dev, spi->irq,
- &iio_trigger_generic_data_rdy_poll, IRQF_NO_AUTOEN | IRQF_ONESHOT,
- indio_dev->name, adc->trig);
+ ret = devm_request_irq(dev, spi->irq, &iio_trigger_generic_data_rdy_poll,
+ IRQF_NO_AUTOEN | IRQF_ONESHOT,
+ indio_dev->name, adc->trig);
if (ret)
return ret;
}
- ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
- NULL,
- mcp3911_trigger_handler, NULL);
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
+ mcp3911_trigger_handler, NULL);
if (ret)
return ret;
- return devm_iio_device_register(&adc->spi->dev, indio_dev);
+ return devm_iio_device_register(dev, indio_dev);
}
+static const struct mcp3911_chip_info mcp3911_chip_info[] = {
+ [MCP3910] = {
+ .channels = mcp3910_channels,
+ .num_channels = ARRAY_SIZE(mcp3910_channels),
+ .config = mcp3910_config,
+ .get_osr = mcp3910_get_osr,
+ .set_osr = mcp3910_set_osr,
+ .enable_offset = mcp3910_enable_offset,
+ .get_offset = mcp3910_get_offset,
+ .set_offset = mcp3910_set_offset,
+ .set_scale = mcp3910_set_scale,
+ },
+ [MCP3911] = {
+ .channels = mcp3911_channels,
+ .num_channels = ARRAY_SIZE(mcp3911_channels),
+ .config = mcp3911_config,
+ .get_osr = mcp3911_get_osr,
+ .set_osr = mcp3911_set_osr,
+ .enable_offset = mcp3911_enable_offset,
+ .get_offset = mcp3911_get_offset,
+ .set_offset = mcp3911_set_offset,
+ .set_scale = mcp3911_set_scale,
+ },
+ [MCP3912] = {
+ .channels = mcp3912_channels,
+ .num_channels = ARRAY_SIZE(mcp3912_channels),
+ .config = mcp3910_config,
+ .get_osr = mcp3910_get_osr,
+ .set_osr = mcp3910_set_osr,
+ .enable_offset = mcp3910_enable_offset,
+ .get_offset = mcp3910_get_offset,
+ .set_offset = mcp3910_set_offset,
+ .set_scale = mcp3910_set_scale,
+ },
+ [MCP3913] = {
+ .channels = mcp3913_channels,
+ .num_channels = ARRAY_SIZE(mcp3913_channels),
+ .config = mcp3910_config,
+ .get_osr = mcp3910_get_osr,
+ .set_osr = mcp3910_set_osr,
+ .enable_offset = mcp3910_enable_offset,
+ .get_offset = mcp3910_get_offset,
+ .set_offset = mcp3910_set_offset,
+ .set_scale = mcp3910_set_scale,
+ },
+ [MCP3914] = {
+ .channels = mcp3914_channels,
+ .num_channels = ARRAY_SIZE(mcp3914_channels),
+ .config = mcp3910_config,
+ .get_osr = mcp3910_get_osr,
+ .set_osr = mcp3910_set_osr,
+ .enable_offset = mcp3910_enable_offset,
+ .get_offset = mcp3910_get_offset,
+ .set_offset = mcp3910_set_offset,
+ .set_scale = mcp3910_set_scale,
+ },
+ [MCP3918] = {
+ .channels = mcp3918_channels,
+ .num_channels = ARRAY_SIZE(mcp3918_channels),
+ .config = mcp3910_config,
+ .get_osr = mcp3910_get_osr,
+ .set_osr = mcp3910_set_osr,
+ .enable_offset = mcp3910_enable_offset,
+ .get_offset = mcp3910_get_offset,
+ .set_offset = mcp3910_set_offset,
+ .set_scale = mcp3910_set_scale,
+ },
+ [MCP3919] = {
+ .channels = mcp3919_channels,
+ .num_channels = ARRAY_SIZE(mcp3919_channels),
+ .config = mcp3910_config,
+ .get_osr = mcp3910_get_osr,
+ .set_osr = mcp3910_set_osr,
+ .enable_offset = mcp3910_enable_offset,
+ .get_offset = mcp3910_get_offset,
+ .set_offset = mcp3910_set_offset,
+ .set_scale = mcp3910_set_scale,
+ },
+};
static const struct of_device_id mcp3911_dt_ids[] = {
- { .compatible = "microchip,mcp3911" },
+ { .compatible = "microchip,mcp3910", .data = &mcp3911_chip_info[MCP3910] },
+ { .compatible = "microchip,mcp3911", .data = &mcp3911_chip_info[MCP3911] },
+ { .compatible = "microchip,mcp3912", .data = &mcp3911_chip_info[MCP3912] },
+ { .compatible = "microchip,mcp3913", .data = &mcp3911_chip_info[MCP3913] },
+ { .compatible = "microchip,mcp3914", .data = &mcp3911_chip_info[MCP3914] },
+ { .compatible = "microchip,mcp3918", .data = &mcp3911_chip_info[MCP3918] },
+ { .compatible = "microchip,mcp3919", .data = &mcp3911_chip_info[MCP3919] },
{ }
};
MODULE_DEVICE_TABLE(of, mcp3911_dt_ids);
static const struct spi_device_id mcp3911_id[] = {
- { "mcp3911", 0 },
+ { "mcp3910", (kernel_ulong_t)&mcp3911_chip_info[MCP3910] },
+ { "mcp3911", (kernel_ulong_t)&mcp3911_chip_info[MCP3911] },
+ { "mcp3912", (kernel_ulong_t)&mcp3911_chip_info[MCP3912] },
+ { "mcp3913", (kernel_ulong_t)&mcp3911_chip_info[MCP3913] },
+ { "mcp3914", (kernel_ulong_t)&mcp3911_chip_info[MCP3914] },
+ { "mcp3918", (kernel_ulong_t)&mcp3911_chip_info[MCP3918] },
+ { "mcp3919", (kernel_ulong_t)&mcp3911_chip_info[MCP3919] },
{ }
};
MODULE_DEVICE_TABLE(spi, mcp3911_id);
diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
index 320e3e7e3d4d..a40986fb285c 100644
--- a/drivers/iio/adc/meson_saradc.c
+++ b/drivers/iio/adc/meson_saradc.c
@@ -1437,15 +1437,13 @@ err:
return ret;
}
-static int meson_sar_adc_remove(struct platform_device *pdev)
+static void meson_sar_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
iio_device_unregister(indio_dev);
meson_sar_adc_hw_disable(indio_dev);
-
- return 0;
}
static int meson_sar_adc_suspend(struct device *dev)
@@ -1480,7 +1478,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(meson_sar_adc_pm_ops,
static struct platform_driver meson_sar_adc_driver = {
.probe = meson_sar_adc_probe,
- .remove = meson_sar_adc_remove,
+ .remove_new = meson_sar_adc_remove,
.driver = {
.name = "meson-saradc",
.of_match_table = meson_sar_adc_of_match,
diff --git a/drivers/iio/adc/mp2629_adc.c b/drivers/iio/adc/mp2629_adc.c
index 88e947f300cf..7c66c2cd5be2 100644
--- a/drivers/iio/adc/mp2629_adc.c
+++ b/drivers/iio/adc/mp2629_adc.c
@@ -171,7 +171,7 @@ fail_disable:
return ret;
}
-static int mp2629_adc_remove(struct platform_device *pdev)
+static void mp2629_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct mp2629_adc *info = iio_priv(indio_dev);
@@ -184,8 +184,6 @@ static int mp2629_adc_remove(struct platform_device *pdev)
MP2629_ADC_CONTINUOUS, 0);
regmap_update_bits(info->regmap, MP2629_REG_ADC_CTRL,
MP2629_ADC_START, 0);
-
- return 0;
}
static const struct of_device_id mp2629_adc_of_match[] = {
@@ -200,7 +198,7 @@ static struct platform_driver mp2629_adc_driver = {
.of_match_table = mp2629_adc_of_match,
},
.probe = mp2629_adc_probe,
- .remove = mp2629_adc_remove,
+ .remove_new = mp2629_adc_remove,
};
module_platform_driver(mp2629_adc_driver);
diff --git a/drivers/iio/adc/mt6577_auxadc.c b/drivers/iio/adc/mt6577_auxadc.c
index 0e134777bdd2..370b84c2d0ba 100644
--- a/drivers/iio/adc/mt6577_auxadc.c
+++ b/drivers/iio/adc/mt6577_auxadc.c
@@ -246,6 +246,14 @@ static int mt6577_auxadc_suspend(struct device *dev)
return 0;
}
+static void mt6577_power_off(void *data)
+{
+ struct mt6577_auxadc_device *adc_dev = data;
+
+ mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
+ 0, MT6577_AUXADC_PDN_EN);
+}
+
static int mt6577_auxadc_probe(struct platform_device *pdev)
{
struct mt6577_auxadc_device *adc_dev;
@@ -265,29 +273,18 @@ static int mt6577_auxadc_probe(struct platform_device *pdev)
indio_dev->num_channels = ARRAY_SIZE(mt6577_auxadc_iio_channels);
adc_dev->reg_base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(adc_dev->reg_base)) {
- dev_err(&pdev->dev, "failed to get auxadc base address\n");
- return PTR_ERR(adc_dev->reg_base);
- }
-
- adc_dev->adc_clk = devm_clk_get(&pdev->dev, "main");
- if (IS_ERR(adc_dev->adc_clk)) {
- dev_err(&pdev->dev, "failed to get auxadc clock\n");
- return PTR_ERR(adc_dev->adc_clk);
- }
+ if (IS_ERR(adc_dev->reg_base))
+ return dev_err_probe(&pdev->dev, PTR_ERR(adc_dev->reg_base),
+ "failed to get auxadc base address\n");
- ret = clk_prepare_enable(adc_dev->adc_clk);
- if (ret) {
- dev_err(&pdev->dev, "failed to enable auxadc clock\n");
- return ret;
- }
+ adc_dev->adc_clk = devm_clk_get_enabled(&pdev->dev, "main");
+ if (IS_ERR(adc_dev->adc_clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(adc_dev->adc_clk),
+ "failed to enable auxadc clock\n");
adc_clk_rate = clk_get_rate(adc_dev->adc_clk);
- if (!adc_clk_rate) {
- ret = -EINVAL;
- dev_err(&pdev->dev, "null clock rate\n");
- goto err_disable_clk;
- }
+ if (!adc_clk_rate)
+ return dev_err_probe(&pdev->dev, -EINVAL, "null clock rate\n");
adc_dev->dev_comp = device_get_match_data(&pdev->dev);
@@ -297,35 +294,14 @@ static int mt6577_auxadc_probe(struct platform_device *pdev)
MT6577_AUXADC_PDN_EN, 0);
mdelay(MT6577_AUXADC_POWER_READY_MS);
- platform_set_drvdata(pdev, indio_dev);
-
- ret = iio_device_register(indio_dev);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to register iio device\n");
- goto err_power_off;
- }
-
- return 0;
-
-err_power_off:
- mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
- 0, MT6577_AUXADC_PDN_EN);
-err_disable_clk:
- clk_disable_unprepare(adc_dev->adc_clk);
- return ret;
-}
-
-static int mt6577_auxadc_remove(struct platform_device *pdev)
-{
- struct iio_dev *indio_dev = platform_get_drvdata(pdev);
- struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
+ ret = devm_add_action_or_reset(&pdev->dev, mt6577_power_off, adc_dev);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to add action to managed power off\n");
- mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
- 0, MT6577_AUXADC_PDN_EN);
-
- clk_disable_unprepare(adc_dev->adc_clk);
+ ret = devm_iio_device_register(&pdev->dev, indio_dev);
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret, "failed to register iio device\n");
return 0;
}
@@ -352,7 +328,6 @@ static struct platform_driver mt6577_auxadc_driver = {
.pm = pm_sleep_ptr(&mt6577_auxadc_pm_ops),
},
.probe = mt6577_auxadc_probe,
- .remove = mt6577_auxadc_remove,
};
module_platform_driver(mt6577_auxadc_driver);
diff --git a/drivers/iio/adc/mxs-lradc-adc.c b/drivers/iio/adc/mxs-lradc-adc.c
index a50f39143d3e..2e60c10ee4ff 100644
--- a/drivers/iio/adc/mxs-lradc-adc.c
+++ b/drivers/iio/adc/mxs-lradc-adc.c
@@ -807,7 +807,7 @@ err_trig:
return ret;
}
-static int mxs_lradc_adc_remove(struct platform_device *pdev)
+static void mxs_lradc_adc_remove(struct platform_device *pdev)
{
struct iio_dev *iio = platform_get_drvdata(pdev);
struct mxs_lradc_adc *adc = iio_priv(iio);
@@ -816,8 +816,6 @@ static int mxs_lradc_adc_remove(struct platform_device *pdev)
mxs_lradc_adc_hw_stop(adc);
iio_triggered_buffer_cleanup(iio);
mxs_lradc_adc_trigger_remove(iio);
-
- return 0;
}
static struct platform_driver mxs_lradc_adc_driver = {
@@ -825,7 +823,7 @@ static struct platform_driver mxs_lradc_adc_driver = {
.name = "mxs-lradc-adc",
},
.probe = mxs_lradc_adc_probe,
- .remove = mxs_lradc_adc_remove,
+ .remove_new = mxs_lradc_adc_remove,
};
module_platform_driver(mxs_lradc_adc_driver);
diff --git a/drivers/iio/adc/npcm_adc.c b/drivers/iio/adc/npcm_adc.c
index 3d9207c160eb..3a55465951e7 100644
--- a/drivers/iio/adc/npcm_adc.c
+++ b/drivers/iio/adc/npcm_adc.c
@@ -320,7 +320,7 @@ err_disable_clk:
return ret;
}
-static int npcm_adc_remove(struct platform_device *pdev)
+static void npcm_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct npcm_adc *info = iio_priv(indio_dev);
@@ -333,13 +333,11 @@ static int npcm_adc_remove(struct platform_device *pdev)
if (!IS_ERR(info->vref))
regulator_disable(info->vref);
clk_disable_unprepare(info->adc_clk);
-
- return 0;
}
static struct platform_driver npcm_adc_driver = {
.probe = npcm_adc_probe,
- .remove = npcm_adc_remove,
+ .remove_new = npcm_adc_remove,
.driver = {
.name = "npcm_adc",
.of_match_table = npcm_adc_match,
diff --git a/drivers/iio/adc/palmas_gpadc.c b/drivers/iio/adc/palmas_gpadc.c
index e202ea18af10..203cbbc70719 100644
--- a/drivers/iio/adc/palmas_gpadc.c
+++ b/drivers/iio/adc/palmas_gpadc.c
@@ -457,7 +457,7 @@ static int palmas_gpadc_get_calibrated_code(struct palmas_gpadc *adc,
*
* The gain error include both gain error, as specified in the datasheet, and
* the gain error drift. These paramenters vary depending on device and whether
- * the the channel is calibrated (trimmed) or not.
+ * the channel is calibrated (trimmed) or not.
*/
static int palmas_gpadc_threshold_with_tolerance(int val, const int INL,
const int gain_error,
diff --git a/drivers/iio/adc/qcom-pm8xxx-xoadc.c b/drivers/iio/adc/qcom-pm8xxx-xoadc.c
index 64a3aeb6261c..01c5586df56d 100644
--- a/drivers/iio/adc/qcom-pm8xxx-xoadc.c
+++ b/drivers/iio/adc/qcom-pm8xxx-xoadc.c
@@ -957,7 +957,7 @@ out_disable_vref:
return ret;
}
-static int pm8xxx_xoadc_remove(struct platform_device *pdev)
+static void pm8xxx_xoadc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct pm8xxx_xoadc *adc = iio_priv(indio_dev);
@@ -965,8 +965,6 @@ static int pm8xxx_xoadc_remove(struct platform_device *pdev)
iio_device_unregister(indio_dev);
regulator_disable(adc->vref);
-
- return 0;
}
static const struct xoadc_variant pm8018_variant = {
@@ -1019,7 +1017,7 @@ static struct platform_driver pm8xxx_xoadc_driver = {
.of_match_table = pm8xxx_xoadc_id_table,
},
.probe = pm8xxx_xoadc_probe,
- .remove = pm8xxx_xoadc_remove,
+ .remove_new = pm8xxx_xoadc_remove,
};
module_platform_driver(pm8xxx_xoadc_driver);
diff --git a/drivers/iio/adc/rcar-gyroadc.c b/drivers/iio/adc/rcar-gyroadc.c
index b8972f673c9d..d524f2e8e927 100644
--- a/drivers/iio/adc/rcar-gyroadc.c
+++ b/drivers/iio/adc/rcar-gyroadc.c
@@ -559,7 +559,7 @@ err_clk_if_enable:
return ret;
}
-static int rcar_gyroadc_remove(struct platform_device *pdev)
+static void rcar_gyroadc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct rcar_gyroadc *priv = iio_priv(indio_dev);
@@ -573,8 +573,6 @@ static int rcar_gyroadc_remove(struct platform_device *pdev)
pm_runtime_set_suspended(dev);
clk_disable_unprepare(priv->clk);
rcar_gyroadc_deinit_supplies(indio_dev);
-
- return 0;
}
static int rcar_gyroadc_suspend(struct device *dev)
@@ -603,7 +601,7 @@ static const struct dev_pm_ops rcar_gyroadc_pm_ops = {
static struct platform_driver rcar_gyroadc_driver = {
.probe = rcar_gyroadc_probe,
- .remove = rcar_gyroadc_remove,
+ .remove_new = rcar_gyroadc_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = rcar_gyroadc_match,
diff --git a/drivers/iio/adc/spear_adc.c b/drivers/iio/adc/spear_adc.c
index ad54ef798109..71362c2ddf89 100644
--- a/drivers/iio/adc/spear_adc.c
+++ b/drivers/iio/adc/spear_adc.c
@@ -274,10 +274,9 @@ static int spear_adc_probe(struct platform_device *pdev)
int irq;
indio_dev = devm_iio_device_alloc(dev, sizeof(struct spear_adc_state));
- if (!indio_dev) {
- dev_err(dev, "failed allocating iio device\n");
- return -ENOMEM;
- }
+ if (!indio_dev)
+ return dev_err_probe(dev, -ENOMEM,
+ "failed allocating iio device\n");
st = iio_priv(indio_dev);
@@ -297,37 +296,24 @@ static int spear_adc_probe(struct platform_device *pdev)
st->adc_base_spear3xx =
(struct adc_regs_spear3xx __iomem *)st->adc_base_spear6xx;
- st->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(st->clk)) {
- dev_err(dev, "failed getting clock\n");
- return PTR_ERR(st->clk);
- }
-
- ret = clk_prepare_enable(st->clk);
- if (ret) {
- dev_err(dev, "failed enabling clock\n");
- return ret;
- }
+ st->clk = devm_clk_get_enabled(dev, NULL);
+ if (IS_ERR(st->clk))
+ return dev_err_probe(dev, PTR_ERR(st->clk),
+ "failed enabling clock\n");
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- ret = irq;
- goto errout2;
- }
+ if (irq < 0)
+ return irq;
ret = devm_request_irq(dev, irq, spear_adc_isr, 0, SPEAR_ADC_MOD_NAME,
st);
- if (ret < 0) {
- dev_err(dev, "failed requesting interrupt\n");
- goto errout2;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed requesting interrupt\n");
if (of_property_read_u32(np, "sampling-frequency",
- &st->sampling_freq)) {
- dev_err(dev, "sampling-frequency missing in DT\n");
- ret = -EINVAL;
- goto errout2;
- }
+ &st->sampling_freq))
+ return dev_err_probe(dev, -EINVAL,
+ "sampling-frequency missing in DT\n");
/*
* Optional avg_samples defaults to 0, resulting in single data
@@ -343,8 +329,6 @@ static int spear_adc_probe(struct platform_device *pdev)
spear_adc_configure(st);
- platform_set_drvdata(pdev, indio_dev);
-
init_completion(&st->completion);
indio_dev->name = SPEAR_ADC_MOD_NAME;
@@ -353,28 +337,13 @@ static int spear_adc_probe(struct platform_device *pdev)
indio_dev->channels = spear_adc_iio_channels;
indio_dev->num_channels = ARRAY_SIZE(spear_adc_iio_channels);
- ret = iio_device_register(indio_dev);
+ ret = devm_iio_device_register(dev, indio_dev);
if (ret)
- goto errout2;
+ return ret;
dev_info(dev, "SPEAR ADC driver loaded, IRQ %d\n", irq);
return 0;
-
-errout2:
- clk_disable_unprepare(st->clk);
- return ret;
-}
-
-static int spear_adc_remove(struct platform_device *pdev)
-{
- struct iio_dev *indio_dev = platform_get_drvdata(pdev);
- struct spear_adc_state *st = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
- clk_disable_unprepare(st->clk);
-
- return 0;
}
#ifdef CONFIG_OF
@@ -387,7 +356,6 @@ MODULE_DEVICE_TABLE(of, spear_adc_dt_ids);
static struct platform_driver spear_adc_driver = {
.probe = spear_adc_probe,
- .remove = spear_adc_remove,
.driver = {
.name = SPEAR_ADC_MOD_NAME,
.of_match_table = of_match_ptr(spear_adc_dt_ids),
diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
index 2f082006550f..c19506b0aac8 100644
--- a/drivers/iio/adc/stm32-adc-core.c
+++ b/drivers/iio/adc/stm32-adc-core.c
@@ -708,6 +708,8 @@ static int stm32_adc_probe(struct platform_device *pdev)
struct stm32_adc_priv *priv;
struct device *dev = &pdev->dev;
struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *of_id;
+
struct resource *res;
u32 max_rate;
int ret;
@@ -720,8 +722,11 @@ static int stm32_adc_probe(struct platform_device *pdev)
return -ENOMEM;
platform_set_drvdata(pdev, &priv->common);
- priv->cfg = (const struct stm32_adc_priv_cfg *)
- of_match_device(dev->driver->of_match_table, dev)->data;
+ of_id = of_match_device(dev->driver->of_match_table, dev);
+ if (!of_id)
+ return -ENODEV;
+
+ priv->cfg = (const struct stm32_adc_priv_cfg *)of_id->data;
priv->nb_adc_max = priv->cfg->num_adcs;
spin_lock_init(&priv->common.lock);
@@ -814,7 +819,7 @@ err_pm_stop:
return ret;
}
-static int stm32_adc_remove(struct platform_device *pdev)
+static void stm32_adc_remove(struct platform_device *pdev)
{
struct stm32_adc_common *common = platform_get_drvdata(pdev);
struct stm32_adc_priv *priv = to_stm32_adc_priv(common);
@@ -826,8 +831,6 @@ static int stm32_adc_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
-
- return 0;
}
static int stm32_adc_core_runtime_suspend(struct device *dev)
@@ -908,7 +911,7 @@ MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
static struct platform_driver stm32_adc_driver = {
.probe = stm32_adc_probe,
- .remove = stm32_adc_remove,
+ .remove_new = stm32_adc_remove,
.driver = {
.name = "stm32-adc-core",
.of_match_table = stm32_adc_of_match,
diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
index f7613efb870d..25a912805439 100644
--- a/drivers/iio/adc/stm32-adc.c
+++ b/drivers/iio/adc/stm32-adc.c
@@ -2513,7 +2513,7 @@ err_dma_disable:
return ret;
}
-static int stm32_adc_remove(struct platform_device *pdev)
+static void stm32_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct stm32_adc *adc = iio_priv(indio_dev);
@@ -2532,8 +2532,6 @@ static int stm32_adc_remove(struct platform_device *pdev)
adc->rx_buf, adc->rx_dma_buf);
dma_release_channel(adc->dma_chan);
}
-
- return 0;
}
static int stm32_adc_suspend(struct device *dev)
@@ -2659,7 +2657,7 @@ MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
static struct platform_driver stm32_adc_driver = {
.probe = stm32_adc_probe,
- .remove = stm32_adc_remove,
+ .remove_new = stm32_adc_remove,
.driver = {
.name = "stm32-adc",
.of_match_table = stm32_adc_of_match,
diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
index b5cc43d12b6f..ca08ae3108b2 100644
--- a/drivers/iio/adc/stm32-dfsdm-adc.c
+++ b/drivers/iio/adc/stm32-dfsdm-adc.c
@@ -1620,7 +1620,7 @@ err_cleanup:
return ret;
}
-static int stm32_dfsdm_adc_remove(struct platform_device *pdev)
+static void stm32_dfsdm_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
@@ -1629,8 +1629,6 @@ static int stm32_dfsdm_adc_remove(struct platform_device *pdev)
of_platform_depopulate(&pdev->dev);
iio_device_unregister(indio_dev);
stm32_dfsdm_dma_release(indio_dev);
-
- return 0;
}
static int stm32_dfsdm_adc_suspend(struct device *dev)
@@ -1677,7 +1675,7 @@ static struct platform_driver stm32_dfsdm_adc_driver = {
.pm = pm_sleep_ptr(&stm32_dfsdm_adc_pm_ops),
},
.probe = stm32_dfsdm_adc_probe,
- .remove = stm32_dfsdm_adc_remove,
+ .remove_new = stm32_dfsdm_adc_remove,
};
module_platform_driver(stm32_dfsdm_adc_driver);
diff --git a/drivers/iio/adc/stm32-dfsdm-core.c b/drivers/iio/adc/stm32-dfsdm-core.c
index 0f6ebb3061a0..a05d978b8cb8 100644
--- a/drivers/iio/adc/stm32-dfsdm-core.c
+++ b/drivers/iio/adc/stm32-dfsdm-core.c
@@ -436,7 +436,7 @@ pm_put:
return ret;
}
-static int stm32_dfsdm_core_remove(struct platform_device *pdev)
+static void stm32_dfsdm_core_remove(struct platform_device *pdev)
{
struct stm32_dfsdm *dfsdm = platform_get_drvdata(pdev);
@@ -446,8 +446,6 @@ static int stm32_dfsdm_core_remove(struct platform_device *pdev)
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
stm32_dfsdm_clk_disable_unprepare(dfsdm);
-
- return 0;
}
static int stm32_dfsdm_core_suspend(struct device *dev)
@@ -508,7 +506,7 @@ static const struct dev_pm_ops stm32_dfsdm_core_pm_ops = {
static struct platform_driver stm32_dfsdm_driver = {
.probe = stm32_dfsdm_probe,
- .remove = stm32_dfsdm_core_remove,
+ .remove_new = stm32_dfsdm_core_remove,
.driver = {
.name = "stm32-dfsdm",
.of_match_table = stm32_dfsdm_of_match,
diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
index 25bba96367a8..100ecced5fc1 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -669,7 +669,7 @@ err_map:
return ret;
}
-static int sun4i_gpadc_remove(struct platform_device *pdev)
+static void sun4i_gpadc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
@@ -678,12 +678,10 @@ static int sun4i_gpadc_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
if (!IS_ENABLED(CONFIG_THERMAL_OF))
- return 0;
+ return;
if (!info->no_irq)
iio_map_array_unregister(indio_dev);
-
- return 0;
}
static const struct platform_device_id sun4i_gpadc_id[] = {
@@ -702,7 +700,7 @@ static struct platform_driver sun4i_gpadc_driver = {
},
.id_table = sun4i_gpadc_id,
.probe = sun4i_gpadc_probe,
- .remove = sun4i_gpadc_remove,
+ .remove_new = sun4i_gpadc_remove,
};
MODULE_DEVICE_TABLE(of, sun4i_gpadc_of_id);
diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c
index 50c450e7a55f..6c2cb3dabbbf 100644
--- a/drivers/iio/adc/ti-adc081c.c
+++ b/drivers/iio/adc/ti-adc081c.c
@@ -154,7 +154,6 @@ static void adc081c_reg_disable(void *reg)
static int adc081c_probe(struct i2c_client *client)
{
- const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct iio_dev *iio;
struct adc081c *adc;
const struct adcxx1c_model *model;
@@ -163,10 +162,7 @@ static int adc081c_probe(struct i2c_client *client)
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
return -EOPNOTSUPP;
- if (dev_fwnode(&client->dev))
- model = device_get_match_data(&client->dev);
- else
- model = &adcxx1c_models[id->driver_data];
+ model = i2c_get_match_data(client);
iio = devm_iio_device_alloc(&client->dev, sizeof(*adc));
if (!iio)
@@ -207,9 +203,9 @@ static int adc081c_probe(struct i2c_client *client)
}
static const struct i2c_device_id adc081c_id[] = {
- { "adc081c", ADC081C },
- { "adc101c", ADC101C },
- { "adc121c", ADC121C },
+ { "adc081c", (kernel_ulong_t)&adcxx1c_models[ADC081C] },
+ { "adc101c", (kernel_ulong_t)&adcxx1c_models[ADC101C] },
+ { "adc121c", (kernel_ulong_t)&adcxx1c_models[ADC121C] },
{ }
};
MODULE_DEVICE_TABLE(i2c, adc081c_id);
diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c
index 075c75a87544..6799ea49dbc7 100644
--- a/drivers/iio/adc/ti-ads1015.c
+++ b/drivers/iio/adc/ti-ads1015.c
@@ -976,16 +976,13 @@ static int ads1015_set_conv_mode(struct ads1015_data *data, int mode)
static int ads1015_probe(struct i2c_client *client)
{
- const struct i2c_device_id *id = i2c_client_get_device_id(client);
const struct ads1015_chip_data *chip;
struct iio_dev *indio_dev;
struct ads1015_data *data;
int ret;
int i;
- chip = device_get_match_data(&client->dev);
- if (!chip)
- chip = (const struct ads1015_chip_data *)id->driver_data;
+ chip = i2c_get_match_data(client);
if (!chip)
return dev_err_probe(&client->dev, -EINVAL, "Unknown chip\n");
@@ -1047,11 +1044,13 @@ static int ads1015_probe(struct i2c_client *client)
1 << ADS1015_CFG_COMP_LAT_SHIFT;
switch (irq_trig) {
+ case IRQF_TRIGGER_FALLING:
case IRQF_TRIGGER_LOW:
cfg_comp |= ADS1015_CFG_COMP_POL_LOW <<
ADS1015_CFG_COMP_POL_SHIFT;
break;
case IRQF_TRIGGER_HIGH:
+ case IRQF_TRIGGER_RISING:
cfg_comp |= ADS1015_CFG_COMP_POL_HIGH <<
ADS1015_CFG_COMP_POL_SHIFT;
break;
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index 8db7a01cb5fb..c755e8cd5220 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -681,7 +681,7 @@ err_dma:
return err;
}
-static int tiadc_remove(struct platform_device *pdev)
+static void tiadc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct tiadc_device *adc_dev = iio_priv(indio_dev);
@@ -697,8 +697,6 @@ static int tiadc_remove(struct platform_device *pdev)
step_en = get_adc_step_mask(adc_dev);
am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
-
- return 0;
}
static int tiadc_suspend(struct device *dev)
@@ -747,7 +745,7 @@ static struct platform_driver tiadc_driver = {
.of_match_table = ti_adc_dt_ids,
},
.probe = tiadc_probe,
- .remove = tiadc_remove,
+ .remove_new = tiadc_remove,
};
module_platform_driver(tiadc_driver);
diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c
index c279c4f2c9b7..4a247ca25a44 100644
--- a/drivers/iio/adc/twl4030-madc.c
+++ b/drivers/iio/adc/twl4030-madc.c
@@ -892,7 +892,7 @@ err_current_generator:
return ret;
}
-static int twl4030_madc_remove(struct platform_device *pdev)
+static void twl4030_madc_remove(struct platform_device *pdev)
{
struct iio_dev *iio_dev = platform_get_drvdata(pdev);
struct twl4030_madc_data *madc = iio_priv(iio_dev);
@@ -903,8 +903,6 @@ static int twl4030_madc_remove(struct platform_device *pdev)
twl4030_madc_set_power(madc, 0);
regulator_disable(madc->usb3v1);
-
- return 0;
}
#ifdef CONFIG_OF
@@ -917,7 +915,7 @@ MODULE_DEVICE_TABLE(of, twl_madc_of_match);
static struct platform_driver twl4030_madc_driver = {
.probe = twl4030_madc_probe,
- .remove = twl4030_madc_remove,
+ .remove_new = twl4030_madc_remove,
.driver = {
.name = "twl4030_madc",
.of_match_table = of_match_ptr(twl_madc_of_match),
diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c
index 32873fb5f367..224e9cb5e147 100644
--- a/drivers/iio/adc/twl6030-gpadc.c
+++ b/drivers/iio/adc/twl6030-gpadc.c
@@ -968,14 +968,12 @@ static int twl6030_gpadc_probe(struct platform_device *pdev)
return iio_device_register(indio_dev);
}
-static int twl6030_gpadc_remove(struct platform_device *pdev)
+static void twl6030_gpadc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
twl6030_gpadc_disable_irq(TWL6030_GPADC_RT_SW1_EOC_MASK);
iio_device_unregister(indio_dev);
-
- return 0;
}
static int twl6030_gpadc_suspend(struct device *pdev)
@@ -1007,7 +1005,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(twl6030_gpadc_pm_ops, twl6030_gpadc_suspend,
static struct platform_driver twl6030_gpadc_driver = {
.probe = twl6030_gpadc_probe,
- .remove = twl6030_gpadc_remove,
+ .remove_new = twl6030_gpadc_remove,
.driver = {
.name = DRIVER_NAME,
.pm = pm_sleep_ptr(&twl6030_gpadc_pm_ops),
diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
index ae31aafd2653..e4548df3f8fb 100644
--- a/drivers/iio/adc/vf610_adc.c
+++ b/drivers/iio/adc/vf610_adc.c
@@ -916,7 +916,7 @@ error_adc_clk_enable:
return ret;
}
-static int vf610_adc_remove(struct platform_device *pdev)
+static void vf610_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct vf610_adc *info = iio_priv(indio_dev);
@@ -925,8 +925,6 @@ static int vf610_adc_remove(struct platform_device *pdev)
iio_triggered_buffer_cleanup(indio_dev);
regulator_disable(info->vref);
clk_disable_unprepare(info->clk);
-
- return 0;
}
static int vf610_adc_suspend(struct device *dev)
@@ -974,7 +972,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(vf610_adc_pm_ops, vf610_adc_suspend,
static struct platform_driver vf610_adc_driver = {
.probe = vf610_adc_probe,
- .remove = vf610_adc_remove,
+ .remove_new = vf610_adc_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = vf610_adc_match,
diff --git a/drivers/iio/addac/Kconfig b/drivers/iio/addac/Kconfig
index 877f9124803c..b2623881f0ec 100644
--- a/drivers/iio/addac/Kconfig
+++ b/drivers/iio/addac/Kconfig
@@ -38,6 +38,7 @@ config STX104
select REGMAP_MMIO
select GPIOLIB
select GPIO_REGMAP
+ select I8254
help
Say yes here to build support for the Apex Embedded Systems STX104
integrated analog PC/104 card.
diff --git a/drivers/iio/addac/ad74413r.c b/drivers/iio/addac/ad74413r.c
index 6b0e8218f150..7af3e4b8fe3b 100644
--- a/drivers/iio/addac/ad74413r.c
+++ b/drivers/iio/addac/ad74413r.c
@@ -442,11 +442,29 @@ static int ad74413r_set_channel_function(struct ad74413r_state *st,
int ret;
ret = regmap_update_bits(st->regmap,
+ AD74413R_REG_CH_FUNC_SETUP_X(channel),
+ AD74413R_CH_FUNC_SETUP_MASK,
+ CH_FUNC_HIGH_IMPEDANCE);
+ if (ret)
+ return ret;
+
+ /* Set DAC code to 0 prior to changing channel function */
+ ret = ad74413r_set_channel_dac_code(st, channel, 0);
+ if (ret)
+ return ret;
+
+ /* Delay required before transition to new desired mode */
+ usleep_range(130, 150);
+
+ ret = regmap_update_bits(st->regmap,
AD74413R_REG_CH_FUNC_SETUP_X(channel),
AD74413R_CH_FUNC_SETUP_MASK, func);
if (ret)
return ret;
+ /* Delay required before updating the new DAC code */
+ usleep_range(150, 170);
+
if (func == CH_FUNC_CURRENT_INPUT_LOOP_POWER)
ret = regmap_set_bits(st->regmap,
AD74413R_REG_ADC_CONFIG_X(channel),
@@ -705,8 +723,8 @@ static int ad74413r_get_input_current_scale(struct ad74413r_state *st,
return IIO_VAL_FRACTIONAL;
}
-static int ad74413_get_input_current_offset(struct ad74413r_state *st,
- unsigned int channel, int *val)
+static int ad74413r_get_input_current_offset(struct ad74413r_state *st,
+ unsigned int channel, int *val)
{
unsigned int range;
int voltage_range;
@@ -991,7 +1009,7 @@ static int ad74413r_read_raw(struct iio_dev *indio_dev,
return ad74413r_get_input_voltage_offset(st,
chan->channel, val);
case IIO_CURRENT:
- return ad74413_get_input_current_offset(st,
+ return ad74413r_get_input_current_offset(st,
chan->channel, val);
default:
return -EINVAL;
diff --git a/drivers/iio/addac/stx104.c b/drivers/iio/addac/stx104.c
index d1f7ce033b46..6946a65512ca 100644
--- a/drivers/iio/addac/stx104.c
+++ b/drivers/iio/addac/stx104.c
@@ -8,6 +8,7 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/gpio/regmap.h>
+#include <linux/i8254.h>
#include <linux/iio/iio.h>
#include <linux/iio/types.h>
#include <linux/isa.h>
@@ -55,6 +56,7 @@ MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses");
#define STX104_ADC_STATUS (STX104_AIO_BASE + 0x8)
#define STX104_ADC_CONTROL (STX104_AIO_BASE + 0x9)
#define STX104_ADC_CONFIGURATION (STX104_AIO_BASE + 0x11)
+#define STX104_I8254_BASE (STX104_AIO_BASE + 0x12)
#define STX104_AIO_DATA_STRIDE 2
#define STX104_DAC_OFFSET(_channel) (STX104_DAC_BASE + STX104_AIO_DATA_STRIDE * (_channel))
@@ -77,6 +79,7 @@ MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses");
/* ADC Configuration */
#define STX104_GAIN GENMASK(1, 0)
#define STX104_ADBU BIT(2)
+#define STX104_RBK GENMASK(7, 4)
#define STX104_BIPOLAR 0
#define STX104_GAIN_X1 0
#define STX104_GAIN_X2 1
@@ -168,6 +171,32 @@ static const struct regmap_config dio_regmap_config = {
.io_port = true,
};
+static const struct regmap_range pit_wr_ranges[] = {
+ regmap_reg_range(0x0, 0x3),
+};
+static const struct regmap_range pit_rd_ranges[] = {
+ regmap_reg_range(0x0, 0x2),
+};
+static const struct regmap_access_table pit_wr_table = {
+ .yes_ranges = pit_wr_ranges,
+ .n_yes_ranges = ARRAY_SIZE(pit_wr_ranges),
+};
+static const struct regmap_access_table pit_rd_table = {
+ .yes_ranges = pit_rd_ranges,
+ .n_yes_ranges = ARRAY_SIZE(pit_rd_ranges),
+};
+
+static const struct regmap_config pit_regmap_config = {
+ .name = "i8254",
+ .reg_bits = 8,
+ .reg_stride = 1,
+ .reg_base = STX104_I8254_BASE,
+ .val_bits = 8,
+ .io_port = true,
+ .wr_table = &pit_wr_table,
+ .rd_table = &pit_rd_table,
+};
+
static int stx104_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val, int *val2, long mask)
{
@@ -339,6 +368,21 @@ static const char *stx104_names[STX104_NGPIO] = {
"DIN0", "DIN1", "DIN2", "DIN3", "DOUT0", "DOUT1", "DOUT2", "DOUT3"
};
+static int bank_select_i8254(struct regmap *map)
+{
+ const u8 select_i8254[] = { 0x3, 0xB, 0xA };
+ size_t i;
+ int err;
+
+ for (i = 0; i < ARRAY_SIZE(select_i8254); i++) {
+ err = regmap_write_bits(map, STX104_ADC_CONFIGURATION, STX104_RBK, select_i8254[i]);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
static int stx104_init_hw(struct stx104_iio *const priv)
{
int err;
@@ -361,7 +405,7 @@ static int stx104_init_hw(struct stx104_iio *const priv)
if (err)
return err;
- return 0;
+ return bank_select_i8254(priv->aio_ctl_map);
}
static int stx104_probe(struct device *dev, unsigned int id)
@@ -369,6 +413,7 @@ static int stx104_probe(struct device *dev, unsigned int id)
struct iio_dev *indio_dev;
struct stx104_iio *priv;
struct gpio_regmap_config gpio_config;
+ struct i8254_regmap_config pit_config;
void __iomem *stx104_base;
struct regmap *aio_ctl_map;
struct regmap *aio_data_map;
@@ -406,6 +451,11 @@ static int stx104_probe(struct device *dev, unsigned int id)
return dev_err_probe(dev, PTR_ERR(dio_map),
"Unable to initialize dio register map\n");
+ pit_config.map = devm_regmap_init_mmio(dev, stx104_base, &pit_regmap_config);
+ if (IS_ERR(pit_config.map))
+ return dev_err_probe(dev, PTR_ERR(pit_config.map),
+ "Unable to initialize i8254 register map\n");
+
priv = iio_priv(indio_dev);
priv->aio_ctl_map = aio_ctl_map;
priv->aio_data_map = aio_data_map;
@@ -449,7 +499,13 @@ static int stx104_probe(struct device *dev, unsigned int id)
.drvdata = dio_map,
};
- return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_config));
+ err = PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_config));
+ if (err)
+ return err;
+
+ pit_config.parent = dev;
+
+ return devm_i8254_regmap_register(dev, &pit_config);
}
static struct isa_driver stx104_driver = {
@@ -464,3 +520,4 @@ module_isa_driver(stx104_driver, num_stx104);
MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
MODULE_DESCRIPTION("Apex Embedded Systems STX104 IIO driver");
MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS(I8254);
diff --git a/drivers/iio/amplifiers/hmc425a.c b/drivers/iio/amplifiers/hmc425a.c
index 108f0f1685ef..e87d35d50a95 100644
--- a/drivers/iio/amplifiers/hmc425a.c
+++ b/drivers/iio/amplifiers/hmc425a.c
@@ -21,6 +21,7 @@
enum hmc425a_type {
ID_HMC425A,
+ ID_HMC540S,
};
struct hmc425a_chip_info {
@@ -70,6 +71,9 @@ static int hmc425a_read_raw(struct iio_dev *indio_dev,
case ID_HMC425A:
gain = ~code * -500;
break;
+ case ID_HMC540S:
+ gain = ~code * -1000;
+ break;
}
*val = gain / 1000;
@@ -106,6 +110,9 @@ static int hmc425a_write_raw(struct iio_dev *indio_dev,
case ID_HMC425A:
code = ~((abs(gain) / 500) & 0x3F);
break;
+ case ID_HMC540S:
+ code = ~((abs(gain) / 1000) & 0xF);
+ break;
}
mutex_lock(&st->lock);
@@ -157,6 +164,7 @@ static const struct iio_chan_spec hmc425a_channels[] = {
/* Match table for of_platform binding */
static const struct of_device_id hmc425a_of_match[] = {
{ .compatible = "adi,hmc425a", .data = (void *)ID_HMC425A },
+ { .compatible = "adi,hmc540s", .data = (void *)ID_HMC540S },
{},
};
MODULE_DEVICE_TABLE(of, hmc425a_of_match);
@@ -171,6 +179,15 @@ static struct hmc425a_chip_info hmc425a_chip_info_tbl[] = {
.gain_max = 0,
.default_gain = -0x40, /* set default gain -31.5db*/
},
+ [ID_HMC540S] = {
+ .name = "hmc540s",
+ .channels = hmc425a_channels,
+ .num_channels = ARRAY_SIZE(hmc425a_channels),
+ .num_gpios = 4,
+ .gain_min = -15000,
+ .gain_max = 0,
+ .default_gain = -0x10, /* set default gain -15.0db*/
+ },
};
static int hmc425a_probe(struct platform_device *pdev)
diff --git a/drivers/iio/chemical/atlas-ezo-sensor.c b/drivers/iio/chemical/atlas-ezo-sensor.c
index 8fc926a2d33b..761a853a4d17 100644
--- a/drivers/iio/chemical/atlas-ezo-sensor.c
+++ b/drivers/iio/chemical/atlas-ezo-sensor.c
@@ -203,7 +203,6 @@ MODULE_DEVICE_TABLE(of, atlas_ezo_dt_ids);
static int atlas_ezo_probe(struct i2c_client *client)
{
- const struct i2c_device_id *id = i2c_client_get_device_id(client);
const struct atlas_ezo_device *chip;
struct atlas_ezo_data *data;
struct iio_dev *indio_dev;
@@ -212,10 +211,7 @@ static int atlas_ezo_probe(struct i2c_client *client)
if (!indio_dev)
return -ENOMEM;
- if (dev_fwnode(&client->dev))
- chip = device_get_match_data(&client->dev);
- else
- chip = (const struct atlas_ezo_device *)id->driver_data;
+ chip = i2c_get_match_data(client);
if (!chip)
return -EINVAL;
diff --git a/drivers/iio/chemical/atlas-sensor.c b/drivers/iio/chemical/atlas-sensor.c
index fb15bb216019..baf93e5e3ca7 100644
--- a/drivers/iio/chemical/atlas-sensor.c
+++ b/drivers/iio/chemical/atlas-sensor.c
@@ -87,7 +87,7 @@ enum {
struct atlas_data {
struct i2c_client *client;
struct iio_trigger *trig;
- struct atlas_device *chip;
+ const struct atlas_device *chip;
struct regmap *regmap;
struct irq_work work;
unsigned int interrupt_enabled;
@@ -353,7 +353,7 @@ struct atlas_device {
int delay;
};
-static struct atlas_device atlas_devices[] = {
+static const struct atlas_device atlas_devices[] = {
[ATLAS_PH_SM] = {
.channels = atlas_ph_channels,
.num_channels = 3,
@@ -589,30 +589,29 @@ static const struct iio_info atlas_info = {
};
static const struct i2c_device_id atlas_id[] = {
- { "atlas-ph-sm", ATLAS_PH_SM },
- { "atlas-ec-sm", ATLAS_EC_SM },
- { "atlas-orp-sm", ATLAS_ORP_SM },
- { "atlas-do-sm", ATLAS_DO_SM },
- { "atlas-rtd-sm", ATLAS_RTD_SM },
+ { "atlas-ph-sm", (kernel_ulong_t)&atlas_devices[ATLAS_PH_SM] },
+ { "atlas-ec-sm", (kernel_ulong_t)&atlas_devices[ATLAS_EC_SM] },
+ { "atlas-orp-sm", (kernel_ulong_t)&atlas_devices[ATLAS_ORP_SM] },
+ { "atlas-do-sm", (kernel_ulong_t)&atlas_devices[ATLAS_DO_SM] },
+ { "atlas-rtd-sm", (kernel_ulong_t)&atlas_devices[ATLAS_RTD_SM] },
{}
};
MODULE_DEVICE_TABLE(i2c, atlas_id);
static const struct of_device_id atlas_dt_ids[] = {
- { .compatible = "atlas,ph-sm", .data = (void *)ATLAS_PH_SM, },
- { .compatible = "atlas,ec-sm", .data = (void *)ATLAS_EC_SM, },
- { .compatible = "atlas,orp-sm", .data = (void *)ATLAS_ORP_SM, },
- { .compatible = "atlas,do-sm", .data = (void *)ATLAS_DO_SM, },
- { .compatible = "atlas,rtd-sm", .data = (void *)ATLAS_RTD_SM, },
+ { .compatible = "atlas,ph-sm", .data = &atlas_devices[ATLAS_PH_SM] },
+ { .compatible = "atlas,ec-sm", .data = &atlas_devices[ATLAS_EC_SM] },
+ { .compatible = "atlas,orp-sm", .data = &atlas_devices[ATLAS_ORP_SM] },
+ { .compatible = "atlas,do-sm", .data = &atlas_devices[ATLAS_DO_SM] },
+ { .compatible = "atlas,rtd-sm", .data = &atlas_devices[ATLAS_RTD_SM] },
{ }
};
MODULE_DEVICE_TABLE(of, atlas_dt_ids);
static int atlas_probe(struct i2c_client *client)
{
- const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct atlas_data *data;
- struct atlas_device *chip;
+ const struct atlas_device *chip;
struct iio_trigger *trig;
struct iio_dev *indio_dev;
int ret;
@@ -621,10 +620,7 @@ static int atlas_probe(struct i2c_client *client)
if (!indio_dev)
return -ENOMEM;
- if (!dev_fwnode(&client->dev))
- chip = &atlas_devices[id->driver_data];
- else
- chip = &atlas_devices[(unsigned long)device_get_match_data(&client->dev)];
+ chip = i2c_get_match_data(client);
indio_dev->info = &atlas_info;
indio_dev->name = ATLAS_DRV_NAME;
diff --git a/drivers/iio/chemical/sgp30.c b/drivers/iio/chemical/sgp30.c
index b509cff9ce37..21730d62b5c8 100644
--- a/drivers/iio/chemical/sgp30.c
+++ b/drivers/iio/chemical/sgp30.c
@@ -114,6 +114,7 @@ struct sgp_data {
};
struct sgp_device {
+ unsigned long product_id;
const struct iio_chan_spec *channels;
int num_channels;
};
@@ -182,10 +183,12 @@ static const struct iio_chan_spec sgpc3_channels[] = {
static const struct sgp_device sgp_devices[] = {
[SGP30] = {
+ .product_id = SGP30,
.channels = sgp30_channels,
.num_channels = ARRAY_SIZE(sgp30_channels),
},
[SGPC3] = {
+ .product_id = SGPC3,
.channels = sgpc3_channels,
.num_channels = ARRAY_SIZE(sgpc3_channels),
},
@@ -491,28 +494,25 @@ static const struct iio_info sgp_info = {
};
static const struct of_device_id sgp_dt_ids[] = {
- { .compatible = "sensirion,sgp30", .data = (void *)SGP30 },
- { .compatible = "sensirion,sgpc3", .data = (void *)SGPC3 },
+ { .compatible = "sensirion,sgp30", .data = &sgp_devices[SGP30] },
+ { .compatible = "sensirion,sgpc3", .data = &sgp_devices[SGPC3] },
{ }
};
static int sgp_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
+ const struct sgp_device *match_data;
struct device *dev = &client->dev;
struct iio_dev *indio_dev;
struct sgp_data *data;
- unsigned long product_id;
int ret;
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
- if (dev_fwnode(dev))
- product_id = (unsigned long)device_get_match_data(dev);
- else
- product_id = id->driver_data;
+ match_data = i2c_get_match_data(client);
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
@@ -528,15 +528,15 @@ static int sgp_probe(struct i2c_client *client)
data->feature_set = be16_to_cpu(data->buffer.raw_words[0].value);
- ret = sgp_check_compat(data, product_id);
+ ret = sgp_check_compat(data, match_data->product_id);
if (ret)
return ret;
indio_dev->info = &sgp_info;
indio_dev->name = id->name;
indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->channels = sgp_devices[product_id].channels;
- indio_dev->num_channels = sgp_devices[product_id].num_channels;
+ indio_dev->channels = match_data->channels;
+ indio_dev->num_channels = match_data->num_channels;
sgp_init(data);
@@ -562,8 +562,8 @@ static void sgp_remove(struct i2c_client *client)
}
static const struct i2c_device_id sgp_id[] = {
- { "sgp30", SGP30 },
- { "sgpc3", SGPC3 },
+ { "sgp30", (kernel_ulong_t)&sgp_devices[SGP30] },
+ { "sgpc3", (kernel_ulong_t)&sgp_devices[SGPC3] },
{ }
};
diff --git a/drivers/iio/chemical/vz89x.c b/drivers/iio/chemical/vz89x.c
index 13555f4f401a..5b358bcd311b 100644
--- a/drivers/iio/chemical/vz89x.c
+++ b/drivers/iio/chemical/vz89x.c
@@ -342,19 +342,17 @@ static const struct vz89x_chip_data vz89x_chips[] = {
};
static const struct of_device_id vz89x_dt_ids[] = {
- { .compatible = "sgx,vz89x", .data = (void *) VZ89X },
- { .compatible = "sgx,vz89te", .data = (void *) VZ89TE },
+ { .compatible = "sgx,vz89x", .data = &vz89x_chips[VZ89X] },
+ { .compatible = "sgx,vz89te", .data = &vz89x_chips[VZ89TE] },
{ }
};
MODULE_DEVICE_TABLE(of, vz89x_dt_ids);
static int vz89x_probe(struct i2c_client *client)
{
- const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct device *dev = &client->dev;
struct iio_dev *indio_dev;
struct vz89x_data *data;
- int chip_id;
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
if (!indio_dev)
@@ -369,14 +367,10 @@ static int vz89x_probe(struct i2c_client *client)
else
return -EOPNOTSUPP;
- if (!dev_fwnode(dev))
- chip_id = id->driver_data;
- else
- chip_id = (unsigned long)device_get_match_data(dev);
+ data->chip = i2c_get_match_data(client);
i2c_set_clientdata(client, indio_dev);
data->client = client;
- data->chip = &vz89x_chips[chip_id];
data->last_update = jiffies - HZ;
mutex_init(&data->lock);
@@ -391,8 +385,8 @@ static int vz89x_probe(struct i2c_client *client)
}
static const struct i2c_device_id vz89x_id[] = {
- { "vz89x", VZ89X },
- { "vz89te", VZ89TE },
+ { "vz89x", (kernel_ulong_t)&vz89x_chips[VZ89X] },
+ { "vz89te", (kernel_ulong_t)&vz89x_chips[VZ89TE] },
{ }
};
MODULE_DEVICE_TABLE(i2c, vz89x_id);
diff --git a/drivers/iio/dac/dpot-dac.c b/drivers/iio/dac/dpot-dac.c
index 83ce9489259c..7332064d0852 100644
--- a/drivers/iio/dac/dpot-dac.c
+++ b/drivers/iio/dac/dpot-dac.c
@@ -226,15 +226,13 @@ disable_reg:
return ret;
}
-static int dpot_dac_remove(struct platform_device *pdev)
+static void dpot_dac_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct dpot_dac *dac = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
regulator_disable(dac->vref);
-
- return 0;
}
static const struct of_device_id dpot_dac_match[] = {
@@ -245,7 +243,7 @@ MODULE_DEVICE_TABLE(of, dpot_dac_match);
static struct platform_driver dpot_dac_driver = {
.probe = dpot_dac_probe,
- .remove = dpot_dac_remove,
+ .remove_new = dpot_dac_remove,
.driver = {
.name = "iio-dpot-dac",
.of_match_table = dpot_dac_match,
diff --git a/drivers/iio/dac/lpc18xx_dac.c b/drivers/iio/dac/lpc18xx_dac.c
index 60467c6f2c6e..b3aa4443a6a4 100644
--- a/drivers/iio/dac/lpc18xx_dac.c
+++ b/drivers/iio/dac/lpc18xx_dac.c
@@ -165,7 +165,7 @@ dis_reg:
return ret;
}
-static int lpc18xx_dac_remove(struct platform_device *pdev)
+static void lpc18xx_dac_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct lpc18xx_dac *dac = iio_priv(indio_dev);
@@ -175,8 +175,6 @@ static int lpc18xx_dac_remove(struct platform_device *pdev)
writel(0, dac->base + LPC18XX_DAC_CTRL);
clk_disable_unprepare(dac->clk);
regulator_disable(dac->vref);
-
- return 0;
}
static const struct of_device_id lpc18xx_dac_match[] = {
@@ -187,7 +185,7 @@ MODULE_DEVICE_TABLE(of, lpc18xx_dac_match);
static struct platform_driver lpc18xx_dac_driver = {
.probe = lpc18xx_dac_probe,
- .remove = lpc18xx_dac_remove,
+ .remove_new = lpc18xx_dac_remove,
.driver = {
.name = "lpc18xx-dac",
.of_match_table = lpc18xx_dac_match,
diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c
index f4a3124d29f2..25bb1c0490af 100644
--- a/drivers/iio/dac/mcp4725.c
+++ b/drivers/iio/dac/mcp4725.c
@@ -30,9 +30,14 @@
#define MCP472X_REF_VREF_UNBUFFERED 0x02
#define MCP472X_REF_VREF_BUFFERED 0x03
+struct mcp4725_chip_info {
+ const struct iio_chan_spec *chan_spec;
+ u8 dac_reg_offset;
+ bool use_ext_ref_voltage;
+};
+
struct mcp4725_data {
struct i2c_client *client;
- int id;
unsigned ref_mode;
bool vref_buffered;
u16 dac_value;
@@ -384,6 +389,7 @@ static int mcp4725_probe_dt(struct device *dev,
static int mcp4725_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
+ const struct mcp4725_chip_info *info;
struct mcp4725_data *data;
struct iio_dev *indio_dev;
struct mcp4725_platform_data *pdata, pdata_dt;
@@ -398,10 +404,7 @@ static int mcp4725_probe(struct i2c_client *client)
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
- if (dev_fwnode(&client->dev))
- data->id = (uintptr_t)device_get_match_data(&client->dev);
- else
- data->id = id->driver_data;
+ info = i2c_get_match_data(client);
pdata = dev_get_platdata(&client->dev);
if (!pdata) {
@@ -414,7 +417,7 @@ static int mcp4725_probe(struct i2c_client *client)
pdata = &pdata_dt;
}
- if (data->id == MCP4725 && pdata->use_vref) {
+ if (info->use_ext_ref_voltage && pdata->use_vref) {
dev_err(&client->dev,
"external reference is unavailable on MCP4725");
return -EINVAL;
@@ -455,12 +458,12 @@ static int mcp4725_probe(struct i2c_client *client)
indio_dev->name = id->name;
indio_dev->info = &mcp4725_info;
- indio_dev->channels = &mcp472x_channel[id->driver_data];
+ indio_dev->channels = info->chan_spec;
indio_dev->num_channels = 1;
indio_dev->modes = INDIO_DIRECT_MODE;
/* read current DAC value and settings */
- err = i2c_master_recv(client, inbuf, data->id == MCP4725 ? 3 : 4);
+ err = i2c_master_recv(client, inbuf, info->dac_reg_offset);
if (err < 0) {
dev_err(&client->dev, "failed to read DAC value");
@@ -470,10 +473,10 @@ static int mcp4725_probe(struct i2c_client *client)
data->powerdown = pd > 0;
data->powerdown_mode = pd ? pd - 1 : 2; /* largest resistor to gnd */
data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);
- if (data->id == MCP4726)
+ if (!info->use_ext_ref_voltage)
ref = (inbuf[3] >> 3) & 0x3;
- if (data->id == MCP4726 && ref != data->ref_mode) {
+ if (!info->use_ext_ref_voltage && ref != data->ref_mode) {
dev_info(&client->dev,
"voltage reference mode differs (conf: %u, eeprom: %u), setting %u",
data->ref_mode, ref, data->ref_mode);
@@ -510,9 +513,20 @@ static void mcp4725_remove(struct i2c_client *client)
regulator_disable(data->vdd_reg);
}
+static const struct mcp4725_chip_info mcp4725 = {
+ .chan_spec = &mcp472x_channel[MCP4725],
+ .dac_reg_offset = 3,
+ .use_ext_ref_voltage = true,
+};
+
+static const struct mcp4725_chip_info mcp4726 = {
+ .chan_spec = &mcp472x_channel[MCP4726],
+ .dac_reg_offset = 4,
+};
+
static const struct i2c_device_id mcp4725_id[] = {
- { "mcp4725", MCP4725 },
- { "mcp4726", MCP4726 },
+ { "mcp4725", (kernel_ulong_t)&mcp4725 },
+ { "mcp4726", (kernel_ulong_t)&mcp4726 },
{ }
};
MODULE_DEVICE_TABLE(i2c, mcp4725_id);
@@ -520,11 +534,11 @@ MODULE_DEVICE_TABLE(i2c, mcp4725_id);
static const struct of_device_id mcp4725_of_match[] = {
{
.compatible = "microchip,mcp4725",
- .data = (void *)MCP4725
+ .data = &mcp4725
},
{
.compatible = "microchip,mcp4726",
- .data = (void *)MCP4726
+ .data = &mcp4726
},
{ }
};
diff --git a/drivers/iio/dac/stm32-dac-core.c b/drivers/iio/dac/stm32-dac-core.c
index 83bf184e3adc..15abe048729e 100644
--- a/drivers/iio/dac/stm32-dac-core.c
+++ b/drivers/iio/dac/stm32-dac-core.c
@@ -183,7 +183,7 @@ err_pm_stop:
return ret;
}
-static int stm32_dac_remove(struct platform_device *pdev)
+static void stm32_dac_remove(struct platform_device *pdev)
{
pm_runtime_get_sync(&pdev->dev);
of_platform_depopulate(&pdev->dev);
@@ -191,8 +191,6 @@ static int stm32_dac_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
-
- return 0;
}
static int stm32_dac_core_resume(struct device *dev)
@@ -249,7 +247,7 @@ MODULE_DEVICE_TABLE(of, stm32_dac_of_match);
static struct platform_driver stm32_dac_driver = {
.probe = stm32_dac_probe,
- .remove = stm32_dac_remove,
+ .remove_new = stm32_dac_remove,
.driver = {
.name = "stm32-dac-core",
.of_match_table = stm32_dac_of_match,
diff --git a/drivers/iio/dac/stm32-dac.c b/drivers/iio/dac/stm32-dac.c
index 15eb44075107..5a722f307e7e 100644
--- a/drivers/iio/dac/stm32-dac.c
+++ b/drivers/iio/dac/stm32-dac.c
@@ -11,12 +11,13 @@
#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/kernel.h>
+#include <linux/kstrtox.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-#include <linux/string_helpers.h>
+#include <linux/string_choices.h>
#include "stm32-dac-core.h"
@@ -361,7 +362,7 @@ err_pm_put:
return ret;
}
-static int stm32_dac_remove(struct platform_device *pdev)
+static void stm32_dac_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@@ -370,8 +371,6 @@ static int stm32_dac_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
-
- return 0;
}
static int stm32_dac_suspend(struct device *dev)
@@ -399,7 +398,7 @@ MODULE_DEVICE_TABLE(of, stm32_dac_of_match);
static struct platform_driver stm32_dac_driver = {
.probe = stm32_dac_probe,
- .remove = stm32_dac_remove,
+ .remove_new = stm32_dac_remove,
.driver = {
.name = "stm32-dac",
.of_match_table = stm32_dac_of_match,
diff --git a/drivers/iio/dac/ti-dac5571.c b/drivers/iio/dac/ti-dac5571.c
index bab11b9adc25..efb1269a77c1 100644
--- a/drivers/iio/dac/ti-dac5571.c
+++ b/drivers/iio/dac/ti-dac5571.c
@@ -313,7 +313,6 @@ static int dac5571_probe(struct i2c_client *client)
const struct dac5571_spec *spec;
struct dac5571_data *data;
struct iio_dev *indio_dev;
- enum chip_id chip_id;
int ret, i;
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
@@ -329,12 +328,7 @@ static int dac5571_probe(struct i2c_client *client)
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = dac5571_channels;
- if (dev_fwnode(dev))
- chip_id = (uintptr_t)device_get_match_data(dev);
- else
- chip_id = id->driver_data;
-
- spec = &dac5571_spec[chip_id];
+ spec = i2c_get_match_data(client);
indio_dev->num_channels = spec->num_channels;
data->spec = spec;
@@ -392,31 +386,31 @@ static void dac5571_remove(struct i2c_client *i2c)
}
static const struct of_device_id dac5571_of_id[] = {
- {.compatible = "ti,dac5571", .data = (void *)single_8bit},
- {.compatible = "ti,dac6571", .data = (void *)single_10bit},
- {.compatible = "ti,dac7571", .data = (void *)single_12bit},
- {.compatible = "ti,dac5574", .data = (void *)quad_8bit},
- {.compatible = "ti,dac6574", .data = (void *)quad_10bit},
- {.compatible = "ti,dac7574", .data = (void *)quad_12bit},
- {.compatible = "ti,dac5573", .data = (void *)quad_8bit},
- {.compatible = "ti,dac6573", .data = (void *)quad_10bit},
- {.compatible = "ti,dac7573", .data = (void *)quad_12bit},
- {.compatible = "ti,dac121c081", .data = (void *)single_12bit},
+ {.compatible = "ti,dac121c081", .data = &dac5571_spec[single_12bit] },
+ {.compatible = "ti,dac5571", .data = &dac5571_spec[single_8bit] },
+ {.compatible = "ti,dac6571", .data = &dac5571_spec[single_10bit] },
+ {.compatible = "ti,dac7571", .data = &dac5571_spec[single_12bit] },
+ {.compatible = "ti,dac5574", .data = &dac5571_spec[quad_8bit] },
+ {.compatible = "ti,dac6574", .data = &dac5571_spec[quad_10bit] },
+ {.compatible = "ti,dac7574", .data = &dac5571_spec[quad_12bit] },
+ {.compatible = "ti,dac5573", .data = &dac5571_spec[quad_8bit] },
+ {.compatible = "ti,dac6573", .data = &dac5571_spec[quad_10bit] },
+ {.compatible = "ti,dac7573", .data = &dac5571_spec[quad_12bit] },
{}
};
MODULE_DEVICE_TABLE(of, dac5571_of_id);
static const struct i2c_device_id dac5571_id[] = {
- {"dac5571", single_8bit},
- {"dac6571", single_10bit},
- {"dac7571", single_12bit},
- {"dac5574", quad_8bit},
- {"dac6574", quad_10bit},
- {"dac7574", quad_12bit},
- {"dac5573", quad_8bit},
- {"dac6573", quad_10bit},
- {"dac7573", quad_12bit},
- {"dac121c081", single_12bit},
+ {"dac121c081", (kernel_ulong_t)&dac5571_spec[single_12bit] },
+ {"dac5571", (kernel_ulong_t)&dac5571_spec[single_8bit] },
+ {"dac6571", (kernel_ulong_t)&dac5571_spec[single_10bit] },
+ {"dac7571", (kernel_ulong_t)&dac5571_spec[single_12bit] },
+ {"dac5574", (kernel_ulong_t)&dac5571_spec[quad_8bit] },
+ {"dac6574", (kernel_ulong_t)&dac5571_spec[quad_10bit] },
+ {"dac7574", (kernel_ulong_t)&dac5571_spec[quad_12bit] },
+ {"dac5573", (kernel_ulong_t)&dac5571_spec[quad_8bit] },
+ {"dac6573", (kernel_ulong_t)&dac5571_spec[quad_10bit] },
+ {"dac7573", (kernel_ulong_t)&dac5571_spec[quad_12bit] },
{}
};
MODULE_DEVICE_TABLE(i2c, dac5571_id);
diff --git a/drivers/iio/dac/vf610_dac.c b/drivers/iio/dac/vf610_dac.c
index fc182250c622..de73bc5a1c93 100644
--- a/drivers/iio/dac/vf610_dac.c
+++ b/drivers/iio/dac/vf610_dac.c
@@ -231,7 +231,7 @@ error_iio_device_register:
return ret;
}
-static int vf610_dac_remove(struct platform_device *pdev)
+static void vf610_dac_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct vf610_dac *info = iio_priv(indio_dev);
@@ -239,8 +239,6 @@ static int vf610_dac_remove(struct platform_device *pdev)
iio_device_unregister(indio_dev);
vf610_dac_exit(info);
clk_disable_unprepare(info->clk);
-
- return 0;
}
static int vf610_dac_suspend(struct device *dev)
@@ -274,7 +272,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(vf610_dac_pm_ops, vf610_dac_suspend,
static struct platform_driver vf610_dac_driver = {
.probe = vf610_dac_probe,
- .remove = vf610_dac_remove,
+ .remove_new = vf610_dac_remove,
.driver = {
.name = "vf610-dac",
.of_match_table = vf610_dac_match,
diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c
index 85e289700c3c..4abf80f75ef5 100644
--- a/drivers/iio/frequency/adf4350.c
+++ b/drivers/iio/frequency/adf4350.c
@@ -33,7 +33,6 @@ enum {
struct adf4350_state {
struct spi_device *spi;
- struct regulator *reg;
struct gpio_desc *lock_detect_gpiod;
struct adf4350_platform_data *pdata;
struct clk *clk;
@@ -469,6 +468,15 @@ static struct adf4350_platform_data *adf4350_parse_dt(struct device *dev)
return pdata;
}
+static void adf4350_power_down(void *data)
+{
+ struct iio_dev *indio_dev = data;
+ struct adf4350_state *st = iio_priv(indio_dev);
+
+ st->regs[ADF4350_REG2] |= ADF4350_REG2_POWER_DOWN_EN;
+ adf4350_sync_config(st);
+}
+
static int adf4350_probe(struct spi_device *spi)
{
struct adf4350_platform_data *pdata;
@@ -491,31 +499,21 @@ static int adf4350_probe(struct spi_device *spi)
}
if (!pdata->clkin) {
- clk = devm_clk_get(&spi->dev, "clkin");
+ clk = devm_clk_get_enabled(&spi->dev, "clkin");
if (IS_ERR(clk))
- return -EPROBE_DEFER;
-
- ret = clk_prepare_enable(clk);
- if (ret < 0)
- return ret;
+ return PTR_ERR(clk);
}
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
- if (indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_disable_clk;
- }
+ if (indio_dev == NULL)
+ return -ENOMEM;
st = iio_priv(indio_dev);
- st->reg = devm_regulator_get(&spi->dev, "vcc");
- if (!IS_ERR(st->reg)) {
- ret = regulator_enable(st->reg);
- if (ret)
- goto error_disable_clk;
- }
+ ret = devm_regulator_get_enable(&spi->dev, "vcc");
+ if (ret)
+ return ret;
- spi_set_drvdata(spi, indio_dev);
st->spi = spi;
st->pdata = pdata;
@@ -544,47 +542,21 @@ static int adf4350_probe(struct spi_device *spi)
st->lock_detect_gpiod = devm_gpiod_get_optional(&spi->dev, NULL,
GPIOD_IN);
- if (IS_ERR(st->lock_detect_gpiod)) {
- ret = PTR_ERR(st->lock_detect_gpiod);
- goto error_disable_reg;
- }
+ if (IS_ERR(st->lock_detect_gpiod))
+ return PTR_ERR(st->lock_detect_gpiod);
if (pdata->power_up_frequency) {
ret = adf4350_set_freq(st, pdata->power_up_frequency);
if (ret)
- goto error_disable_reg;
+ return ret;
}
- ret = iio_device_register(indio_dev);
+ ret = devm_add_action_or_reset(&spi->dev, adf4350_power_down, indio_dev);
if (ret)
- goto error_disable_reg;
-
- return 0;
-
-error_disable_reg:
- if (!IS_ERR(st->reg))
- regulator_disable(st->reg);
-error_disable_clk:
- clk_disable_unprepare(clk);
-
- return ret;
-}
-
-static void adf4350_remove(struct spi_device *spi)
-{
- struct iio_dev *indio_dev = spi_get_drvdata(spi);
- struct adf4350_state *st = iio_priv(indio_dev);
- struct regulator *reg = st->reg;
-
- st->regs[ADF4350_REG2] |= ADF4350_REG2_POWER_DOWN_EN;
- adf4350_sync_config(st);
-
- iio_device_unregister(indio_dev);
-
- clk_disable_unprepare(st->clk);
+ return dev_err_probe(&spi->dev, ret,
+ "Failed to add action to managed power down\n");
- if (!IS_ERR(reg))
- regulator_disable(reg);
+ return devm_iio_device_register(&spi->dev, indio_dev);
}
static const struct of_device_id adf4350_of_match[] = {
@@ -607,7 +579,6 @@ static struct spi_driver adf4350_driver = {
.of_match_table = adf4350_of_match,
},
.probe = adf4350_probe,
- .remove = adf4350_remove,
.id_table = adf4350_id,
};
module_spi_driver(adf4350_driver);
diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index 698c50da1f10..59a38bf9459b 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -359,7 +359,7 @@ error_remove_trigger:
}
/* Function to deinitialize the processing for usage id */
-static int hid_gyro_3d_remove(struct platform_device *pdev)
+static void hid_gyro_3d_remove(struct platform_device *pdev)
{
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@@ -368,8 +368,6 @@ static int hid_gyro_3d_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_GYRO_3D);
iio_device_unregister(indio_dev);
hid_sensor_remove_trigger(indio_dev, &gyro_state->common_attributes);
-
- return 0;
}
static const struct platform_device_id hid_gyro_3d_ids[] = {
@@ -388,7 +386,7 @@ static struct platform_driver hid_gyro_3d_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_gyro_3d_probe,
- .remove = hid_gyro_3d_remove,
+ .remove_new = hid_gyro_3d_remove,
};
module_platform_driver(hid_gyro_3d_platform_driver);
diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c
index fa0fe404a70a..bf6d2636a85e 100644
--- a/drivers/iio/humidity/hid-sensor-humidity.c
+++ b/drivers/iio/humidity/hid-sensor-humidity.c
@@ -260,7 +260,7 @@ error_remove_trigger:
}
/* Function to deinitialize the processing for usage id */
-static int hid_humidity_remove(struct platform_device *pdev)
+static void hid_humidity_remove(struct platform_device *pdev)
{
struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@@ -269,8 +269,6 @@ static int hid_humidity_remove(struct platform_device *pdev)
iio_device_unregister(indio_dev);
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_HUMIDITY);
hid_sensor_remove_trigger(indio_dev, &humid_st->common_attributes);
-
- return 0;
}
static const struct platform_device_id hid_humidity_ids[] = {
@@ -289,7 +287,7 @@ static struct platform_driver hid_humidity_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_humidity_probe,
- .remove = hid_humidity_remove,
+ .remove_new = hid_humidity_remove,
};
module_platform_driver(hid_humidity_platform_driver);
diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h
index 501e286702ef..1a38b1915e7a 100644
--- a/drivers/iio/iio_core.h
+++ b/drivers/iio/iio_core.h
@@ -30,9 +30,6 @@ struct iio_ioctl_handler {
unsigned int cmd, unsigned long arg);
};
-long iio_device_ioctl(struct iio_dev *indio_dev, struct file *filp,
- unsigned int cmd, unsigned long arg);
-
void iio_device_ioctl_handler_register(struct iio_dev *indio_dev,
struct iio_ioctl_handler *h);
void iio_device_ioctl_handler_unregister(struct iio_ioctl_handler *h);
diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c
index 17275a53ca2c..00e4e09cdafb 100644
--- a/drivers/iio/imu/adis16475.c
+++ b/drivers/iio/imu/adis16475.c
@@ -31,6 +31,12 @@
#define ADIS16475_REG_Y_ACCEL_L 0x14
#define ADIS16475_REG_Z_ACCEL_L 0x18
#define ADIS16475_REG_TEMP_OUT 0x1c
+#define ADIS16475_REG_X_DELTANG_L 0x24
+#define ADIS16475_REG_Y_DELTANG_L 0x28
+#define ADIS16475_REG_Z_DELTANG_L 0x2C
+#define ADIS16475_REG_X_DELTVEL_L 0x30
+#define ADIS16475_REG_Y_DELTVEL_L 0x34
+#define ADIS16475_REG_Z_DELTVEL_L 0x38
#define ADIS16475_REG_X_GYRO_BIAS_L 0x40
#define ADIS16475_REG_Y_GYRO_BIAS_L 0x44
#define ADIS16475_REG_Z_GYRO_BIAS_L 0x48
@@ -55,6 +61,7 @@
#define ADIS16475_REG_PROD_ID 0x72
#define ADIS16475_REG_SERIAL_NUM 0x74
#define ADIS16475_REG_FLASH_CNT 0x7c
+#define ADIS16500_BURST_DATA_SEL_MASK BIT(8)
#define ADIS16500_BURST32_MASK BIT(9)
#define ADIS16500_BURST32(x) FIELD_PREP(ADIS16500_BURST32_MASK, x)
/* number of data elements in burst mode */
@@ -65,6 +72,8 @@
#define ADIS16475_BURST_MAX_SPEED 1000000
#define ADIS16475_LSB_DEC_MASK BIT(0)
#define ADIS16475_LSB_FIR_MASK BIT(1)
+#define ADIS16500_BURST_DATA_SEL_0_CHN_MASK GENMASK(5, 0)
+#define ADIS16500_BURST_DATA_SEL_1_CHN_MASK GENMASK(12, 7)
enum {
ADIS16475_SYNC_DIRECT = 1,
@@ -84,16 +93,20 @@ struct adis16475_chip_info {
const struct adis16475_sync *sync;
const struct adis_data adis_data;
const char *name;
+#define ADIS16475_HAS_BURST32 BIT(0)
+#define ADIS16475_HAS_BURST_DELTA_DATA BIT(1)
+ const long flags;
u32 num_channels;
u32 gyro_max_val;
u32 gyro_max_scale;
u32 accel_max_val;
u32 accel_max_scale;
u32 temp_scale;
+ u32 deltang_max_val;
+ u32 deltvel_max_val;
u32 int_clk;
u16 max_dec;
u8 num_sync;
- bool has_burst32;
};
struct adis16475 {
@@ -115,6 +128,12 @@ enum {
ADIS16475_SCAN_ACCEL_Y,
ADIS16475_SCAN_ACCEL_Z,
ADIS16475_SCAN_TEMP,
+ ADIS16475_SCAN_DELTANG_X,
+ ADIS16475_SCAN_DELTANG_Y,
+ ADIS16475_SCAN_DELTANG_Z,
+ ADIS16475_SCAN_DELTVEL_X,
+ ADIS16475_SCAN_DELTVEL_Y,
+ ADIS16475_SCAN_DELTVEL_Z,
};
static bool low_rate_allow;
@@ -451,6 +470,14 @@ static int adis16475_read_raw(struct iio_dev *indio_dev,
case IIO_TEMP:
*val = st->info->temp_scale;
return IIO_VAL_INT;
+ case IIO_DELTA_ANGL:
+ *val = st->info->deltang_max_val;
+ *val2 = 31;
+ return IIO_VAL_FRACTIONAL_LOG2;
+ case IIO_DELTA_VELOCITY:
+ *val = st->info->deltvel_max_val;
+ *val2 = 31;
+ return IIO_VAL_FRACTIONAL_LOG2;
default:
return -EINVAL;
}
@@ -551,6 +578,32 @@ static int adis16475_write_raw(struct iio_dev *indio_dev,
}, \
}
+#define ADIS16475_MOD_CHAN_DELTA(_type, _mod, _address, _si, _r_bits, _s_bits) { \
+ .type = (_type), \
+ .modified = 1, \
+ .channel2 = (_mod), \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .address = (_address), \
+ .scan_index = _si, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = (_r_bits), \
+ .storagebits = (_s_bits), \
+ .endianness = IIO_BE, \
+ }, \
+ }
+
+#define ADIS16475_DELTANG_CHAN(_mod) \
+ ADIS16475_MOD_CHAN_DELTA(IIO_DELTA_ANGL, IIO_MOD_ ## _mod, \
+ ADIS16475_REG_ ## _mod ## _DELTANG_L, ADIS16475_SCAN_DELTANG_ ## _mod, 32, 32)
+
+#define ADIS16475_DELTVEL_CHAN(_mod) \
+ ADIS16475_MOD_CHAN_DELTA(IIO_DELTA_VELOCITY, IIO_MOD_ ## _mod, \
+ ADIS16475_REG_ ## _mod ## _DELTVEL_L, ADIS16475_SCAN_DELTVEL_ ## _mod, 32, 32)
+
static const struct iio_chan_spec adis16475_channels[] = {
ADIS16475_GYRO_CHANNEL(X),
ADIS16475_GYRO_CHANNEL(Y),
@@ -559,7 +612,13 @@ static const struct iio_chan_spec adis16475_channels[] = {
ADIS16475_ACCEL_CHANNEL(Y),
ADIS16475_ACCEL_CHANNEL(Z),
ADIS16475_TEMP_CHANNEL(),
- IIO_CHAN_SOFT_TIMESTAMP(7)
+ ADIS16475_DELTANG_CHAN(X),
+ ADIS16475_DELTANG_CHAN(Y),
+ ADIS16475_DELTANG_CHAN(Z),
+ ADIS16475_DELTVEL_CHAN(X),
+ ADIS16475_DELTVEL_CHAN(Y),
+ ADIS16475_DELTVEL_CHAN(Z),
+ IIO_CHAN_SOFT_TIMESTAMP(13)
};
enum adis16475_variant {
@@ -662,6 +721,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
.temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(2160),
+ .deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
@@ -677,6 +738,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
.temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(360),
+ .deltvel_max_val = 100,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
@@ -692,6 +755,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
.temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(720),
+ .deltvel_max_val = 100,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
@@ -707,6 +772,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
.temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(2160),
+ .deltvel_max_val = 100,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
@@ -722,11 +789,13 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
.temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(360),
+ .deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
- .has_burst32 = true,
+ .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16477, &adis16475_timeouts),
},
[ADIS16477_2] = {
@@ -738,11 +807,13 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
.temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(720),
+ .deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
- .has_burst32 = true,
+ .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16477, &adis16475_timeouts),
},
[ADIS16477_3] = {
@@ -754,11 +825,13 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
.temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(2160),
+ .deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
- .has_burst32 = true,
+ .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16477, &adis16475_timeouts),
},
[ADIS16465_1] = {
@@ -770,6 +843,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
.temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(360),
+ .deltvel_max_val = 100,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
@@ -785,6 +860,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
.temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(720),
+ .deltvel_max_val = 100,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
@@ -800,6 +877,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
.temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(2160),
+ .deltvel_max_val = 100,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
@@ -815,6 +894,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
.temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(360),
+ .deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
@@ -830,6 +911,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
.temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(720),
+ .deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
@@ -845,6 +928,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
.temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(2160),
+ .deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
@@ -860,12 +945,14 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 392,
.accel_max_scale = 32000 << 16,
.temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(2160),
+ .deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
- .has_burst32 = true,
+ .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16500, &adis1650x_timeouts),
},
[ADIS16505_1] = {
@@ -877,12 +964,14 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 78,
.accel_max_scale = 32000 << 16,
.temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(360),
+ .deltvel_max_val = 100,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
- .has_burst32 = true,
+ .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts),
},
[ADIS16505_2] = {
@@ -894,12 +983,14 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 78,
.accel_max_scale = 32000 << 16,
.temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(720),
+ .deltvel_max_val = 100,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
- .has_burst32 = true,
+ .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts),
},
[ADIS16505_3] = {
@@ -911,12 +1002,14 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 78,
.accel_max_scale = 32000 << 16,
.temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(2160),
+ .deltvel_max_val = 100,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
- .has_burst32 = true,
+ .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts),
},
[ADIS16507_1] = {
@@ -928,12 +1021,14 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 392,
.accel_max_scale = 32000 << 16,
.temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(360),
+ .deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
- .has_burst32 = true,
+ .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts),
},
[ADIS16507_2] = {
@@ -945,12 +1040,14 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 392,
.accel_max_scale = 32000 << 16,
.temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(720),
+ .deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
- .has_burst32 = true,
+ .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts),
},
[ADIS16507_3] = {
@@ -962,20 +1059,47 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 392,
.accel_max_scale = 32000 << 16,
.temp_scale = 100,
+ .deltang_max_val = IIO_DEGREE_TO_RAD(2160),
+ .deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
- .has_burst32 = true,
+ .flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts),
},
};
+static int adis16475_update_scan_mode(struct iio_dev *indio_dev,
+ const unsigned long *scan_mask)
+{
+ u16 en;
+ int ret;
+ struct adis16475 *st = iio_priv(indio_dev);
+
+ if (st->info->flags & ADIS16475_HAS_BURST_DELTA_DATA) {
+ if ((*scan_mask & ADIS16500_BURST_DATA_SEL_0_CHN_MASK) &&
+ (*scan_mask & ADIS16500_BURST_DATA_SEL_1_CHN_MASK))
+ return -EINVAL;
+ if (*scan_mask & ADIS16500_BURST_DATA_SEL_0_CHN_MASK)
+ en = FIELD_PREP(ADIS16500_BURST_DATA_SEL_MASK, 0);
+ else
+ en = FIELD_PREP(ADIS16500_BURST_DATA_SEL_MASK, 1);
+
+ ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
+ ADIS16500_BURST_DATA_SEL_MASK, en);
+ if (ret)
+ return ret;
+ }
+
+ return adis_update_scan_mode(indio_dev, scan_mask);
+}
+
static const struct iio_info adis16475_info = {
.read_raw = &adis16475_read_raw,
.write_raw = &adis16475_write_raw,
- .update_scan_mode = adis_update_scan_mode,
+ .update_scan_mode = adis16475_update_scan_mode,
.debugfs_reg_access = adis_debugfs_reg_access,
};
@@ -998,7 +1122,7 @@ static void adis16475_burst32_check(struct adis16475 *st)
int ret;
struct adis *adis = &st->adis;
- if (!st->info->has_burst32)
+ if (!(st->info->flags & ADIS16475_HAS_BURST32))
return;
if (st->lsb_flag && !st->burst32) {
@@ -1044,7 +1168,7 @@ static irqreturn_t adis16475_trigger_handler(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev;
struct adis16475 *st = iio_priv(indio_dev);
struct adis *adis = &st->adis;
- int ret, bit, i = 0;
+ int ret, bit, buff_offset = 0, i = 0;
__be16 *buffer;
u16 crc;
bool valid;
@@ -1074,6 +1198,9 @@ static irqreturn_t adis16475_trigger_handler(int irq, void *p)
case ADIS16475_SCAN_TEMP:
st->data[i++] = buffer[offset];
break;
+ case ADIS16475_SCAN_DELTANG_X ... ADIS16475_SCAN_DELTVEL_Z:
+ buff_offset = ADIS16475_SCAN_DELTANG_X;
+ fallthrough;
case ADIS16475_SCAN_GYRO_X ... ADIS16475_SCAN_ACCEL_Z:
/*
* The first 2 bytes on the received data are the
@@ -1081,18 +1208,18 @@ static irqreturn_t adis16475_trigger_handler(int irq, void *p)
*/
if (st->burst32) {
/* upper 16 */
- st->data[i++] = buffer[bit * 2 + 2];
+ st->data[i++] = buffer[(bit - buff_offset) * 2 + 2];
/* lower 16 */
- st->data[i++] = buffer[bit * 2 + 1];
+ st->data[i++] = buffer[(bit - buff_offset) * 2 + 1];
} else {
- st->data[i++] = buffer[bit + 1];
+ st->data[i++] = buffer[(bit - buff_offset) + 1];
/*
* Don't bother in doing the manual read if the
* device supports burst32. burst32 will be
* enabled in the next call to
* adis16475_burst32_check()...
*/
- if (st->lsb_flag && !st->info->has_burst32) {
+ if (st->lsb_flag && !(st->info->flags & ADIS16475_HAS_BURST32)) {
u16 val = 0;
const u32 reg = ADIS16475_REG_X_GYRO_L +
bit * 4;
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index ed5a96e78df0..95f548235de7 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -464,7 +464,6 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type);
int inv_mpu6050_prepare_fifo(struct inv_mpu6050_state *st, bool enable);
int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en,
unsigned int mask);
-int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 val);
int inv_mpu_acpi_create_mux_client(struct i2c_client *client);
void inv_mpu_acpi_delete_mux_client(struct i2c_client *client);
int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 6dc4d2b296bb..c77745b594bd 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -90,6 +90,8 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_POSITIONRELATIVE] = "positionrelative",
[IIO_PHASE] = "phase",
[IIO_MASSCONCENTRATION] = "massconcentration",
+ [IIO_DELTA_ANGL] = "deltaangl",
+ [IIO_DELTA_VELOCITY] = "deltavelocity",
[IIO_COLORTEMP] = "colortemp",
[IIO_CHROMATICITY] = "chromaticity",
};
diff --git a/drivers/iio/light/cm3605.c b/drivers/iio/light/cm3605.c
index e7f0b81b7f5a..22a63a89f289 100644
--- a/drivers/iio/light/cm3605.c
+++ b/drivers/iio/light/cm3605.c
@@ -266,7 +266,7 @@ out_disable_vdd:
return ret;
}
-static int cm3605_remove(struct platform_device *pdev)
+static void cm3605_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct cm3605 *cm3605 = iio_priv(indio_dev);
@@ -276,8 +276,6 @@ static int cm3605_remove(struct platform_device *pdev)
gpiod_set_value_cansleep(cm3605->aset, 0);
iio_device_unregister(indio_dev);
regulator_disable(cm3605->vdd);
-
- return 0;
}
static int cm3605_pm_suspend(struct device *dev)
@@ -320,7 +318,7 @@ static struct platform_driver cm3605_driver = {
.pm = pm_sleep_ptr(&cm3605_dev_pm_ops),
},
.probe = cm3605_probe,
- .remove = cm3605_remove,
+ .remove_new = cm3605_remove,
};
module_platform_driver(cm3605_driver);
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index c9d114ff080a..f17304b54468 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -445,7 +445,7 @@ error_remove_trigger:
}
/* Function to deinitialize the processing for usage id */
-static int hid_als_remove(struct platform_device *pdev)
+static void hid_als_remove(struct platform_device *pdev)
{
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@@ -454,8 +454,6 @@ static int hid_als_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, hsdev->usage);
iio_device_unregister(indio_dev);
hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes);
-
- return 0;
}
static const struct platform_device_id hid_als_ids[] = {
@@ -478,7 +476,7 @@ static struct platform_driver hid_als_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_als_probe,
- .remove = hid_als_remove,
+ .remove_new = hid_als_remove,
};
module_platform_driver(hid_als_platform_driver);
diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
index a47591e1bad9..26c481d2998c 100644
--- a/drivers/iio/light/hid-sensor-prox.c
+++ b/drivers/iio/light/hid-sensor-prox.c
@@ -313,7 +313,7 @@ error_remove_trigger:
}
/* Function to deinitialize the processing for usage id */
-static int hid_prox_remove(struct platform_device *pdev)
+static void hid_prox_remove(struct platform_device *pdev)
{
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@@ -322,8 +322,6 @@ static int hid_prox_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, hsdev->usage);
iio_device_unregister(indio_dev);
hid_sensor_remove_trigger(indio_dev, &prox_state->common_attributes);
-
- return 0;
}
static const struct platform_device_id hid_prox_ids[] = {
@@ -346,7 +344,7 @@ static struct platform_driver hid_prox_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_prox_probe,
- .remove = hid_prox_remove,
+ .remove_new = hid_prox_remove,
};
module_platform_driver(hid_prox_platform_driver);
diff --git a/drivers/iio/light/lm3533-als.c b/drivers/iio/light/lm3533-als.c
index 827bc25269e9..7800f7fa51b7 100644
--- a/drivers/iio/light/lm3533-als.c
+++ b/drivers/iio/light/lm3533-als.c
@@ -895,7 +895,7 @@ err_free_irq:
return ret;
}
-static int lm3533_als_remove(struct platform_device *pdev)
+static void lm3533_als_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct lm3533_als *als = iio_priv(indio_dev);
@@ -905,8 +905,6 @@ static int lm3533_als_remove(struct platform_device *pdev)
lm3533_als_disable(als);
if (als->irq)
free_irq(als->irq, indio_dev);
-
- return 0;
}
static struct platform_driver lm3533_als_driver = {
@@ -914,7 +912,7 @@ static struct platform_driver lm3533_als_driver = {
.name = "lm3533-als",
},
.probe = lm3533_als_probe,
- .remove = lm3533_als_remove,
+ .remove_new = lm3533_als_remove,
};
module_platform_driver(lm3533_als_driver);
diff --git a/drivers/iio/light/opt4001.c b/drivers/iio/light/opt4001.c
index 502946bf9f94..6cf60151b3d8 100644
--- a/drivers/iio/light/opt4001.c
+++ b/drivers/iio/light/opt4001.c
@@ -412,7 +412,7 @@ static int opt4001_probe(struct i2c_client *client)
if (dev_id != OPT4001_DEVICE_ID_VAL)
dev_warn(&client->dev, "Device ID: %#04x unknown\n", dev_id);
- chip->chip_info = device_get_match_data(&client->dev);
+ chip->chip_info = i2c_get_match_data(client);
indio_dev->channels = opt4001_channels;
indio_dev->num_channels = ARRAY_SIZE(opt4001_channels);
diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c
index eb706d0bf70b..8cfceb007936 100644
--- a/drivers/iio/magnetometer/ak8975.c
+++ b/drivers/iio/magnetometer/ak8975.c
@@ -812,18 +812,6 @@ static const struct iio_info ak8975_info = {
.read_raw = &ak8975_read_raw,
};
-static const struct acpi_device_id ak_acpi_match[] = {
- {"AK8975", AK8975},
- {"AK8963", AK8963},
- {"INVN6500", AK8963},
- {"AK009911", AK09911},
- {"AK09911", AK09911},
- {"AKM9911", AK09911},
- {"AK09912", AK09912},
- { }
-};
-MODULE_DEVICE_TABLE(acpi, ak_acpi_match);
-
static void ak8975_fill_buffer(struct iio_dev *indio_dev)
{
struct ak8975_data *data = iio_priv(indio_dev);
@@ -883,10 +871,7 @@ static int ak8975_probe(struct i2c_client *client)
struct iio_dev *indio_dev;
struct gpio_desc *eoc_gpiod;
struct gpio_desc *reset_gpiod;
- const void *match;
- unsigned int i;
int err;
- enum asahi_compass_chipset chipset;
const char *name = NULL;
/*
@@ -928,27 +913,15 @@ static int ak8975_probe(struct i2c_client *client)
return err;
/* id will be NULL when enumerated via ACPI */
- match = device_get_match_data(&client->dev);
- if (match) {
- chipset = (uintptr_t)match;
- name = dev_name(&client->dev);
- } else if (id) {
- chipset = (enum asahi_compass_chipset)(id->driver_data);
- name = id->name;
- } else
- return -ENOSYS;
-
- for (i = 0; i < ARRAY_SIZE(ak_def_array); i++)
- if (ak_def_array[i].type == chipset)
- break;
-
- if (i == ARRAY_SIZE(ak_def_array)) {
- dev_err(&client->dev, "AKM device type unsupported: %d\n",
- chipset);
+ data->def = i2c_get_match_data(client);
+ if (!data->def)
return -ENODEV;
- }
- data->def = &ak_def_array[i];
+ /* If enumerated via firmware node, fix the ABI */
+ if (dev_fwnode(&client->dev))
+ name = dev_name(&client->dev);
+ else
+ name = id->name;
/* Fetch the regulators */
data->vdd = devm_regulator_get(&client->dev, "vdd");
@@ -1076,29 +1049,40 @@ static int ak8975_runtime_resume(struct device *dev)
static DEFINE_RUNTIME_DEV_PM_OPS(ak8975_dev_pm_ops, ak8975_runtime_suspend,
ak8975_runtime_resume, NULL);
+static const struct acpi_device_id ak_acpi_match[] = {
+ {"AK8963", (kernel_ulong_t)&ak_def_array[AK8963] },
+ {"AK8975", (kernel_ulong_t)&ak_def_array[AK8975] },
+ {"AK009911", (kernel_ulong_t)&ak_def_array[AK09911] },
+ {"AK09911", (kernel_ulong_t)&ak_def_array[AK09911] },
+ {"AK09912", (kernel_ulong_t)&ak_def_array[AK09912] },
+ {"AKM9911", (kernel_ulong_t)&ak_def_array[AK09911] },
+ {"INVN6500", (kernel_ulong_t)&ak_def_array[AK8963] },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, ak_acpi_match);
+
static const struct i2c_device_id ak8975_id[] = {
- {"ak8975", AK8975},
- {"ak8963", AK8963},
- {"AK8963", AK8963},
- {"ak09911", AK09911},
- {"ak09912", AK09912},
- {"ak09916", AK09916},
+ {"AK8963", (kernel_ulong_t)&ak_def_array[AK8963] },
+ {"ak8963", (kernel_ulong_t)&ak_def_array[AK8963] },
+ {"ak8975", (kernel_ulong_t)&ak_def_array[AK8975] },
+ {"ak09911", (kernel_ulong_t)&ak_def_array[AK09911] },
+ {"ak09912", (kernel_ulong_t)&ak_def_array[AK09912] },
+ {"ak09916", (kernel_ulong_t)&ak_def_array[AK09916] },
{}
};
-
MODULE_DEVICE_TABLE(i2c, ak8975_id);
static const struct of_device_id ak8975_of_match[] = {
- { .compatible = "asahi-kasei,ak8975", },
- { .compatible = "ak8975", },
- { .compatible = "asahi-kasei,ak8963", },
- { .compatible = "ak8963", },
- { .compatible = "asahi-kasei,ak09911", },
- { .compatible = "ak09911", },
- { .compatible = "asahi-kasei,ak09912", },
- { .compatible = "ak09912", },
- { .compatible = "asahi-kasei,ak09916", },
- { .compatible = "ak09916", },
+ { .compatible = "asahi-kasei,ak8975", .data = &ak_def_array[AK8975] },
+ { .compatible = "ak8975", .data = &ak_def_array[AK8975] },
+ { .compatible = "asahi-kasei,ak8963", .data = &ak_def_array[AK8963] },
+ { .compatible = "ak8963", .data = &ak_def_array[AK8963] },
+ { .compatible = "asahi-kasei,ak09911", .data = &ak_def_array[AK09911] },
+ { .compatible = "ak09911", .data = &ak_def_array[AK09911] },
+ { .compatible = "asahi-kasei,ak09912", .data = &ak_def_array[AK09912] },
+ { .compatible = "ak09912", .data = &ak_def_array[AK09912] },
+ { .compatible = "asahi-kasei,ak09916", .data = &ak_def_array[AK09916] },
+ { .compatible = "ak09916", .data = &ak_def_array[AK09916] },
{}
};
MODULE_DEVICE_TABLE(of, ak8975_of_match);
diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
index e85a3a8eea90..5c795a430d09 100644
--- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -547,7 +547,7 @@ error_remove_trigger:
}
/* Function to deinitialize the processing for usage id */
-static int hid_magn_3d_remove(struct platform_device *pdev)
+static void hid_magn_3d_remove(struct platform_device *pdev)
{
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@@ -556,8 +556,6 @@ static int hid_magn_3d_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_COMPASS_3D);
iio_device_unregister(indio_dev);
hid_sensor_remove_trigger(indio_dev, &magn_state->magn_flux_attributes);
-
- return 0;
}
static const struct platform_device_id hid_magn_3d_ids[] = {
@@ -576,7 +574,7 @@ static struct platform_driver hid_magn_3d_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_magn_3d_probe,
- .remove = hid_magn_3d_remove,
+ .remove_new = hid_magn_3d_remove,
};
module_platform_driver(hid_magn_3d_platform_driver);
diff --git a/drivers/iio/magnetometer/yamaha-yas530.c b/drivers/iio/magnetometer/yamaha-yas530.c
index c5e485bfc6fc..7b041bb38693 100644
--- a/drivers/iio/magnetometer/yamaha-yas530.c
+++ b/drivers/iio/magnetometer/yamaha-yas530.c
@@ -1434,9 +1434,7 @@ static int yas5xx_probe(struct i2c_client *i2c)
goto assert_reset;
}
- ci = device_get_match_data(dev);
- if (!ci)
- ci = (const struct yas5xx_chip_info *)id->driver_data;
+ ci = i2c_get_match_data(i2c);
yas5xx->chip_info = ci;
ret = regmap_read(yas5xx->map, YAS5XX_DEVICE_ID, &id_check);
diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c
index ba5b581d5b25..8943d5c78bc0 100644
--- a/drivers/iio/orientation/hid-sensor-incl-3d.c
+++ b/drivers/iio/orientation/hid-sensor-incl-3d.c
@@ -383,7 +383,7 @@ error_remove_trigger:
}
/* Function to deinitialize the processing for usage id */
-static int hid_incl_3d_remove(struct platform_device *pdev)
+static void hid_incl_3d_remove(struct platform_device *pdev)
{
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@@ -392,8 +392,6 @@ static int hid_incl_3d_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_INCLINOMETER_3D);
iio_device_unregister(indio_dev);
hid_sensor_remove_trigger(indio_dev, &incl_state->common_attributes);
-
- return 0;
}
static const struct platform_device_id hid_incl_3d_ids[] = {
@@ -412,7 +410,7 @@ static struct platform_driver hid_incl_3d_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_incl_3d_probe,
- .remove = hid_incl_3d_remove,
+ .remove_new = hid_incl_3d_remove,
};
module_platform_driver(hid_incl_3d_platform_driver);
diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c
index a033699910e8..5e8cadd5177a 100644
--- a/drivers/iio/orientation/hid-sensor-rotation.c
+++ b/drivers/iio/orientation/hid-sensor-rotation.c
@@ -327,7 +327,7 @@ error_remove_trigger:
}
/* Function to deinitialize the processing for usage id */
-static int hid_dev_rot_remove(struct platform_device *pdev)
+static void hid_dev_rot_remove(struct platform_device *pdev)
{
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@@ -336,8 +336,6 @@ static int hid_dev_rot_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, hsdev->usage);
iio_device_unregister(indio_dev);
hid_sensor_remove_trigger(indio_dev, &rot_state->common_attributes);
-
- return 0;
}
static const struct platform_device_id hid_dev_rot_ids[] = {
@@ -364,7 +362,7 @@ static struct platform_driver hid_dev_rot_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_dev_rot_probe,
- .remove = hid_dev_rot_remove,
+ .remove_new = hid_dev_rot_remove,
};
module_platform_driver(hid_dev_rot_platform_driver);
diff --git a/drivers/iio/position/hid-sensor-custom-intel-hinge.c b/drivers/iio/position/hid-sensor-custom-intel-hinge.c
index 07c30d217255..76e173850a35 100644
--- a/drivers/iio/position/hid-sensor-custom-intel-hinge.c
+++ b/drivers/iio/position/hid-sensor-custom-intel-hinge.c
@@ -342,7 +342,7 @@ error_remove_trigger:
}
/* Function to deinitialize the processing for usage id */
-static int hid_hinge_remove(struct platform_device *pdev)
+static void hid_hinge_remove(struct platform_device *pdev)
{
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@@ -351,8 +351,6 @@ static int hid_hinge_remove(struct platform_device *pdev)
iio_device_unregister(indio_dev);
sensor_hub_remove_callback(hsdev, hsdev->usage);
hid_sensor_remove_trigger(indio_dev, &st->common_attributes);
-
- return 0;
}
static const struct platform_device_id hid_hinge_ids[] = {
@@ -371,7 +369,7 @@ static struct platform_driver hid_hinge_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_hinge_probe,
- .remove = hid_hinge_remove,
+ .remove_new = hid_hinge_remove,
};
module_platform_driver(hid_hinge_platform_driver);
diff --git a/drivers/iio/potentiometer/ad5110.c b/drivers/iio/potentiometer/ad5110.c
index 991e745c4f93..aaf02cc7aeba 100644
--- a/drivers/iio/potentiometer/ad5110.c
+++ b/drivers/iio/potentiometer/ad5110.c
@@ -278,14 +278,19 @@ static const struct of_device_id ad5110_of_match[] = {
};
MODULE_DEVICE_TABLE(of, ad5110_of_match);
+#define AD5110_ID_TABLE(_name, cfg) { \
+ .name = _name, \
+ .driver_data = (kernel_ulong_t)&ad5110_cfg[cfg], \
+}
+
static const struct i2c_device_id ad5110_id[] = {
- { "ad5110-10", AD5110_10 },
- { "ad5110-80", AD5110_80 },
- { "ad5112-05", AD5112_05 },
- { "ad5112-10", AD5112_10 },
- { "ad5112-80", AD5112_80 },
- { "ad5114-10", AD5114_10 },
- { "ad5114-80", AD5114_80 },
+ AD5110_ID_TABLE("ad5110-10", AD5110_10),
+ AD5110_ID_TABLE("ad5110-80", AD5110_80),
+ AD5110_ID_TABLE("ad5112-05", AD5112_05),
+ AD5110_ID_TABLE("ad5112-10", AD5112_10),
+ AD5110_ID_TABLE("ad5112-80", AD5112_80),
+ AD5110_ID_TABLE("ad5114-10", AD5114_10),
+ AD5110_ID_TABLE("ad5114-80", AD5114_80),
{ }
};
MODULE_DEVICE_TABLE(i2c, ad5110_id);
@@ -305,7 +310,7 @@ static int ad5110_probe(struct i2c_client *client)
data->client = client;
mutex_init(&data->lock);
data->enable = 1;
- data->cfg = device_get_match_data(dev);
+ data->cfg = i2c_get_match_data(client);
/* refresh RDAC register with EEPROM */
ret = ad5110_write(data, AD5110_RESET, 0);
diff --git a/drivers/iio/potentiometer/ds1803.c b/drivers/iio/potentiometer/ds1803.c
index fc183e0790da..e0526dd0e3cb 100644
--- a/drivers/iio/potentiometer/ds1803.c
+++ b/drivers/iio/potentiometer/ds1803.c
@@ -204,7 +204,6 @@ static const struct iio_info ds1803_info = {
static int ds1803_probe(struct i2c_client *client)
{
- const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct device *dev = &client->dev;
struct ds1803_data *data;
struct iio_dev *indio_dev;
@@ -217,9 +216,7 @@ static int ds1803_probe(struct i2c_client *client)
data = iio_priv(indio_dev);
data->client = client;
- data->cfg = device_get_match_data(dev);
- if (!data->cfg)
- data->cfg = &ds1803_cfg[id->driver_data];
+ data->cfg = i2c_get_match_data(client);
indio_dev->info = &ds1803_info;
indio_dev->channels = data->cfg->channels;
@@ -239,10 +236,10 @@ static const struct of_device_id ds1803_dt_ids[] = {
MODULE_DEVICE_TABLE(of, ds1803_dt_ids);
static const struct i2c_device_id ds1803_id[] = {
- { "ds1803-010", DS1803_010 },
- { "ds1803-050", DS1803_050 },
- { "ds1803-100", DS1803_100 },
- { "ds3502", DS3502 },
+ { "ds1803-010", (kernel_ulong_t)&ds1803_cfg[DS1803_010] },
+ { "ds1803-050", (kernel_ulong_t)&ds1803_cfg[DS1803_050] },
+ { "ds1803-100", (kernel_ulong_t)&ds1803_cfg[DS1803_100] },
+ { "ds3502", (kernel_ulong_t)&ds1803_cfg[DS3502] },
{}
};
MODULE_DEVICE_TABLE(i2c, ds1803_id);
diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c
index a9215eb32d70..956045e2db29 100644
--- a/drivers/iio/pressure/hid-sensor-press.c
+++ b/drivers/iio/pressure/hid-sensor-press.c
@@ -323,7 +323,7 @@ error_remove_trigger:
}
/* Function to deinitialize the processing for usage id */
-static int hid_press_remove(struct platform_device *pdev)
+static void hid_press_remove(struct platform_device *pdev)
{
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@@ -332,8 +332,6 @@ static int hid_press_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_PRESSURE);
iio_device_unregister(indio_dev);
hid_sensor_remove_trigger(indio_dev, &press_state->common_attributes);
-
- return 0;
}
static const struct platform_device_id hid_press_ids[] = {
@@ -352,7 +350,7 @@ static struct platform_driver hid_press_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_press_probe,
- .remove = hid_press_remove,
+ .remove_new = hid_press_remove,
};
module_platform_driver(hid_press_platform_driver);
diff --git a/drivers/iio/pressure/ms5637.c b/drivers/iio/pressure/ms5637.c
index 9b3abffb724b..ac30d76285d1 100644
--- a/drivers/iio/pressure/ms5637.c
+++ b/drivers/iio/pressure/ms5637.c
@@ -144,7 +144,6 @@ static const struct iio_info ms5637_info = {
static int ms5637_probe(struct i2c_client *client)
{
- const struct i2c_device_id *id = i2c_client_get_device_id(client);
const struct ms_tp_data *data;
struct ms_tp_dev *dev_data;
struct iio_dev *indio_dev;
@@ -159,10 +158,7 @@ static int ms5637_probe(struct i2c_client *client)
return -EOPNOTSUPP;
}
- if (id)
- data = (const struct ms_tp_data *)id->driver_data;
- else
- data = device_get_match_data(&client->dev);
+ data = i2c_get_match_data(client);
if (!data)
return -EINVAL;
diff --git a/drivers/iio/proximity/cros_ec_mkbp_proximity.c b/drivers/iio/proximity/cros_ec_mkbp_proximity.c
index 571ea1812246..4df506bb8b38 100644
--- a/drivers/iio/proximity/cros_ec_mkbp_proximity.c
+++ b/drivers/iio/proximity/cros_ec_mkbp_proximity.c
@@ -239,15 +239,13 @@ static int cros_ec_mkbp_proximity_probe(struct platform_device *pdev)
return 0;
}
-static int cros_ec_mkbp_proximity_remove(struct platform_device *pdev)
+static void cros_ec_mkbp_proximity_remove(struct platform_device *pdev)
{
struct cros_ec_mkbp_proximity_data *data = platform_get_drvdata(pdev);
struct cros_ec_device *ec = data->ec;
blocking_notifier_chain_unregister(&ec->event_notifier,
&data->notifier);
-
- return 0;
}
static const struct of_device_id cros_ec_mkbp_proximity_of_match[] = {
@@ -263,7 +261,7 @@ static struct platform_driver cros_ec_mkbp_proximity_driver = {
.pm = pm_sleep_ptr(&cros_ec_mkbp_proximity_pm_ops),
},
.probe = cros_ec_mkbp_proximity_probe,
- .remove = cros_ec_mkbp_proximity_remove,
+ .remove_new = cros_ec_mkbp_proximity_remove,
};
module_platform_driver(cros_ec_mkbp_proximity_driver);
diff --git a/drivers/iio/proximity/srf04.c b/drivers/iio/proximity/srf04.c
index faf2f806ce80..86c57672fc7e 100644
--- a/drivers/iio/proximity/srf04.c
+++ b/drivers/iio/proximity/srf04.c
@@ -344,7 +344,7 @@ static int srf04_probe(struct platform_device *pdev)
return ret;
}
-static int srf04_remove(struct platform_device *pdev)
+static void srf04_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct srf04_data *data = iio_priv(indio_dev);
@@ -355,8 +355,6 @@ static int srf04_remove(struct platform_device *pdev)
pm_runtime_disable(data->dev);
pm_runtime_set_suspended(data->dev);
}
-
- return 0;
}
static int srf04_pm_runtime_suspend(struct device *dev)
@@ -391,7 +389,7 @@ static const struct dev_pm_ops srf04_pm_ops = {
static struct platform_driver srf04_driver = {
.probe = srf04_probe,
- .remove = srf04_remove,
+ .remove_new = srf04_remove,
.driver = {
.name = "srf04-gpio",
.of_match_table = of_srf04_match,
diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c
index d977aacb7491..0d230a0dff56 100644
--- a/drivers/iio/proximity/sx9310.c
+++ b/drivers/iio/proximity/sx9310.c
@@ -159,6 +159,11 @@ static_assert(SX9310_NUM_CHANNELS <= SX_COMMON_MAX_NUM_CHANNELS);
}
#define SX9310_CHANNEL(idx) SX9310_NAMED_CHANNEL(idx, NULL)
+struct sx931x_info {
+ const char *name;
+ unsigned int whoami;
+};
+
static const struct iio_chan_spec sx9310_channels[] = {
SX9310_CHANNEL(0), /* CS0 */
SX9310_CHANNEL(1), /* CS1 */
@@ -902,7 +907,7 @@ static int sx9310_check_whoami(struct device *dev,
struct iio_dev *indio_dev)
{
struct sx_common_data *data = iio_priv(indio_dev);
- unsigned int long ddata;
+ const struct sx931x_info *ddata;
unsigned int whoami;
int ret;
@@ -910,20 +915,11 @@ static int sx9310_check_whoami(struct device *dev,
if (ret)
return ret;
- ddata = (uintptr_t)device_get_match_data(dev);
- if (ddata != whoami)
- return -EINVAL;
-
- switch (whoami) {
- case SX9310_WHOAMI_VALUE:
- indio_dev->name = "sx9310";
- break;
- case SX9311_WHOAMI_VALUE:
- indio_dev->name = "sx9311";
- break;
- default:
+ ddata = device_get_match_data(dev);
+ if (ddata->whoami != whoami)
return -ENODEV;
- }
+
+ indio_dev->name = ddata->name;
return 0;
}
@@ -1015,23 +1011,33 @@ out:
static DEFINE_SIMPLE_DEV_PM_OPS(sx9310_pm_ops, sx9310_suspend, sx9310_resume);
+static const struct sx931x_info sx9310_info = {
+ .name = "sx9310",
+ .whoami = SX9310_WHOAMI_VALUE,
+};
+
+static const struct sx931x_info sx9311_info = {
+ .name = "sx9311",
+ .whoami = SX9311_WHOAMI_VALUE,
+};
+
static const struct acpi_device_id sx9310_acpi_match[] = {
- { "STH9310", SX9310_WHOAMI_VALUE },
- { "STH9311", SX9311_WHOAMI_VALUE },
+ { "STH9310", (kernel_ulong_t)&sx9310_info },
+ { "STH9311", (kernel_ulong_t)&sx9311_info },
{}
};
MODULE_DEVICE_TABLE(acpi, sx9310_acpi_match);
static const struct of_device_id sx9310_of_match[] = {
- { .compatible = "semtech,sx9310", (void *)SX9310_WHOAMI_VALUE },
- { .compatible = "semtech,sx9311", (void *)SX9311_WHOAMI_VALUE },
+ { .compatible = "semtech,sx9310", &sx9310_info },
+ { .compatible = "semtech,sx9311", &sx9311_info },
{}
};
MODULE_DEVICE_TABLE(of, sx9310_of_match);
static const struct i2c_device_id sx9310_id[] = {
- { "sx9310", SX9310_WHOAMI_VALUE },
- { "sx9311", SX9311_WHOAMI_VALUE },
+ { "sx9310", (kernel_ulong_t)&sx9310_info },
+ { "sx9311", (kernel_ulong_t)&sx9311_info },
{}
};
MODULE_DEVICE_TABLE(i2c, sx9310_id);
diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c
index d40f235af1d4..0143fd478933 100644
--- a/drivers/iio/temperature/hid-sensor-temperature.c
+++ b/drivers/iio/temperature/hid-sensor-temperature.c
@@ -257,7 +257,7 @@ error_remove_trigger:
}
/* Function to deinitialize the processing for usage id */
-static int hid_temperature_remove(struct platform_device *pdev)
+static void hid_temperature_remove(struct platform_device *pdev)
{
struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@@ -265,8 +265,6 @@ static int hid_temperature_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TEMPERATURE);
hid_sensor_remove_trigger(indio_dev, &temp_st->common_attributes);
-
- return 0;
}
static const struct platform_device_id hid_temperature_ids[] = {
@@ -285,7 +283,7 @@ static struct platform_driver hid_temperature_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_temperature_probe,
- .remove = hid_temperature_remove,
+ .remove_new = hid_temperature_remove,
};
module_platform_driver(hid_temperature_platform_driver);
diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c
index 07bb5df24ab3..740018d4b3df 100644
--- a/drivers/iio/temperature/mlx90614.c
+++ b/drivers/iio/temperature/mlx90614.c
@@ -600,7 +600,7 @@ static int mlx90614_probe(struct i2c_client *client)
data->client = client;
mutex_init(&data->lock);
data->wakeup_gpio = mlx90614_probe_wakeup(client);
- data->chip_info = device_get_match_data(&client->dev);
+ data->chip_info = i2c_get_match_data(client);
mlx90614_wakeup(data);
diff --git a/drivers/iio/temperature/tmp117.c b/drivers/iio/temperature/tmp117.c
index fc02f491688b..059953015ae7 100644
--- a/drivers/iio/temperature/tmp117.c
+++ b/drivers/iio/temperature/tmp117.c
@@ -42,6 +42,12 @@ struct tmp117_data {
s16 calibbias;
};
+struct tmp11x_info {
+ const char *name;
+ struct iio_chan_spec const *channels;
+ int num_channels;
+};
+
static int tmp117_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *channel, int *val,
int *val2, long mask)
@@ -119,57 +125,54 @@ static const struct iio_chan_spec tmp116_channels[] = {
},
};
+static const struct tmp11x_info tmp116_channels_info = {
+ .name = "tmp116",
+ .channels = tmp116_channels,
+ .num_channels = ARRAY_SIZE(tmp116_channels)
+};
+
+static const struct tmp11x_info tmp117_channels_info = {
+ .name = "tmp117",
+ .channels = tmp117_channels,
+ .num_channels = ARRAY_SIZE(tmp117_channels)
+};
+
static const struct iio_info tmp117_info = {
.read_raw = tmp117_read_raw,
.write_raw = tmp117_write_raw,
};
-static int tmp117_identify(struct i2c_client *client)
+static int tmp117_probe(struct i2c_client *client)
{
- const struct i2c_device_id *id;
- unsigned long match_data;
+ const struct tmp11x_info *match_data;
+ struct tmp117_data *data;
+ struct iio_dev *indio_dev;
int dev_id;
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
+ return -EOPNOTSUPP;
+
dev_id = i2c_smbus_read_word_swapped(client, TMP117_REG_DEVICE_ID);
if (dev_id < 0)
return dev_id;
switch (dev_id) {
case TMP116_DEVICE_ID:
+ match_data = &tmp116_channels_info;
+ break;
case TMP117_DEVICE_ID:
- return dev_id;
+ match_data = &tmp117_channels_info;
+ break;
+ default:
+ dev_info(&client->dev,
+ "Unknown device id (0x%x), use fallback compatible\n",
+ dev_id);
+ match_data = i2c_get_match_data(client);
}
- dev_info(&client->dev, "Unknown device id (0x%x), use fallback compatible\n",
- dev_id);
-
- match_data = (uintptr_t)device_get_match_data(&client->dev);
- if (match_data)
- return match_data;
-
- id = i2c_client_get_device_id(client);
- if (id)
- return id->driver_data;
-
- dev_err(&client->dev, "Failed to identify unsupported device\n");
-
- return -ENODEV;
-}
-
-static int tmp117_probe(struct i2c_client *client)
-{
- struct tmp117_data *data;
- struct iio_dev *indio_dev;
- int ret, dev_id;
-
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
- return -EOPNOTSUPP;
-
- ret = tmp117_identify(client);
- if (ret < 0)
- return ret;
-
- dev_id = ret;
+ if (!match_data)
+ return dev_err_probe(&client->dev, -ENODEV,
+ "Failed to identify unsupported device\n");
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
@@ -181,33 +184,24 @@ static int tmp117_probe(struct i2c_client *client)
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &tmp117_info;
+ indio_dev->channels = match_data->channels;
+ indio_dev->num_channels = match_data->num_channels;
+ indio_dev->name = match_data->name;
- switch (dev_id) {
- case TMP116_DEVICE_ID:
- indio_dev->channels = tmp116_channels;
- indio_dev->num_channels = ARRAY_SIZE(tmp116_channels);
- indio_dev->name = "tmp116";
- break;
- case TMP117_DEVICE_ID:
- indio_dev->channels = tmp117_channels;
- indio_dev->num_channels = ARRAY_SIZE(tmp117_channels);
- indio_dev->name = "tmp117";
- break;
- }
return devm_iio_device_register(&client->dev, indio_dev);
}
static const struct of_device_id tmp117_of_match[] = {
- { .compatible = "ti,tmp116", .data = (void *)TMP116_DEVICE_ID },
- { .compatible = "ti,tmp117", .data = (void *)TMP117_DEVICE_ID },
+ { .compatible = "ti,tmp116", .data = &tmp116_channels_info },
+ { .compatible = "ti,tmp117", .data = &tmp117_channels_info },
{ }
};
MODULE_DEVICE_TABLE(of, tmp117_of_match);
static const struct i2c_device_id tmp117_id[] = {
- { "tmp116", TMP116_DEVICE_ID },
- { "tmp117", TMP117_DEVICE_ID },
+ { "tmp116", (kernel_ulong_t)&tmp116_channels_info },
+ { "tmp117", (kernel_ulong_t)&tmp117_channels_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, tmp117_id);
diff --git a/drivers/iio/trigger/iio-trig-interrupt.c b/drivers/iio/trigger/iio-trig-interrupt.c
index 5f49cd105fae..dec256bfbd73 100644
--- a/drivers/iio/trigger/iio-trig-interrupt.c
+++ b/drivers/iio/trigger/iio-trig-interrupt.c
@@ -81,7 +81,7 @@ error_ret:
return ret;
}
-static int iio_interrupt_trigger_remove(struct platform_device *pdev)
+static void iio_interrupt_trigger_remove(struct platform_device *pdev)
{
struct iio_trigger *trig;
struct iio_interrupt_trigger_info *trig_info;
@@ -92,13 +92,11 @@ static int iio_interrupt_trigger_remove(struct platform_device *pdev)
free_irq(trig_info->irq, trig);
kfree(trig_info);
iio_trigger_free(trig);
-
- return 0;
}
static struct platform_driver iio_interrupt_trigger_driver = {
.probe = iio_interrupt_trigger_probe,
- .remove = iio_interrupt_trigger_remove,
+ .remove_new = iio_interrupt_trigger_remove,
.driver = {
.name = "iio_interrupt_trigger",
},
diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c
index 3643c4afae67..d76444030a28 100644
--- a/drivers/iio/trigger/stm32-timer-trigger.c
+++ b/drivers/iio/trigger/stm32-timer-trigger.c
@@ -809,7 +809,7 @@ static int stm32_timer_trigger_probe(struct platform_device *pdev)
return 0;
}
-static int stm32_timer_trigger_remove(struct platform_device *pdev)
+static void stm32_timer_trigger_remove(struct platform_device *pdev)
{
struct stm32_timer_trigger *priv = platform_get_drvdata(pdev);
u32 val;
@@ -824,8 +824,6 @@ static int stm32_timer_trigger_remove(struct platform_device *pdev)
if (priv->enabled)
clk_disable(priv->clk);
-
- return 0;
}
static int stm32_timer_trigger_suspend(struct device *dev)
@@ -904,7 +902,7 @@ MODULE_DEVICE_TABLE(of, stm32_trig_of_match);
static struct platform_driver stm32_timer_trigger_driver = {
.probe = stm32_timer_trigger_probe,
- .remove = stm32_timer_trigger_remove,
+ .remove_new = stm32_timer_trigger_remove,
.driver = {
.name = "stm32-timer-trigger",
.of_match_table = stm32_trig_of_match,
diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c
index 6f9eebd6c7ee..6c390c4eb26d 100644
--- a/drivers/staging/iio/frequency/ad9832.c
+++ b/drivers/staging/iio/frequency/ad9832.c
@@ -299,11 +299,6 @@ static void ad9832_reg_disable(void *reg)
regulator_disable(reg);
}
-static void ad9832_clk_disable(void *clk)
-{
- clk_disable_unprepare(clk);
-}
-
static int ad9832_probe(struct spi_device *spi)
{
struct ad9832_platform_data *pdata = dev_get_platdata(&spi->dev);
@@ -350,18 +345,10 @@ static int ad9832_probe(struct spi_device *spi)
if (ret)
return ret;
- st->mclk = devm_clk_get(&spi->dev, "mclk");
+ st->mclk = devm_clk_get_enabled(&spi->dev, "mclk");
if (IS_ERR(st->mclk))
return PTR_ERR(st->mclk);
- ret = clk_prepare_enable(st->mclk);
- if (ret < 0)
- return ret;
-
- ret = devm_add_action_or_reset(&spi->dev, ad9832_clk_disable, st->mclk);
- if (ret)
- return ret;
-
st->spi = spi;
mutex_init(&st->lock);
diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c
index 285df0e489a6..a7a5cdcc6590 100644
--- a/drivers/staging/iio/frequency/ad9834.c
+++ b/drivers/staging/iio/frequency/ad9834.c
@@ -394,13 +394,6 @@ static void ad9834_disable_reg(void *data)
regulator_disable(reg);
}
-static void ad9834_disable_clk(void *data)
-{
- struct clk *clk = data;
-
- clk_disable_unprepare(clk);
-}
-
static int ad9834_probe(struct spi_device *spi)
{
struct ad9834_state *st;
@@ -429,22 +422,12 @@ static int ad9834_probe(struct spi_device *spi)
}
st = iio_priv(indio_dev);
mutex_init(&st->lock);
- st->mclk = devm_clk_get(&spi->dev, NULL);
+ st->mclk = devm_clk_get_enabled(&spi->dev, NULL);
if (IS_ERR(st->mclk)) {
- ret = PTR_ERR(st->mclk);
- return ret;
- }
-
- ret = clk_prepare_enable(st->mclk);
- if (ret) {
dev_err(&spi->dev, "Failed to enable master clock\n");
- return ret;
+ return PTR_ERR(st->mclk);
}
- ret = devm_add_action_or_reset(&spi->dev, ad9834_disable_clk, st->mclk);
- if (ret)
- return ret;
-
st->spi = spi;
st->devid = spi_get_device_id(spi)->driver_data;
indio_dev->name = spi_get_device_id(spi)->name;
diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
index 46db6d91542a..e748a5d04e97 100644
--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
@@ -667,13 +667,6 @@ static void ad5933_reg_disable(void *data)
regulator_disable(st->reg);
}
-static void ad5933_clk_disable(void *data)
-{
- struct ad5933_state *st = data;
-
- clk_disable_unprepare(st->mclk);
-}
-
static int ad5933_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
@@ -712,23 +705,12 @@ static int ad5933_probe(struct i2c_client *client)
st->vref_mv = ret / 1000;
- st->mclk = devm_clk_get(&client->dev, "mclk");
+ st->mclk = devm_clk_get_enabled(&client->dev, "mclk");
if (IS_ERR(st->mclk) && PTR_ERR(st->mclk) != -ENOENT)
return PTR_ERR(st->mclk);
- if (!IS_ERR(st->mclk)) {
- ret = clk_prepare_enable(st->mclk);
- if (ret < 0)
- return ret;
-
- ret = devm_add_action_or_reset(&client->dev,
- ad5933_clk_disable,
- st);
- if (ret)
- return ret;
-
+ if (!IS_ERR(st->mclk))
ext_clk_hz = clk_get_rate(st->mclk);
- }
if (ext_clk_hz) {
st->mclk_hz = ext_clk_hz;
diff --git a/include/linux/iio/sw_device.h b/include/linux/iio/sw_device.h
index eff1e6b2595c..0f7fe7b522e3 100644
--- a/include/linux/iio/sw_device.h
+++ b/include/linux/iio/sw_device.h
@@ -51,9 +51,6 @@ void iio_unregister_sw_device_type(struct iio_sw_device_type *dt);
struct iio_sw_device *iio_sw_device_create(const char *, const char *);
void iio_sw_device_destroy(struct iio_sw_device *);
-int iio_sw_device_type_configfs_register(struct iio_sw_device_type *dt);
-void iio_sw_device_type_configfs_unregister(struct iio_sw_device_type *dt);
-
static inline
void iio_swd_group_init_type_name(struct iio_sw_device *d,
const char *name,
diff --git a/include/linux/iio/sw_trigger.h b/include/linux/iio/sw_trigger.h
index 47de2443e984..bc77f88df303 100644
--- a/include/linux/iio/sw_trigger.h
+++ b/include/linux/iio/sw_trigger.h
@@ -51,9 +51,6 @@ void iio_unregister_sw_trigger_type(struct iio_sw_trigger_type *tt);
struct iio_sw_trigger *iio_sw_trigger_create(const char *, const char *);
void iio_sw_trigger_destroy(struct iio_sw_trigger *);
-int iio_sw_trigger_type_configfs_register(struct iio_sw_trigger_type *tt);
-void iio_sw_trigger_type_configfs_unregister(struct iio_sw_trigger_type *tt);
-
static inline
void iio_swt_group_init_type_name(struct iio_sw_trigger *t,
const char *name,
diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h
index 4832c611c027..9c2ffdcd6623 100644
--- a/include/uapi/linux/iio/types.h
+++ b/include/uapi/linux/iio/types.h
@@ -47,6 +47,8 @@ enum iio_chan_type {
IIO_POSITIONRELATIVE,
IIO_PHASE,
IIO_MASSCONCENTRATION,
+ IIO_DELTA_ANGL,
+ IIO_DELTA_VELOCITY,
IIO_COLORTEMP,
IIO_CHROMATICITY,
};
diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c
index a28a86f2bd5b..2eaaa7123b04 100644
--- a/tools/iio/iio_event_monitor.c
+++ b/tools/iio/iio_event_monitor.c
@@ -59,6 +59,8 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_POSITIONRELATIVE] = "positionrelative",
[IIO_PHASE] = "phase",
[IIO_MASSCONCENTRATION] = "massconcentration",
+ [IIO_DELTA_ANGL] = "deltaangl",
+ [IIO_DELTA_VELOCITY] = "deltavelocity",
[IIO_COLORTEMP] = "colortemp",
[IIO_CHROMATICITY] = "chromaticity",
};
@@ -175,6 +177,8 @@ static bool event_is_known(struct iio_event_data *event)
case IIO_POSITIONRELATIVE:
case IIO_PHASE:
case IIO_MASSCONCENTRATION:
+ case IIO_DELTA_ANGL:
+ case IIO_DELTA_VELOCITY:
case IIO_COLORTEMP:
case IIO_CHROMATICITY:
break;