mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-28 00:32:00 +00:00
Merge branch 'togreg' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git
This commit is contained in:
commit
7af5576bb3
23
Documentation/ABI/testing/sysfs-bus-iio-adc-ad-sigma-delta
Normal file
23
Documentation/ABI/testing/sysfs-bus-iio-adc-ad-sigma-delta
Normal file
@ -0,0 +1,23 @@
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_sys_calibration
|
||||
KernelVersion: 5.5
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
This attribute, if available, initiates the system calibration procedure. This is done on a
|
||||
single channel at a time. Write '1' to start the calibration.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_sys_calibration_mode_available
|
||||
KernelVersion: 5.5
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
This attribute, if available, returns a list with the possible calibration modes.
|
||||
There are two available options:
|
||||
"zero_scale" - calibrate to zero scale
|
||||
"full_scale" - calibrate to full scale
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_sys_calibration_mode
|
||||
KernelVersion: 5.5
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
This attribute, if available, sets up the calibration mode used in the system calibration
|
||||
procedure. Reading returns the current calibration mode.
|
||||
Writing sets the system calibration mode.
|
@ -19,33 +19,9 @@ Description:
|
||||
the bridge can be disconnected (when it is not being used
|
||||
using the bridge_switch_en attribute.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltagex_sys_calibration
|
||||
KernelVersion:
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Initiates the system calibration procedure. This is done on a
|
||||
single channel at a time. Write '1' to start the calibration.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltage2-voltage2_shorted_raw
|
||||
KernelVersion:
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Measure voltage from AIN2 pin connected to AIN(+)
|
||||
and AIN(-) shorted.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltagex_sys_calibration_mode_available
|
||||
KernelVersion:
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Reading returns a list with the possible calibration modes.
|
||||
There are two available options:
|
||||
"zero_scale" - calibrate to zero scale
|
||||
"full_scale" - calibrate to full scale
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltagex_sys_calibration_mode
|
||||
KernelVersion:
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Sets up the calibration mode used in the system calibration
|
||||
procedure. Reading returns the current calibration mode.
|
||||
Writing sets the system calibration mode.
|
||||
|
@ -4,23 +4,26 @@
|
||||
$id: http://devicetree.org/schemas/iio/accel/kionix,kx022a.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ROHM/Kionix KX022A, KX132-1211 and KX132ACR-LBZ Accelerometers
|
||||
title: ROHM/Kionix KX022A, KX132/134-1211 and KX132/134ACR-LBZ Accelerometers
|
||||
|
||||
maintainers:
|
||||
- Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
|
||||
description: |
|
||||
KX022A, KX132ACR-LBZ and KX132-1211 are 3-axis accelerometers supporting
|
||||
+/- 2G, 4G, 8G and 16G ranges, variable output data-rates and a
|
||||
hardware-fifo buffering. These accelerometers can be accessed either
|
||||
via I2C or SPI.
|
||||
+/- 2G, 4G, 8G and 16G ranges. The KX134ACR-LBZ and KX134-1211 support
|
||||
+/- 8G, 16G, 32G and 64G. All the sensors also have variable output
|
||||
data-rates and a hardware-fifo buffering. These accelerometers can be
|
||||
accessed either via I2C or SPI.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- kionix,kx022a
|
||||
- kionix,kx132-1211
|
||||
- kionix,kx134-1211
|
||||
- rohm,kx132acr-lbz
|
||||
- rohm,kx134acr-lbz
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -14,12 +14,20 @@ description: |
|
||||
SPI and I2C interface.
|
||||
https://www.nxp.com/docs/en/data-sheet/FXLS8962AF.pdf
|
||||
https://www.nxp.com/docs/en/data-sheet/FXLS8964AF.pdf
|
||||
https://www.nxp.com/docs/en/data-sheet/FXLS8967AF.pdf
|
||||
https://www.nxp.com/docs/en/data-sheet/FXLS8974CF.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- nxp,fxls8962af
|
||||
- nxp,fxls8964af
|
||||
oneOf:
|
||||
- enum:
|
||||
- nxp,fxls8962af
|
||||
- nxp,fxls8964af
|
||||
- items:
|
||||
- enum:
|
||||
- nxp,fxls8967af
|
||||
- nxp,fxls8974cf
|
||||
- const: nxp,fxls8962af
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@ -38,6 +46,11 @@ properties:
|
||||
drive-open-drain:
|
||||
type: boolean
|
||||
|
||||
wakeup-source:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description:
|
||||
Enable wake on accelerometer event
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
@ -61,6 +74,7 @@ examples:
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "INT1";
|
||||
wakeup-source;
|
||||
};
|
||||
};
|
||||
- |
|
||||
|
@ -19,49 +19,82 @@ description: |
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad4020-4021-4022.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4001.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4003.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7685.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7686.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7687.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7688.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7690.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7691.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7693.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7942.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7946.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7980.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7982.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7983.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7984.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7988-1_7988-5.pdf
|
||||
|
||||
$ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: adi,ad4000
|
||||
- enum:
|
||||
- adi,ad4000
|
||||
- adi,ad4001
|
||||
- adi,ad4002
|
||||
- adi,ad4003
|
||||
- adi,ad4020
|
||||
- adi,adaq4001
|
||||
- adi,adaq4003
|
||||
- adi,ad7687
|
||||
- adi,ad7691
|
||||
- adi,ad7942
|
||||
- adi,ad7946
|
||||
- adi,ad7983
|
||||
- items:
|
||||
- enum:
|
||||
- adi,ad4004
|
||||
- adi,ad4008
|
||||
- const: adi,ad4000
|
||||
|
||||
- const: adi,ad4001
|
||||
- items:
|
||||
- enum:
|
||||
- adi,ad4005
|
||||
- const: adi,ad4001
|
||||
|
||||
- const: adi,ad4002
|
||||
- items:
|
||||
- enum:
|
||||
- adi,ad4006
|
||||
- adi,ad4010
|
||||
- const: adi,ad4002
|
||||
|
||||
- const: adi,ad4003
|
||||
- items:
|
||||
- enum:
|
||||
- adi,ad4007
|
||||
- adi,ad4011
|
||||
- const: adi,ad4003
|
||||
|
||||
- const: adi,ad4020
|
||||
- items:
|
||||
- enum:
|
||||
- adi,ad4021
|
||||
- adi,ad4022
|
||||
- const: adi,ad4020
|
||||
|
||||
- const: adi,adaq4001
|
||||
|
||||
- const: adi,adaq4003
|
||||
- items:
|
||||
- enum:
|
||||
- adi,ad7685
|
||||
- adi,ad7686
|
||||
- adi,ad7980
|
||||
- adi,ad7988-1
|
||||
- adi,ad7988-5
|
||||
- const: adi,ad7983
|
||||
- items:
|
||||
- enum:
|
||||
- adi,ad7688
|
||||
- adi,ad7693
|
||||
- const: adi,ad7687
|
||||
- items:
|
||||
- enum:
|
||||
- adi,ad7690
|
||||
- adi,ad7982
|
||||
- adi,ad7984
|
||||
- const: adi,ad7691
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@ -133,6 +166,22 @@ required:
|
||||
- ref-supply
|
||||
|
||||
allOf:
|
||||
# Single-channel PulSAR devices have SDI either tied to VIO, GND, or host CS.
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- adi,ad7687
|
||||
- adi,ad7691
|
||||
- adi,ad7942
|
||||
- adi,ad7946
|
||||
- adi,ad7983
|
||||
then:
|
||||
properties:
|
||||
adi,sdi-pin:
|
||||
enum: [ high, low, cs ]
|
||||
default: cs
|
||||
# The configuration register can only be accessed if SDI is connected to MOSI
|
||||
- if:
|
||||
required:
|
||||
|
@ -134,8 +134,9 @@ patternProperties:
|
||||
description:
|
||||
Describes the common mode channel for single channels. 0xFF is REFGND
|
||||
and OxFE is COM. Macros are available for these values in
|
||||
dt-bindings/iio/adi,ad4695.h. Values 1 to 15 correspond to INx inputs.
|
||||
Only odd numbered INx inputs can be used as common mode channels.
|
||||
dt-bindings/iio/adc/adi,ad4695.h. Values 1 to 15 correspond to INx
|
||||
inputs. Only odd numbered INx inputs can be used as common mode
|
||||
channels.
|
||||
enum: [1, 3, 5, 7, 9, 11, 13, 15, 0xFE, 0xFF]
|
||||
default: 0xFF
|
||||
|
||||
@ -209,7 +210,7 @@ unevaluatedProperties: false
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/iio/adi,ad4695.h>
|
||||
#include <dt-bindings/iio/adc/adi,ad4695.h>
|
||||
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
|
@ -37,6 +37,17 @@ properties:
|
||||
description: IRQ line for the ADC
|
||||
maxItems: 1
|
||||
|
||||
rdy-gpios:
|
||||
description:
|
||||
GPIO reading the R̅D̅Y̅ line. Having such a GPIO is technically optional but
|
||||
highly recommended because DOUT/R̅D̅Y̅ toggles during SPI transfers (in its
|
||||
DOUT aka MISO role) and so usually triggers a spurious interrupt. The
|
||||
distinction between such a spurious event and a real one can only be done
|
||||
by reading such a GPIO. (There is a register telling the same
|
||||
information, but accessing that one needs a SPI transfer which then
|
||||
triggers another interrupt event.)
|
||||
maxItems: 1
|
||||
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
@ -111,6 +122,7 @@ unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
@ -121,6 +133,7 @@ examples:
|
||||
spi-max-frequency = <5000000>;
|
||||
interrupts = <25 2>;
|
||||
interrupt-parent = <&gpio>;
|
||||
rdy-gpios = <&gpio 25 GPIO_ACTIVE_LOW>;
|
||||
refin1-supply = <&adc_vref>;
|
||||
clocks = <&ad7124_mclk>;
|
||||
clock-names = "mclk";
|
||||
|
@ -135,6 +135,17 @@ properties:
|
||||
'#clock-cells':
|
||||
const: 0
|
||||
|
||||
rdy-gpios:
|
||||
description:
|
||||
GPIO reading the R̅D̅Y̅ line. Having such a GPIO is technically optional but
|
||||
highly recommended because DOUT/R̅D̅Y̅ toggles during SPI transfers (in its
|
||||
DOUT aka MISO role) and so usually triggers a spurious interrupt. The
|
||||
distinction between such a spurious event and a real one can only be done
|
||||
by reading such a GPIO. (There is a register telling the same
|
||||
information, but accessing that one needs a SPI transfer which then
|
||||
triggers another interrupt event.)
|
||||
maxItems: 1
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-9a-f]$":
|
||||
type: object
|
||||
@ -443,6 +454,7 @@ examples:
|
||||
interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
|
||||
interrupt-names = "rdy";
|
||||
interrupt-parent = <&gpio>;
|
||||
rdy-gpios = <&gpio 25 GPIO_ACTIVE_LOW>;
|
||||
spi-max-frequency = <5000000>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
@ -106,6 +106,17 @@ properties:
|
||||
description: see Documentation/devicetree/bindings/iio/adc/adc.yaml
|
||||
type: boolean
|
||||
|
||||
rdy-gpios:
|
||||
description:
|
||||
GPIO reading the R̅D̅Y̅ line. Having such a GPIO is technically optional but
|
||||
highly recommended because DOUT/R̅D̅Y̅ toggles during SPI transfers (in its
|
||||
DOUT aka MISO role) and so usually triggers a spurious interrupt. The
|
||||
distinction between such a spurious event and a real one can only be done
|
||||
by reading such a GPIO. (There is a register telling the same
|
||||
information, but accessing that one needs a SPI transfer which then
|
||||
triggers another interrupt event.)
|
||||
maxItems: 1
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-9a-f]+$":
|
||||
type: object
|
||||
@ -181,6 +192,7 @@ unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
@ -195,6 +207,7 @@ examples:
|
||||
clock-names = "mclk";
|
||||
interrupts = <25 0x2>;
|
||||
interrupt-parent = <&gpio>;
|
||||
rdy-gpios = <&gpio 25 GPIO_ACTIVE_LOW>;
|
||||
aincom-supply = <&aincom>;
|
||||
dvdd-supply = <&dvdd>;
|
||||
avdd-supply = <&avdd>;
|
||||
@ -207,6 +220,7 @@ examples:
|
||||
};
|
||||
};
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
@ -224,6 +238,7 @@ examples:
|
||||
#clock-cells = <0>;
|
||||
interrupts = <25 0x2>;
|
||||
interrupt-parent = <&gpio>;
|
||||
rdy-gpios = <&gpio 25 GPIO_ACTIVE_LOW>;
|
||||
aincom-supply = <&aincom>;
|
||||
dvdd-supply = <&dvdd>;
|
||||
avdd-supply = <&avdd>;
|
||||
|
@ -63,6 +63,17 @@ properties:
|
||||
marked GPIO_ACTIVE_LOW.
|
||||
maxItems: 1
|
||||
|
||||
rdy-gpios:
|
||||
description:
|
||||
GPIO reading the R̅D̅Y̅ line. Having such a GPIO is technically optional but
|
||||
highly recommended because DOUT/R̅D̅Y̅ toggles during SPI transfers (in its
|
||||
DOUT aka MISO role) and so usually triggers a spurious interrupt. The
|
||||
distinction between such a spurious event and a real one can only be done
|
||||
by reading such a GPIO. (There is a register telling the same
|
||||
information, but accessing that one needs a SPI transfer which then
|
||||
triggers another interrupt event.)
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -17,12 +17,15 @@ description: |
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- renesas,r9a07g043-adc # RZ/G2UL and RZ/Five
|
||||
- renesas,r9a07g044-adc # RZ/G2L
|
||||
- renesas,r9a07g054-adc # RZ/V2L
|
||||
- const: renesas,rzg2l-adc
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- renesas,r9a07g043-adc # RZ/G2UL and RZ/Five
|
||||
- renesas,r9a07g044-adc # RZ/G2L
|
||||
- renesas,r9a07g054-adc # RZ/V2L
|
||||
- const: renesas,rzg2l-adc
|
||||
- items:
|
||||
- const: renesas,r9a08g045-adc # RZ/G3S
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@ -57,6 +60,9 @@ properties:
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
"#io-channel-cells":
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
@ -68,7 +74,7 @@ required:
|
||||
- reset-names
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-7]$":
|
||||
"^channel@[0-8]$":
|
||||
$ref: adc.yaml
|
||||
type: object
|
||||
description: |
|
||||
@ -78,6 +84,8 @@ patternProperties:
|
||||
reg:
|
||||
description: |
|
||||
The channel number.
|
||||
minimum: 0
|
||||
maximum: 8
|
||||
|
||||
required:
|
||||
- reg
|
||||
@ -92,18 +100,25 @@ allOf:
|
||||
const: renesas,r9a07g043-adc
|
||||
then:
|
||||
patternProperties:
|
||||
"^channel@[2-7]$": false
|
||||
"^channel@[2-8]$": false
|
||||
"^channel@[0-1]$":
|
||||
properties:
|
||||
reg:
|
||||
minimum: 0
|
||||
maximum: 1
|
||||
else:
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- renesas,r9a07g044-adc
|
||||
- renesas,r9a07g054-adc
|
||||
then:
|
||||
patternProperties:
|
||||
"^channel@[8]$": false
|
||||
"^channel@[0-7]$":
|
||||
properties:
|
||||
reg:
|
||||
minimum: 0
|
||||
maximum: 7
|
||||
|
||||
additionalProperties: false
|
||||
|
@ -0,0 +1,62 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/chemical/bosch,bme680.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Bosch BME680 Gas sensor
|
||||
|
||||
maintainers:
|
||||
- Vasileios Amoiridis <vassilisamir@gmail.com>
|
||||
|
||||
description: >
|
||||
BME680 is a gas sensor which combines relative humidity, barometric pressure,
|
||||
ambient temperature and gas (VOC - Volatile Organic Compounds) measurements.
|
||||
|
||||
https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bme680-ds001.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: bosch,bme680
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
vddio-supply: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
co2-sensor@77 {
|
||||
compatible = "bosch,bme680";
|
||||
reg = <0x77>;
|
||||
vddio-supply = <&vddio>;
|
||||
vdd-supply = <&vdd>;
|
||||
};
|
||||
};
|
||||
- |
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
co2-sensor@0 {
|
||||
compatible = "bosch,bme680";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <500000>;
|
||||
vddio-supply = <&vddio>;
|
||||
vdd-supply = <&vdd>;
|
||||
};
|
||||
};
|
@ -11,24 +11,30 @@ maintainers:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,adis16375
|
||||
- adi,adis16480
|
||||
- adi,adis16485
|
||||
- adi,adis16488
|
||||
- adi,adis16490
|
||||
- adi,adis16495-1
|
||||
- adi,adis16495-2
|
||||
- adi,adis16495-3
|
||||
- adi,adis16497-1
|
||||
- adi,adis16497-2
|
||||
- adi,adis16497-3
|
||||
- adi,adis16545-1
|
||||
- adi,adis16545-2
|
||||
- adi,adis16545-3
|
||||
- adi,adis16547-1
|
||||
- adi,adis16547-2
|
||||
- adi,adis16547-3
|
||||
oneOf:
|
||||
- enum:
|
||||
- adi,adis16375
|
||||
- adi,adis16480
|
||||
- adi,adis16485
|
||||
- adi,adis16486
|
||||
- adi,adis16488
|
||||
- adi,adis16489
|
||||
- adi,adis16490
|
||||
- adi,adis16495-1
|
||||
- adi,adis16495-2
|
||||
- adi,adis16495-3
|
||||
- adi,adis16497-1
|
||||
- adi,adis16497-2
|
||||
- adi,adis16497-3
|
||||
- adi,adis16545-1
|
||||
- adi,adis16545-2
|
||||
- adi,adis16545-3
|
||||
- adi,adis16547-1
|
||||
- adi,adis16547-2
|
||||
- adi,adis16547-3
|
||||
- items:
|
||||
- const: adi,adis16487
|
||||
- const: adi,adis16485
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -16,6 +16,7 @@ properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- enum:
|
||||
- invensense,iam20380
|
||||
- invensense,iam20680
|
||||
- invensense,icm20608
|
||||
- invensense,icm20609
|
||||
|
@ -1,49 +0,0 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/light/rohm,bu27008.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ROHM BU27008 color sensor
|
||||
|
||||
maintainers:
|
||||
- Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
|
||||
description:
|
||||
The ROHM BU27008 is a sensor with 5 photodiodes (red, green, blue, clear
|
||||
and IR) with four configurable channels. Red and green being always
|
||||
available and two out of the rest three (blue, clear, IR) can be
|
||||
selected to be simultaneously measured. Typical application is adjusting
|
||||
LCD backlight of TVs, mobile phones and tablet PCs.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: rohm,bu27008
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
light-sensor@38 {
|
||||
compatible = "rohm,bu27008";
|
||||
reg = <0x38>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -1,50 +0,0 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/light/rohm,bu27010.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ROHM BU27010 color sensor
|
||||
|
||||
maintainers:
|
||||
- Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
|
||||
description: |
|
||||
The ROHM BU27010 is a sensor with 6 photodiodes (red, green, blue, clear,
|
||||
IR and flickering detection) with five configurable channels. Red, green
|
||||
and flickering detection being always available and two out of the rest
|
||||
three (blue, clear, IR) can be selected to be simultaneously measured.
|
||||
Typical application is adjusting LCD/OLED backlight of TVs, mobile phones
|
||||
and tablet PCs.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: rohm,bu27010
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
light-sensor@38 {
|
||||
compatible = "rohm,bu27010";
|
||||
reg = <0x38>;
|
||||
vdd-supply = <&vdd>;
|
||||
};
|
||||
};
|
@ -55,8 +55,6 @@ properties:
|
||||
- atmel,atsha204a
|
||||
# BPA-RS600: Power Supply
|
||||
- blutek,bpa-rs600
|
||||
# Bosch Sensortec pressure, temperature, humididty and VOC sensor
|
||||
- bosch,bme680
|
||||
# CM32181: Ambient Light Sensor
|
||||
- capella,cm32181
|
||||
# CM3232: Ambient Light Sensor
|
||||
|
@ -101,7 +101,7 @@ The macro comes from:
|
||||
|
||||
.. code-block::
|
||||
|
||||
#include <dt-bindings/iio/adi,ad4695.h>
|
||||
#include <dt-bindings/iio/adc/adi,ad4695.h>
|
||||
|
||||
Pairing two INx pins
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -12,7 +12,10 @@ This driver supports Analog Device's IMUs on SPI bus.
|
||||
* `ADIS16375 <https://www.analog.com/ADIS16375>`_
|
||||
* `ADIS16480 <https://www.analog.com/ADIS16480>`_
|
||||
* `ADIS16485 <https://www.analog.com/ADIS16485>`_
|
||||
* `ADIS16486 <https://www.analog.com/ADIS16486>`_
|
||||
* `ADIS16487 <https://www.analog.com/ADIS16487>`_
|
||||
* `ADIS16488 <https://www.analog.com/ADIS16488>`_
|
||||
* `ADIS16489 <https://www.analog.com/ADIS16489>`_
|
||||
* `ADIS16490 <https://www.analog.com/ADIS16490>`_
|
||||
* `ADIS16495 <https://www.analog.com/ADIS16495>`_
|
||||
* `ADIS16497 <https://www.analog.com/ADIS16497>`_
|
||||
|
@ -1311,7 +1311,7 @@ W: https://ez.analog.com/linux-software-drivers
|
||||
F: Documentation/devicetree/bindings/iio/adc/adi,ad4695.yaml
|
||||
F: Documentation/iio/ad4695.rst
|
||||
F: drivers/iio/adc/ad4695.c
|
||||
F: include/dt-bindings/iio/adi,ad4695.h
|
||||
F: include/dt-bindings/iio/adc/adi,ad4695.h
|
||||
|
||||
ANALOG DEVICES INC AD7091R DRIVER
|
||||
M: Marcelo Schmitt <marcelo.schmitt@analog.com>
|
||||
@ -20406,7 +20406,6 @@ ROHM BU270xx LIGHT SENSOR DRIVERs
|
||||
M: Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/iio/light/rohm-bu27008.c
|
||||
F: drivers/iio/light/rohm-bu27034.c
|
||||
|
||||
ROHM MULTIFUNCTION BD9571MWV-M PMIC DEVICE DRIVERS
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include "adxl345.h"
|
||||
|
||||
struct adxl345_data {
|
||||
struct adxl345_state {
|
||||
const struct adxl345_chip_info *info;
|
||||
struct regmap *regmap;
|
||||
};
|
||||
@ -43,7 +43,7 @@ static int adxl345_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val, int *val2, long mask)
|
||||
{
|
||||
struct adxl345_data *data = iio_priv(indio_dev);
|
||||
struct adxl345_state *st = iio_priv(indio_dev);
|
||||
__le16 accel;
|
||||
long long samp_freq_nhz;
|
||||
unsigned int regval;
|
||||
@ -56,7 +56,7 @@ static int adxl345_read_raw(struct iio_dev *indio_dev,
|
||||
* ADXL345_REG_DATA(X0/Y0/Z0) contain the least significant byte
|
||||
* and ADXL345_REG_DATA(X0/Y0/Z0) + 1 the most significant byte
|
||||
*/
|
||||
ret = regmap_bulk_read(data->regmap,
|
||||
ret = regmap_bulk_read(st->regmap,
|
||||
ADXL345_REG_DATA_AXIS(chan->address),
|
||||
&accel, sizeof(accel));
|
||||
if (ret < 0)
|
||||
@ -66,10 +66,10 @@ static int adxl345_read_raw(struct iio_dev *indio_dev,
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
*val = 0;
|
||||
*val2 = data->info->uscale;
|
||||
*val2 = st->info->uscale;
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
case IIO_CHAN_INFO_CALIBBIAS:
|
||||
ret = regmap_read(data->regmap,
|
||||
ret = regmap_read(st->regmap,
|
||||
ADXL345_REG_OFS_AXIS(chan->address), ®val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -81,7 +81,7 @@ static int adxl345_read_raw(struct iio_dev *indio_dev,
|
||||
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
ret = regmap_read(data->regmap, ADXL345_REG_BW_RATE, ®val);
|
||||
ret = regmap_read(st->regmap, ADXL345_REG_BW_RATE, ®val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -99,7 +99,7 @@ static int adxl345_write_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int val, int val2, long mask)
|
||||
{
|
||||
struct adxl345_data *data = iio_priv(indio_dev);
|
||||
struct adxl345_state *st = iio_priv(indio_dev);
|
||||
s64 n;
|
||||
|
||||
switch (mask) {
|
||||
@ -108,14 +108,14 @@ static int adxl345_write_raw(struct iio_dev *indio_dev,
|
||||
* 8-bit resolution at +/- 2g, that is 4x accel data scale
|
||||
* factor
|
||||
*/
|
||||
return regmap_write(data->regmap,
|
||||
return regmap_write(st->regmap,
|
||||
ADXL345_REG_OFS_AXIS(chan->address),
|
||||
val / 4);
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
n = div_s64(val * NANOHZ_PER_HZ + val2,
|
||||
ADXL345_BASE_RATE_NANO_HZ);
|
||||
|
||||
return regmap_update_bits(data->regmap, ADXL345_REG_BW_RATE,
|
||||
return regmap_update_bits(st->regmap, ADXL345_REG_BW_RATE,
|
||||
ADXL345_BW_RATE,
|
||||
clamp_val(ilog2(n), 0,
|
||||
ADXL345_BW_RATE));
|
||||
@ -169,8 +169,7 @@ static void adxl345_powerdown(void *regmap)
|
||||
}
|
||||
|
||||
/**
|
||||
* adxl345_core_probe() - probe and setup for the adxl345 accelerometer,
|
||||
* also covers the adlx375 accelerometer
|
||||
* adxl345_core_probe() - Probe and setup for the accelerometer.
|
||||
* @dev: Driver model representation of the device
|
||||
* @regmap: Regmap instance for the device
|
||||
* @setup: Setup routine to be executed right before the standard device
|
||||
@ -181,7 +180,7 @@ static void adxl345_powerdown(void *regmap)
|
||||
int adxl345_core_probe(struct device *dev, struct regmap *regmap,
|
||||
int (*setup)(struct device*, struct regmap*))
|
||||
{
|
||||
struct adxl345_data *data;
|
||||
struct adxl345_state *st;
|
||||
struct iio_dev *indio_dev;
|
||||
u32 regval;
|
||||
unsigned int data_format_mask = (ADXL345_DATA_FORMAT_RANGE |
|
||||
@ -190,17 +189,17 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap,
|
||||
ADXL345_DATA_FORMAT_SELF_TEST);
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
|
||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
data = iio_priv(indio_dev);
|
||||
data->regmap = regmap;
|
||||
data->info = device_get_match_data(dev);
|
||||
if (!data->info)
|
||||
st = iio_priv(indio_dev);
|
||||
st->regmap = regmap;
|
||||
st->info = device_get_match_data(dev);
|
||||
if (!st->info)
|
||||
return -ENODEV;
|
||||
|
||||
indio_dev->name = data->info->name;
|
||||
indio_dev->name = st->info->name;
|
||||
indio_dev->info = &adxl345_info;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->channels = adxl345_channels;
|
||||
@ -208,12 +207,12 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap,
|
||||
|
||||
if (setup) {
|
||||
/* Perform optional initial bus specific configuration */
|
||||
ret = setup(dev, data->regmap);
|
||||
ret = setup(dev, st->regmap);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Enable full-resolution mode */
|
||||
ret = regmap_update_bits(data->regmap, ADXL345_REG_DATA_FORMAT,
|
||||
ret = regmap_update_bits(st->regmap, ADXL345_REG_DATA_FORMAT,
|
||||
data_format_mask,
|
||||
ADXL345_DATA_FORMAT_FULL_RES);
|
||||
if (ret)
|
||||
@ -222,14 +221,14 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap,
|
||||
|
||||
} else {
|
||||
/* Enable full-resolution mode (init all data_format bits) */
|
||||
ret = regmap_write(data->regmap, ADXL345_REG_DATA_FORMAT,
|
||||
ret = regmap_write(st->regmap, ADXL345_REG_DATA_FORMAT,
|
||||
ADXL345_DATA_FORMAT_FULL_RES);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"Failed to set data range\n");
|
||||
}
|
||||
|
||||
ret = regmap_read(data->regmap, ADXL345_REG_DEVID, ®val);
|
||||
ret = regmap_read(st->regmap, ADXL345_REG_DEVID, ®val);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "Error reading device ID\n");
|
||||
|
||||
@ -238,11 +237,11 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap,
|
||||
regval, ADXL345_DEVID);
|
||||
|
||||
/* Enable measurement mode */
|
||||
ret = adxl345_powerup(data->regmap);
|
||||
ret = adxl345_powerup(st->regmap);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "Failed to enable measurement mode\n");
|
||||
|
||||
ret = devm_add_action_or_reset(dev, adxl345_powerdown, data->regmap);
|
||||
ret = devm_add_action_or_reset(dev, adxl345_powerdown, st->regmap);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -129,6 +129,8 @@
|
||||
|
||||
#define FXLS8962AF_DEVICE_ID 0x62
|
||||
#define FXLS8964AF_DEVICE_ID 0x84
|
||||
#define FXLS8974CF_DEVICE_ID 0x86
|
||||
#define FXLS8967AF_DEVICE_ID 0x87
|
||||
|
||||
/* Raw temp channel offset */
|
||||
#define FXLS8962AF_TEMP_CENTER_VAL 25
|
||||
@ -766,6 +768,18 @@ static const struct fxls8962af_chip_info fxls_chip_info_table[] = {
|
||||
.channels = fxls8962af_channels,
|
||||
.num_channels = ARRAY_SIZE(fxls8962af_channels),
|
||||
},
|
||||
[fxls8967af] = {
|
||||
.chip_id = FXLS8967AF_DEVICE_ID,
|
||||
.name = "fxls8967af",
|
||||
.channels = fxls8962af_channels,
|
||||
.num_channels = ARRAY_SIZE(fxls8962af_channels),
|
||||
},
|
||||
[fxls8974cf] = {
|
||||
.chip_id = FXLS8974CF_DEVICE_ID,
|
||||
.name = "fxls8974cf",
|
||||
.channels = fxls8962af_channels,
|
||||
.num_channels = ARRAY_SIZE(fxls8962af_channels),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct iio_info fxls8962af_info = {
|
||||
|
@ -30,6 +30,8 @@ static int fxls8962af_probe(struct i2c_client *client)
|
||||
static const struct i2c_device_id fxls8962af_id[] = {
|
||||
{ "fxls8962af", fxls8962af },
|
||||
{ "fxls8964af", fxls8964af },
|
||||
{ "fxls8967af", fxls8967af },
|
||||
{ "fxls8974cf", fxls8974cf },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, fxls8962af_id);
|
||||
|
@ -11,6 +11,8 @@ struct device;
|
||||
enum {
|
||||
fxls8962af,
|
||||
fxls8964af,
|
||||
fxls8967af,
|
||||
fxls8974cf,
|
||||
};
|
||||
|
||||
int fxls8962af_core_probe(struct device *dev, struct regmap *regmap, int irq);
|
||||
|
@ -38,7 +38,9 @@ static int kx022a_i2c_probe(struct i2c_client *i2c)
|
||||
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 },
|
||||
{ .name = "kx134-1211", .driver_data = (kernel_ulong_t)&kx134_chip_info },
|
||||
{ .name = "kx132acr-lbz", .driver_data = (kernel_ulong_t)&kx132acr_chip_info },
|
||||
{ .name = "kx134acr-lbz", .driver_data = (kernel_ulong_t)&kx134acr_chip_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, kx022a_i2c_id);
|
||||
@ -46,7 +48,9 @@ MODULE_DEVICE_TABLE(i2c, kx022a_i2c_id);
|
||||
static const struct of_device_id kx022a_of_match[] = {
|
||||
{ .compatible = "kionix,kx022a", .data = &kx022a_chip_info },
|
||||
{ .compatible = "kionix,kx132-1211", .data = &kx132_chip_info },
|
||||
{ .compatible = "kionix,kx134-1211", .data = &kx134_chip_info },
|
||||
{ .compatible = "rohm,kx132acr-lbz", .data = &kx132acr_chip_info },
|
||||
{ .compatible = "rohm,kx134acr-lbz", .data = &kx134acr_chip_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, kx022a_of_match);
|
||||
|
@ -38,7 +38,9 @@ static int kx022a_spi_probe(struct spi_device *spi)
|
||||
static const struct spi_device_id kx022a_id[] = {
|
||||
{ .name = "kx022a", .driver_data = (kernel_ulong_t)&kx022a_chip_info },
|
||||
{ .name = "kx132-1211", .driver_data = (kernel_ulong_t)&kx132_chip_info },
|
||||
{ .name = "kx134-1211", .driver_data = (kernel_ulong_t)&kx134_chip_info },
|
||||
{ .name = "kx132acr-lbz", .driver_data = (kernel_ulong_t)&kx132acr_chip_info },
|
||||
{ .name = "kx134acr-lbz", .driver_data = (kernel_ulong_t)&kx134acr_chip_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, kx022a_id);
|
||||
@ -46,7 +48,9 @@ MODULE_DEVICE_TABLE(spi, kx022a_id);
|
||||
static const struct of_device_id kx022a_of_match[] = {
|
||||
{ .compatible = "kionix,kx022a", .data = &kx022a_chip_info },
|
||||
{ .compatible = "kionix,kx132-1211", .data = &kx132_chip_info },
|
||||
{ .compatible = "kionix,kx134-1211", .data = &kx134_chip_info },
|
||||
{ .compatible = "rohm,kx132acr-lbz", .data = &kx132acr_chip_info },
|
||||
{ .compatible = "rohm,kx134acr-lbz", .data = &kx134acr_chip_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, kx022a_of_match);
|
||||
|
@ -5,6 +5,7 @@
|
||||
* ROHM/KIONIX accelerometer driver
|
||||
*/
|
||||
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/interrupt.h>
|
||||
@ -407,11 +408,21 @@ static const int kx022a_scale_table[][2] = {
|
||||
{ 0, 4788403 },
|
||||
};
|
||||
|
||||
/* KX134ACR-LBZ ranges are (+/-) 8, 16, 32, 64 G */
|
||||
static const int kx134acr_lbz_scale_table[][2] = {
|
||||
{ 0, 2394202 },
|
||||
{ 0, 4788403 },
|
||||
{ 0, 9576807 },
|
||||
{ 0, 19153613 },
|
||||
};
|
||||
|
||||
static int kx022a_read_avail(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
const int **vals, int *type, int *length,
|
||||
long mask)
|
||||
{
|
||||
struct kx022a_data *data = iio_priv(indio_dev);
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
*vals = (const int *)kx022a_accel_samp_freq_table;
|
||||
@ -420,9 +431,8 @@ static int kx022a_read_avail(struct iio_dev *indio_dev,
|
||||
*type = IIO_VAL_INT_PLUS_MICRO;
|
||||
return IIO_AVAIL_LIST;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
*vals = (const int *)kx022a_scale_table;
|
||||
*length = ARRAY_SIZE(kx022a_scale_table) *
|
||||
ARRAY_SIZE(kx022a_scale_table[0]);
|
||||
*vals = (const int *)data->chip_info->scale_table;
|
||||
*length = data->chip_info->scale_table_size;
|
||||
*type = IIO_VAL_INT_PLUS_NANO;
|
||||
return IIO_AVAIL_LIST;
|
||||
default:
|
||||
@ -438,17 +448,17 @@ static void kx022a_reg2freq(unsigned int val, int *val1, int *val2)
|
||||
*val2 = kx022a_accel_samp_freq_table[val & KX022A_MASK_ODR][1];
|
||||
}
|
||||
|
||||
static void kx022a_reg2scale(unsigned int val, unsigned int *val1,
|
||||
unsigned int *val2)
|
||||
static void kx022a_reg2scale(struct kx022a_data *data, unsigned int val,
|
||||
unsigned int *val1, unsigned int *val2)
|
||||
{
|
||||
val &= KX022A_MASK_GSEL;
|
||||
val >>= KX022A_GSEL_SHIFT;
|
||||
|
||||
*val1 = kx022a_scale_table[val][0];
|
||||
*val2 = kx022a_scale_table[val][1];
|
||||
*val1 = data->chip_info->scale_table[val][0];
|
||||
*val2 = data->chip_info->scale_table[val][1];
|
||||
}
|
||||
|
||||
static int kx022a_turn_on_off_unlocked(struct kx022a_data *data, bool on)
|
||||
static int __kx022a_turn_on_off(struct kx022a_data *data, bool on)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -469,7 +479,7 @@ static int kx022a_turn_off_lock(struct kx022a_data *data)
|
||||
int ret;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
ret = kx022a_turn_on_off_unlocked(data, false);
|
||||
ret = __kx022a_turn_on_off(data, false);
|
||||
if (ret)
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
@ -480,7 +490,7 @@ static int kx022a_turn_on_unlock(struct kx022a_data *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = kx022a_turn_on_off_unlocked(data, true);
|
||||
ret = __kx022a_turn_on_off(data, true);
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
@ -543,11 +553,11 @@ static int kx022a_write_raw(struct iio_dev *idev,
|
||||
kx022a_turn_on_unlock(data);
|
||||
break;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
n = ARRAY_SIZE(kx022a_scale_table);
|
||||
n = data->chip_info->scale_table_size / 2;
|
||||
|
||||
while (n-- > 0)
|
||||
if (val == kx022a_scale_table[n][0] &&
|
||||
val2 == kx022a_scale_table[n][1])
|
||||
if (val == data->chip_info->scale_table[n][0] &&
|
||||
val2 == data->chip_info->scale_table[n][1])
|
||||
break;
|
||||
if (n < 0) {
|
||||
ret = -EINVAL;
|
||||
@ -642,7 +652,7 @@ static int kx022a_read_raw(struct iio_dev *idev,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
kx022a_reg2scale(regval, val, val2);
|
||||
kx022a_reg2scale(data, regval, val, val2);
|
||||
|
||||
return IIO_VAL_INT_PLUS_NANO;
|
||||
}
|
||||
@ -912,18 +922,19 @@ static int kx022a_fifo_disable(struct kx022a_data *data)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = kx022a_turn_off_lock(data);
|
||||
guard(mutex)(&data->mutex);
|
||||
ret = __kx022a_turn_on_off(data, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_clear_bits(data->regmap, data->ien_reg, KX022A_MASK_WMI);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
|
||||
ret = regmap_clear_bits(data->regmap, data->chip_info->buf_cntl2,
|
||||
KX022A_MASK_BUF_EN);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
|
||||
data->state &= ~KX022A_STATE_FIFO;
|
||||
|
||||
@ -931,12 +942,7 @@ static int kx022a_fifo_disable(struct kx022a_data *data)
|
||||
|
||||
kfree(data->fifo_buffer);
|
||||
|
||||
return kx022a_turn_on_unlock(data);
|
||||
|
||||
unlock_out:
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
return __kx022a_turn_on_off(data, true);
|
||||
}
|
||||
|
||||
static int kx022a_buffer_predisable(struct iio_dev *idev)
|
||||
@ -959,33 +965,29 @@ static int kx022a_fifo_enable(struct kx022a_data *data)
|
||||
if (!data->fifo_buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = kx022a_turn_off_lock(data);
|
||||
guard(mutex)(&data->mutex);
|
||||
ret = __kx022a_turn_on_off(data, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Update watermark to HW */
|
||||
ret = kx022a_fifo_set_wmi(data);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
|
||||
/* Enable buffer */
|
||||
ret = regmap_set_bits(data->regmap, data->chip_info->buf_cntl2,
|
||||
KX022A_MASK_BUF_EN);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
|
||||
data->state |= KX022A_STATE_FIFO;
|
||||
ret = regmap_set_bits(data->regmap, data->ien_reg,
|
||||
KX022A_MASK_WMI);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
|
||||
return kx022a_turn_on_unlock(data);
|
||||
|
||||
unlock_out:
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
return __kx022a_turn_on_off(data, true);
|
||||
}
|
||||
|
||||
static int kx022a_buffer_postenable(struct iio_dev *idev)
|
||||
@ -1053,7 +1055,7 @@ static irqreturn_t kx022a_irq_thread_handler(int irq, void *private)
|
||||
struct kx022a_data *data = iio_priv(idev);
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
guard(mutex)(&data->mutex);
|
||||
|
||||
if (data->trigger_enabled) {
|
||||
iio_trigger_poll_nested(data->trig);
|
||||
@ -1068,8 +1070,6 @@ static irqreturn_t kx022a_irq_thread_handler(int irq, void *private)
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1079,32 +1079,26 @@ static int kx022a_trigger_set_state(struct iio_trigger *trig,
|
||||
struct kx022a_data *data = iio_trigger_get_drvdata(trig);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
guard(mutex)(&data->mutex);
|
||||
|
||||
if (data->trigger_enabled == state)
|
||||
goto unlock_out;
|
||||
return 0;
|
||||
|
||||
if (data->state & KX022A_STATE_FIFO) {
|
||||
dev_warn(data->dev, "Can't set trigger when FIFO enabled\n");
|
||||
ret = -EBUSY;
|
||||
goto unlock_out;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
ret = kx022a_turn_on_off_unlocked(data, false);
|
||||
ret = __kx022a_turn_on_off(data, false);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
|
||||
data->trigger_enabled = state;
|
||||
ret = kx022a_set_drdy_irq(data, state);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
|
||||
ret = kx022a_turn_on_off_unlocked(data, true);
|
||||
|
||||
unlock_out:
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
return __kx022a_turn_on_off(data, true);
|
||||
}
|
||||
|
||||
static const struct iio_trigger_ops kx022a_trigger_ops = {
|
||||
@ -1121,10 +1115,15 @@ static int kx022a_chip_init(struct kx022a_data *data)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* I've seen I2C read failures if we poll too fast after the sensor
|
||||
* reset. Slight delay gives I2C block the time to recover.
|
||||
* According to the power-on procedure documents, there is (at least)
|
||||
* 2ms delay required after the software reset. This should be same for
|
||||
* all, KX022ACR-Z, KX132-1211, KX132ACR-LBZ and KX134ACR-LBZ.
|
||||
*
|
||||
* https://fscdn.rohm.com/kionix/en/document/AN010_KX022ACR-Z_Power-on_Procedure_E.pdf
|
||||
* https://fscdn.rohm.com/kionix/en/document/TN027-Power-On-Procedure.pdf
|
||||
* https://fscdn.rohm.com/kionix/en/document/AN011_KX134ACR-LBZ_Power-on_Procedure_E.pdf
|
||||
*/
|
||||
msleep(1);
|
||||
msleep(2);
|
||||
|
||||
ret = regmap_read_poll_timeout(data->regmap, data->chip_info->cntl2, val,
|
||||
!(val & KX022A_MASK_SRST),
|
||||
@ -1158,6 +1157,9 @@ const struct kx022a_chip_info kx022a_chip_info = {
|
||||
.regmap_config = &kx022a_regmap_config,
|
||||
.channels = kx022a_channels,
|
||||
.num_channels = ARRAY_SIZE(kx022a_channels),
|
||||
.scale_table = kx022a_scale_table,
|
||||
.scale_table_size = ARRAY_SIZE(kx022a_scale_table) *
|
||||
ARRAY_SIZE(kx022a_scale_table[0]),
|
||||
.fifo_length = KX022A_FIFO_LENGTH,
|
||||
.who = KX022A_REG_WHO,
|
||||
.id = KX022A_ID,
|
||||
@ -1183,6 +1185,9 @@ const struct kx022a_chip_info kx132_chip_info = {
|
||||
.regmap_config = &kx132_regmap_config,
|
||||
.channels = kx132_channels,
|
||||
.num_channels = ARRAY_SIZE(kx132_channels),
|
||||
.scale_table = kx022a_scale_table,
|
||||
.scale_table_size = ARRAY_SIZE(kx022a_scale_table) *
|
||||
ARRAY_SIZE(kx022a_scale_table[0]),
|
||||
.fifo_length = KX132_FIFO_LENGTH,
|
||||
.who = KX132_REG_WHO,
|
||||
.id = KX132_ID,
|
||||
@ -1204,6 +1209,35 @@ const struct kx022a_chip_info kx132_chip_info = {
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(kx132_chip_info, "IIO_KX022A");
|
||||
|
||||
const struct kx022a_chip_info kx134_chip_info = {
|
||||
.name = "kx134-1211",
|
||||
.regmap_config = &kx132_regmap_config,
|
||||
.channels = kx132_channels,
|
||||
.num_channels = ARRAY_SIZE(kx132_channels),
|
||||
.scale_table = kx134acr_lbz_scale_table,
|
||||
.scale_table_size = ARRAY_SIZE(kx134acr_lbz_scale_table) *
|
||||
ARRAY_SIZE(kx134acr_lbz_scale_table[0]),
|
||||
.fifo_length = KX132_FIFO_LENGTH,
|
||||
.who = KX132_REG_WHO,
|
||||
.id = KX134_1211_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(kx134_chip_info, "IIO_KX022A");
|
||||
|
||||
/*
|
||||
* Despite the naming, KX132ACR-LBZ is not similar to KX132-1211 but it is
|
||||
* exact subset of KX022A. KX132ACR-LBZ is meant to be used for industrial
|
||||
@ -1216,6 +1250,9 @@ const struct kx022a_chip_info kx132acr_chip_info = {
|
||||
.regmap_config = &kx022a_regmap_config,
|
||||
.channels = kx022a_channels,
|
||||
.num_channels = ARRAY_SIZE(kx022a_channels),
|
||||
.scale_table = kx022a_scale_table,
|
||||
.scale_table_size = ARRAY_SIZE(kx022a_scale_table) *
|
||||
ARRAY_SIZE(kx022a_scale_table[0]),
|
||||
.fifo_length = KX022A_FIFO_LENGTH,
|
||||
.who = KX022A_REG_WHO,
|
||||
.id = KX132ACR_LBZ_ID,
|
||||
@ -1236,6 +1273,34 @@ const struct kx022a_chip_info kx132acr_chip_info = {
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(kx132acr_chip_info, "IIO_KX022A");
|
||||
|
||||
const struct kx022a_chip_info kx134acr_chip_info = {
|
||||
.name = "kx134acr-lbz",
|
||||
.regmap_config = &kx022a_regmap_config,
|
||||
.channels = kx022a_channels,
|
||||
.num_channels = ARRAY_SIZE(kx022a_channels),
|
||||
.scale_table = kx134acr_lbz_scale_table,
|
||||
.scale_table_size = ARRAY_SIZE(kx134acr_lbz_scale_table) *
|
||||
ARRAY_SIZE(kx134acr_lbz_scale_table[0]),
|
||||
.fifo_length = KX022A_FIFO_LENGTH,
|
||||
.who = KX022A_REG_WHO,
|
||||
.id = KX134ACR_LBZ_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(kx134acr_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"};
|
||||
|
@ -14,6 +14,7 @@
|
||||
#define KX022A_REG_WHO 0x0f
|
||||
#define KX022A_ID 0xc8
|
||||
#define KX132ACR_LBZ_ID 0xd8
|
||||
#define KX134ACR_LBZ_ID 0xcc
|
||||
|
||||
#define KX022A_REG_CNTL2 0x19
|
||||
#define KX022A_MASK_SRST BIT(7)
|
||||
@ -77,6 +78,7 @@
|
||||
|
||||
#define KX132_REG_WHO 0x13
|
||||
#define KX132_ID 0x3d
|
||||
#define KX134_1211_ID 0x46
|
||||
|
||||
#define KX132_FIFO_LENGTH 86
|
||||
|
||||
@ -135,6 +137,14 @@ struct kx022a_data;
|
||||
*
|
||||
* @name: name of the device
|
||||
* @regmap_config: pointer to register map configuration
|
||||
* @scale_table: An array of tables of scaling factors for
|
||||
* a supported acceleration measurement range.
|
||||
* Each table containing a single scaling
|
||||
* factor consisting of two integers. The first
|
||||
* value in a table is the integer part, and
|
||||
* the second value is the fractional part as
|
||||
* parts per billion.
|
||||
* @scale_table_size: Amount of values in tables.
|
||||
* @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
|
||||
@ -161,6 +171,8 @@ struct kx022a_data;
|
||||
struct kx022a_chip_info {
|
||||
const char *name;
|
||||
const struct regmap_config *regmap_config;
|
||||
const int (*scale_table)[2];
|
||||
const int scale_table_size;
|
||||
const struct iio_chan_spec *channels;
|
||||
unsigned int num_channels;
|
||||
unsigned int fifo_length;
|
||||
@ -187,6 +199,8 @@ int kx022a_probe_internal(struct device *dev, const struct kx022a_chip_info *chi
|
||||
|
||||
extern const struct kx022a_chip_info kx022a_chip_info;
|
||||
extern const struct kx022a_chip_info kx132_chip_info;
|
||||
extern const struct kx022a_chip_info kx134_chip_info;
|
||||
extern const struct kx022a_chip_info kx132acr_chip_info;
|
||||
extern const struct kx022a_chip_info kx134acr_chip_info;
|
||||
|
||||
#endif
|
||||
|
@ -35,10 +35,6 @@
|
||||
|
||||
#define AD4000_SCALE_OPTIONS 2
|
||||
|
||||
#define AD4000_TQUIET1_NS 190
|
||||
#define AD4000_TQUIET2_NS 60
|
||||
#define AD4000_TCONV_NS 320
|
||||
|
||||
#define __AD4000_DIFF_CHANNEL(_sign, _real_bits, _storage_bits, _reg_access) \
|
||||
{ \
|
||||
.type = IIO_VOLTAGE, \
|
||||
@ -49,6 +45,7 @@
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||
BIT(IIO_CHAN_INFO_SCALE), \
|
||||
.info_mask_separate_available = _reg_access ? BIT(IIO_CHAN_INFO_SCALE) : 0,\
|
||||
.scan_index = 0, \
|
||||
.scan_type = { \
|
||||
.sign = _sign, \
|
||||
.realbits = _real_bits, \
|
||||
@ -62,6 +59,12 @@
|
||||
__AD4000_DIFF_CHANNEL((_sign), (_real_bits), \
|
||||
((_real_bits) > 16 ? 32 : 16), (_reg_access))
|
||||
|
||||
#define AD4000_DIFF_CHANNELS(_sign, _real_bits, _reg_access) \
|
||||
{ \
|
||||
AD4000_DIFF_CHANNEL(_sign, _real_bits, _reg_access), \
|
||||
IIO_CHAN_SOFT_TIMESTAMP(1), \
|
||||
}
|
||||
|
||||
#define __AD4000_PSEUDO_DIFF_CHANNEL(_sign, _real_bits, _storage_bits, _reg_access)\
|
||||
{ \
|
||||
.type = IIO_VOLTAGE, \
|
||||
@ -71,6 +74,7 @@
|
||||
BIT(IIO_CHAN_INFO_SCALE) | \
|
||||
BIT(IIO_CHAN_INFO_OFFSET), \
|
||||
.info_mask_separate_available = _reg_access ? BIT(IIO_CHAN_INFO_SCALE) : 0,\
|
||||
.scan_index = 0, \
|
||||
.scan_type = { \
|
||||
.sign = _sign, \
|
||||
.realbits = _real_bits, \
|
||||
@ -84,6 +88,12 @@
|
||||
__AD4000_PSEUDO_DIFF_CHANNEL((_sign), (_real_bits), \
|
||||
((_real_bits) > 16 ? 32 : 16), (_reg_access))
|
||||
|
||||
#define AD4000_PSEUDO_DIFF_CHANNELS(_sign, _real_bits, _reg_access) \
|
||||
{ \
|
||||
AD4000_PSEUDO_DIFF_CHANNEL(_sign, _real_bits, _reg_access), \
|
||||
IIO_CHAN_SOFT_TIMESTAMP(1), \
|
||||
}
|
||||
|
||||
static const char * const ad4000_power_supplies[] = {
|
||||
"vdd", "vio"
|
||||
};
|
||||
@ -108,111 +118,280 @@ static const int ad4000_gains[] = {
|
||||
454, 909, 1000, 1900,
|
||||
};
|
||||
|
||||
struct ad4000_time_spec {
|
||||
int t_conv_ns;
|
||||
int t_quiet2_ns;
|
||||
};
|
||||
|
||||
/*
|
||||
* Same timing specifications for all of AD4000, AD4001, ..., AD4008, AD4010,
|
||||
* ADAQ4001, and ADAQ4003.
|
||||
*/
|
||||
static const struct ad4000_time_spec ad4000_t_spec = {
|
||||
.t_conv_ns = 320,
|
||||
.t_quiet2_ns = 60,
|
||||
};
|
||||
|
||||
/* AD4020, AD4021, AD4022 */
|
||||
static const struct ad4000_time_spec ad4020_t_spec = {
|
||||
.t_conv_ns = 350,
|
||||
.t_quiet2_ns = 60,
|
||||
};
|
||||
|
||||
/* AD7983, AD7984 */
|
||||
static const struct ad4000_time_spec ad7983_t_spec = {
|
||||
.t_conv_ns = 500,
|
||||
.t_quiet2_ns = 0,
|
||||
};
|
||||
|
||||
/* AD7980, AD7982 */
|
||||
static const struct ad4000_time_spec ad7980_t_spec = {
|
||||
.t_conv_ns = 800,
|
||||
.t_quiet2_ns = 0,
|
||||
};
|
||||
|
||||
/* AD7946, AD7686, AD7688, AD7988-5, AD7693 */
|
||||
static const struct ad4000_time_spec ad7686_t_spec = {
|
||||
.t_conv_ns = 1600,
|
||||
.t_quiet2_ns = 0,
|
||||
};
|
||||
|
||||
/* AD7690 */
|
||||
static const struct ad4000_time_spec ad7690_t_spec = {
|
||||
.t_conv_ns = 2100,
|
||||
.t_quiet2_ns = 0,
|
||||
};
|
||||
|
||||
/* AD7942, AD7685, AD7687 */
|
||||
static const struct ad4000_time_spec ad7687_t_spec = {
|
||||
.t_conv_ns = 3200,
|
||||
.t_quiet2_ns = 0,
|
||||
};
|
||||
|
||||
/* AD7691 */
|
||||
static const struct ad4000_time_spec ad7691_t_spec = {
|
||||
.t_conv_ns = 3700,
|
||||
.t_quiet2_ns = 0,
|
||||
};
|
||||
|
||||
/* AD7988-1 */
|
||||
static const struct ad4000_time_spec ad7988_1_t_spec = {
|
||||
.t_conv_ns = 9500,
|
||||
.t_quiet2_ns = 0,
|
||||
};
|
||||
|
||||
struct ad4000_chip_info {
|
||||
const char *dev_name;
|
||||
struct iio_chan_spec chan_spec;
|
||||
struct iio_chan_spec reg_access_chan_spec;
|
||||
struct iio_chan_spec chan_spec[2];
|
||||
struct iio_chan_spec reg_access_chan_spec[2];
|
||||
const struct ad4000_time_spec *time_spec;
|
||||
bool has_hardware_gain;
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4000_chip_info = {
|
||||
.dev_name = "ad4000",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0),
|
||||
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 1),
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
|
||||
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4001_chip_info = {
|
||||
.dev_name = "ad4001",
|
||||
.chan_spec = AD4000_DIFF_CHANNEL('s', 16, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 1),
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 16, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4002_chip_info = {
|
||||
.dev_name = "ad4002",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18, 1),
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4003_chip_info = {
|
||||
.dev_name = "ad4003",
|
||||
.chan_spec = AD4000_DIFF_CHANNEL('s', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 1),
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 18, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4004_chip_info = {
|
||||
.dev_name = "ad4004",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0),
|
||||
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 1),
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
|
||||
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4005_chip_info = {
|
||||
.dev_name = "ad4005",
|
||||
.chan_spec = AD4000_DIFF_CHANNEL('s', 16, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 1),
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 16, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4006_chip_info = {
|
||||
.dev_name = "ad4006",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18, 1),
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4007_chip_info = {
|
||||
.dev_name = "ad4007",
|
||||
.chan_spec = AD4000_DIFF_CHANNEL('s', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 1),
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 18, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4008_chip_info = {
|
||||
.dev_name = "ad4008",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0),
|
||||
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 1),
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
|
||||
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4010_chip_info = {
|
||||
.dev_name = "ad4010",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18, 1),
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4011_chip_info = {
|
||||
.dev_name = "ad4011",
|
||||
.chan_spec = AD4000_DIFF_CHANNEL('s', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 1),
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 18, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4020_chip_info = {
|
||||
.dev_name = "ad4020",
|
||||
.chan_spec = AD4000_DIFF_CHANNEL('s', 20, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNEL('s', 20, 1),
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 20, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 20, 1),
|
||||
.time_spec = &ad4020_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4021_chip_info = {
|
||||
.dev_name = "ad4021",
|
||||
.chan_spec = AD4000_DIFF_CHANNEL('s', 20, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNEL('s', 20, 1),
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 20, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 20, 1),
|
||||
.time_spec = &ad4020_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4022_chip_info = {
|
||||
.dev_name = "ad4022",
|
||||
.chan_spec = AD4000_DIFF_CHANNEL('s', 20, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNEL('s', 20, 1),
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 20, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 20, 1),
|
||||
.time_spec = &ad4020_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info adaq4001_chip_info = {
|
||||
.dev_name = "adaq4001",
|
||||
.chan_spec = AD4000_DIFF_CHANNEL('s', 16, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 1),
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 16, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
.has_hardware_gain = true,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info adaq4003_chip_info = {
|
||||
.dev_name = "adaq4003",
|
||||
.chan_spec = AD4000_DIFF_CHANNEL('s', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 1),
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 18, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
.has_hardware_gain = true,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7685_chip_info = {
|
||||
.dev_name = "ad7685",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
|
||||
.time_spec = &ad7687_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7686_chip_info = {
|
||||
.dev_name = "ad7686",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
|
||||
.time_spec = &ad7686_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7687_chip_info = {
|
||||
.dev_name = "ad7687",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0),
|
||||
.time_spec = &ad7687_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7688_chip_info = {
|
||||
.dev_name = "ad7688",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0),
|
||||
.time_spec = &ad7686_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7690_chip_info = {
|
||||
.dev_name = "ad7690",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0),
|
||||
.time_spec = &ad7690_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7691_chip_info = {
|
||||
.dev_name = "ad7691",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0),
|
||||
.time_spec = &ad7691_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7693_chip_info = {
|
||||
.dev_name = "ad7693",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0),
|
||||
.time_spec = &ad7686_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7942_chip_info = {
|
||||
.dev_name = "ad7942",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 14, 0),
|
||||
.time_spec = &ad7687_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7946_chip_info = {
|
||||
.dev_name = "ad7946",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 14, 0),
|
||||
.time_spec = &ad7686_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7980_chip_info = {
|
||||
.dev_name = "ad7980",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
|
||||
.time_spec = &ad7980_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7982_chip_info = {
|
||||
.dev_name = "ad7982",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0),
|
||||
.time_spec = &ad7980_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7983_chip_info = {
|
||||
.dev_name = "ad7983",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
|
||||
.time_spec = &ad7983_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7984_chip_info = {
|
||||
.dev_name = "ad7984",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0),
|
||||
.time_spec = &ad7983_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7988_1_chip_info = {
|
||||
.dev_name = "ad7988-1",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
|
||||
.time_spec = &ad7988_1_t_spec,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7988_5_chip_info = {
|
||||
.dev_name = "ad7988-5",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
|
||||
.time_spec = &ad7686_t_spec,
|
||||
};
|
||||
|
||||
struct ad4000_state {
|
||||
struct spi_device *spi;
|
||||
struct gpio_desc *cnv_gpio;
|
||||
@ -224,6 +403,7 @@ struct ad4000_state {
|
||||
bool span_comp;
|
||||
u16 gain_milli;
|
||||
int scale_tbl[AD4000_SCALE_OPTIONS][2];
|
||||
const struct ad4000_time_spec *time_spec;
|
||||
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) requires the transfer buffers
|
||||
@ -488,16 +668,15 @@ static const struct iio_info ad4000_info = {
|
||||
static int ad4000_prepare_3wire_mode_message(struct ad4000_state *st,
|
||||
const struct iio_chan_spec *chan)
|
||||
{
|
||||
unsigned int cnv_pulse_time = AD4000_TCONV_NS;
|
||||
struct spi_transfer *xfers = st->xfers;
|
||||
|
||||
xfers[0].cs_change = 1;
|
||||
xfers[0].cs_change_delay.value = cnv_pulse_time;
|
||||
xfers[0].cs_change_delay.value = st->time_spec->t_conv_ns;
|
||||
xfers[0].cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
|
||||
|
||||
xfers[1].rx_buf = &st->scan.data;
|
||||
xfers[1].len = BITS_TO_BYTES(chan->scan_type.storagebits);
|
||||
xfers[1].delay.value = AD4000_TQUIET2_NS;
|
||||
xfers[1].delay.value = st->time_spec->t_quiet2_ns;
|
||||
xfers[1].delay.unit = SPI_DELAY_UNIT_NSECS;
|
||||
|
||||
spi_message_init_with_transfers(&st->msg, st->xfers, 2);
|
||||
@ -515,7 +694,6 @@ static int ad4000_prepare_3wire_mode_message(struct ad4000_state *st,
|
||||
static int ad4000_prepare_4wire_mode_message(struct ad4000_state *st,
|
||||
const struct iio_chan_spec *chan)
|
||||
{
|
||||
unsigned int cnv_to_sdi_time = AD4000_TCONV_NS;
|
||||
struct spi_transfer *xfers = st->xfers;
|
||||
|
||||
/*
|
||||
@ -523,7 +701,7 @@ static int ad4000_prepare_4wire_mode_message(struct ad4000_state *st,
|
||||
* going low.
|
||||
*/
|
||||
xfers[0].cs_off = 1;
|
||||
xfers[0].delay.value = cnv_to_sdi_time;
|
||||
xfers[0].delay.value = st->time_spec->t_conv_ns;
|
||||
xfers[0].delay.unit = SPI_DELAY_UNIT_NSECS;
|
||||
|
||||
xfers[1].rx_buf = &st->scan.data;
|
||||
@ -562,6 +740,7 @@ static int ad4000_probe(struct spi_device *spi)
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
st->spi = spi;
|
||||
st->time_spec = chip->time_spec;
|
||||
|
||||
ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(ad4000_power_supplies),
|
||||
ad4000_power_supplies);
|
||||
@ -591,7 +770,7 @@ static int ad4000_probe(struct spi_device *spi)
|
||||
switch (st->sdi_pin) {
|
||||
case AD4000_SDI_MOSI:
|
||||
indio_dev->info = &ad4000_reg_access_info;
|
||||
indio_dev->channels = &chip->reg_access_chan_spec;
|
||||
indio_dev->channels = chip->reg_access_chan_spec;
|
||||
|
||||
/*
|
||||
* In "3-wire mode", the ADC SDI line must be kept high when
|
||||
@ -603,7 +782,7 @@ static int ad4000_probe(struct spi_device *spi)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ad4000_prepare_3wire_mode_message(st, indio_dev->channels);
|
||||
ret = ad4000_prepare_3wire_mode_message(st, &indio_dev->channels[0]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -614,16 +793,16 @@ static int ad4000_probe(struct spi_device *spi)
|
||||
break;
|
||||
case AD4000_SDI_VIO:
|
||||
indio_dev->info = &ad4000_info;
|
||||
indio_dev->channels = &chip->chan_spec;
|
||||
ret = ad4000_prepare_3wire_mode_message(st, indio_dev->channels);
|
||||
indio_dev->channels = chip->chan_spec;
|
||||
ret = ad4000_prepare_3wire_mode_message(st, &indio_dev->channels[0]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
break;
|
||||
case AD4000_SDI_CS:
|
||||
indio_dev->info = &ad4000_info;
|
||||
indio_dev->channels = &chip->chan_spec;
|
||||
ret = ad4000_prepare_4wire_mode_message(st, indio_dev->channels);
|
||||
indio_dev->channels = chip->chan_spec;
|
||||
ret = ad4000_prepare_4wire_mode_message(st, &indio_dev->channels[0]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -637,7 +816,7 @@ static int ad4000_probe(struct spi_device *spi)
|
||||
}
|
||||
|
||||
indio_dev->name = chip->dev_name;
|
||||
indio_dev->num_channels = 1;
|
||||
indio_dev->num_channels = 2;
|
||||
|
||||
ret = devm_mutex_init(dev, &st->lock);
|
||||
if (ret)
|
||||
@ -658,7 +837,7 @@ static int ad4000_probe(struct spi_device *spi)
|
||||
}
|
||||
}
|
||||
|
||||
ad4000_fill_scale_tbl(st, indio_dev->channels);
|
||||
ad4000_fill_scale_tbl(st, &indio_dev->channels[0]);
|
||||
|
||||
ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
|
||||
&iio_pollfunc_store_time,
|
||||
@ -686,6 +865,21 @@ static const struct spi_device_id ad4000_id[] = {
|
||||
{ "ad4022", (kernel_ulong_t)&ad4022_chip_info },
|
||||
{ "adaq4001", (kernel_ulong_t)&adaq4001_chip_info },
|
||||
{ "adaq4003", (kernel_ulong_t)&adaq4003_chip_info },
|
||||
{ "ad7685", (kernel_ulong_t)&ad7685_chip_info },
|
||||
{ "ad7686", (kernel_ulong_t)&ad7686_chip_info },
|
||||
{ "ad7687", (kernel_ulong_t)&ad7687_chip_info },
|
||||
{ "ad7688", (kernel_ulong_t)&ad7688_chip_info },
|
||||
{ "ad7690", (kernel_ulong_t)&ad7690_chip_info },
|
||||
{ "ad7691", (kernel_ulong_t)&ad7691_chip_info },
|
||||
{ "ad7693", (kernel_ulong_t)&ad7693_chip_info },
|
||||
{ "ad7942", (kernel_ulong_t)&ad7942_chip_info },
|
||||
{ "ad7946", (kernel_ulong_t)&ad7946_chip_info },
|
||||
{ "ad7980", (kernel_ulong_t)&ad7980_chip_info },
|
||||
{ "ad7982", (kernel_ulong_t)&ad7982_chip_info },
|
||||
{ "ad7983", (kernel_ulong_t)&ad7983_chip_info },
|
||||
{ "ad7984", (kernel_ulong_t)&ad7984_chip_info },
|
||||
{ "ad7988-1", (kernel_ulong_t)&ad7988_1_chip_info },
|
||||
{ "ad7988-5", (kernel_ulong_t)&ad7988_5_chip_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, ad4000_id);
|
||||
@ -707,6 +901,21 @@ static const struct of_device_id ad4000_of_match[] = {
|
||||
{ .compatible = "adi,ad4022", .data = &ad4022_chip_info },
|
||||
{ .compatible = "adi,adaq4001", .data = &adaq4001_chip_info },
|
||||
{ .compatible = "adi,adaq4003", .data = &adaq4003_chip_info },
|
||||
{ .compatible = "adi,ad7685", .data = &ad7685_chip_info },
|
||||
{ .compatible = "adi,ad7686", .data = &ad7686_chip_info },
|
||||
{ .compatible = "adi,ad7687", .data = &ad7687_chip_info },
|
||||
{ .compatible = "adi,ad7688", .data = &ad7688_chip_info },
|
||||
{ .compatible = "adi,ad7690", .data = &ad7690_chip_info },
|
||||
{ .compatible = "adi,ad7691", .data = &ad7691_chip_info },
|
||||
{ .compatible = "adi,ad7693", .data = &ad7693_chip_info },
|
||||
{ .compatible = "adi,ad7942", .data = &ad7942_chip_info },
|
||||
{ .compatible = "adi,ad7946", .data = &ad7946_chip_info },
|
||||
{ .compatible = "adi,ad7980", .data = &ad7980_chip_info },
|
||||
{ .compatible = "adi,ad7982", .data = &ad7982_chip_info },
|
||||
{ .compatible = "adi,ad7983", .data = &ad7983_chip_info },
|
||||
{ .compatible = "adi,ad7984", .data = &ad7984_chip_info },
|
||||
{ .compatible = "adi,ad7988-1", .data = &ad7988_1_chip_info },
|
||||
{ .compatible = "adi,ad7988-5", .data = &ad7988_5_chip_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ad4000_of_match);
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#include <dt-bindings/iio/adi,ad4695.h>
|
||||
#include <dt-bindings/iio/adc/adi,ad4695.h>
|
||||
|
||||
/* AD4695 registers */
|
||||
#define AD4695_REG_SPI_CONFIG_A 0x0000
|
||||
|
@ -95,6 +95,10 @@
|
||||
#define AD7124_MAX_CONFIGS 8
|
||||
#define AD7124_MAX_CHANNELS 16
|
||||
|
||||
/* AD7124 input sources */
|
||||
#define AD7124_INPUT_TEMPSENSOR 16
|
||||
#define AD7124_INPUT_AVSS 17
|
||||
|
||||
enum ad7124_ids {
|
||||
ID_AD7124_4,
|
||||
ID_AD7124_8,
|
||||
@ -360,20 +364,21 @@ static int ad7124_find_free_config_slot(struct ad7124_state *st)
|
||||
return free_cfg_slot;
|
||||
}
|
||||
|
||||
/* Only called during probe, so dev_err_probe() can be used */
|
||||
static int ad7124_init_config_vref(struct ad7124_state *st, struct ad7124_channel_config *cfg)
|
||||
{
|
||||
struct device *dev = &st->sd.spi->dev;
|
||||
unsigned int refsel = cfg->refsel;
|
||||
|
||||
switch (refsel) {
|
||||
case AD7124_REFIN1:
|
||||
case AD7124_REFIN2:
|
||||
case AD7124_AVDD_REF:
|
||||
if (IS_ERR(st->vref[refsel])) {
|
||||
dev_err(&st->sd.spi->dev,
|
||||
"Error, trying to use external voltage reference without a %s regulator.\n",
|
||||
ad7124_ref_names[refsel]);
|
||||
return PTR_ERR(st->vref[refsel]);
|
||||
}
|
||||
if (IS_ERR(st->vref[refsel]))
|
||||
return dev_err_probe(dev, PTR_ERR(st->vref[refsel]),
|
||||
"Error, trying to use external voltage reference without a %s regulator.\n",
|
||||
ad7124_ref_names[refsel]);
|
||||
|
||||
cfg->vref_mv = regulator_get_voltage(st->vref[refsel]);
|
||||
/* Conversion from uV to mV */
|
||||
cfg->vref_mv /= 1000;
|
||||
@ -384,8 +389,7 @@ static int ad7124_init_config_vref(struct ad7124_state *st, struct ad7124_channe
|
||||
st->adc_control |= AD7124_ADC_CTRL_REF_EN(1);
|
||||
return 0;
|
||||
default:
|
||||
dev_err(&st->sd.spi->dev, "Invalid reference %d\n", refsel);
|
||||
return -EINVAL;
|
||||
return dev_err_probe(dev, -EINVAL, "Invalid reference %d\n", refsel);
|
||||
}
|
||||
}
|
||||
|
||||
@ -571,6 +575,7 @@ static const struct ad_sigma_delta_info ad7124_sigma_delta_info = {
|
||||
.data_reg = AD7124_DATA,
|
||||
.num_slots = 8,
|
||||
.irq_flags = IRQF_TRIGGER_FALLING,
|
||||
.num_resetclks = 64,
|
||||
};
|
||||
|
||||
static int ad7124_read_raw(struct iio_dev *indio_dev,
|
||||
@ -588,26 +593,59 @@ static int ad7124_read_raw(struct iio_dev *indio_dev,
|
||||
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
mutex_lock(&st->cfgs_lock);
|
||||
switch (chan->type) {
|
||||
case IIO_VOLTAGE:
|
||||
mutex_lock(&st->cfgs_lock);
|
||||
|
||||
idx = st->channels[chan->address].cfg.pga_bits;
|
||||
*val = st->channels[chan->address].cfg.vref_mv;
|
||||
if (st->channels[chan->address].cfg.bipolar)
|
||||
*val2 = chan->scan_type.realbits - 1 + idx;
|
||||
else
|
||||
*val2 = chan->scan_type.realbits + idx;
|
||||
idx = st->channels[chan->address].cfg.pga_bits;
|
||||
*val = st->channels[chan->address].cfg.vref_mv;
|
||||
if (st->channels[chan->address].cfg.bipolar)
|
||||
*val2 = chan->scan_type.realbits - 1 + idx;
|
||||
else
|
||||
*val2 = chan->scan_type.realbits + idx;
|
||||
|
||||
mutex_unlock(&st->cfgs_lock);
|
||||
return IIO_VAL_FRACTIONAL_LOG2;
|
||||
|
||||
case IIO_TEMP:
|
||||
/*
|
||||
* According to the data sheet
|
||||
* Temperature (°C)
|
||||
* = ((Conversion − 0x800000)/13584) − 272.5
|
||||
* = (Conversion − 0x800000 - 13584 * 272.5) / 13584
|
||||
* = (Conversion − 12090248) / 13584
|
||||
* So scale with 1000/13584 to yield °mC. Reduce by 8 to
|
||||
* 125/1698.
|
||||
*/
|
||||
*val = 125;
|
||||
*val2 = 1698;
|
||||
return IIO_VAL_FRACTIONAL;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_unlock(&st->cfgs_lock);
|
||||
return IIO_VAL_FRACTIONAL_LOG2;
|
||||
case IIO_CHAN_INFO_OFFSET:
|
||||
mutex_lock(&st->cfgs_lock);
|
||||
if (st->channels[chan->address].cfg.bipolar)
|
||||
*val = -(1 << (chan->scan_type.realbits - 1));
|
||||
else
|
||||
*val = 0;
|
||||
switch (chan->type) {
|
||||
case IIO_VOLTAGE:
|
||||
mutex_lock(&st->cfgs_lock);
|
||||
if (st->channels[chan->address].cfg.bipolar)
|
||||
*val = -(1 << (chan->scan_type.realbits - 1));
|
||||
else
|
||||
*val = 0;
|
||||
|
||||
mutex_unlock(&st->cfgs_lock);
|
||||
return IIO_VAL_INT;
|
||||
|
||||
case IIO_TEMP:
|
||||
/* see calculation above */
|
||||
*val = -12090248;
|
||||
return IIO_VAL_INT;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_unlock(&st->cfgs_lock);
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
mutex_lock(&st->cfgs_lock);
|
||||
*val = st->channels[chan->address].cfg.odr;
|
||||
@ -751,12 +789,14 @@ static const struct iio_info ad7124_info = {
|
||||
.attrs = &ad7124_attrs_group,
|
||||
};
|
||||
|
||||
/* Only called during probe, so dev_err_probe() can be used */
|
||||
static int ad7124_soft_reset(struct ad7124_state *st)
|
||||
{
|
||||
struct device *dev = &st->sd.spi->dev;
|
||||
unsigned int readval, timeout;
|
||||
int ret;
|
||||
|
||||
ret = ad_sd_reset(&st->sd, 64);
|
||||
ret = ad_sd_reset(&st->sd);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -765,7 +805,7 @@ static int ad7124_soft_reset(struct ad7124_state *st)
|
||||
do {
|
||||
ret = ad_sd_read_reg(&st->sd, AD7124_STATUS, 1, &readval);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return dev_err_probe(dev, ret, "Error reading status register\n");
|
||||
|
||||
if (!(readval & AD7124_STATUS_POR_FLAG_MSK))
|
||||
return 0;
|
||||
@ -774,39 +814,47 @@ static int ad7124_soft_reset(struct ad7124_state *st)
|
||||
usleep_range(100, 2000);
|
||||
} while (--timeout);
|
||||
|
||||
dev_err(&st->sd.spi->dev, "Soft reset failed\n");
|
||||
|
||||
return -EIO;
|
||||
return dev_err_probe(dev, -EIO, "Soft reset failed\n");
|
||||
}
|
||||
|
||||
static int ad7124_check_chip_id(struct ad7124_state *st)
|
||||
{
|
||||
struct device *dev = &st->sd.spi->dev;
|
||||
unsigned int readval, chip_id, silicon_rev;
|
||||
int ret;
|
||||
|
||||
ret = ad_sd_read_reg(&st->sd, AD7124_ID, 1, &readval);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return dev_err_probe(dev, ret, "Failure to read ID register\n");
|
||||
|
||||
chip_id = AD7124_DEVICE_ID_GET(readval);
|
||||
silicon_rev = AD7124_SILICON_REV_GET(readval);
|
||||
|
||||
if (chip_id != st->chip_info->chip_id) {
|
||||
dev_err(&st->sd.spi->dev,
|
||||
"Chip ID mismatch: expected %u, got %u\n",
|
||||
st->chip_info->chip_id, chip_id);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (chip_id != st->chip_info->chip_id)
|
||||
return dev_err_probe(dev, -ENODEV,
|
||||
"Chip ID mismatch: expected %u, got %u\n",
|
||||
st->chip_info->chip_id, chip_id);
|
||||
|
||||
if (silicon_rev == 0) {
|
||||
dev_err(&st->sd.spi->dev,
|
||||
"Silicon revision empty. Chip may not be present\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (silicon_rev == 0)
|
||||
return dev_err_probe(dev, -ENODEV,
|
||||
"Silicon revision empty. Chip may not be present\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Input specifiers 8 - 15 are explicitly reserved for ad7124-4
|
||||
* while they are fine for ad7124-8. Values above 31 don't fit
|
||||
* into the register field and so are invalid for sure.
|
||||
*/
|
||||
static bool ad7124_valid_input_select(unsigned int ain, const struct ad7124_chip_info *info)
|
||||
{
|
||||
if (ain >= info->num_inputs && ain < 16)
|
||||
return false;
|
||||
|
||||
return ain <= FIELD_MAX(AD7124_CHANNEL_AINM_MSK);
|
||||
}
|
||||
|
||||
static int ad7124_parse_channel_config(struct iio_dev *indio_dev,
|
||||
struct device *dev)
|
||||
{
|
||||
@ -815,11 +863,23 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev,
|
||||
struct ad7124_channel *channels;
|
||||
struct iio_chan_spec *chan;
|
||||
unsigned int ain[2], channel = 0, tmp;
|
||||
unsigned int num_channels;
|
||||
int ret;
|
||||
|
||||
st->num_channels = device_get_child_node_count(dev);
|
||||
if (!st->num_channels)
|
||||
return dev_err_probe(dev, -ENODEV, "no channel children\n");
|
||||
num_channels = device_get_child_node_count(dev);
|
||||
|
||||
/*
|
||||
* The driver assigns each logical channel defined in the device tree
|
||||
* statically one channel register. So only accept 16 such logical
|
||||
* channels to not treat CONFIG_0 (i.e. the register following
|
||||
* CHANNEL_15) as an additional channel register. The driver could be
|
||||
* improved to lift this limitation.
|
||||
*/
|
||||
if (num_channels > AD7124_MAX_CHANNELS)
|
||||
return dev_err_probe(dev, -EINVAL, "Too many channels defined\n");
|
||||
|
||||
/* Add one for temperature */
|
||||
st->num_channels = min(num_channels + 1, AD7124_MAX_CHANNELS);
|
||||
|
||||
chan = devm_kcalloc(indio_dev->dev.parent, st->num_channels,
|
||||
sizeof(*chan), GFP_KERNEL);
|
||||
@ -838,16 +898,23 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev,
|
||||
device_for_each_child_node_scoped(dev, child) {
|
||||
ret = fwnode_property_read_u32(child, "reg", &channel);
|
||||
if (ret)
|
||||
return ret;
|
||||
return dev_err_probe(dev, ret,
|
||||
"Failed to parse reg property of %pfwP\n", child);
|
||||
|
||||
if (channel >= indio_dev->num_channels)
|
||||
if (channel >= num_channels)
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"Channel index >= number of channels\n");
|
||||
"Channel index >= number of channels in %pfwP\n", child);
|
||||
|
||||
ret = fwnode_property_read_u32_array(child, "diff-channels",
|
||||
ain, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
return dev_err_probe(dev, ret,
|
||||
"Failed to parse diff-channels property of %pfwP\n", child);
|
||||
|
||||
if (!ad7124_valid_input_select(ain[0], st->chip_info) ||
|
||||
!ad7124_valid_input_select(ain[1], st->chip_info))
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"diff-channels property of %pfwP contains invalid data\n", child);
|
||||
|
||||
st->channels[channel].nr = channel;
|
||||
st->channels[channel].ain = AD7124_CHANNEL_AINP(ain[0]) |
|
||||
@ -874,17 +941,49 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev,
|
||||
chan[channel].channel2 = ain[1];
|
||||
}
|
||||
|
||||
if (num_channels < AD7124_MAX_CHANNELS) {
|
||||
st->channels[num_channels] = (struct ad7124_channel) {
|
||||
.nr = num_channels,
|
||||
.ain = AD7124_CHANNEL_AINP(AD7124_INPUT_TEMPSENSOR) |
|
||||
AD7124_CHANNEL_AINM(AD7124_INPUT_AVSS),
|
||||
.cfg = {
|
||||
.bipolar = true,
|
||||
},
|
||||
};
|
||||
|
||||
chan[num_channels] = (struct iio_chan_spec) {
|
||||
.type = IIO_TEMP,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
|
||||
BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET) |
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ),
|
||||
.scan_type = {
|
||||
/*
|
||||
* You might find it strange that a bipolar
|
||||
* measurement yields an unsigned value, but
|
||||
* this matches the device's manual.
|
||||
*/
|
||||
.sign = 'u',
|
||||
.realbits = 24,
|
||||
.storagebits = 32,
|
||||
.endianness = IIO_BE,
|
||||
},
|
||||
.address = num_channels,
|
||||
.scan_index = num_channels,
|
||||
};
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ad7124_setup(struct ad7124_state *st)
|
||||
{
|
||||
struct device *dev = &st->sd.spi->dev;
|
||||
unsigned int fclk, power_mode;
|
||||
int i, ret;
|
||||
|
||||
fclk = clk_get_rate(st->mclk);
|
||||
if (!fclk)
|
||||
return -EINVAL;
|
||||
return dev_err_probe(dev, -EINVAL, "Failed to get mclk rate\n");
|
||||
|
||||
/* The power mode changes the master clock frequency */
|
||||
power_mode = ad7124_find_closest_match(ad7124_master_clk_freq_hz,
|
||||
@ -893,7 +992,7 @@ static int ad7124_setup(struct ad7124_state *st)
|
||||
if (fclk != ad7124_master_clk_freq_hz[power_mode]) {
|
||||
ret = clk_set_rate(st->mclk, fclk);
|
||||
if (ret)
|
||||
return ret;
|
||||
return dev_err_probe(dev, ret, "Failed to set mclk rate\n");
|
||||
}
|
||||
|
||||
/* Set the power mode */
|
||||
@ -924,7 +1023,7 @@ static int ad7124_setup(struct ad7124_state *st)
|
||||
|
||||
ret = ad_sd_write_reg(&st->sd, AD7124_ADC_CONTROL, 2, st->adc_control);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return dev_err_probe(dev, ret, "Failed to setup CONTROL register\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -937,13 +1036,14 @@ static void ad7124_reg_disable(void *r)
|
||||
static int ad7124_probe(struct spi_device *spi)
|
||||
{
|
||||
const struct ad7124_chip_info *info;
|
||||
struct device *dev = &spi->dev;
|
||||
struct ad7124_state *st;
|
||||
struct iio_dev *indio_dev;
|
||||
int i, ret;
|
||||
|
||||
info = spi_get_device_match_data(spi);
|
||||
if (!info)
|
||||
return -ENODEV;
|
||||
return dev_err_probe(dev, -ENODEV, "Failed to get match data\n");
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (!indio_dev)
|
||||
@ -978,17 +1078,17 @@ static int ad7124_probe(struct spi_device *spi)
|
||||
|
||||
ret = regulator_enable(st->vref[i]);
|
||||
if (ret)
|
||||
return ret;
|
||||
return dev_err_probe(dev, ret, "Failed to enable regulator #%d\n", i);
|
||||
|
||||
ret = devm_add_action_or_reset(&spi->dev, ad7124_reg_disable,
|
||||
st->vref[i]);
|
||||
if (ret)
|
||||
return ret;
|
||||
return dev_err_probe(dev, ret, "Failed to register disable handler for regulator #%d\n", i);
|
||||
}
|
||||
|
||||
st->mclk = devm_clk_get_enabled(&spi->dev, "mclk");
|
||||
if (IS_ERR(st->mclk))
|
||||
return PTR_ERR(st->mclk);
|
||||
return dev_err_probe(dev, PTR_ERR(st->mclk), "Failed to get mclk\n");
|
||||
|
||||
ret = ad7124_soft_reset(st);
|
||||
if (ret < 0)
|
||||
@ -1004,10 +1104,13 @@ static int ad7124_probe(struct spi_device *spi)
|
||||
|
||||
ret = devm_ad_sd_setup_buffer_and_trigger(&spi->dev, indio_dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return dev_err_probe(dev, ret, "Failed to setup triggers\n");
|
||||
|
||||
return devm_iio_device_register(&spi->dev, indio_dev);
|
||||
ret = devm_iio_device_register(&spi->dev, indio_dev);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "Failed to register iio device\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id ad7124_of_match[] = {
|
||||
|
@ -150,6 +150,11 @@
|
||||
#define AD7173_FILTER_ODR0_MASK GENMASK(5, 0)
|
||||
#define AD7173_MAX_CONFIGS 8
|
||||
|
||||
#define AD7173_MODE_CAL_INT_ZERO 0x4 /* Internal Zero-Scale Calibration */
|
||||
#define AD7173_MODE_CAL_INT_FULL 0x5 /* Internal Full-Scale Calibration */
|
||||
#define AD7173_MODE_CAL_SYS_ZERO 0x6 /* System Zero-Scale Calibration */
|
||||
#define AD7173_MODE_CAL_SYS_FULL 0x7 /* System Full-Scale Calibration */
|
||||
|
||||
struct ad7173_device_info {
|
||||
const unsigned int *sinc5_data_rates;
|
||||
unsigned int num_sinc5_data_rates;
|
||||
@ -175,6 +180,7 @@ struct ad7173_device_info {
|
||||
bool has_input_buf;
|
||||
bool has_int_ref;
|
||||
bool has_ref2;
|
||||
bool has_internal_fs_calibration;
|
||||
bool higher_gpio_bits;
|
||||
u8 num_gpios;
|
||||
};
|
||||
@ -193,9 +199,9 @@ struct ad7173_channel_config {
|
||||
};
|
||||
|
||||
struct ad7173_channel {
|
||||
unsigned int chan_reg;
|
||||
unsigned int ain;
|
||||
struct ad7173_channel_config cfg;
|
||||
u8 syscalib_mode;
|
||||
};
|
||||
|
||||
struct ad7173_state {
|
||||
@ -273,6 +279,7 @@ static const struct ad7173_device_info ad4111_device_info = {
|
||||
.has_input_buf = true,
|
||||
.has_current_inputs = true,
|
||||
.has_int_ref = true,
|
||||
.has_internal_fs_calibration = true,
|
||||
.clock = 2 * HZ_PER_MHZ,
|
||||
.sinc5_data_rates = ad7173_sinc5_data_rates,
|
||||
.num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates),
|
||||
@ -292,6 +299,7 @@ static const struct ad7173_device_info ad4112_device_info = {
|
||||
.has_input_buf = true,
|
||||
.has_current_inputs = true,
|
||||
.has_int_ref = true,
|
||||
.has_internal_fs_calibration = true,
|
||||
.clock = 2 * HZ_PER_MHZ,
|
||||
.sinc5_data_rates = ad7173_sinc5_data_rates,
|
||||
.num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates),
|
||||
@ -327,6 +335,7 @@ static const struct ad7173_device_info ad4114_device_info = {
|
||||
.has_temp = true,
|
||||
.has_input_buf = true,
|
||||
.has_int_ref = true,
|
||||
.has_internal_fs_calibration = true,
|
||||
.clock = 2 * HZ_PER_MHZ,
|
||||
.sinc5_data_rates = ad7173_sinc5_data_rates,
|
||||
.num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates),
|
||||
@ -344,6 +353,7 @@ static const struct ad7173_device_info ad4115_device_info = {
|
||||
.has_temp = true,
|
||||
.has_input_buf = true,
|
||||
.has_int_ref = true,
|
||||
.has_internal_fs_calibration = true,
|
||||
.clock = 8 * HZ_PER_MHZ,
|
||||
.sinc5_data_rates = ad4115_sinc5_data_rates,
|
||||
.num_sinc5_data_rates = ARRAY_SIZE(ad4115_sinc5_data_rates),
|
||||
@ -361,6 +371,7 @@ static const struct ad7173_device_info ad4116_device_info = {
|
||||
.has_temp = true,
|
||||
.has_input_buf = true,
|
||||
.has_int_ref = true,
|
||||
.has_internal_fs_calibration = true,
|
||||
.clock = 4 * HZ_PER_MHZ,
|
||||
.sinc5_data_rates = ad4116_sinc5_data_rates,
|
||||
.num_sinc5_data_rates = ARRAY_SIZE(ad4116_sinc5_data_rates),
|
||||
@ -506,6 +517,105 @@ static const struct regmap_config ad7173_regmap_config = {
|
||||
.read_flag_mask = BIT(6),
|
||||
};
|
||||
|
||||
enum {
|
||||
AD7173_SYSCALIB_ZERO_SCALE,
|
||||
AD7173_SYSCALIB_FULL_SCALE,
|
||||
};
|
||||
|
||||
static const char * const ad7173_syscalib_modes[] = {
|
||||
[AD7173_SYSCALIB_ZERO_SCALE] = "zero_scale",
|
||||
[AD7173_SYSCALIB_FULL_SCALE] = "full_scale",
|
||||
};
|
||||
|
||||
static int ad7173_set_syscalib_mode(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
unsigned int mode)
|
||||
{
|
||||
struct ad7173_state *st = iio_priv(indio_dev);
|
||||
|
||||
st->channels[chan->channel].syscalib_mode = mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ad7173_get_syscalib_mode(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan)
|
||||
{
|
||||
struct ad7173_state *st = iio_priv(indio_dev);
|
||||
|
||||
return st->channels[chan->channel].syscalib_mode;
|
||||
}
|
||||
|
||||
static ssize_t ad7173_write_syscalib(struct iio_dev *indio_dev,
|
||||
uintptr_t private,
|
||||
const struct iio_chan_spec *chan,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct ad7173_state *st = iio_priv(indio_dev);
|
||||
bool sys_calib;
|
||||
int ret, mode;
|
||||
|
||||
ret = kstrtobool(buf, &sys_calib);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mode = st->channels[chan->channel].syscalib_mode;
|
||||
if (sys_calib) {
|
||||
if (mode == AD7173_SYSCALIB_ZERO_SCALE)
|
||||
ret = ad_sd_calibrate(&st->sd, AD7173_MODE_CAL_SYS_ZERO,
|
||||
chan->address);
|
||||
else
|
||||
ret = ad_sd_calibrate(&st->sd, AD7173_MODE_CAL_SYS_FULL,
|
||||
chan->address);
|
||||
}
|
||||
|
||||
return ret ? : len;
|
||||
}
|
||||
|
||||
static const struct iio_enum ad7173_syscalib_mode_enum = {
|
||||
.items = ad7173_syscalib_modes,
|
||||
.num_items = ARRAY_SIZE(ad7173_syscalib_modes),
|
||||
.set = ad7173_set_syscalib_mode,
|
||||
.get = ad7173_get_syscalib_mode
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec_ext_info ad7173_calibsys_ext_info[] = {
|
||||
{
|
||||
.name = "sys_calibration",
|
||||
.write = ad7173_write_syscalib,
|
||||
.shared = IIO_SEPARATE,
|
||||
},
|
||||
IIO_ENUM("sys_calibration_mode", IIO_SEPARATE,
|
||||
&ad7173_syscalib_mode_enum),
|
||||
IIO_ENUM_AVAILABLE("sys_calibration_mode", IIO_SHARED_BY_TYPE,
|
||||
&ad7173_syscalib_mode_enum),
|
||||
{ }
|
||||
};
|
||||
|
||||
static int ad7173_calibrate_all(struct ad7173_state *st, struct iio_dev *indio_dev)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < st->num_channels; i++) {
|
||||
if (indio_dev->channels[i].type != IIO_VOLTAGE)
|
||||
continue;
|
||||
|
||||
ret = ad_sd_calibrate(&st->sd, AD7173_MODE_CAL_INT_ZERO, st->channels[i].ain);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (st->info->has_internal_fs_calibration) {
|
||||
ret = ad_sd_calibrate(&st->sd, AD7173_MODE_CAL_INT_FULL,
|
||||
st->channels[i].ain);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ad7173_mask_xlate(struct gpio_regmap *gpio, unsigned int base,
|
||||
unsigned int offset, unsigned int *reg,
|
||||
unsigned int *mask)
|
||||
@ -765,6 +875,7 @@ static const struct ad_sigma_delta_info ad7173_sigma_delta_info = {
|
||||
.read_mask = BIT(6),
|
||||
.status_ch_mask = GENMASK(3, 0),
|
||||
.data_reg = AD7173_REG_DATA,
|
||||
.num_resetclks = 64,
|
||||
};
|
||||
|
||||
static int ad7173_setup(struct iio_dev *indio_dev)
|
||||
@ -802,6 +913,10 @@ static int ad7173_setup(struct iio_dev *indio_dev)
|
||||
if (!st->config_cnts)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = ad7173_calibrate_all(st, indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* All channels are enabled by default after a reset */
|
||||
return ad7173_disable_all(&st->sd);
|
||||
}
|
||||
@ -1024,6 +1139,7 @@ static const struct iio_chan_spec ad7173_channel_template = {
|
||||
.storagebits = 32,
|
||||
.endianness = IIO_BE,
|
||||
},
|
||||
.ext_info = ad7173_calibsys_ext_info,
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec ad7173_temp_iio_channel_template = {
|
||||
@ -1317,7 +1433,6 @@ static int ad7173_fw_parse_channel_config(struct iio_dev *indio_dev)
|
||||
chan->address = chan_index;
|
||||
chan->scan_index = chan_index;
|
||||
chan->channel = ain[0];
|
||||
chan_st_priv->chan_reg = chan_index;
|
||||
chan_st_priv->cfg.input_buf = st->info->has_input_buf;
|
||||
chan_st_priv->cfg.odr = 0;
|
||||
|
||||
|
@ -361,6 +361,7 @@ static const struct ad_sigma_delta_info ad7192_sigma_delta_info = {
|
||||
.status_ch_mask = GENMASK(3, 0),
|
||||
.num_slots = 4,
|
||||
.irq_flags = IRQF_TRIGGER_FALLING,
|
||||
.num_resetclks = 40,
|
||||
};
|
||||
|
||||
static const struct ad_sigma_delta_info ad7194_sigma_delta_info = {
|
||||
@ -373,6 +374,7 @@ static const struct ad_sigma_delta_info ad7194_sigma_delta_info = {
|
||||
.read_mask = BIT(6),
|
||||
.status_ch_mask = GENMASK(3, 0),
|
||||
.irq_flags = IRQF_TRIGGER_FALLING,
|
||||
.num_resetclks = 40,
|
||||
};
|
||||
|
||||
static const struct ad_sd_calib_data ad7192_calib_arr[8] = {
|
||||
@ -565,7 +567,7 @@ static int ad7192_setup(struct iio_dev *indio_dev, struct device *dev)
|
||||
int i, ret, id;
|
||||
|
||||
/* reset the serial interface */
|
||||
ret = ad_sd_reset(&st->sd, 48);
|
||||
ret = ad_sd_reset(&st->sd);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
usleep_range(500, 1000); /* Wait for at least 500us */
|
||||
|
@ -254,6 +254,7 @@ static const struct ad_sigma_delta_info ad7791_sigma_delta_info = {
|
||||
.addr_shift = 4,
|
||||
.read_mask = BIT(3),
|
||||
.irq_flags = IRQF_TRIGGER_FALLING,
|
||||
.num_resetclks = 32,
|
||||
};
|
||||
|
||||
static int ad7791_read_raw(struct iio_dev *indio_dev,
|
||||
|
@ -206,6 +206,7 @@ static const struct ad_sigma_delta_info ad7793_sigma_delta_info = {
|
||||
.addr_shift = 3,
|
||||
.read_mask = BIT(6),
|
||||
.irq_flags = IRQF_TRIGGER_FALLING,
|
||||
.num_resetclks = 32,
|
||||
};
|
||||
|
||||
static const struct ad_sd_calib_data ad7793_calib_arr[6] = {
|
||||
@ -265,7 +266,7 @@ static int ad7793_setup(struct iio_dev *indio_dev,
|
||||
return ret;
|
||||
|
||||
/* reset the serial interface */
|
||||
ret = ad_sd_reset(&st->sd, 32);
|
||||
ret = ad_sd_reset(&st->sd);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
usleep_range(500, 2000); /* Wait for at least 500us */
|
||||
|
@ -29,8 +29,11 @@
|
||||
#define AD_SD_COMM_CHAN_MASK 0x3
|
||||
|
||||
#define AD_SD_REG_COMM 0x00
|
||||
#define AD_SD_REG_STATUS 0x00
|
||||
#define AD_SD_REG_DATA 0x03
|
||||
|
||||
#define AD_SD_REG_STATUS_RDY 0x80
|
||||
|
||||
/**
|
||||
* ad_sd_set_comm() - Set communications register
|
||||
*
|
||||
@ -109,7 +112,7 @@ static int ad_sd_read_reg_raw(struct ad_sigma_delta *sigma_delta,
|
||||
}, {
|
||||
.rx_buf = val,
|
||||
.len = size,
|
||||
.cs_change = sigma_delta->bus_locked,
|
||||
.cs_change = sigma_delta->keep_cs_asserted,
|
||||
},
|
||||
};
|
||||
struct spi_message m;
|
||||
@ -178,13 +181,12 @@ EXPORT_SYMBOL_NS_GPL(ad_sd_read_reg, "IIO_AD_SIGMA_DELTA");
|
||||
* ad_sd_reset() - Reset the serial interface
|
||||
*
|
||||
* @sigma_delta: The sigma delta device
|
||||
* @reset_length: Number of SCLKs with DIN = 1
|
||||
*
|
||||
* Returns 0 on success, an error code otherwise.
|
||||
**/
|
||||
int ad_sd_reset(struct ad_sigma_delta *sigma_delta,
|
||||
unsigned int reset_length)
|
||||
int ad_sd_reset(struct ad_sigma_delta *sigma_delta)
|
||||
{
|
||||
unsigned int reset_length = sigma_delta->info->num_resetclks;
|
||||
uint8_t *buf;
|
||||
unsigned int size;
|
||||
int ret;
|
||||
@ -202,6 +204,107 @@ int ad_sd_reset(struct ad_sigma_delta *sigma_delta,
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(ad_sd_reset, "IIO_AD_SIGMA_DELTA");
|
||||
|
||||
static bool ad_sd_disable_irq(struct ad_sigma_delta *sigma_delta)
|
||||
{
|
||||
guard(spinlock_irqsave)(&sigma_delta->irq_lock);
|
||||
|
||||
/* It's already off, return false to indicate nothing was changed */
|
||||
if (sigma_delta->irq_dis)
|
||||
return false;
|
||||
|
||||
sigma_delta->irq_dis = true;
|
||||
disable_irq_nosync(sigma_delta->irq_line);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ad_sd_enable_irq(struct ad_sigma_delta *sigma_delta)
|
||||
{
|
||||
guard(spinlock_irqsave)(&sigma_delta->irq_lock);
|
||||
|
||||
sigma_delta->irq_dis = false;
|
||||
enable_irq(sigma_delta->irq_line);
|
||||
}
|
||||
|
||||
#define AD_SD_CLEAR_DATA_BUFLEN 9
|
||||
|
||||
/* Called with `sigma_delta->bus_locked == true` only. */
|
||||
static int ad_sigma_delta_clear_pending_event(struct ad_sigma_delta *sigma_delta)
|
||||
{
|
||||
bool pending_event;
|
||||
unsigned int data_read_len = BITS_TO_BYTES(sigma_delta->info->num_resetclks);
|
||||
u8 *data;
|
||||
struct spi_transfer t[] = {
|
||||
{
|
||||
.len = 1,
|
||||
}, {
|
||||
.len = data_read_len,
|
||||
}
|
||||
};
|
||||
struct spi_message m;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Read R̅D̅Y̅ pin (if possible) or status register to check if there is an
|
||||
* old event.
|
||||
*/
|
||||
if (sigma_delta->rdy_gpiod) {
|
||||
pending_event = gpiod_get_value(sigma_delta->rdy_gpiod);
|
||||
} else {
|
||||
unsigned status_reg;
|
||||
|
||||
ret = ad_sd_read_reg(sigma_delta, AD_SD_REG_STATUS, 1, &status_reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pending_event = !(status_reg & AD_SD_REG_STATUS_RDY);
|
||||
}
|
||||
|
||||
if (!pending_event)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* In general the size of the data register is unknown. It varies from
|
||||
* device to device, might be one byte longer if CONTROL.DATA_STATUS is
|
||||
* set and even varies on some devices depending on which input is
|
||||
* selected. So send one byte to start reading the data register and
|
||||
* then just clock for some bytes with DIN (aka MOSI) high to not
|
||||
* confuse the register access state machine after the data register was
|
||||
* completely read. Note however that the sequence length must be
|
||||
* shorter than the reset procedure.
|
||||
*/
|
||||
|
||||
data = kzalloc(data_read_len + 1, GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
spi_message_init(&m);
|
||||
if (sigma_delta->info->has_registers) {
|
||||
unsigned int data_reg = sigma_delta->info->data_reg ?: AD_SD_REG_DATA;
|
||||
|
||||
data[0] = data_reg << sigma_delta->info->addr_shift;
|
||||
data[0] |= sigma_delta->info->read_mask;
|
||||
data[0] |= sigma_delta->comm;
|
||||
t[0].tx_buf = data;
|
||||
spi_message_add_tail(&t[0], &m);
|
||||
}
|
||||
|
||||
/*
|
||||
* The first transferred byte is part of the real data register,
|
||||
* so this doesn't need to be 0xff. In the remaining
|
||||
* `data_read_len - 1` bytes are less than $num_resetclks ones.
|
||||
*/
|
||||
t[1].tx_buf = data + 1;
|
||||
data[1] = 0x00;
|
||||
memset(data + 2, 0xff, data_read_len - 1);
|
||||
spi_message_add_tail(&t[1], &m);
|
||||
|
||||
ret = spi_sync_locked(sigma_delta->spi, &m);
|
||||
|
||||
kfree(data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,
|
||||
unsigned int mode, unsigned int channel)
|
||||
{
|
||||
@ -217,16 +320,18 @@ int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,
|
||||
sigma_delta->keep_cs_asserted = true;
|
||||
reinit_completion(&sigma_delta->completion);
|
||||
|
||||
ret = ad_sigma_delta_clear_pending_event(sigma_delta);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = ad_sigma_delta_set_mode(sigma_delta, mode);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
sigma_delta->irq_dis = false;
|
||||
enable_irq(sigma_delta->irq_line);
|
||||
ad_sd_enable_irq(sigma_delta);
|
||||
time_left = wait_for_completion_timeout(&sigma_delta->completion, 2 * HZ);
|
||||
if (time_left == 0) {
|
||||
sigma_delta->irq_dis = true;
|
||||
disable_irq_nosync(sigma_delta->irq_line);
|
||||
ad_sd_disable_irq(sigma_delta);
|
||||
ret = -EIO;
|
||||
} else {
|
||||
ret = 0;
|
||||
@ -292,10 +397,13 @@ int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
|
||||
sigma_delta->keep_cs_asserted = true;
|
||||
reinit_completion(&sigma_delta->completion);
|
||||
|
||||
ret = ad_sigma_delta_clear_pending_event(sigma_delta);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_SINGLE);
|
||||
|
||||
sigma_delta->irq_dis = false;
|
||||
enable_irq(sigma_delta->irq_line);
|
||||
ad_sd_enable_irq(sigma_delta);
|
||||
ret = wait_for_completion_interruptible_timeout(
|
||||
&sigma_delta->completion, HZ);
|
||||
|
||||
@ -314,14 +422,13 @@ int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
|
||||
&raw_sample);
|
||||
|
||||
out:
|
||||
if (!sigma_delta->irq_dis) {
|
||||
disable_irq_nosync(sigma_delta->irq_line);
|
||||
sigma_delta->irq_dis = true;
|
||||
}
|
||||
ad_sd_disable_irq(sigma_delta);
|
||||
|
||||
sigma_delta->keep_cs_asserted = false;
|
||||
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
|
||||
ad_sigma_delta_disable_one(sigma_delta, chan->address);
|
||||
|
||||
out_unlock:
|
||||
sigma_delta->keep_cs_asserted = false;
|
||||
sigma_delta->bus_locked = false;
|
||||
spi_bus_unlock(sigma_delta->spi->controller);
|
||||
iio_device_release_direct_mode(indio_dev);
|
||||
@ -392,12 +499,15 @@ static int ad_sd_buffer_postenable(struct iio_dev *indio_dev)
|
||||
sigma_delta->bus_locked = true;
|
||||
sigma_delta->keep_cs_asserted = true;
|
||||
|
||||
ret = ad_sigma_delta_clear_pending_event(sigma_delta);
|
||||
if (ret)
|
||||
goto err_unlock;
|
||||
|
||||
ret = ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_CONTINUOUS);
|
||||
if (ret)
|
||||
goto err_unlock;
|
||||
|
||||
sigma_delta->irq_dis = false;
|
||||
enable_irq(sigma_delta->irq_line);
|
||||
ad_sd_enable_irq(sigma_delta);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -414,10 +524,7 @@ static int ad_sd_buffer_postdisable(struct iio_dev *indio_dev)
|
||||
reinit_completion(&sigma_delta->completion);
|
||||
wait_for_completion_timeout(&sigma_delta->completion, HZ);
|
||||
|
||||
if (!sigma_delta->irq_dis) {
|
||||
disable_irq_nosync(sigma_delta->irq_line);
|
||||
sigma_delta->irq_dis = true;
|
||||
}
|
||||
ad_sd_disable_irq(sigma_delta);
|
||||
|
||||
sigma_delta->keep_cs_asserted = false;
|
||||
ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
|
||||
@ -516,8 +623,7 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
|
||||
|
||||
irq_handled:
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
sigma_delta->irq_dis = false;
|
||||
enable_irq(sigma_delta->irq_line);
|
||||
ad_sd_enable_irq(sigma_delta);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -539,12 +645,31 @@ static irqreturn_t ad_sd_data_rdy_trig_poll(int irq, void *private)
|
||||
{
|
||||
struct ad_sigma_delta *sigma_delta = private;
|
||||
|
||||
complete(&sigma_delta->completion);
|
||||
disable_irq_nosync(irq);
|
||||
sigma_delta->irq_dis = true;
|
||||
iio_trigger_poll(sigma_delta->trig);
|
||||
/*
|
||||
* AD7124 and a few others use the same physical line for interrupt
|
||||
* reporting (R̅D̅Y̅) and MISO.
|
||||
* As MISO toggles when reading a register, this likely results in a
|
||||
* pending interrupt. This has two consequences: a) The irq might
|
||||
* trigger immediately after it's enabled even though the conversion
|
||||
* isn't done yet; and b) checking the STATUS register's R̅D̅Y̅ flag is
|
||||
* off-limits as reading that would trigger another irq event.
|
||||
*
|
||||
* So read the MOSI line as GPIO (if available) and only trigger the irq
|
||||
* if the line is active. Without such a GPIO assume this is a valid
|
||||
* interrupt.
|
||||
*
|
||||
* Also as disable_irq_nosync() is used to disable the irq, only act if
|
||||
* the irq wasn't disabled before.
|
||||
*/
|
||||
if ((!sigma_delta->rdy_gpiod || gpiod_get_value(sigma_delta->rdy_gpiod)) &&
|
||||
ad_sd_disable_irq(sigma_delta)) {
|
||||
complete(&sigma_delta->completion);
|
||||
iio_trigger_poll(sigma_delta->trig);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -674,11 +799,24 @@ int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev,
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_init(&sigma_delta->irq_lock);
|
||||
|
||||
if (info->irq_line)
|
||||
sigma_delta->irq_line = info->irq_line;
|
||||
else
|
||||
sigma_delta->irq_line = spi->irq;
|
||||
|
||||
sigma_delta->rdy_gpiod = devm_gpiod_get_optional(&spi->dev, "rdy", GPIOD_IN);
|
||||
if (IS_ERR(sigma_delta->rdy_gpiod))
|
||||
return dev_err_probe(&spi->dev, PTR_ERR(sigma_delta->rdy_gpiod),
|
||||
"Failed to find rdy gpio\n");
|
||||
|
||||
if (sigma_delta->rdy_gpiod && !sigma_delta->irq_line) {
|
||||
sigma_delta->irq_line = gpiod_to_irq(sigma_delta->rdy_gpiod);
|
||||
if (sigma_delta->irq_line < 0)
|
||||
return sigma_delta->irq_line;
|
||||
}
|
||||
|
||||
iio_device_set_drvdata(indio_dev, sigma_delta);
|
||||
|
||||
return 0;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/iio/triggered_buffer.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
@ -67,6 +68,14 @@ enum pac1921_mxsl {
|
||||
#define PAC1921_DEFAULT_DI_GAIN 0 /* 2^(value): 1x gain (HW default) */
|
||||
#define PAC1921_DEFAULT_NUM_SAMPLES 0 /* 2^(value): 1 sample (HW default) */
|
||||
|
||||
#define PAC1921_ACPI_GET_uOHMS_VALS 0
|
||||
#define PAC1921_ACPI_GET_LABEL 1
|
||||
|
||||
/* f7bb9932-86ee-4516-a236-7a7a742e55cb */
|
||||
static const guid_t pac1921_guid =
|
||||
GUID_INIT(0xf7bb9932, 0x86ee, 0x4516, 0xa2,
|
||||
0x36, 0x7a, 0x7a, 0x74, 0x2e, 0x55, 0xcb);
|
||||
|
||||
/*
|
||||
* Pre-computed scale factors for BUS voltage
|
||||
* format: IIO_VAL_INT_PLUS_NANO
|
||||
@ -782,7 +791,7 @@ static ssize_t pac1921_write_shunt_resistor(struct iio_dev *indio_dev,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct pac1921_priv *priv = iio_priv(indio_dev);
|
||||
u64 rshunt_uohm;
|
||||
u32 rshunt_uohm;
|
||||
int val, val_fract;
|
||||
int ret;
|
||||
|
||||
@ -793,10 +802,17 @@ static ssize_t pac1921_write_shunt_resistor(struct iio_dev *indio_dev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rshunt_uohm = val * MICRO + val_fract;
|
||||
if (rshunt_uohm == 0 || rshunt_uohm > INT_MAX)
|
||||
/*
|
||||
* This check validates the shunt is not zero and does not surpass
|
||||
* INT_MAX. The check is done before calculating in order to avoid
|
||||
* val * MICRO overflowing.
|
||||
*/
|
||||
if ((!val && !val_fract) || val > INT_MAX / MICRO ||
|
||||
(val == INT_MAX / MICRO && val_fract > INT_MAX % MICRO))
|
||||
return -EINVAL;
|
||||
|
||||
rshunt_uohm = val * MICRO + val_fract;
|
||||
|
||||
guard(mutex)(&priv->lock);
|
||||
|
||||
priv->rshunt_uohm = rshunt_uohm;
|
||||
@ -1151,6 +1167,61 @@ static void pac1921_regulator_disable(void *data)
|
||||
regulator_disable(regulator);
|
||||
}
|
||||
|
||||
/*
|
||||
* Documentation related to the ACPI device definition
|
||||
* https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ApplicationNotes/ApplicationNotes/PAC193X-Integration-Notes-for-Microsoft-Windows-10-and-Windows-11-Driver-Support-DS00002534.pdf
|
||||
*/
|
||||
static int pac1921_match_acpi_device(struct iio_dev *indio_dev)
|
||||
{
|
||||
acpi_handle handle;
|
||||
union acpi_object *status;
|
||||
char *label;
|
||||
struct pac1921_priv *priv = iio_priv(indio_dev);
|
||||
struct device *dev = &priv->client->dev;
|
||||
|
||||
handle = ACPI_HANDLE(dev);
|
||||
|
||||
status = acpi_evaluate_dsm(handle, &pac1921_guid, 1,
|
||||
PAC1921_ACPI_GET_uOHMS_VALS, NULL);
|
||||
if (!status)
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"Could not read shunt from ACPI table\n");
|
||||
|
||||
priv->rshunt_uohm = status->package.elements[0].integer.value;
|
||||
ACPI_FREE(status);
|
||||
|
||||
status = acpi_evaluate_dsm(handle, &pac1921_guid, 1,
|
||||
PAC1921_ACPI_GET_LABEL, NULL);
|
||||
if (!status)
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"Could not read label from ACPI table\n");
|
||||
|
||||
label = devm_kstrdup(dev, status->package.elements[0].string.pointer,
|
||||
GFP_KERNEL);
|
||||
if (!label)
|
||||
return -ENOMEM;
|
||||
|
||||
indio_dev->label = label;
|
||||
ACPI_FREE(status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pac1921_parse_of_fw(struct iio_dev *indio_dev)
|
||||
{
|
||||
int ret;
|
||||
struct pac1921_priv *priv = iio_priv(indio_dev);
|
||||
struct device *dev = &priv->client->dev;
|
||||
|
||||
ret = device_property_read_u32(dev, "shunt-resistor-micro-ohms",
|
||||
&priv->rshunt_uohm);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"Cannot read shunt resistor property\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pac1921_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
@ -1179,11 +1250,14 @@ static int pac1921_probe(struct i2c_client *client)
|
||||
priv->di_gain = PAC1921_DEFAULT_DI_GAIN;
|
||||
priv->n_samples = PAC1921_DEFAULT_NUM_SAMPLES;
|
||||
|
||||
ret = device_property_read_u32(dev, "shunt-resistor-micro-ohms",
|
||||
&priv->rshunt_uohm);
|
||||
if (is_acpi_device_node(dev->fwnode))
|
||||
ret = pac1921_match_acpi_device(indio_dev);
|
||||
else
|
||||
ret = pac1921_parse_of_fw(indio_dev);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"Cannot read shunt resistor property\n");
|
||||
"Parameter parsing error\n");
|
||||
|
||||
if (priv->rshunt_uohm == 0 || priv->rshunt_uohm > INT_MAX)
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"Invalid shunt resistor: %u\n",
|
||||
@ -1246,11 +1320,18 @@ static const struct of_device_id pac1921_of_match[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pac1921_of_match);
|
||||
|
||||
static const struct acpi_device_id pac1921_acpi_match[] = {
|
||||
{ "MCHP1921" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, pac1921_acpi_match);
|
||||
|
||||
static struct i2c_driver pac1921_driver = {
|
||||
.driver = {
|
||||
.name = "pac1921",
|
||||
.pm = pm_sleep_ptr(&pac1921_pm_ops),
|
||||
.of_match_table = pac1921_of_match,
|
||||
.acpi_match_table = pac1921_acpi_match,
|
||||
},
|
||||
.probe = pac1921_probe,
|
||||
.id_table = pac1921_id,
|
||||
|
@ -8,12 +8,13 @@
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
@ -32,20 +33,15 @@
|
||||
#define RZG2L_ADM1_MS BIT(2)
|
||||
#define RZG2L_ADM1_BS BIT(4)
|
||||
#define RZG2L_ADM1_EGA_MASK GENMASK(13, 12)
|
||||
#define RZG2L_ADM2_CHSEL_MASK GENMASK(7, 0)
|
||||
#define RZG2L_ADM3_ADIL_MASK GENMASK(31, 24)
|
||||
#define RZG2L_ADM3_ADCMP_MASK GENMASK(23, 16)
|
||||
#define RZG2L_ADM3_ADCMP_E FIELD_PREP(RZG2L_ADM3_ADCMP_MASK, 0xe)
|
||||
#define RZG2L_ADM3_ADSMP_MASK GENMASK(15, 0)
|
||||
|
||||
#define RZG2L_ADINT 0x20
|
||||
#define RZG2L_ADINT_INTEN_MASK GENMASK(7, 0)
|
||||
#define RZG2L_ADINT_CSEEN BIT(16)
|
||||
#define RZG2L_ADINT_INTS BIT(31)
|
||||
|
||||
#define RZG2L_ADSTS 0x24
|
||||
#define RZG2L_ADSTS_CSEST BIT(16)
|
||||
#define RZG2L_ADSTS_INTST_MASK GENMASK(7, 0)
|
||||
|
||||
#define RZG2L_ADIVC 0x28
|
||||
#define RZG2L_ADIVC_DIVADC_MASK GENMASK(8, 0)
|
||||
@ -56,12 +52,28 @@
|
||||
#define RZG2L_ADCR(n) (0x30 + ((n) * 0x4))
|
||||
#define RZG2L_ADCR_AD_MASK GENMASK(11, 0)
|
||||
|
||||
#define RZG2L_ADSMP_DEFAULT_SAMPLING 0x578
|
||||
|
||||
#define RZG2L_ADC_MAX_CHANNELS 8
|
||||
#define RZG2L_ADC_CHN_MASK 0x7
|
||||
#define RZG2L_ADC_MAX_CHANNELS 9
|
||||
#define RZG2L_ADC_TIMEOUT usecs_to_jiffies(1 * 4)
|
||||
|
||||
/**
|
||||
* struct rzg2l_adc_hw_params - ADC hardware specific parameters
|
||||
* @default_adsmp: default ADC sampling period (see ADM3 register); index 0 is
|
||||
* used for voltage channels, index 1 is used for temperature channel
|
||||
* @adsmp_mask: ADC sampling period mask (see ADM3 register)
|
||||
* @adint_inten_mask: conversion end interrupt mask (see ADINT register)
|
||||
* @default_adcmp: default ADC cmp (see ADM3 register)
|
||||
* @num_channels: number of supported channels
|
||||
* @adivc: specifies if ADVIC register is available
|
||||
*/
|
||||
struct rzg2l_adc_hw_params {
|
||||
u16 default_adsmp[2];
|
||||
u16 adsmp_mask;
|
||||
u16 adint_inten_mask;
|
||||
u8 default_adcmp;
|
||||
u8 num_channels;
|
||||
bool adivc;
|
||||
};
|
||||
|
||||
struct rzg2l_adc_data {
|
||||
const struct iio_chan_spec *channels;
|
||||
u8 num_channels;
|
||||
@ -69,25 +81,36 @@ struct rzg2l_adc_data {
|
||||
|
||||
struct rzg2l_adc {
|
||||
void __iomem *base;
|
||||
struct clk *pclk;
|
||||
struct clk *adclk;
|
||||
struct reset_control *presetn;
|
||||
struct reset_control *adrstn;
|
||||
struct completion completion;
|
||||
const struct rzg2l_adc_data *data;
|
||||
const struct rzg2l_adc_hw_params *hw_params;
|
||||
struct completion completion;
|
||||
struct mutex lock;
|
||||
u16 last_val[RZG2L_ADC_MAX_CHANNELS];
|
||||
bool was_rpm_active;
|
||||
};
|
||||
|
||||
static const char * const rzg2l_adc_channel_name[] = {
|
||||
"adc0",
|
||||
"adc1",
|
||||
"adc2",
|
||||
"adc3",
|
||||
"adc4",
|
||||
"adc5",
|
||||
"adc6",
|
||||
"adc7",
|
||||
/**
|
||||
* struct rzg2l_adc_channel - ADC channel descriptor
|
||||
* @name: ADC channel name
|
||||
* @type: ADC channel type
|
||||
*/
|
||||
struct rzg2l_adc_channel {
|
||||
const char * const name;
|
||||
enum iio_chan_type type;
|
||||
};
|
||||
|
||||
static const struct rzg2l_adc_channel rzg2l_adc_channels[] = {
|
||||
{ "adc0", IIO_VOLTAGE },
|
||||
{ "adc1", IIO_VOLTAGE },
|
||||
{ "adc2", IIO_VOLTAGE },
|
||||
{ "adc3", IIO_VOLTAGE },
|
||||
{ "adc4", IIO_VOLTAGE },
|
||||
{ "adc5", IIO_VOLTAGE },
|
||||
{ "adc6", IIO_VOLTAGE },
|
||||
{ "adc7", IIO_VOLTAGE },
|
||||
{ "adc8", IIO_TEMP },
|
||||
};
|
||||
|
||||
static unsigned int rzg2l_adc_readl(struct rzg2l_adc *adc, u32 reg)
|
||||
@ -115,7 +138,7 @@ static void rzg2l_adc_pwr(struct rzg2l_adc *adc, bool on)
|
||||
|
||||
static void rzg2l_adc_start_stop(struct rzg2l_adc *adc, bool start)
|
||||
{
|
||||
int timeout = 5;
|
||||
int ret;
|
||||
u32 reg;
|
||||
|
||||
reg = rzg2l_adc_readl(adc, RZG2L_ADM(0));
|
||||
@ -128,15 +151,10 @@ static void rzg2l_adc_start_stop(struct rzg2l_adc *adc, bool start)
|
||||
if (start)
|
||||
return;
|
||||
|
||||
do {
|
||||
usleep_range(100, 200);
|
||||
reg = rzg2l_adc_readl(adc, RZG2L_ADM(0));
|
||||
timeout--;
|
||||
if (!timeout) {
|
||||
pr_err("%s stopping ADC timed out\n", __func__);
|
||||
break;
|
||||
}
|
||||
} while (((reg & RZG2L_ADM0_ADBSY) || (reg & RZG2L_ADM0_ADCE)));
|
||||
ret = read_poll_timeout(rzg2l_adc_readl, reg, !(reg & (RZG2L_ADM0_ADBSY | RZG2L_ADM0_ADCE)),
|
||||
200, 1000, true, adc, RZG2L_ADM(0));
|
||||
if (ret)
|
||||
pr_err("%s stopping ADC timed out\n", __func__);
|
||||
}
|
||||
|
||||
static void rzg2l_set_trigger(struct rzg2l_adc *adc)
|
||||
@ -158,8 +176,18 @@ static void rzg2l_set_trigger(struct rzg2l_adc *adc)
|
||||
rzg2l_adc_writel(adc, RZG2L_ADM(1), reg);
|
||||
}
|
||||
|
||||
static u8 rzg2l_adc_ch_to_adsmp_index(u8 ch)
|
||||
{
|
||||
if (rzg2l_adc_channels[ch].type == IIO_VOLTAGE)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rzg2l_adc_conversion_setup(struct rzg2l_adc *adc, u8 ch)
|
||||
{
|
||||
const struct rzg2l_adc_hw_params *hw_params = adc->hw_params;
|
||||
u8 index = rzg2l_adc_ch_to_adsmp_index(ch);
|
||||
u32 reg;
|
||||
|
||||
if (rzg2l_adc_readl(adc, RZG2L_ADM(0)) & RZG2L_ADM0_ADBSY)
|
||||
@ -169,10 +197,15 @@ static int rzg2l_adc_conversion_setup(struct rzg2l_adc *adc, u8 ch)
|
||||
|
||||
/* Select analog input channel subjected to conversion. */
|
||||
reg = rzg2l_adc_readl(adc, RZG2L_ADM(2));
|
||||
reg &= ~RZG2L_ADM2_CHSEL_MASK;
|
||||
reg &= ~GENMASK(hw_params->num_channels - 1, 0);
|
||||
reg |= BIT(ch);
|
||||
rzg2l_adc_writel(adc, RZG2L_ADM(2), reg);
|
||||
|
||||
reg = rzg2l_adc_readl(adc, RZG2L_ADM(3));
|
||||
reg &= ~hw_params->adsmp_mask;
|
||||
reg |= hw_params->default_adsmp[index];
|
||||
rzg2l_adc_writel(adc, RZG2L_ADM(3), reg);
|
||||
|
||||
/*
|
||||
* Setup ADINT
|
||||
* INTS[31] - Select pulse signal
|
||||
@ -181,36 +214,26 @@ static int rzg2l_adc_conversion_setup(struct rzg2l_adc *adc, u8 ch)
|
||||
*/
|
||||
reg = rzg2l_adc_readl(adc, RZG2L_ADINT);
|
||||
reg &= ~RZG2L_ADINT_INTS;
|
||||
reg &= ~RZG2L_ADINT_INTEN_MASK;
|
||||
reg &= ~hw_params->adint_inten_mask;
|
||||
reg |= (RZG2L_ADINT_CSEEN | BIT(ch));
|
||||
rzg2l_adc_writel(adc, RZG2L_ADINT, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rzg2l_adc_set_power(struct iio_dev *indio_dev, bool on)
|
||||
{
|
||||
struct device *dev = indio_dev->dev.parent;
|
||||
|
||||
if (on)
|
||||
return pm_runtime_resume_and_get(dev);
|
||||
|
||||
return pm_runtime_put_sync(dev);
|
||||
}
|
||||
|
||||
static int rzg2l_adc_conversion(struct iio_dev *indio_dev, struct rzg2l_adc *adc, u8 ch)
|
||||
{
|
||||
const struct rzg2l_adc_hw_params *hw_params = adc->hw_params;
|
||||
struct device *dev = indio_dev->dev.parent;
|
||||
int ret;
|
||||
|
||||
ret = rzg2l_adc_set_power(indio_dev, true);
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rzg2l_adc_conversion_setup(adc, ch);
|
||||
if (ret) {
|
||||
rzg2l_adc_set_power(indio_dev, false);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
goto rpm_put;
|
||||
|
||||
reinit_completion(&adc->completion);
|
||||
|
||||
@ -218,13 +241,16 @@ static int rzg2l_adc_conversion(struct iio_dev *indio_dev, struct rzg2l_adc *adc
|
||||
|
||||
if (!wait_for_completion_timeout(&adc->completion, RZG2L_ADC_TIMEOUT)) {
|
||||
rzg2l_adc_writel(adc, RZG2L_ADINT,
|
||||
rzg2l_adc_readl(adc, RZG2L_ADINT) & ~RZG2L_ADINT_INTEN_MASK);
|
||||
rzg2l_adc_start_stop(adc, false);
|
||||
rzg2l_adc_set_power(indio_dev, false);
|
||||
return -ETIMEDOUT;
|
||||
rzg2l_adc_readl(adc, RZG2L_ADINT) & ~hw_params->adint_inten_mask);
|
||||
ret = -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return rzg2l_adc_set_power(indio_dev, false);
|
||||
rzg2l_adc_start_stop(adc, false);
|
||||
|
||||
rpm_put:
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rzg2l_adc_read_raw(struct iio_dev *indio_dev,
|
||||
@ -233,24 +259,22 @@ static int rzg2l_adc_read_raw(struct iio_dev *indio_dev,
|
||||
{
|
||||
struct rzg2l_adc *adc = iio_priv(indio_dev);
|
||||
int ret;
|
||||
u8 ch;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
if (chan->type != IIO_VOLTAGE)
|
||||
case IIO_CHAN_INFO_RAW: {
|
||||
if (chan->type != IIO_VOLTAGE && chan->type != IIO_TEMP)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&adc->lock);
|
||||
ch = chan->channel & RZG2L_ADC_CHN_MASK;
|
||||
ret = rzg2l_adc_conversion(indio_dev, adc, ch);
|
||||
if (ret) {
|
||||
mutex_unlock(&adc->lock);
|
||||
guard(mutex)(&adc->lock);
|
||||
|
||||
ret = rzg2l_adc_conversion(indio_dev, adc, chan->channel);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
*val = adc->last_val[ch];
|
||||
mutex_unlock(&adc->lock);
|
||||
|
||||
*val = adc->last_val[chan->channel];
|
||||
|
||||
return IIO_VAL_INT;
|
||||
}
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -261,7 +285,7 @@ static int rzg2l_adc_read_label(struct iio_dev *iio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
char *label)
|
||||
{
|
||||
return sysfs_emit(label, "%s\n", rzg2l_adc_channel_name[chan->channel]);
|
||||
return sysfs_emit(label, "%s\n", rzg2l_adc_channels[chan->channel].name);
|
||||
}
|
||||
|
||||
static const struct iio_info rzg2l_adc_iio_info = {
|
||||
@ -272,6 +296,7 @@ static const struct iio_info rzg2l_adc_iio_info = {
|
||||
static irqreturn_t rzg2l_adc_isr(int irq, void *dev_id)
|
||||
{
|
||||
struct rzg2l_adc *adc = dev_id;
|
||||
const struct rzg2l_adc_hw_params *hw_params = adc->hw_params;
|
||||
unsigned long intst;
|
||||
u32 reg;
|
||||
int ch;
|
||||
@ -284,11 +309,11 @@ static irqreturn_t rzg2l_adc_isr(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
intst = reg & RZG2L_ADSTS_INTST_MASK;
|
||||
intst = reg & GENMASK(hw_params->num_channels - 1, 0);
|
||||
if (!intst)
|
||||
return IRQ_NONE;
|
||||
|
||||
for_each_set_bit(ch, &intst, RZG2L_ADC_MAX_CHANNELS)
|
||||
for_each_set_bit(ch, &intst, hw_params->num_channels)
|
||||
adc->last_val[ch] = rzg2l_adc_readl(adc, RZG2L_ADCR(ch)) & RZG2L_ADCR_AD_MASK;
|
||||
|
||||
/* clear the channel interrupt */
|
||||
@ -301,6 +326,7 @@ static irqreturn_t rzg2l_adc_isr(int irq, void *dev_id)
|
||||
|
||||
static int rzg2l_adc_parse_properties(struct platform_device *pdev, struct rzg2l_adc *adc)
|
||||
{
|
||||
const struct rzg2l_adc_hw_params *hw_params = adc->hw_params;
|
||||
struct iio_chan_spec *chan_array;
|
||||
struct rzg2l_adc_data *data;
|
||||
unsigned int channel;
|
||||
@ -313,15 +339,12 @@ static int rzg2l_adc_parse_properties(struct platform_device *pdev, struct rzg2l
|
||||
return -ENOMEM;
|
||||
|
||||
num_channels = device_get_child_node_count(&pdev->dev);
|
||||
if (!num_channels) {
|
||||
dev_err(&pdev->dev, "no channel children\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (!num_channels)
|
||||
return dev_err_probe(&pdev->dev, -ENODEV, "no channel children\n");
|
||||
|
||||
if (num_channels > RZG2L_ADC_MAX_CHANNELS) {
|
||||
dev_err(&pdev->dev, "num of channel children out of range\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (num_channels > hw_params->num_channels)
|
||||
return dev_err_probe(&pdev->dev, -EINVAL,
|
||||
"num of channel children out of range\n");
|
||||
|
||||
chan_array = devm_kcalloc(&pdev->dev, num_channels, sizeof(*chan_array),
|
||||
GFP_KERNEL);
|
||||
@ -334,14 +357,14 @@ static int rzg2l_adc_parse_properties(struct platform_device *pdev, struct rzg2l
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (channel >= RZG2L_ADC_MAX_CHANNELS)
|
||||
if (channel >= hw_params->num_channels)
|
||||
return -EINVAL;
|
||||
|
||||
chan_array[i].type = IIO_VOLTAGE;
|
||||
chan_array[i].type = rzg2l_adc_channels[channel].type;
|
||||
chan_array[i].indexed = 1;
|
||||
chan_array[i].channel = channel;
|
||||
chan_array[i].info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
|
||||
chan_array[i].datasheet_name = rzg2l_adc_channel_name[channel];
|
||||
chan_array[i].datasheet_name = rzg2l_adc_channels[channel].name;
|
||||
i++;
|
||||
}
|
||||
|
||||
@ -352,13 +375,13 @@ static int rzg2l_adc_parse_properties(struct platform_device *pdev, struct rzg2l
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rzg2l_adc_hw_init(struct rzg2l_adc *adc)
|
||||
static int rzg2l_adc_hw_init(struct device *dev, struct rzg2l_adc *adc)
|
||||
{
|
||||
int timeout = 5;
|
||||
const struct rzg2l_adc_hw_params *hw_params = adc->hw_params;
|
||||
u32 reg;
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(adc->pclk);
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -367,20 +390,18 @@ static int rzg2l_adc_hw_init(struct rzg2l_adc *adc)
|
||||
reg |= RZG2L_ADM0_SRESB;
|
||||
rzg2l_adc_writel(adc, RZG2L_ADM(0), reg);
|
||||
|
||||
while (!(rzg2l_adc_readl(adc, RZG2L_ADM(0)) & RZG2L_ADM0_SRESB)) {
|
||||
if (!timeout) {
|
||||
ret = -EBUSY;
|
||||
goto exit_hw_init;
|
||||
}
|
||||
timeout--;
|
||||
usleep_range(100, 200);
|
||||
}
|
||||
ret = read_poll_timeout(rzg2l_adc_readl, reg, reg & RZG2L_ADM0_SRESB,
|
||||
200, 1000, false, adc, RZG2L_ADM(0));
|
||||
if (ret)
|
||||
goto exit_hw_init;
|
||||
|
||||
/* Only division by 4 can be set */
|
||||
reg = rzg2l_adc_readl(adc, RZG2L_ADIVC);
|
||||
reg &= ~RZG2L_ADIVC_DIVADC_MASK;
|
||||
reg |= RZG2L_ADIVC_DIVADC_4;
|
||||
rzg2l_adc_writel(adc, RZG2L_ADIVC, reg);
|
||||
if (hw_params->adivc) {
|
||||
/* Only division by 4 can be set */
|
||||
reg = rzg2l_adc_readl(adc, RZG2L_ADIVC);
|
||||
reg &= ~RZG2L_ADIVC_DIVADC_MASK;
|
||||
reg |= RZG2L_ADIVC_DIVADC_4;
|
||||
rzg2l_adc_writel(adc, RZG2L_ADIVC, reg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup AMD3
|
||||
@ -391,35 +412,18 @@ static int rzg2l_adc_hw_init(struct rzg2l_adc *adc)
|
||||
reg = rzg2l_adc_readl(adc, RZG2L_ADM(3));
|
||||
reg &= ~RZG2L_ADM3_ADIL_MASK;
|
||||
reg &= ~RZG2L_ADM3_ADCMP_MASK;
|
||||
reg &= ~RZG2L_ADM3_ADSMP_MASK;
|
||||
reg |= (RZG2L_ADM3_ADCMP_E | RZG2L_ADSMP_DEFAULT_SAMPLING);
|
||||
reg &= ~hw_params->adsmp_mask;
|
||||
reg |= FIELD_PREP(RZG2L_ADM3_ADCMP_MASK, hw_params->default_adcmp) |
|
||||
hw_params->default_adsmp[0];
|
||||
|
||||
rzg2l_adc_writel(adc, RZG2L_ADM(3), reg);
|
||||
|
||||
exit_hw_init:
|
||||
clk_disable_unprepare(adc->pclk);
|
||||
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rzg2l_adc_pm_runtime_disable(void *data)
|
||||
{
|
||||
struct device *dev = data;
|
||||
|
||||
pm_runtime_disable(dev->parent);
|
||||
}
|
||||
|
||||
static void rzg2l_adc_pm_runtime_set_suspended(void *data)
|
||||
{
|
||||
struct device *dev = data;
|
||||
|
||||
pm_runtime_set_suspended(dev->parent);
|
||||
}
|
||||
|
||||
static void rzg2l_adc_reset_assert(void *data)
|
||||
{
|
||||
reset_control_assert(data);
|
||||
}
|
||||
|
||||
static int rzg2l_adc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@ -434,6 +438,10 @@ static int rzg2l_adc_probe(struct platform_device *pdev)
|
||||
|
||||
adc = iio_priv(indio_dev);
|
||||
|
||||
adc->hw_params = device_get_match_data(dev);
|
||||
if (!adc->hw_params || adc->hw_params->num_channels > RZG2L_ADC_MAX_CHANNELS)
|
||||
return -EINVAL;
|
||||
|
||||
ret = rzg2l_adc_parse_properties(pdev, adc);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -444,63 +452,28 @@ static int rzg2l_adc_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(adc->base))
|
||||
return PTR_ERR(adc->base);
|
||||
|
||||
adc->pclk = devm_clk_get(dev, "pclk");
|
||||
if (IS_ERR(adc->pclk)) {
|
||||
dev_err(dev, "Failed to get pclk");
|
||||
return PTR_ERR(adc->pclk);
|
||||
}
|
||||
adc->adrstn = devm_reset_control_get_exclusive_deasserted(dev, "adrst-n");
|
||||
if (IS_ERR(adc->adrstn))
|
||||
return dev_err_probe(dev, PTR_ERR(adc->adrstn),
|
||||
"failed to get/deassert adrst-n\n");
|
||||
|
||||
adc->adclk = devm_clk_get(dev, "adclk");
|
||||
if (IS_ERR(adc->adclk)) {
|
||||
dev_err(dev, "Failed to get adclk");
|
||||
return PTR_ERR(adc->adclk);
|
||||
}
|
||||
adc->presetn = devm_reset_control_get_exclusive_deasserted(dev, "presetn");
|
||||
if (IS_ERR(adc->presetn))
|
||||
return dev_err_probe(dev, PTR_ERR(adc->presetn),
|
||||
"failed to get/deassert presetn\n");
|
||||
|
||||
adc->adrstn = devm_reset_control_get_exclusive(dev, "adrst-n");
|
||||
if (IS_ERR(adc->adrstn)) {
|
||||
dev_err(dev, "failed to get adrstn\n");
|
||||
return PTR_ERR(adc->adrstn);
|
||||
}
|
||||
|
||||
adc->presetn = devm_reset_control_get_exclusive(dev, "presetn");
|
||||
if (IS_ERR(adc->presetn)) {
|
||||
dev_err(dev, "failed to get presetn\n");
|
||||
return PTR_ERR(adc->presetn);
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(adc->adrstn);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to deassert adrstn pin, %d\n", ret);
|
||||
pm_runtime_set_autosuspend_delay(dev, 300);
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
ret = devm_pm_runtime_enable(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_add_action_or_reset(&pdev->dev,
|
||||
rzg2l_adc_reset_assert, adc->adrstn);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register adrstn assert devm action, %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
platform_set_drvdata(pdev, indio_dev);
|
||||
|
||||
ret = reset_control_deassert(adc->presetn);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to deassert presetn pin, %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_add_action_or_reset(&pdev->dev,
|
||||
rzg2l_adc_reset_assert, adc->presetn);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register presetn assert devm action, %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rzg2l_adc_hw_init(adc);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to initialize ADC HW, %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = rzg2l_adc_hw_init(dev, adc);
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret,
|
||||
"failed to initialize ADC HW\n");
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
@ -513,72 +486,130 @@ static int rzg2l_adc_probe(struct platform_device *pdev)
|
||||
|
||||
init_completion(&adc->completion);
|
||||
|
||||
platform_set_drvdata(pdev, indio_dev);
|
||||
|
||||
indio_dev->name = DRIVER_NAME;
|
||||
indio_dev->info = &rzg2l_adc_iio_info;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->channels = adc->data->channels;
|
||||
indio_dev->num_channels = adc->data->num_channels;
|
||||
|
||||
pm_runtime_set_suspended(dev);
|
||||
ret = devm_add_action_or_reset(&pdev->dev,
|
||||
rzg2l_adc_pm_runtime_set_suspended, &indio_dev->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
ret = devm_add_action_or_reset(&pdev->dev,
|
||||
rzg2l_adc_pm_runtime_disable, &indio_dev->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return devm_iio_device_register(dev, indio_dev);
|
||||
}
|
||||
|
||||
static const struct rzg2l_adc_hw_params rzg2l_hw_params = {
|
||||
.num_channels = 8,
|
||||
.default_adcmp = 0xe,
|
||||
.default_adsmp = { 0x578 },
|
||||
.adsmp_mask = GENMASK(15, 0),
|
||||
.adint_inten_mask = GENMASK(7, 0),
|
||||
.adivc = true
|
||||
};
|
||||
|
||||
static const struct rzg2l_adc_hw_params rzg3s_hw_params = {
|
||||
.num_channels = 9,
|
||||
.default_adcmp = 0x1d,
|
||||
.default_adsmp = { 0x7f, 0xff },
|
||||
.adsmp_mask = GENMASK(7, 0),
|
||||
.adint_inten_mask = GENMASK(11, 0),
|
||||
};
|
||||
|
||||
static const struct of_device_id rzg2l_adc_match[] = {
|
||||
{ .compatible = "renesas,rzg2l-adc",},
|
||||
{ .compatible = "renesas,r9a08g045-adc", .data = &rzg3s_hw_params },
|
||||
{ .compatible = "renesas,rzg2l-adc", .data = &rzg2l_hw_params },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rzg2l_adc_match);
|
||||
|
||||
static int __maybe_unused rzg2l_adc_pm_runtime_suspend(struct device *dev)
|
||||
static int rzg2l_adc_pm_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct rzg2l_adc *adc = iio_priv(indio_dev);
|
||||
|
||||
rzg2l_adc_pwr(adc, false);
|
||||
clk_disable_unprepare(adc->adclk);
|
||||
clk_disable_unprepare(adc->pclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused rzg2l_adc_pm_runtime_resume(struct device *dev)
|
||||
static int rzg2l_adc_pm_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct rzg2l_adc *adc = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(adc->pclk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(adc->adclk);
|
||||
if (ret) {
|
||||
clk_disable_unprepare(adc->pclk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rzg2l_adc_pwr(adc, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rzg2l_adc_suspend(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct rzg2l_adc *adc = iio_priv(indio_dev);
|
||||
struct reset_control_bulk_data resets[] = {
|
||||
{ .rstc = adc->presetn },
|
||||
{ .rstc = adc->adrstn },
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (pm_runtime_suspended(dev)) {
|
||||
adc->was_rpm_active = false;
|
||||
} else {
|
||||
ret = pm_runtime_force_suspend(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
adc->was_rpm_active = true;
|
||||
}
|
||||
|
||||
ret = reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
|
||||
if (ret)
|
||||
goto rpm_restore;
|
||||
|
||||
return 0;
|
||||
|
||||
rpm_restore:
|
||||
if (adc->was_rpm_active)
|
||||
pm_runtime_force_resume(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rzg2l_adc_resume(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct rzg2l_adc *adc = iio_priv(indio_dev);
|
||||
struct reset_control_bulk_data resets[] = {
|
||||
{ .rstc = adc->adrstn },
|
||||
{ .rstc = adc->presetn },
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = reset_control_bulk_deassert(ARRAY_SIZE(resets), resets);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (adc->was_rpm_active) {
|
||||
ret = pm_runtime_force_resume(dev);
|
||||
if (ret)
|
||||
goto resets_restore;
|
||||
}
|
||||
|
||||
ret = rzg2l_adc_hw_init(dev, adc);
|
||||
if (ret)
|
||||
goto rpm_restore;
|
||||
|
||||
return 0;
|
||||
|
||||
rpm_restore:
|
||||
if (adc->was_rpm_active) {
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
}
|
||||
resets_restore:
|
||||
reset_control_bulk_assert(ARRAY_SIZE(resets), resets);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops rzg2l_adc_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(rzg2l_adc_pm_runtime_suspend,
|
||||
rzg2l_adc_pm_runtime_resume,
|
||||
NULL)
|
||||
RUNTIME_PM_OPS(rzg2l_adc_pm_runtime_suspend, rzg2l_adc_pm_runtime_resume, NULL)
|
||||
SYSTEM_SLEEP_PM_OPS(rzg2l_adc_suspend, rzg2l_adc_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver rzg2l_adc_driver = {
|
||||
@ -586,7 +617,7 @@ static struct platform_driver rzg2l_adc_driver = {
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.of_match_table = rzg2l_adc_match,
|
||||
.pm = &rzg2l_adc_pm_ops,
|
||||
.pm = pm_ptr(&rzg2l_adc_pm_ops),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -177,6 +177,10 @@ struct vf610_adc {
|
||||
} scan;
|
||||
};
|
||||
|
||||
struct vf610_chip_info {
|
||||
u8 num_channels;
|
||||
};
|
||||
|
||||
static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 };
|
||||
static const u32 vf610_lst_adder[] = { 3, 5, 7, 9, 13, 17, 21, 25 };
|
||||
|
||||
@ -808,14 +812,31 @@ static const struct iio_info vf610_adc_iio_info = {
|
||||
.attrs = &vf610_attribute_group,
|
||||
};
|
||||
|
||||
static const struct vf610_chip_info vf610_chip_info = {
|
||||
.num_channels = ARRAY_SIZE(vf610_adc_iio_channels),
|
||||
};
|
||||
|
||||
static const struct vf610_chip_info imx6sx_chip_info = {
|
||||
.num_channels = 4,
|
||||
};
|
||||
|
||||
static const struct of_device_id vf610_adc_match[] = {
|
||||
{ .compatible = "fsl,vf610-adc", },
|
||||
{ .compatible = "fsl,imx6sx-adc", .data = &imx6sx_chip_info},
|
||||
{ .compatible = "fsl,vf610-adc", .data = &vf610_chip_info},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, vf610_adc_match);
|
||||
|
||||
static void vf610_adc_action_remove(void *d)
|
||||
{
|
||||
struct vf610_adc *info = d;
|
||||
|
||||
regulator_disable(info->vref);
|
||||
}
|
||||
|
||||
static int vf610_adc_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct vf610_chip_info *chip_info;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct vf610_adc *info;
|
||||
struct iio_dev *indio_dev;
|
||||
@ -823,10 +844,8 @@ static int vf610_adc_probe(struct platform_device *pdev)
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct vf610_adc));
|
||||
if (!indio_dev) {
|
||||
dev_err(&pdev->dev, "Failed allocating iio device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (!indio_dev)
|
||||
return dev_err_probe(&pdev->dev, -ENOMEM, "Failed allocating iio device\n");
|
||||
|
||||
info = iio_priv(indio_dev);
|
||||
info->dev = &pdev->dev;
|
||||
@ -835,6 +854,8 @@ static int vf610_adc_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(info->regs))
|
||||
return PTR_ERR(info->regs);
|
||||
|
||||
chip_info = device_get_match_data(dev);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
@ -842,17 +863,12 @@ static int vf610_adc_probe(struct platform_device *pdev)
|
||||
ret = devm_request_irq(info->dev, irq,
|
||||
vf610_adc_isr, 0,
|
||||
dev_name(&pdev->dev), indio_dev);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed requesting irq, irq = %d\n", irq);
|
||||
return ret;
|
||||
}
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&pdev->dev, ret, "failed requesting irq, irq = %d\n", irq);
|
||||
|
||||
info->clk = devm_clk_get(&pdev->dev, "adc");
|
||||
if (IS_ERR(info->clk)) {
|
||||
dev_err(&pdev->dev, "failed getting clock, err = %ld\n",
|
||||
PTR_ERR(info->clk));
|
||||
return PTR_ERR(info->clk);
|
||||
}
|
||||
info->clk = devm_clk_get_enabled(&pdev->dev, "adc");
|
||||
if (IS_ERR(info->clk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(info->clk), "failed getting clock\n");
|
||||
|
||||
info->vref = devm_regulator_get(&pdev->dev, "vref");
|
||||
if (IS_ERR(info->vref))
|
||||
@ -862,6 +878,10 @@ static int vf610_adc_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(&pdev->dev, vf610_adc_action_remove, info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
info->vref_uv = regulator_get_voltage(info->vref);
|
||||
|
||||
device_property_read_u32_array(dev, "fsl,adck-max-frequency", info->max_adck_rate, 3);
|
||||
@ -877,54 +897,23 @@ static int vf610_adc_probe(struct platform_device *pdev)
|
||||
indio_dev->info = &vf610_adc_iio_info;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->channels = vf610_adc_iio_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(vf610_adc_iio_channels);
|
||||
|
||||
ret = clk_prepare_enable(info->clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Could not prepare or enable the clock.\n");
|
||||
goto error_adc_clk_enable;
|
||||
}
|
||||
indio_dev->num_channels = chip_info->num_channels;
|
||||
|
||||
vf610_adc_cfg_init(info);
|
||||
vf610_adc_hw_init(info);
|
||||
|
||||
ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
|
||||
NULL, &iio_triggered_buffer_setup_ops);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Couldn't initialise the buffer\n");
|
||||
goto error_iio_device_register;
|
||||
}
|
||||
ret = devm_iio_triggered_buffer_setup(&pdev->dev, indio_dev, &iio_pollfunc_store_time,
|
||||
NULL, &iio_triggered_buffer_setup_ops);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&pdev->dev, ret, "Couldn't initialise the buffer\n");
|
||||
|
||||
mutex_init(&info->lock);
|
||||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Couldn't register the device.\n");
|
||||
goto error_adc_buffer_init;
|
||||
}
|
||||
ret = devm_iio_device_register(&pdev->dev, indio_dev);
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret, "Couldn't register the device.\n");
|
||||
|
||||
return 0;
|
||||
|
||||
error_adc_buffer_init:
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
error_iio_device_register:
|
||||
clk_disable_unprepare(info->clk);
|
||||
error_adc_clk_enable:
|
||||
regulator_disable(info->vref);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
regulator_disable(info->vref);
|
||||
clk_disable_unprepare(info->clk);
|
||||
}
|
||||
|
||||
static int vf610_adc_suspend(struct device *dev)
|
||||
@ -972,7 +961,6 @@ 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,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.of_match_table = vf610_adc_match,
|
||||
|
@ -206,7 +206,7 @@ static const struct iio_dev_attr *iio_dmaengine_buffer_attrs[] = {
|
||||
|
||||
/**
|
||||
* iio_dmaengine_buffer_alloc() - Allocate new buffer which uses DMAengine
|
||||
* @dev: Parent device for the buffer
|
||||
* @dev: DMA channel consumer device
|
||||
* @channel: DMA channel name, typically "rx".
|
||||
*
|
||||
* This allocates a new IIO buffer which internally uses the DMAengine framework
|
||||
@ -288,6 +288,21 @@ void iio_dmaengine_buffer_free(struct iio_buffer *buffer)
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(iio_dmaengine_buffer_free, "IIO_DMAENGINE_BUFFER");
|
||||
|
||||
/**
|
||||
* iio_dmaengine_buffer_setup_ext() - Setup a DMA buffer for an IIO device
|
||||
* @dev: DMA channel consumer device
|
||||
* @indio_dev: IIO device to which to attach this buffer.
|
||||
* @channel: DMA channel name, typically "rx".
|
||||
* @dir: Direction of buffer (in or out)
|
||||
*
|
||||
* This allocates a new IIO buffer with devm_iio_dmaengine_buffer_alloc()
|
||||
* and attaches it to an IIO device with iio_device_attach_buffer().
|
||||
* It also appends the INDIO_BUFFER_HARDWARE mode to the supported modes of the
|
||||
* IIO device.
|
||||
*
|
||||
* Once done using the buffer iio_dmaengine_buffer_free() should be used to
|
||||
* release it.
|
||||
*/
|
||||
struct iio_buffer *iio_dmaengine_buffer_setup_ext(struct device *dev,
|
||||
struct iio_dev *indio_dev,
|
||||
const char *channel,
|
||||
@ -321,7 +336,7 @@ static void __devm_iio_dmaengine_buffer_free(void *buffer)
|
||||
|
||||
/**
|
||||
* devm_iio_dmaengine_buffer_setup_ext() - Setup a DMA buffer for an IIO device
|
||||
* @dev: Parent device for the buffer
|
||||
* @dev: Device for devm ownership and DMA channel consumer device
|
||||
* @indio_dev: IIO device to which to attach this buffer.
|
||||
* @channel: DMA channel name, typically "rx".
|
||||
* @dir: Direction of buffer (in or out)
|
||||
|
@ -2,6 +2,7 @@
|
||||
#ifndef BME680_H_
|
||||
#define BME680_H_
|
||||
|
||||
#include <linux/pm.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define BME680_REG_CHIP_ID 0xD0
|
||||
@ -80,6 +81,7 @@
|
||||
#define BME680_CALIB_RANGE_3_LEN 5
|
||||
|
||||
extern const struct regmap_config bme680_regmap_config;
|
||||
extern const struct dev_pm_ops bme680_dev_pm_ops;
|
||||
|
||||
int bme680_core_probe(struct device *dev, struct regmap *regmap,
|
||||
const char *name);
|
||||
|
@ -14,7 +14,10 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/iio.h>
|
||||
@ -111,6 +114,8 @@ enum bme680_scan {
|
||||
BME680_GAS,
|
||||
};
|
||||
|
||||
static const char *const bme680_supply_names[] = { "vdd", "vddio" };
|
||||
|
||||
struct bme680_data {
|
||||
struct regmap *regmap;
|
||||
struct bme680_calib bme680;
|
||||
@ -817,9 +822,9 @@ static int bme680_read_gas(struct bme680_data *data, int *comp_gas_res)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bme680_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val, int *val2, long mask)
|
||||
static int __bme680_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val, int *val2, long mask)
|
||||
{
|
||||
struct bme680_data *data = iio_priv(indio_dev);
|
||||
int chan_val, ret;
|
||||
@ -932,14 +937,33 @@ static int bme680_read_raw(struct iio_dev *indio_dev,
|
||||
}
|
||||
}
|
||||
|
||||
static int bme680_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val, int *val2, long mask)
|
||||
{
|
||||
struct bme680_data *data = iio_priv(indio_dev);
|
||||
struct device *dev = regmap_get_device(data->regmap);
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = __bme680_read_raw(indio_dev, chan, val, val2, mask);
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool bme680_is_valid_oversampling(int rate)
|
||||
{
|
||||
return (rate > 0 && rate <= 16 && is_power_of_2(rate));
|
||||
}
|
||||
|
||||
static int bme680_write_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int val, int val2, long mask)
|
||||
static int __bme680_write_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int val, int val2, long mask)
|
||||
{
|
||||
struct bme680_data *data = iio_priv(indio_dev);
|
||||
|
||||
@ -984,6 +1008,25 @@ static int bme680_write_raw(struct iio_dev *indio_dev,
|
||||
}
|
||||
}
|
||||
|
||||
static int bme680_write_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int val, int val2, long mask)
|
||||
{
|
||||
struct bme680_data *data = iio_priv(indio_dev);
|
||||
struct device *dev = regmap_get_device(data->regmap);
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = __bme680_write_raw(indio_dev, chan, val, val2, mask);
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char bme680_oversampling_ratio_show[] = "1 2 4 8 16";
|
||||
|
||||
static IIO_CONST_ATTR(oversampling_ratio_available,
|
||||
@ -1084,6 +1127,29 @@ static irqreturn_t bme680_trigger_handler(int irq, void *p)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int bme680_buffer_preenable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct bme680_data *data = iio_priv(indio_dev);
|
||||
struct device *dev = regmap_get_device(data->regmap);
|
||||
|
||||
return pm_runtime_resume_and_get(dev);
|
||||
}
|
||||
|
||||
static int bme680_buffer_postdisable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct bme680_data *data = iio_priv(indio_dev);
|
||||
struct device *dev = regmap_get_device(data->regmap);
|
||||
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct iio_buffer_setup_ops bme680_buffer_setup_ops = {
|
||||
.preenable = bme680_buffer_preenable,
|
||||
.postdisable = bme680_buffer_postdisable,
|
||||
};
|
||||
|
||||
int bme680_core_probe(struct device *dev, struct regmap *regmap,
|
||||
const char *name)
|
||||
{
|
||||
@ -1114,6 +1180,14 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap,
|
||||
data->heater_dur = 150; /* milliseconds */
|
||||
data->preheat_curr_mA = 0;
|
||||
|
||||
ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(bme680_supply_names),
|
||||
bme680_supply_names);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"failed to get and enable supplies.\n");
|
||||
|
||||
fsleep(BME680_STARTUP_TIME_US);
|
||||
|
||||
ret = regmap_write(regmap, BME680_REG_SOFT_RESET, BME680_CMD_SOFTRESET);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "Failed to reset chip\n");
|
||||
@ -1149,15 +1223,47 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap,
|
||||
ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
|
||||
iio_pollfunc_store_time,
|
||||
bme680_trigger_handler,
|
||||
NULL);
|
||||
&bme680_buffer_setup_ops);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"iio triggered buffer setup failed\n");
|
||||
|
||||
/* Enable runtime PM */
|
||||
pm_runtime_set_autosuspend_delay(dev, BME680_STARTUP_TIME_US);
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_set_active(dev);
|
||||
ret = devm_pm_runtime_enable(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return devm_iio_device_register(dev, indio_dev);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(bme680_core_probe, "IIO_BME680");
|
||||
|
||||
static int bme680_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct bme680_data *data = iio_priv(indio_dev);
|
||||
|
||||
return bme680_set_mode(data, BME680_MODE_SLEEP);
|
||||
}
|
||||
|
||||
static int bme680_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct bme680_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
ret = bme680_chip_config(data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return bme680_gas_config(data);
|
||||
}
|
||||
|
||||
EXPORT_RUNTIME_DEV_PM_OPS(bme680_dev_pm_ops, bme680_runtime_suspend,
|
||||
bme680_runtime_resume, NULL);
|
||||
|
||||
MODULE_AUTHOR("Himanshu Jha <himanshujha199640@gmail.com>");
|
||||
MODULE_DESCRIPTION("Bosch BME680 Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -51,6 +51,7 @@ static struct i2c_driver bme680_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "bme680_i2c",
|
||||
.of_match_table = bme680_of_i2c_match,
|
||||
.pm = pm_ptr(&bme680_dev_pm_ops),
|
||||
},
|
||||
.probe = bme680_i2c_probe,
|
||||
.id_table = bme680_i2c_id,
|
||||
|
@ -154,6 +154,7 @@ static struct spi_driver bme680_spi_driver = {
|
||||
.driver = {
|
||||
.name = "bme680_spi",
|
||||
.of_match_table = bme680_of_spi_match,
|
||||
.pm = pm_ptr(&bme680_dev_pm_ops),
|
||||
},
|
||||
.probe = bme680_spi_probe,
|
||||
.id_table = bme680_spi_id,
|
||||
|
@ -109,8 +109,8 @@ static bool inv_update_chip_period(struct inv_sensors_timestamp *ts,
|
||||
|
||||
static void inv_align_timestamp_it(struct inv_sensors_timestamp *ts)
|
||||
{
|
||||
const int64_t period_min = ts->min_period * ts->mult;
|
||||
const int64_t period_max = ts->max_period * ts->mult;
|
||||
const int64_t period_min = (int64_t)ts->min_period * ts->mult;
|
||||
const int64_t period_max = (int64_t)ts->max_period * ts->mult;
|
||||
int64_t add_max, sub_max;
|
||||
int64_t delta, jitter;
|
||||
int64_t adjust;
|
||||
|
@ -80,7 +80,7 @@ config AD5421
|
||||
depends on SPI
|
||||
help
|
||||
Say yes here to build support for Analog Devices AD5421 loop-powered
|
||||
digital-to-analog convertors (DAC).
|
||||
digital-to-analog converters (DAC).
|
||||
|
||||
To compile this driver as module choose M here: the module will be called
|
||||
ad5421.
|
||||
|
@ -41,7 +41,7 @@ struct ad5624r_chip_info {
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ad5446_state - driver instance specific data
|
||||
* struct ad5624r_state - driver instance specific data
|
||||
* @indio_dev: the industrial I/O device
|
||||
* @us: spi_device
|
||||
* @chip_info: chip model specific constants, available modes etc
|
||||
|
@ -95,11 +95,6 @@ static int ad5686_spi_probe(struct spi_device *spi)
|
||||
ad5686_spi_write, ad5686_spi_read);
|
||||
}
|
||||
|
||||
static void ad5686_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
ad5686_remove(&spi->dev);
|
||||
}
|
||||
|
||||
static const struct spi_device_id ad5686_spi_id[] = {
|
||||
{"ad5310r", ID_AD5310R},
|
||||
{"ad5672r", ID_AD5672R},
|
||||
@ -126,7 +121,6 @@ static struct spi_driver ad5686_spi_driver = {
|
||||
.name = "ad5686",
|
||||
},
|
||||
.probe = ad5686_spi_probe,
|
||||
.remove = ad5686_spi_remove,
|
||||
.id_table = ad5686_spi_id,
|
||||
};
|
||||
|
||||
|
@ -455,39 +455,28 @@ int ad5686_probe(struct device *dev,
|
||||
struct ad5686_state *st;
|
||||
struct iio_dev *indio_dev;
|
||||
unsigned int val, ref_bit_msk;
|
||||
bool has_external_vref;
|
||||
u8 cmd;
|
||||
int ret, i, voltage_uv = 0;
|
||||
int ret, i;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
dev_set_drvdata(dev, indio_dev);
|
||||
|
||||
st->dev = dev;
|
||||
st->write = write;
|
||||
st->read = read;
|
||||
|
||||
st->reg = devm_regulator_get_optional(dev, "vcc");
|
||||
if (!IS_ERR(st->reg)) {
|
||||
ret = regulator_enable(st->reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regulator_get_voltage(st->reg);
|
||||
if (ret < 0)
|
||||
goto error_disable_reg;
|
||||
|
||||
voltage_uv = ret;
|
||||
}
|
||||
|
||||
st->chip_info = &ad5686_chip_info_tbl[chip_type];
|
||||
|
||||
if (voltage_uv)
|
||||
st->vref_mv = voltage_uv / 1000;
|
||||
else
|
||||
st->vref_mv = st->chip_info->int_vref_mv;
|
||||
ret = devm_regulator_get_enable_read_voltage(dev, "vcc");
|
||||
if (ret < 0 && ret != -ENODEV)
|
||||
return ret;
|
||||
|
||||
has_external_vref = ret != -ENODEV;
|
||||
st->vref_mv = has_external_vref ? ret / 1000 : st->chip_info->int_vref_mv;
|
||||
|
||||
/* Set all the power down mode for all channels to 1K pulldown */
|
||||
for (i = 0; i < st->chip_info->num_channels; i++)
|
||||
@ -505,12 +494,12 @@ int ad5686_probe(struct device *dev,
|
||||
case AD5310_REGMAP:
|
||||
cmd = AD5686_CMD_CONTROL_REG;
|
||||
ref_bit_msk = AD5310_REF_BIT_MSK;
|
||||
st->use_internal_vref = !voltage_uv;
|
||||
st->use_internal_vref = !has_external_vref;
|
||||
break;
|
||||
case AD5683_REGMAP:
|
||||
cmd = AD5686_CMD_CONTROL_REG;
|
||||
ref_bit_msk = AD5683_REF_BIT_MSK;
|
||||
st->use_internal_vref = !voltage_uv;
|
||||
st->use_internal_vref = !has_external_vref;
|
||||
break;
|
||||
case AD5686_REGMAP:
|
||||
cmd = AD5686_CMD_INTERNAL_REFER_SETUP;
|
||||
@ -519,43 +508,22 @@ int ad5686_probe(struct device *dev,
|
||||
case AD5693_REGMAP:
|
||||
cmd = AD5686_CMD_CONTROL_REG;
|
||||
ref_bit_msk = AD5693_REF_BIT_MSK;
|
||||
st->use_internal_vref = !voltage_uv;
|
||||
st->use_internal_vref = !has_external_vref;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto error_disable_reg;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
val = (voltage_uv | ref_bit_msk);
|
||||
val = (has_external_vref | ref_bit_msk);
|
||||
|
||||
ret = st->write(st, cmd, 0, !!val);
|
||||
if (ret)
|
||||
goto error_disable_reg;
|
||||
return ret;
|
||||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret)
|
||||
goto error_disable_reg;
|
||||
|
||||
return 0;
|
||||
|
||||
error_disable_reg:
|
||||
if (!IS_ERR(st->reg))
|
||||
regulator_disable(st->reg);
|
||||
return ret;
|
||||
return devm_iio_device_register(dev, indio_dev);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(ad5686_probe, "IIO_AD5686");
|
||||
|
||||
void ad5686_remove(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct ad5686_state *st = iio_priv(indio_dev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
if (!IS_ERR(st->reg))
|
||||
regulator_disable(st->reg);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(ad5686_remove, "IIO_AD5686");
|
||||
|
||||
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
|
||||
MODULE_DESCRIPTION("Analog Devices AD5686/85/84 DAC");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -115,10 +115,9 @@ struct ad5686_chip_info {
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ad5446_state - driver instance specific data
|
||||
* struct ad5686_state - driver instance specific data
|
||||
* @spi: spi_device
|
||||
* @chip_info: chip model specific constants, available modes etc
|
||||
* @reg: supply regulator
|
||||
* @vref_mv: actual reference voltage used
|
||||
* @pwr_down_mask: power down mask
|
||||
* @pwr_down_mode: current power down mode
|
||||
@ -130,7 +129,6 @@ struct ad5686_chip_info {
|
||||
struct ad5686_state {
|
||||
struct device *dev;
|
||||
const struct ad5686_chip_info *chip_info;
|
||||
struct regulator *reg;
|
||||
unsigned short vref_mv;
|
||||
unsigned int pwr_down_mask;
|
||||
unsigned int pwr_down_mode;
|
||||
@ -157,7 +155,5 @@ int ad5686_probe(struct device *dev,
|
||||
const char *name, ad5686_write_func write,
|
||||
ad5686_read_func read);
|
||||
|
||||
void ad5686_remove(struct device *dev);
|
||||
|
||||
|
||||
#endif /* __DRIVERS_IIO_DAC_AD5686_H__ */
|
||||
|
@ -65,11 +65,6 @@ static int ad5686_i2c_probe(struct i2c_client *i2c)
|
||||
ad5686_i2c_write, ad5686_i2c_read);
|
||||
}
|
||||
|
||||
static void ad5686_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
ad5686_remove(&i2c->dev);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id ad5686_i2c_id[] = {
|
||||
{"ad5311r", ID_AD5311R},
|
||||
{"ad5337r", ID_AD5337R},
|
||||
@ -116,7 +111,6 @@ static struct i2c_driver ad5686_i2c_driver = {
|
||||
.of_match_table = ad5686_of_match,
|
||||
},
|
||||
.probe = ad5686_i2c_probe,
|
||||
.remove = ad5686_i2c_remove,
|
||||
.id_table = ad5686_i2c_id,
|
||||
};
|
||||
|
||||
|
@ -23,8 +23,6 @@ struct ad8801_state {
|
||||
unsigned char dac_cache[8]; /* Value write on each channel */
|
||||
unsigned int vrefh_mv;
|
||||
unsigned int vrefl_mv;
|
||||
struct regulator *vrefh_reg;
|
||||
struct regulator *vrefl_reg;
|
||||
|
||||
__be16 data __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
@ -122,86 +120,34 @@ static int ad8801_probe(struct spi_device *spi)
|
||||
state->spi = spi;
|
||||
id = spi_get_device_id(spi);
|
||||
|
||||
state->vrefh_reg = devm_regulator_get(&spi->dev, "vrefh");
|
||||
if (IS_ERR(state->vrefh_reg))
|
||||
return dev_err_probe(&spi->dev, PTR_ERR(state->vrefh_reg),
|
||||
"Vrefh regulator not specified\n");
|
||||
ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vrefh");
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&spi->dev, ret,
|
||||
"failed to get Vrefh voltage\n");
|
||||
|
||||
ret = regulator_enable(state->vrefh_reg);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Failed to enable vrefh regulator: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regulator_get_voltage(state->vrefh_reg);
|
||||
if (ret < 0) {
|
||||
dev_err(&spi->dev, "Failed to read vrefh regulator: %d\n",
|
||||
ret);
|
||||
goto error_disable_vrefh_reg;
|
||||
}
|
||||
state->vrefh_mv = ret / 1000;
|
||||
|
||||
if (id->driver_data == ID_AD8803) {
|
||||
state->vrefl_reg = devm_regulator_get(&spi->dev, "vrefl");
|
||||
if (IS_ERR(state->vrefl_reg)) {
|
||||
ret = dev_err_probe(&spi->dev, PTR_ERR(state->vrefl_reg),
|
||||
"Vrefl regulator not specified\n");
|
||||
goto error_disable_vrefh_reg;
|
||||
}
|
||||
ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vrefl");
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&spi->dev, ret,
|
||||
"failed to get Vrefl voltage\n");
|
||||
|
||||
ret = regulator_enable(state->vrefl_reg);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Failed to enable vrefl regulator: %d\n",
|
||||
ret);
|
||||
goto error_disable_vrefh_reg;
|
||||
}
|
||||
|
||||
ret = regulator_get_voltage(state->vrefl_reg);
|
||||
if (ret < 0) {
|
||||
dev_err(&spi->dev, "Failed to read vrefl regulator: %d\n",
|
||||
ret);
|
||||
goto error_disable_vrefl_reg;
|
||||
}
|
||||
state->vrefl_mv = ret / 1000;
|
||||
} else {
|
||||
state->vrefl_mv = 0;
|
||||
state->vrefl_reg = NULL;
|
||||
}
|
||||
|
||||
spi_set_drvdata(spi, indio_dev);
|
||||
indio_dev->info = &ad8801_info;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->channels = ad8801_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(ad8801_channels);
|
||||
indio_dev->name = id->name;
|
||||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Failed to register iio device: %d\n",
|
||||
ret);
|
||||
goto error_disable_vrefl_reg;
|
||||
}
|
||||
ret = devm_iio_device_register(&spi->dev, indio_dev);
|
||||
if (ret)
|
||||
return dev_err_probe(&spi->dev, ret,
|
||||
"Failed to register iio device\n");
|
||||
|
||||
return 0;
|
||||
|
||||
error_disable_vrefl_reg:
|
||||
if (state->vrefl_reg)
|
||||
regulator_disable(state->vrefl_reg);
|
||||
error_disable_vrefh_reg:
|
||||
regulator_disable(state->vrefh_reg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ad8801_remove(struct spi_device *spi)
|
||||
{
|
||||
struct iio_dev *indio_dev = spi_get_drvdata(spi);
|
||||
struct ad8801_state *state = iio_priv(indio_dev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
if (state->vrefl_reg)
|
||||
regulator_disable(state->vrefl_reg);
|
||||
regulator_disable(state->vrefh_reg);
|
||||
}
|
||||
|
||||
static const struct spi_device_id ad8801_ids[] = {
|
||||
@ -216,7 +162,6 @@ static struct spi_driver ad8801_driver = {
|
||||
.name = "ad8801",
|
||||
},
|
||||
.probe = ad8801_probe,
|
||||
.remove = ad8801_remove,
|
||||
.id_table = ad8801_ids,
|
||||
};
|
||||
module_spi_driver(ad8801_driver);
|
||||
|
@ -41,13 +41,11 @@ struct ltc2632_chip_info {
|
||||
* @spi_dev: pointer to the spi_device struct
|
||||
* @powerdown_cache_mask: used to show current channel powerdown state
|
||||
* @vref_mv: used reference voltage (internal or external)
|
||||
* @vref_reg: regulator for the reference voltage
|
||||
*/
|
||||
struct ltc2632_state {
|
||||
struct spi_device *spi_dev;
|
||||
unsigned int powerdown_cache_mask;
|
||||
int vref_mv;
|
||||
struct regulator *vref_reg;
|
||||
};
|
||||
|
||||
enum ltc2632_supported_device_ids {
|
||||
@ -310,6 +308,7 @@ static int ltc2632_probe(struct spi_device *spi)
|
||||
struct ltc2632_state *st;
|
||||
struct iio_dev *indio_dev;
|
||||
struct ltc2632_chip_info *chip_info;
|
||||
bool has_external_vref;
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
@ -318,49 +317,31 @@ static int ltc2632_probe(struct spi_device *spi)
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
|
||||
spi_set_drvdata(spi, indio_dev);
|
||||
st->spi_dev = spi;
|
||||
|
||||
chip_info = (struct ltc2632_chip_info *)
|
||||
spi_get_device_id(spi)->driver_data;
|
||||
|
||||
st->vref_reg = devm_regulator_get_optional(&spi->dev, "vref");
|
||||
if (PTR_ERR(st->vref_reg) == -ENODEV) {
|
||||
/* use internal reference voltage */
|
||||
st->vref_reg = NULL;
|
||||
st->vref_mv = chip_info->vref_mv;
|
||||
ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref");
|
||||
if (ret < 0 && ret != -ENODEV)
|
||||
return dev_err_probe(&spi->dev, ret,
|
||||
"Failed to get vref regulator voltage\n");
|
||||
|
||||
ret = ltc2632_spi_write(spi, LTC2632_CMD_INTERNAL_REFER,
|
||||
0, 0, 0);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev,
|
||||
"Set internal reference command failed, %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
} else if (IS_ERR(st->vref_reg)) {
|
||||
dev_err(&spi->dev,
|
||||
"Error getting voltage reference regulator\n");
|
||||
return PTR_ERR(st->vref_reg);
|
||||
} else {
|
||||
/* use external reference voltage */
|
||||
ret = regulator_enable(st->vref_reg);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev,
|
||||
"enable reference regulator failed, %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
st->vref_mv = regulator_get_voltage(st->vref_reg) / 1000;
|
||||
has_external_vref = ret != -ENODEV;
|
||||
st->vref_mv = has_external_vref ? ret / 1000 : chip_info->vref_mv;
|
||||
|
||||
if (has_external_vref) {
|
||||
ret = ltc2632_spi_write(spi, LTC2632_CMD_EXTERNAL_REFER,
|
||||
0, 0, 0);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev,
|
||||
"Set external reference command failed, %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
0, 0, 0);
|
||||
if (ret)
|
||||
return dev_err_probe(&spi->dev, ret,
|
||||
"Set external reference command failed\n");
|
||||
} else {
|
||||
ret = ltc2632_spi_write(spi, LTC2632_CMD_INTERNAL_REFER,
|
||||
0, 0, 0);
|
||||
if (ret)
|
||||
return dev_err_probe(&spi->dev, ret,
|
||||
"Set internal reference command failed\n");
|
||||
}
|
||||
|
||||
indio_dev->name = fwnode_get_name(dev_fwnode(&spi->dev)) ?: spi_get_device_id(spi)->name;
|
||||
@ -369,18 +350,7 @@ static int ltc2632_probe(struct spi_device *spi)
|
||||
indio_dev->channels = chip_info->channels;
|
||||
indio_dev->num_channels = chip_info->num_channels;
|
||||
|
||||
return iio_device_register(indio_dev);
|
||||
}
|
||||
|
||||
static void ltc2632_remove(struct spi_device *spi)
|
||||
{
|
||||
struct iio_dev *indio_dev = spi_get_drvdata(spi);
|
||||
struct ltc2632_state *st = iio_priv(indio_dev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
|
||||
if (st->vref_reg)
|
||||
regulator_disable(st->vref_reg);
|
||||
return devm_iio_device_register(&spi->dev, indio_dev);
|
||||
}
|
||||
|
||||
static const struct spi_device_id ltc2632_id[] = {
|
||||
@ -472,7 +442,6 @@ static struct spi_driver ltc2632_driver = {
|
||||
.of_match_table = ltc2632_of_match,
|
||||
},
|
||||
.probe = ltc2632_probe,
|
||||
.remove = ltc2632_remove,
|
||||
.id_table = ltc2632_id,
|
||||
};
|
||||
module_spi_driver(ltc2632_driver);
|
||||
|
@ -842,7 +842,7 @@ static int ltc2688_channel_config(struct ltc2688_state *st)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ltc2688_setup(struct ltc2688_state *st, struct regulator *vref)
|
||||
static int ltc2688_setup(struct ltc2688_state *st, bool has_external_vref)
|
||||
{
|
||||
struct device *dev = &st->spi->dev;
|
||||
struct gpio_desc *gpio;
|
||||
@ -881,18 +881,13 @@ static int ltc2688_setup(struct ltc2688_state *st, struct regulator *vref)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!vref)
|
||||
if (!has_external_vref)
|
||||
return 0;
|
||||
|
||||
return regmap_set_bits(st->regmap, LTC2688_CMD_CONFIG,
|
||||
LTC2688_CONFIG_EXT_REF);
|
||||
}
|
||||
|
||||
static void ltc2688_disable_regulator(void *regulator)
|
||||
{
|
||||
regulator_disable(regulator);
|
||||
}
|
||||
|
||||
static bool ltc2688_reg_readable(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
@ -947,8 +942,8 @@ static int ltc2688_probe(struct spi_device *spi)
|
||||
static const char * const regulators[] = { "vcc", "iovcc" };
|
||||
struct ltc2688_state *st;
|
||||
struct iio_dev *indio_dev;
|
||||
struct regulator *vref_reg;
|
||||
struct device *dev = &spi->dev;
|
||||
bool has_external_vref;
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
|
||||
@ -973,34 +968,15 @@ static int ltc2688_probe(struct spi_device *spi)
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to enable regulators\n");
|
||||
|
||||
vref_reg = devm_regulator_get_optional(dev, "vref");
|
||||
if (IS_ERR(vref_reg)) {
|
||||
if (PTR_ERR(vref_reg) != -ENODEV)
|
||||
return dev_err_probe(dev, PTR_ERR(vref_reg),
|
||||
"Failed to get vref regulator");
|
||||
ret = devm_regulator_get_enable_read_voltage(dev, "vref");
|
||||
if (ret < 0 && ret != -ENODEV)
|
||||
return dev_err_probe(dev, ret,
|
||||
"Failed to get vref regulator voltage\n");
|
||||
|
||||
vref_reg = NULL;
|
||||
/* internal reference */
|
||||
st->vref = 4096;
|
||||
} else {
|
||||
ret = regulator_enable(vref_reg);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"Failed to enable vref regulators\n");
|
||||
has_external_vref = ret != -ENODEV;
|
||||
st->vref = has_external_vref ? ret / 1000 : 0;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, ltc2688_disable_regulator,
|
||||
vref_reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regulator_get_voltage(vref_reg);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "Failed to get vref\n");
|
||||
|
||||
st->vref = ret / 1000;
|
||||
}
|
||||
|
||||
ret = ltc2688_setup(st, vref_reg);
|
||||
ret = ltc2688_setup(st, has_external_vref);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -32,7 +32,6 @@ enum max5821_device_ids {
|
||||
|
||||
struct max5821_data {
|
||||
struct i2c_client *client;
|
||||
struct regulator *vref_reg;
|
||||
unsigned short vref_mv;
|
||||
bool powerdown[MAX5821_MAX_DAC_CHANNELS];
|
||||
u8 powerdown_mode[MAX5821_MAX_DAC_CHANNELS];
|
||||
@ -295,11 +294,6 @@ static const struct iio_info max5821_info = {
|
||||
.write_raw = max5821_write_raw,
|
||||
};
|
||||
|
||||
static void max5821_regulator_disable(void *reg)
|
||||
{
|
||||
regulator_disable(reg);
|
||||
}
|
||||
|
||||
static int max5821_probe(struct i2c_client *client)
|
||||
{
|
||||
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||
@ -321,32 +315,10 @@ static int max5821_probe(struct i2c_client *client)
|
||||
data->powerdown_mode[tmp] = MAX5821_100KOHM_TO_GND;
|
||||
}
|
||||
|
||||
data->vref_reg = devm_regulator_get(&client->dev, "vref");
|
||||
if (IS_ERR(data->vref_reg))
|
||||
return dev_err_probe(&client->dev, PTR_ERR(data->vref_reg),
|
||||
"Failed to get vref regulator\n");
|
||||
|
||||
ret = regulator_enable(data->vref_reg);
|
||||
if (ret) {
|
||||
dev_err(&client->dev,
|
||||
"Failed to enable vref regulator: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_add_action_or_reset(&client->dev, max5821_regulator_disable,
|
||||
data->vref_reg);
|
||||
if (ret) {
|
||||
dev_err(&client->dev,
|
||||
"Failed to add action to managed regulator: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regulator_get_voltage(data->vref_reg);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev,
|
||||
"Failed to get voltage on regulator: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = devm_regulator_get_enable_read_voltage(&client->dev, "vref");
|
||||
if (ret)
|
||||
return dev_err_probe(&client->dev, ret,
|
||||
"Failed to get vref regulator voltage\n");
|
||||
|
||||
data->vref_mv = ret / 1000;
|
||||
|
||||
|
@ -379,7 +379,7 @@ static int mcp4725_probe_dt(struct device *dev,
|
||||
struct mcp4725_platform_data *pdata)
|
||||
{
|
||||
/* check if is the vref-supply defined */
|
||||
pdata->use_vref = device_property_read_bool(dev, "vref-supply");
|
||||
pdata->use_vref = device_property_present(dev, "vref-supply");
|
||||
pdata->vref_buffered =
|
||||
device_property_read_bool(dev, "microchip,vref-buffered");
|
||||
|
||||
|
@ -878,11 +878,32 @@ static const struct iio_chan_spec adis16545_channels[] = {
|
||||
IIO_CHAN_SOFT_TIMESTAMP(17),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec adis16489_channels[] = {
|
||||
ADIS16480_GYRO_CHANNEL(X),
|
||||
ADIS16480_GYRO_CHANNEL(Y),
|
||||
ADIS16480_GYRO_CHANNEL(Z),
|
||||
ADIS16480_ACCEL_CHANNEL(X),
|
||||
ADIS16480_ACCEL_CHANNEL(Y),
|
||||
ADIS16480_ACCEL_CHANNEL(Z),
|
||||
ADIS16480_PRESSURE_CHANNEL(),
|
||||
ADIS16480_TEMP_CHANNEL(),
|
||||
IIO_CHAN_SOFT_TIMESTAMP(8),
|
||||
ADIS16480_DELTANG_CHANNEL_NO_SCAN(X),
|
||||
ADIS16480_DELTANG_CHANNEL_NO_SCAN(Y),
|
||||
ADIS16480_DELTANG_CHANNEL_NO_SCAN(Z),
|
||||
ADIS16480_DELTVEL_CHANNEL_NO_SCAN(X),
|
||||
ADIS16480_DELTVEL_CHANNEL_NO_SCAN(Y),
|
||||
ADIS16480_DELTVEL_CHANNEL_NO_SCAN(Z),
|
||||
};
|
||||
|
||||
enum adis16480_variant {
|
||||
ADIS16375,
|
||||
ADIS16480,
|
||||
ADIS16485,
|
||||
ADIS16486,
|
||||
ADIS16487,
|
||||
ADIS16488,
|
||||
ADIS16489,
|
||||
ADIS16490,
|
||||
ADIS16495_1,
|
||||
ADIS16495_2,
|
||||
@ -1038,6 +1059,38 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
|
||||
.filter_freqs = adis16480_def_filter_freqs,
|
||||
.adis_data = ADIS16480_DATA(16485, &adis16485_timeouts, 0, 0),
|
||||
},
|
||||
[ADIS16486] = {
|
||||
.channels = adis16485_channels,
|
||||
.num_channels = ARRAY_SIZE(adis16485_channels),
|
||||
.gyro_max_val = 22500 << 16,
|
||||
.gyro_max_scale = IIO_DEGREE_TO_RAD(450),
|
||||
.accel_max_val = IIO_M_S_2_TO_G(20000 << 16),
|
||||
.accel_max_scale = 18,
|
||||
.temp_scale = 5650, /* 5.65 milli degree Celsius */
|
||||
.deltang_max_val = IIO_DEGREE_TO_RAD(720),
|
||||
.deltvel_max_val = 200,
|
||||
.int_clk = 2460000,
|
||||
.max_dec_rate = 2048,
|
||||
.has_sleep_cnt = true,
|
||||
.filter_freqs = adis16480_def_filter_freqs,
|
||||
.adis_data = ADIS16480_DATA(16486, &adis16480_timeouts, 0, 0),
|
||||
},
|
||||
[ADIS16487] = {
|
||||
.channels = adis16485_channels,
|
||||
.num_channels = ARRAY_SIZE(adis16485_channels),
|
||||
.gyro_max_val = 22500 << 16,
|
||||
.gyro_max_scale = IIO_DEGREE_TO_RAD(450),
|
||||
.accel_max_val = IIO_M_S_2_TO_G(20000 << 16),
|
||||
.accel_max_scale = 5,
|
||||
.temp_scale = 5650, /* 5.65 milli degree Celsius */
|
||||
.deltang_max_val = IIO_DEGREE_TO_RAD(720),
|
||||
.deltvel_max_val = 50,
|
||||
.int_clk = 2460000,
|
||||
.max_dec_rate = 2048,
|
||||
.has_sleep_cnt = true,
|
||||
.filter_freqs = adis16480_def_filter_freqs,
|
||||
.adis_data = ADIS16480_DATA(16487, &adis16485_timeouts, 0, 0),
|
||||
},
|
||||
[ADIS16488] = {
|
||||
.channels = adis16480_channels,
|
||||
.num_channels = ARRAY_SIZE(adis16480_channels),
|
||||
@ -1054,6 +1107,22 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
|
||||
.filter_freqs = adis16480_def_filter_freqs,
|
||||
.adis_data = ADIS16480_DATA(16488, &adis16485_timeouts, 0, 0),
|
||||
},
|
||||
[ADIS16489] = {
|
||||
.channels = adis16489_channels,
|
||||
.num_channels = ARRAY_SIZE(adis16489_channels),
|
||||
.gyro_max_val = 22500 << 16,
|
||||
.gyro_max_scale = IIO_DEGREE_TO_RAD(450),
|
||||
.accel_max_val = IIO_M_S_2_TO_G(20000 << 16),
|
||||
.accel_max_scale = 18,
|
||||
.temp_scale = 5650, /* 5.65 milli degree Celsius */
|
||||
.deltang_max_val = IIO_DEGREE_TO_RAD(720),
|
||||
.deltvel_max_val = 200,
|
||||
.int_clk = 2460000,
|
||||
.max_dec_rate = 2048,
|
||||
.has_sleep_cnt = true,
|
||||
.filter_freqs = adis16480_def_filter_freqs,
|
||||
.adis_data = ADIS16480_DATA(16489, &adis16480_timeouts, 0, 0),
|
||||
},
|
||||
[ADIS16490] = {
|
||||
.channels = adis16485_channels,
|
||||
.num_channels = ARRAY_SIZE(adis16485_channels),
|
||||
@ -1741,7 +1810,10 @@ static const struct spi_device_id adis16480_ids[] = {
|
||||
{ "adis16375", ADIS16375 },
|
||||
{ "adis16480", ADIS16480 },
|
||||
{ "adis16485", ADIS16485 },
|
||||
{ "adis16486", ADIS16486 },
|
||||
{ "adis16487", ADIS16487 },
|
||||
{ "adis16488", ADIS16488 },
|
||||
{ "adis16489", ADIS16489 },
|
||||
{ "adis16490", ADIS16490 },
|
||||
{ "adis16495-1", ADIS16495_1 },
|
||||
{ "adis16495-2", ADIS16495_2 },
|
||||
@ -1763,7 +1835,10 @@ static const struct of_device_id adis16480_of_match[] = {
|
||||
{ .compatible = "adi,adis16375" },
|
||||
{ .compatible = "adi,adis16480" },
|
||||
{ .compatible = "adi,adis16485" },
|
||||
{ .compatible = "adi,adis16486" },
|
||||
{ .compatible = "adi,adis16487" },
|
||||
{ .compatible = "adi,adis16488" },
|
||||
{ .compatible = "adi,adis16489" },
|
||||
{ .compatible = "adi,adis16490" },
|
||||
{ .compatible = "adi,adis16495-1" },
|
||||
{ .compatible = "adi,adis16495-2" },
|
||||
|
@ -277,6 +277,14 @@ static const struct inv_mpu6050_hw hw_info[] = {
|
||||
.temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
|
||||
.startup_time = {INV_ICM20690_GYRO_STARTUP_TIME, INV_ICM20690_ACCEL_STARTUP_TIME},
|
||||
},
|
||||
{ .whoami = INV_IAM20380_WHOAMI_VALUE,
|
||||
.name = "IAM20380",
|
||||
.reg = ®_set_6500,
|
||||
.config = &chip_config_6500,
|
||||
.fifo_size = 512,
|
||||
.temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
|
||||
.startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
|
||||
},
|
||||
{
|
||||
.whoami = INV_IAM20680_WHOAMI_VALUE,
|
||||
.name = "IAM20680",
|
||||
@ -1519,6 +1527,14 @@ static const struct iio_chan_spec inv_mpu6050_channels[] = {
|
||||
INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec inv_iam20380_channels[] = {
|
||||
IIO_CHAN_SOFT_TIMESTAMP(INV_MPU6050_SCAN_TIMESTAMP),
|
||||
|
||||
INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X),
|
||||
INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y),
|
||||
INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec inv_mpu6500_channels[] = {
|
||||
IIO_CHAN_SOFT_TIMESTAMP(INV_MPU6050_SCAN_TIMESTAMP),
|
||||
|
||||
@ -1623,6 +1639,10 @@ static const struct iio_chan_spec inv_mpu9250_channels[] = {
|
||||
| BIT(INV_MPU9X50_SCAN_MAGN_Y) \
|
||||
| BIT(INV_MPU9X50_SCAN_MAGN_Z))
|
||||
|
||||
static const unsigned long inv_iam20380_scan_masks[] = {
|
||||
INV_MPU6050_SCAN_MASK_3AXIS_GYRO,
|
||||
};
|
||||
|
||||
static const unsigned long inv_mpu9x50_scan_masks[] = {
|
||||
/* 3-axis accel */
|
||||
INV_MPU6050_SCAN_MASK_3AXIS_ACCEL,
|
||||
@ -2026,6 +2046,11 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
|
||||
indio_dev->num_channels = ARRAY_SIZE(inv_mpu9250_channels);
|
||||
indio_dev->available_scan_masks = inv_mpu9x50_scan_masks;
|
||||
break;
|
||||
case INV_IAM20380:
|
||||
indio_dev->channels = inv_iam20380_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(inv_iam20380_channels);
|
||||
indio_dev->available_scan_masks = inv_iam20380_scan_masks;
|
||||
break;
|
||||
case INV_ICM20600:
|
||||
case INV_ICM20602:
|
||||
indio_dev->channels = inv_mpu6500_channels;
|
||||
|
@ -34,6 +34,7 @@ static bool inv_mpu_i2c_aux_bus(struct device *dev)
|
||||
case INV_ICM20689:
|
||||
case INV_ICM20600:
|
||||
case INV_ICM20602:
|
||||
case INV_IAM20380:
|
||||
case INV_IAM20680:
|
||||
/* no i2c auxiliary bus on the chip */
|
||||
return false;
|
||||
@ -187,6 +188,7 @@ static const struct i2c_device_id inv_mpu_id[] = {
|
||||
{"icm20600", INV_ICM20600},
|
||||
{"icm20602", INV_ICM20602},
|
||||
{"icm20690", INV_ICM20690},
|
||||
{"iam20380", INV_IAM20380},
|
||||
{"iam20680", INV_IAM20680},
|
||||
{"iam20680hp", INV_IAM20680HP},
|
||||
{"iam20680ht", INV_IAM20680HT},
|
||||
@ -252,6 +254,10 @@ static const struct of_device_id inv_of_match[] = {
|
||||
.compatible = "invensense,icm20690",
|
||||
.data = (void *)INV_ICM20690
|
||||
},
|
||||
{
|
||||
.compatible = "invensense,iam20380",
|
||||
.data = (void *)INV_IAM20380
|
||||
},
|
||||
{
|
||||
.compatible = "invensense,iam20680",
|
||||
.data = (void *)INV_IAM20680
|
||||
|
@ -84,6 +84,7 @@ enum inv_devices {
|
||||
INV_ICM20600,
|
||||
INV_ICM20602,
|
||||
INV_ICM20690,
|
||||
INV_IAM20380,
|
||||
INV_IAM20680,
|
||||
INV_IAM20680HP,
|
||||
INV_IAM20680HT,
|
||||
@ -425,6 +426,7 @@ struct inv_mpu6050_state {
|
||||
#define INV_ICM20600_WHOAMI_VALUE 0x11
|
||||
#define INV_ICM20602_WHOAMI_VALUE 0x12
|
||||
#define INV_ICM20690_WHOAMI_VALUE 0x20
|
||||
#define INV_IAM20380_WHOAMI_VALUE 0xB5
|
||||
#define INV_IAM20680_WHOAMI_VALUE 0xA9
|
||||
#define INV_IAM20680HP_WHOAMI_VALUE 0xF8
|
||||
#define INV_IAM20680HT_WHOAMI_VALUE 0xFA
|
||||
|
@ -79,6 +79,7 @@ static const struct spi_device_id inv_mpu_id[] = {
|
||||
{"icm20600", INV_ICM20600},
|
||||
{"icm20602", INV_ICM20602},
|
||||
{"icm20690", INV_ICM20690},
|
||||
{"iam20380", INV_IAM20380},
|
||||
{"iam20680", INV_IAM20680},
|
||||
{"iam20680hp", INV_IAM20680HP},
|
||||
{"iam20680ht", INV_IAM20680HT},
|
||||
@ -140,6 +141,10 @@ static const struct of_device_id inv_of_match[] = {
|
||||
.compatible = "invensense,icm20690",
|
||||
.data = (void *)INV_ICM20690
|
||||
},
|
||||
{
|
||||
.compatible = "invensense,iam20380",
|
||||
.data = (void *)INV_IAM20380
|
||||
},
|
||||
{
|
||||
.compatible = "invensense,iam20680",
|
||||
.data = (void *)INV_IAM20680
|
||||
|
@ -6,9 +6,6 @@ config IIO_ST_LSM6DSX
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
select IIO_KFIFO_BUF
|
||||
select IIO_ST_LSM6DSX_I2C if (I2C)
|
||||
select IIO_ST_LSM6DSX_SPI if (SPI_MASTER)
|
||||
select IIO_ST_LSM6DSX_I3C if (I3C)
|
||||
help
|
||||
Say yes here to build support for STMicroelectronics LSM6DSx imu
|
||||
sensor.
|
||||
@ -42,16 +39,19 @@ config IIO_ST_LSM6DSX
|
||||
will be called st_lsm6dsx.
|
||||
|
||||
config IIO_ST_LSM6DSX_I2C
|
||||
tristate
|
||||
depends on IIO_ST_LSM6DSX
|
||||
tristate "ST_LSM6DSx driver for STM 6-axis IMU MEMS sensors I2C Interface"
|
||||
depends on I2C && IIO_ST_LSM6DSX
|
||||
default I2C && IIO_ST_LSM6DSX
|
||||
select REGMAP_I2C
|
||||
|
||||
config IIO_ST_LSM6DSX_SPI
|
||||
tristate
|
||||
depends on IIO_ST_LSM6DSX
|
||||
tristate "ST_LSM6DSx driver for STM 6-axis IMU MEMS sensors SPI Interface"
|
||||
depends on SPI_MASTER && IIO_ST_LSM6DSX
|
||||
default SPI_MASTER && IIO_ST_LSM6DSX
|
||||
select REGMAP_SPI
|
||||
|
||||
config IIO_ST_LSM6DSX_I3C
|
||||
tristate
|
||||
depends on IIO_ST_LSM6DSX
|
||||
tristate "ST_LSM6DSx driver for STM 6-axis IMU MEMS sensors I3C Interface"
|
||||
depends on I3C && IIO_ST_LSM6DSX
|
||||
default I3C && IIO_ST_LSM6DSX
|
||||
select REGMAP_I3C
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/i3c/device.h>
|
||||
#include <linux/i3c/master.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
@ -30,15 +29,16 @@ static int st_lsm6dsx_i3c_probe(struct i3c_device *i3cdev)
|
||||
};
|
||||
const struct i3c_device_id *id = i3c_device_match_id(i3cdev,
|
||||
st_lsm6dsx_i3c_ids);
|
||||
struct device *dev = i3cdev_to_dev(i3cdev);
|
||||
struct regmap *regmap;
|
||||
|
||||
regmap = devm_regmap_init_i3c(i3cdev, &st_lsm6dsx_i3c_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&i3cdev->dev, "Failed to register i3c regmap %ld\n", PTR_ERR(regmap));
|
||||
dev_err(dev, "Failed to register i3c regmap %ld\n", PTR_ERR(regmap));
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
return st_lsm6dsx_probe(&i3cdev->dev, 0, (uintptr_t)id->data, regmap);
|
||||
return st_lsm6dsx_probe(dev, 0, (uintptr_t)id->data, regmap);
|
||||
}
|
||||
|
||||
static struct i3c_driver st_lsm6dsx_driver = {
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/slab.h>
|
||||
@ -989,6 +990,11 @@ ssize_t iio_read_channel_ext_info(struct iio_channel *chan,
|
||||
{
|
||||
const struct iio_chan_spec_ext_info *ext_info;
|
||||
|
||||
if (!buf || offset_in_page(buf)) {
|
||||
pr_err("iio: invalid ext_info read buffer\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ext_info = iio_lookup_ext_info(chan, attr);
|
||||
if (!ext_info)
|
||||
return -EINVAL;
|
||||
@ -1014,6 +1020,11 @@ EXPORT_SYMBOL_GPL(iio_write_channel_ext_info);
|
||||
|
||||
ssize_t iio_read_channel_label(struct iio_channel *chan, char *buf)
|
||||
{
|
||||
if (!buf || offset_in_page(buf)) {
|
||||
pr_err("iio: invalid label read buffer\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return do_iio_read_channel_label(chan->indio_dev, chan->channel, buf);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iio_read_channel_label);
|
||||
|
@ -329,22 +329,6 @@ config JSA1212
|
||||
To compile this driver as a module, choose M here:
|
||||
the module will be called jsa1212.
|
||||
|
||||
config ROHM_BU27008
|
||||
tristate "ROHM BU27008 color (RGB+C/IR) sensor"
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
select IIO_GTS_HELPER
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
help
|
||||
Enable support for the ROHM BU27008 color sensor.
|
||||
The ROHM BU27008 is a sensor with 5 photodiodes (red, green,
|
||||
blue, clear and IR) with four configurable channels. Red and
|
||||
green being always available and two out of the rest three
|
||||
(blue, clear, IR) can be selected to be simultaneously measured.
|
||||
Typical application is adjusting LCD backlight of TVs,
|
||||
mobile phones and tablet PCs.
|
||||
|
||||
config ROHM_BU27034
|
||||
tristate "ROHM BU27034 ambient light sensor"
|
||||
depends on I2C
|
||||
@ -683,6 +667,8 @@ config VEML3235
|
||||
config VEML6030
|
||||
tristate "VEML6030 and VEML6035 ambient light sensors"
|
||||
select REGMAP_I2C
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here if you want to build a driver for the Vishay VEML6030
|
||||
|
@ -43,7 +43,6 @@ obj-$(CONFIG_NOA1305) += noa1305.o
|
||||
obj-$(CONFIG_OPT3001) += opt3001.o
|
||||
obj-$(CONFIG_OPT4001) += opt4001.o
|
||||
obj-$(CONFIG_PA12203001) += pa12203001.o
|
||||
obj-$(CONFIG_ROHM_BU27008) += rohm-bu27008.o
|
||||
obj-$(CONFIG_ROHM_BU27034) += rohm-bu27034.o
|
||||
obj-$(CONFIG_RPR0521) += rpr0521.o
|
||||
obj-$(CONFIG_SI1133) += si1133.o
|
||||
|
@ -89,6 +89,15 @@ static int cm3232_reg_init(struct cm3232_chip *chip)
|
||||
|
||||
chip->als_info = &cm3232_als_info_default;
|
||||
|
||||
/* Disable and reset device */
|
||||
chip->regs_cmd = CM3232_CMD_ALS_DISABLE | CM3232_CMD_ALS_RESET;
|
||||
ret = i2c_smbus_write_byte_data(client, CM3232_REG_ADDR_CMD,
|
||||
chip->regs_cmd);
|
||||
if (ret < 0) {
|
||||
dev_err(&chip->client->dev, "Error writing reg_cmd\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Identify device */
|
||||
ret = i2c_smbus_read_word_data(client, CM3232_REG_ADDR_ID);
|
||||
if (ret < 0) {
|
||||
@ -99,15 +108,6 @@ static int cm3232_reg_init(struct cm3232_chip *chip)
|
||||
if ((ret & 0xFF) != chip->als_info->hw_id)
|
||||
return -ENODEV;
|
||||
|
||||
/* Disable and reset device */
|
||||
chip->regs_cmd = CM3232_CMD_ALS_DISABLE | CM3232_CMD_ALS_RESET;
|
||||
ret = i2c_smbus_write_byte_data(client, CM3232_REG_ADDR_CMD,
|
||||
chip->regs_cmd);
|
||||
if (ret < 0) {
|
||||
dev_err(&chip->client->dev, "Error writing reg_cmd\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Register default value */
|
||||
chip->regs_cmd = chip->als_info->regs_cmd_default;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,6 +7,7 @@
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
@ -395,30 +396,26 @@ static int bu27034_try_set_int_time(struct bu27034_data *data, int time_us)
|
||||
int numg = ARRAY_SIZE(gains);
|
||||
int ret, int_time_old, i;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
guard(mutex)(&data->mutex);
|
||||
ret = bu27034_get_int_time(data);
|
||||
if (ret < 0)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
|
||||
int_time_old = ret;
|
||||
|
||||
if (!iio_gts_valid_time(&data->gts, time_us)) {
|
||||
dev_err(data->dev, "Unsupported integration time %u\n",
|
||||
time_us);
|
||||
ret = -EINVAL;
|
||||
|
||||
goto unlock_out;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (time_us == int_time_old) {
|
||||
ret = 0;
|
||||
goto unlock_out;
|
||||
}
|
||||
if (time_us == int_time_old)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < numg; i++) {
|
||||
ret = bu27034_get_gain(data, gains[i].chan, &gains[i].old_gain);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return 0;
|
||||
|
||||
ret = iio_gts_find_new_gain_by_old_gain_time(&data->gts,
|
||||
gains[i].old_gain,
|
||||
@ -434,7 +431,7 @@ static int bu27034_try_set_int_time(struct bu27034_data *data, int time_us)
|
||||
gains[i].chan, time_us, scale1, scale2);
|
||||
|
||||
if (gains[i].new_gain < 0)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* If caller requests for integration time change and we
|
||||
@ -455,7 +452,7 @@ static int bu27034_try_set_int_time(struct bu27034_data *data, int time_us)
|
||||
"Total gain increase. Risk of saturation");
|
||||
ret = iio_gts_get_min_gain(&data->gts);
|
||||
if (ret < 0)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
}
|
||||
dev_dbg(data->dev, "chan %u scale changed\n",
|
||||
gains[i].chan);
|
||||
@ -468,15 +465,10 @@ static int bu27034_try_set_int_time(struct bu27034_data *data, int time_us)
|
||||
for (i = 0; i < numg; i++) {
|
||||
ret = bu27034_set_gain(data, gains[i].chan, gains[i].new_gain);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = bu27034_set_int_time(data, time_us);
|
||||
|
||||
unlock_out:
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
return bu27034_set_int_time(data, time_us);
|
||||
}
|
||||
|
||||
static int bu27034_set_scale(struct bu27034_data *data, int chan,
|
||||
@ -492,10 +484,10 @@ static int bu27034_set_scale(struct bu27034_data *data, int chan,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
guard(mutex)(&data->mutex);
|
||||
ret = regmap_read(data->regmap, BU27034_REG_MODE_CONTROL1, &time_sel);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
|
||||
ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts, time_sel,
|
||||
val, val2, &gain_sel);
|
||||
@ -518,7 +510,7 @@ static int bu27034_set_scale(struct bu27034_data *data, int chan,
|
||||
|
||||
ret = bu27034_get_gain(data, gain.chan, &gain.old_gain);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Iterate through all the times to see if we find one which
|
||||
@ -551,26 +543,20 @@ static int bu27034_set_scale(struct bu27034_data *data, int chan,
|
||||
if (!found) {
|
||||
dev_dbg(data->dev,
|
||||
"Can't set scale maintaining other channel\n");
|
||||
ret = -EINVAL;
|
||||
|
||||
goto unlock_out;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = bu27034_set_gain(data, gain.chan, gain.new_gain);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
|
||||
ret = regmap_update_bits(data->regmap, BU27034_REG_MODE_CONTROL1,
|
||||
BU27034_MASK_MEAS_MODE, new_time_sel);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = bu27034_write_gain_sel(data, chan, gain_sel);
|
||||
unlock_out:
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
return bu27034_write_gain_sel(data, chan, gain_sel);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1221,42 +1207,33 @@ static int bu27034_buffer_enable(struct iio_dev *idev)
|
||||
struct task_struct *task;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
guard(mutex)(&data->mutex);
|
||||
ret = bu27034_meas_set(data, true);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
|
||||
task = kthread_run(bu27034_buffer_thread, idev,
|
||||
"bu27034-buffering-%u",
|
||||
iio_device_id(idev));
|
||||
if (IS_ERR(task)) {
|
||||
ret = PTR_ERR(task);
|
||||
goto unlock_out;
|
||||
}
|
||||
if (IS_ERR(task))
|
||||
return PTR_ERR(task);
|
||||
|
||||
data->task = task;
|
||||
|
||||
unlock_out:
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bu27034_buffer_disable(struct iio_dev *idev)
|
||||
{
|
||||
struct bu27034_data *data = iio_priv(idev);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
guard(mutex)(&data->mutex);
|
||||
if (data->task) {
|
||||
kthread_stop(data->task);
|
||||
data->task = NULL;
|
||||
}
|
||||
|
||||
ret = bu27034_meas_set(data, false);
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
return bu27034_meas_set(data, false);
|
||||
}
|
||||
|
||||
static const struct iio_buffer_setup_ops bu27034_buffer_ops = {
|
||||
|
@ -28,6 +28,8 @@
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/events.h>
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/iio/triggered_buffer.h>
|
||||
|
||||
/* Device registers */
|
||||
#define VEML6030_REG_ALS_CONF 0x00
|
||||
@ -37,6 +39,7 @@
|
||||
#define VEML6030_REG_ALS_DATA 0x04
|
||||
#define VEML6030_REG_WH_DATA 0x05
|
||||
#define VEML6030_REG_ALS_INT 0x06
|
||||
#define VEML6030_REG_DATA(ch) (VEML6030_REG_ALS_DATA + (ch))
|
||||
|
||||
/* Bit masks for specific functionality */
|
||||
#define VEML6030_ALS_IT GENMASK(9, 6)
|
||||
@ -56,6 +59,12 @@
|
||||
#define VEML6035_INT_CHAN BIT(3)
|
||||
#define VEML6035_CHAN_EN BIT(2)
|
||||
|
||||
enum veml6030_scan {
|
||||
VEML6030_SCAN_ALS,
|
||||
VEML6030_SCAN_WH,
|
||||
VEML6030_SCAN_TIMESTAMP,
|
||||
};
|
||||
|
||||
struct veml603x_chip {
|
||||
const char *name;
|
||||
const int(*scale_vals)[][2];
|
||||
@ -242,6 +251,13 @@ static const struct iio_chan_spec veml6030_channels[] = {
|
||||
BIT(IIO_CHAN_INFO_SCALE),
|
||||
.event_spec = veml6030_event_spec,
|
||||
.num_event_specs = ARRAY_SIZE(veml6030_event_spec),
|
||||
.scan_index = VEML6030_SCAN_ALS,
|
||||
.scan_type = {
|
||||
.sign = 'u',
|
||||
.realbits = 16,
|
||||
.storagebits = 16,
|
||||
.endianness = IIO_CPU,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = IIO_INTENSITY,
|
||||
@ -253,7 +269,15 @@ static const struct iio_chan_spec veml6030_channels[] = {
|
||||
BIT(IIO_CHAN_INFO_SCALE),
|
||||
.info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
|
||||
BIT(IIO_CHAN_INFO_SCALE),
|
||||
.scan_index = VEML6030_SCAN_WH,
|
||||
.scan_type = {
|
||||
.sign = 'u',
|
||||
.realbits = 16,
|
||||
.storagebits = 16,
|
||||
.endianness = IIO_CPU,
|
||||
},
|
||||
},
|
||||
IIO_CHAN_SOFT_TIMESTAMP(VEML6030_SCAN_TIMESTAMP),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec veml7700_channels[] = {
|
||||
@ -266,6 +290,13 @@ static const struct iio_chan_spec veml7700_channels[] = {
|
||||
BIT(IIO_CHAN_INFO_SCALE),
|
||||
.info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
|
||||
BIT(IIO_CHAN_INFO_SCALE),
|
||||
.scan_index = VEML6030_SCAN_ALS,
|
||||
.scan_type = {
|
||||
.sign = 'u',
|
||||
.realbits = 16,
|
||||
.storagebits = 16,
|
||||
.endianness = IIO_CPU,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = IIO_INTENSITY,
|
||||
@ -277,7 +308,15 @@ static const struct iio_chan_spec veml7700_channels[] = {
|
||||
BIT(IIO_CHAN_INFO_SCALE),
|
||||
.info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
|
||||
BIT(IIO_CHAN_INFO_SCALE),
|
||||
.scan_index = VEML6030_SCAN_WH,
|
||||
.scan_type = {
|
||||
.sign = 'u',
|
||||
.realbits = 16,
|
||||
.storagebits = 16,
|
||||
.endianness = IIO_CPU,
|
||||
},
|
||||
},
|
||||
IIO_CHAN_SOFT_TIMESTAMP(VEML6030_SCAN_TIMESTAMP),
|
||||
};
|
||||
|
||||
static const struct regmap_config veml6030_regmap_config = {
|
||||
@ -889,6 +928,37 @@ static irqreturn_t veml6030_event_handler(int irq, void *private)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t veml6030_trigger_handler(int irq, void *p)
|
||||
{
|
||||
struct iio_poll_func *pf = p;
|
||||
struct iio_dev *iio = pf->indio_dev;
|
||||
struct veml6030_data *data = iio_priv(iio);
|
||||
unsigned int reg;
|
||||
int ch, ret, i = 0;
|
||||
struct {
|
||||
u16 chans[2];
|
||||
aligned_s64 timestamp;
|
||||
} scan;
|
||||
|
||||
memset(&scan, 0, sizeof(scan));
|
||||
|
||||
iio_for_each_active_channel(iio, ch) {
|
||||
ret = regmap_read(data->regmap, VEML6030_REG_DATA(ch),
|
||||
®);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
scan.chans[i++] = reg;
|
||||
}
|
||||
|
||||
iio_push_to_buffers_with_timestamp(iio, &scan, pf->timestamp);
|
||||
|
||||
done:
|
||||
iio_trigger_notify_done(iio->trig);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int veml6030_set_info(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct veml6030_data *data = iio_priv(indio_dev);
|
||||
@ -1077,6 +1147,12 @@ static int veml6030_probe(struct i2c_client *client)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL,
|
||||
veml6030_trigger_handler, NULL);
|
||||
if (ret)
|
||||
return dev_err_probe(&client->dev, ret,
|
||||
"Failed to register triggered buffer");
|
||||
|
||||
return devm_iio_device_register(&client->dev, indio_dev);
|
||||
}
|
||||
|
||||
|
@ -1002,7 +1002,7 @@ static int bmp280_preinit(struct bmp280_data *data)
|
||||
* after resetting, the device uses the complete power-on sequence so
|
||||
* it needs to wait for the defined start-up time.
|
||||
*/
|
||||
fsleep(data->start_up_time);
|
||||
fsleep(data->start_up_time_us);
|
||||
|
||||
ret = regmap_read(data->regmap, BMP280_REG_STATUS, ®);
|
||||
if (ret)
|
||||
@ -1161,7 +1161,7 @@ const struct bmp280_chip_info bmp280_chip_info = {
|
||||
.chip_id = bmp280_chip_ids,
|
||||
.num_chip_id = ARRAY_SIZE(bmp280_chip_ids),
|
||||
.regmap_config = &bmp280_regmap_config,
|
||||
.start_up_time = 2000,
|
||||
.start_up_time_us = 2000,
|
||||
.channels = bmp280_channels,
|
||||
.num_channels = ARRAY_SIZE(bmp280_channels),
|
||||
.avail_scan_masks = bmp280_avail_scan_masks,
|
||||
@ -1347,7 +1347,7 @@ const struct bmp280_chip_info bme280_chip_info = {
|
||||
.chip_id = bme280_chip_ids,
|
||||
.num_chip_id = ARRAY_SIZE(bme280_chip_ids),
|
||||
.regmap_config = &bme280_regmap_config,
|
||||
.start_up_time = 2000,
|
||||
.start_up_time_us = 2000,
|
||||
.channels = bme280_channels,
|
||||
.num_channels = ARRAY_SIZE(bme280_channels),
|
||||
.avail_scan_masks = bme280_avail_scan_masks,
|
||||
@ -1414,7 +1414,7 @@ static int bmp380_cmd(struct bmp280_data *data, u8 cmd)
|
||||
return ret;
|
||||
}
|
||||
/* Wait for 2ms for command to be processed */
|
||||
usleep_range(data->start_up_time, data->start_up_time + 100);
|
||||
fsleep(data->start_up_time_us);
|
||||
/* Check for command processing error */
|
||||
ret = regmap_read(data->regmap, BMP380_REG_ERROR, ®);
|
||||
if (ret) {
|
||||
@ -1806,7 +1806,7 @@ static int bmp380_chip_config(struct bmp280_data *data)
|
||||
* formula in datasheet section 3.9.2 with an offset of ~+15%
|
||||
* as it seen as well in table 3.9.1.
|
||||
*/
|
||||
msleep(150);
|
||||
fsleep(150 * USEC_PER_MSEC);
|
||||
|
||||
/* Check config error flag */
|
||||
ret = regmap_read(data->regmap, BMP380_REG_ERROR, &tmp);
|
||||
@ -1957,7 +1957,7 @@ const struct bmp280_chip_info bmp380_chip_info = {
|
||||
.num_chip_id = ARRAY_SIZE(bmp380_chip_ids),
|
||||
.regmap_config = &bmp380_regmap_config,
|
||||
.spi_read_extra_byte = true,
|
||||
.start_up_time = 2000,
|
||||
.start_up_time_us = 2000,
|
||||
.channels = bmp380_channels,
|
||||
.num_channels = ARRAY_SIZE(bmp380_channels),
|
||||
.avail_scan_masks = bmp280_avail_scan_masks,
|
||||
@ -2006,7 +2006,8 @@ static int bmp580_soft_reset(struct bmp280_data *data)
|
||||
dev_err(data->dev, "failed to send reset command to device\n");
|
||||
return ret;
|
||||
}
|
||||
usleep_range(2000, 2500);
|
||||
/* From datasheet's table 4: electrical characteristics */
|
||||
fsleep(2000);
|
||||
|
||||
/* Dummy read of chip_id */
|
||||
ret = regmap_read(data->regmap, BMP580_REG_CHIP_ID, ®);
|
||||
@ -2208,7 +2209,7 @@ static int bmp580_nvmem_read_impl(void *priv, unsigned int offset, void *val,
|
||||
goto exit;
|
||||
}
|
||||
/* Wait standby transition time */
|
||||
usleep_range(2500, 3000);
|
||||
fsleep(2500);
|
||||
|
||||
while (bytes >= sizeof(*dst)) {
|
||||
addr = bmp580_nvmem_addrs[offset / sizeof(*dst)];
|
||||
@ -2274,7 +2275,7 @@ static int bmp580_nvmem_write_impl(void *priv, unsigned int offset, void *val,
|
||||
goto exit;
|
||||
}
|
||||
/* Wait standby transition time */
|
||||
usleep_range(2500, 3000);
|
||||
fsleep(2500);
|
||||
|
||||
while (bytes >= sizeof(*buf)) {
|
||||
addr = bmp580_nvmem_addrs[offset / sizeof(*buf)];
|
||||
@ -2458,7 +2459,7 @@ static int bmp580_chip_config(struct bmp280_data *data)
|
||||
return ret;
|
||||
}
|
||||
/* From datasheet's table 4: electrical characteristics */
|
||||
usleep_range(2500, 3000);
|
||||
fsleep(2500);
|
||||
|
||||
/* Set default DSP mode settings */
|
||||
reg_val = FIELD_PREP(BMP580_DSP_COMP_MASK, BMP580_DSP_PRESS_TEMP_COMP_EN) |
|
||||
@ -2649,7 +2650,7 @@ const struct bmp280_chip_info bmp580_chip_info = {
|
||||
.chip_id = bmp580_chip_ids,
|
||||
.num_chip_id = ARRAY_SIZE(bmp580_chip_ids),
|
||||
.regmap_config = &bmp580_regmap_config,
|
||||
.start_up_time = 2000,
|
||||
.start_up_time_us = 2000,
|
||||
.channels = bmp580_channels,
|
||||
.num_channels = ARRAY_SIZE(bmp580_channels),
|
||||
.avail_scan_masks = bmp280_avail_scan_masks,
|
||||
@ -2720,7 +2721,7 @@ static int bmp180_wait_for_eoc(struct bmp280_data *data, u8 ctrl_meas)
|
||||
delay_us =
|
||||
conversion_time_max[data->oversampling_press];
|
||||
|
||||
usleep_range(delay_us, delay_us + 1000);
|
||||
fsleep(delay_us);
|
||||
}
|
||||
|
||||
ret = regmap_read(data->regmap, BMP280_REG_CTRL_MEAS, &ctrl);
|
||||
@ -2988,7 +2989,7 @@ const struct bmp280_chip_info bmp180_chip_info = {
|
||||
.chip_id = bmp180_chip_ids,
|
||||
.num_chip_id = ARRAY_SIZE(bmp180_chip_ids),
|
||||
.regmap_config = &bmp180_regmap_config,
|
||||
.start_up_time = 2000,
|
||||
.start_up_time_us = 2000,
|
||||
.channels = bmp280_channels,
|
||||
.num_channels = ARRAY_SIZE(bmp280_channels),
|
||||
.avail_scan_masks = bmp280_avail_scan_masks,
|
||||
@ -3066,7 +3067,7 @@ const struct bmp280_chip_info bmp085_chip_info = {
|
||||
.chip_id = bmp180_chip_ids,
|
||||
.num_chip_id = ARRAY_SIZE(bmp180_chip_ids),
|
||||
.regmap_config = &bmp180_regmap_config,
|
||||
.start_up_time = 2000,
|
||||
.start_up_time_us = 2000,
|
||||
.channels = bmp280_channels,
|
||||
.num_channels = ARRAY_SIZE(bmp280_channels),
|
||||
.avail_scan_masks = bmp280_avail_scan_masks,
|
||||
@ -3175,7 +3176,7 @@ int bmp280_common_probe(struct device *dev,
|
||||
data->oversampling_temp = chip_info->oversampling_temp_default;
|
||||
data->iir_filter_coeff = chip_info->iir_filter_coeff_default;
|
||||
data->sampling_freq = chip_info->sampling_freq_default;
|
||||
data->start_up_time = chip_info->start_up_time;
|
||||
data->start_up_time_us = chip_info->start_up_time_us;
|
||||
|
||||
/* Bring up regulators */
|
||||
regulator_bulk_set_supply_names(data->supplies,
|
||||
@ -3201,7 +3202,7 @@ int bmp280_common_probe(struct device *dev,
|
||||
return ret;
|
||||
|
||||
/* Wait to make sure we started up properly */
|
||||
usleep_range(data->start_up_time, data->start_up_time + 100);
|
||||
fsleep(data->start_up_time_us);
|
||||
|
||||
/* Bring chip out of reset if there is an assigned GPIO line */
|
||||
gpiod = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
|
||||
@ -3287,7 +3288,7 @@ int bmp280_common_probe(struct device *dev,
|
||||
* Set autosuspend to two orders of magnitude larger than the
|
||||
* start-up time.
|
||||
*/
|
||||
pm_runtime_set_autosuspend_delay(dev, data->start_up_time / 10);
|
||||
pm_runtime_set_autosuspend_delay(dev, data->start_up_time_us / 10);
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_put(dev);
|
||||
|
||||
@ -3306,7 +3307,7 @@ static int bmp280_runtime_suspend(struct device *dev)
|
||||
|
||||
data->chip_info->set_mode(data, BMP280_SLEEP);
|
||||
|
||||
fsleep(data->start_up_time);
|
||||
fsleep(data->start_up_time_us);
|
||||
return regulator_bulk_disable(BMP280_NUM_SUPPLIES, data->supplies);
|
||||
}
|
||||
|
||||
@ -3320,7 +3321,7 @@ static int bmp280_runtime_resume(struct device *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
usleep_range(data->start_up_time, data->start_up_time + 100);
|
||||
fsleep(data->start_up_time_us);
|
||||
|
||||
ret = data->chip_info->chip_config(data);
|
||||
if (ret)
|
||||
|
@ -434,7 +434,7 @@ struct bmp280_data {
|
||||
struct bmp380_calib bmp380;
|
||||
} calib;
|
||||
struct regulator_bulk_data supplies[BMP280_NUM_SUPPLIES];
|
||||
unsigned int start_up_time; /* in microseconds */
|
||||
unsigned int start_up_time_us;
|
||||
|
||||
/* log of base 2 of oversampling rate */
|
||||
u8 oversampling_press;
|
||||
@ -470,8 +470,8 @@ struct bmp280_data {
|
||||
/* Sensor data buffer */
|
||||
u8 buf[BME280_BURST_READ_BYTES];
|
||||
/* Calibration data buffers */
|
||||
__le16 bmp280_cal_buf[BMP280_CONTIGUOUS_CALIB_REGS / 2];
|
||||
__be16 bmp180_cal_buf[BMP180_REG_CALIB_COUNT / 2];
|
||||
__le16 bmp280_cal_buf[BMP280_CONTIGUOUS_CALIB_REGS / sizeof(__le16)];
|
||||
__be16 bmp180_cal_buf[BMP180_REG_CALIB_COUNT / sizeof(__be16)];
|
||||
u8 bme280_humid_cal_buf[BME280_CONTIGUOUS_CALIB_REGS];
|
||||
u8 bmp380_cal_buf[BMP380_CALIB_REG_COUNT];
|
||||
/* Miscellaneous, endianness-aware data buffers */
|
||||
@ -490,7 +490,7 @@ struct bmp280_chip_info {
|
||||
|
||||
const struct iio_chan_spec *channels;
|
||||
int num_channels;
|
||||
unsigned int start_up_time;
|
||||
unsigned int start_up_time_us;
|
||||
const unsigned long *avail_scan_masks;
|
||||
|
||||
const int *oversampling_temp_avail;
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
@ -263,14 +264,14 @@ static int bm1390_read_data(struct bm1390_data *data,
|
||||
{
|
||||
int ret, warn;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
guard(mutex)(&data->mutex);
|
||||
/*
|
||||
* We use 'continuous mode' even for raw read because according to the
|
||||
* data-sheet an one-shot mode can't be used with IIR filter.
|
||||
*/
|
||||
ret = bm1390_meas_set(data, BM1390_MEAS_MODE_CONTINUOUS);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
|
||||
switch (chan->type) {
|
||||
case IIO_PRESSURE:
|
||||
@ -287,10 +288,8 @@ static int bm1390_read_data(struct bm1390_data *data,
|
||||
warn = bm1390_meas_set(data, BM1390_MEAS_MODE_STOP);
|
||||
if (warn)
|
||||
dev_warn(data->dev, "Failed to stop measurement (%d)\n", warn);
|
||||
unlock_out:
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bm1390_read_raw(struct iio_dev *idev,
|
||||
@ -543,38 +542,33 @@ static int bm1390_fifo_enable(struct iio_dev *idev)
|
||||
if (data->irq <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
if (data->trigger_enabled) {
|
||||
ret = -EBUSY;
|
||||
goto unlock_out;
|
||||
}
|
||||
guard(mutex)(&data->mutex);
|
||||
|
||||
if (data->trigger_enabled)
|
||||
return -EBUSY;
|
||||
|
||||
/* Update watermark to HW */
|
||||
ret = bm1390_fifo_set_wmi(data);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
|
||||
/* Enable WMI_IRQ */
|
||||
ret = regmap_set_bits(data->regmap, BM1390_REG_MODE_CTRL,
|
||||
BM1390_MASK_WMI_EN);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
|
||||
/* Enable FIFO */
|
||||
ret = regmap_set_bits(data->regmap, BM1390_REG_FIFO_CTRL,
|
||||
BM1390_MASK_FIFO_EN);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
|
||||
data->state = BM1390_STATE_FIFO;
|
||||
|
||||
data->old_timestamp = iio_get_time_ns(idev);
|
||||
ret = bm1390_meas_set(data, BM1390_MEAS_MODE_CONTINUOUS);
|
||||
|
||||
unlock_out:
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
return bm1390_meas_set(data, BM1390_MEAS_MODE_CONTINUOUS);
|
||||
}
|
||||
|
||||
static int bm1390_fifo_disable(struct iio_dev *idev)
|
||||
@ -584,27 +578,22 @@ static int bm1390_fifo_disable(struct iio_dev *idev)
|
||||
|
||||
msleep(1);
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
guard(mutex)(&data->mutex);
|
||||
ret = bm1390_meas_set(data, BM1390_MEAS_MODE_STOP);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
|
||||
/* Disable FIFO */
|
||||
ret = regmap_clear_bits(data->regmap, BM1390_REG_FIFO_CTRL,
|
||||
BM1390_MASK_FIFO_EN);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
|
||||
data->state = BM1390_STATE_SAMPLE;
|
||||
|
||||
/* Disable WMI_IRQ */
|
||||
ret = regmap_clear_bits(data->regmap, BM1390_REG_MODE_CTRL,
|
||||
return regmap_clear_bits(data->regmap, BM1390_REG_MODE_CTRL,
|
||||
BM1390_MASK_WMI_EN);
|
||||
|
||||
unlock_out:
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bm1390_buffer_postenable(struct iio_dev *idev)
|
||||
@ -688,25 +677,24 @@ static irqreturn_t bm1390_irq_thread_handler(int irq, void *private)
|
||||
{
|
||||
struct iio_dev *idev = private;
|
||||
struct bm1390_data *data = iio_priv(idev);
|
||||
int ret = IRQ_NONE;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
guard(mutex)(&data->mutex);
|
||||
|
||||
if (data->trigger_enabled) {
|
||||
iio_trigger_poll_nested(data->trig);
|
||||
ret = IRQ_HANDLED;
|
||||
} else if (data->state == BM1390_STATE_FIFO) {
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if (data->state == BM1390_STATE_FIFO) {
|
||||
int ok;
|
||||
|
||||
ok = __bm1390_fifo_flush(idev, BM1390_FIFO_LENGTH,
|
||||
data->timestamp);
|
||||
if (ok > 0)
|
||||
ret = IRQ_HANDLED;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static int bm1390_set_drdy_irq(struct bm1390_data *data, bool en)
|
||||
@ -722,17 +710,16 @@ static int bm1390_trigger_set_state(struct iio_trigger *trig,
|
||||
bool state)
|
||||
{
|
||||
struct bm1390_data *data = iio_trigger_get_drvdata(trig);
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
guard(mutex)(&data->mutex);
|
||||
|
||||
if (data->trigger_enabled == state)
|
||||
goto unlock_out;
|
||||
return 0;
|
||||
|
||||
if (data->state == BM1390_STATE_FIFO) {
|
||||
dev_warn(data->dev, "Can't set trigger when FIFO enabled\n");
|
||||
ret = -EBUSY;
|
||||
goto unlock_out;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
data->trigger_enabled = state;
|
||||
@ -740,13 +727,13 @@ static int bm1390_trigger_set_state(struct iio_trigger *trig,
|
||||
if (state) {
|
||||
ret = bm1390_meas_set(data, BM1390_MEAS_MODE_CONTINUOUS);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
} else {
|
||||
int dummy;
|
||||
|
||||
ret = bm1390_meas_set(data, BM1390_MEAS_MODE_STOP);
|
||||
if (ret)
|
||||
goto unlock_out;
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* We need to read the status register in order to ACK the
|
||||
@ -758,12 +745,7 @@ static int bm1390_trigger_set_state(struct iio_trigger *trig,
|
||||
dev_warn(data->dev, "status read failed\n");
|
||||
}
|
||||
|
||||
ret = bm1390_set_drdy_irq(data, state);
|
||||
|
||||
unlock_out:
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
return bm1390_set_drdy_irq(data, state);
|
||||
}
|
||||
|
||||
static const struct iio_trigger_ops bm1390_trigger_ops = {
|
||||
|
@ -433,7 +433,7 @@ static int aw96103_write_event_config(struct iio_dev *indio_dev,
|
||||
state ? BIT(chan->channel) : 0);
|
||||
}
|
||||
|
||||
static struct iio_info iio_info = {
|
||||
static const struct iio_info iio_info = {
|
||||
.read_raw = aw96103_read_raw,
|
||||
.read_event_value = aw96103_read_event_val,
|
||||
.write_event_value = aw96103_write_event_val,
|
||||
|
@ -119,7 +119,7 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv,
|
||||
unsigned int frequency)
|
||||
{
|
||||
unsigned long long prd, div;
|
||||
int prescaler = 0;
|
||||
int prescaler = 0, ret;
|
||||
u32 ccer;
|
||||
|
||||
/* Period and prescaler values depends of clock rate */
|
||||
@ -150,10 +150,12 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv,
|
||||
if (ccer & TIM_CCER_CCXE)
|
||||
return -EBUSY;
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
guard(mutex)(&priv->lock);
|
||||
if (!priv->enabled) {
|
||||
priv->enabled = true;
|
||||
clk_enable(priv->clk);
|
||||
ret = clk_enable(priv->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
regmap_write(priv->regmap, TIM_PSC, prescaler);
|
||||
@ -173,7 +175,6 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv,
|
||||
|
||||
/* Enable controller */
|
||||
regmap_set_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN);
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -307,7 +308,7 @@ static ssize_t stm32_tt_store_master_mode(struct device *dev,
|
||||
struct stm32_timer_trigger *priv = dev_get_drvdata(dev);
|
||||
struct iio_trigger *trig = to_iio_trigger(dev);
|
||||
u32 mask, shift, master_mode_max;
|
||||
int i;
|
||||
int i, ret;
|
||||
|
||||
if (stm32_timer_is_trgo2_name(trig->name)) {
|
||||
mask = TIM_CR2_MMS2;
|
||||
@ -322,15 +323,16 @@ static ssize_t stm32_tt_store_master_mode(struct device *dev,
|
||||
for (i = 0; i <= master_mode_max; i++) {
|
||||
if (!strncmp(master_mode_table[i], buf,
|
||||
strlen(master_mode_table[i]))) {
|
||||
mutex_lock(&priv->lock);
|
||||
guard(mutex)(&priv->lock);
|
||||
if (!priv->enabled) {
|
||||
/* Clock should be enabled first */
|
||||
priv->enabled = true;
|
||||
clk_enable(priv->clk);
|
||||
ret = clk_enable(priv->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
regmap_update_bits(priv->regmap, TIM_CR2, mask,
|
||||
i << shift);
|
||||
mutex_unlock(&priv->lock);
|
||||
return len;
|
||||
}
|
||||
}
|
||||
@ -482,6 +484,7 @@ static int stm32_counter_write_raw(struct iio_dev *indio_dev,
|
||||
int val, int val2, long mask)
|
||||
{
|
||||
struct stm32_timer_trigger *priv = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
@ -491,12 +494,14 @@ static int stm32_counter_write_raw(struct iio_dev *indio_dev,
|
||||
/* fixed scale */
|
||||
return -EINVAL;
|
||||
|
||||
case IIO_CHAN_INFO_ENABLE:
|
||||
mutex_lock(&priv->lock);
|
||||
case IIO_CHAN_INFO_ENABLE: {
|
||||
guard(mutex)(&priv->lock);
|
||||
if (val) {
|
||||
if (!priv->enabled) {
|
||||
priv->enabled = true;
|
||||
clk_enable(priv->clk);
|
||||
ret = clk_enable(priv->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
regmap_set_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN);
|
||||
} else {
|
||||
@ -506,11 +511,12 @@ static int stm32_counter_write_raw(struct iio_dev *indio_dev,
|
||||
clk_disable(priv->clk);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int stm32_counter_validate_trigger(struct iio_dev *indio_dev,
|
||||
@ -602,6 +608,7 @@ static int stm32_set_enable_mode(struct iio_dev *indio_dev,
|
||||
{
|
||||
struct stm32_timer_trigger *priv = iio_priv(indio_dev);
|
||||
int sms = stm32_enable_mode2sms(mode);
|
||||
int ret;
|
||||
|
||||
if (sms < 0)
|
||||
return sms;
|
||||
@ -609,12 +616,15 @@ static int stm32_set_enable_mode(struct iio_dev *indio_dev,
|
||||
* Triggered mode sets CEN bit automatically by hardware. So, first
|
||||
* enable counter clock, so it can use it. Keeps it in sync with CEN.
|
||||
*/
|
||||
mutex_lock(&priv->lock);
|
||||
if (sms == 6 && !priv->enabled) {
|
||||
clk_enable(priv->clk);
|
||||
priv->enabled = true;
|
||||
scoped_guard(mutex, &priv->lock) {
|
||||
if (sms == 6 && !priv->enabled) {
|
||||
ret = clk_enable(priv->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->enabled = true;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, sms);
|
||||
|
||||
|
@ -29,6 +29,7 @@ struct ad_sd_calib_data {
|
||||
|
||||
struct ad_sigma_delta;
|
||||
struct device;
|
||||
struct gpio_desc;
|
||||
struct iio_dev;
|
||||
|
||||
/**
|
||||
@ -53,6 +54,7 @@ struct iio_dev;
|
||||
* @irq_flags: flags for the interrupt used by the triggered buffer
|
||||
* @num_slots: Number of sequencer slots
|
||||
* @irq_line: IRQ for reading conversions. If 0, spi->irq will be used
|
||||
* @num_resetclks: Number of SPI clk cycles with MOSI=1 to reset the chip.
|
||||
*/
|
||||
struct ad_sigma_delta_info {
|
||||
int (*set_channel)(struct ad_sigma_delta *, unsigned int channel);
|
||||
@ -69,6 +71,7 @@ struct ad_sigma_delta_info {
|
||||
unsigned long irq_flags;
|
||||
unsigned int num_slots;
|
||||
int irq_line;
|
||||
unsigned int num_resetclks;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -85,6 +88,7 @@ struct ad_sigma_delta {
|
||||
|
||||
/* private: */
|
||||
struct completion completion;
|
||||
spinlock_t irq_lock; /* protects .irq_dis and irq en/disable state */
|
||||
bool irq_dis;
|
||||
|
||||
bool bus_locked;
|
||||
@ -96,7 +100,8 @@ struct ad_sigma_delta {
|
||||
unsigned int active_slots;
|
||||
unsigned int current_slot;
|
||||
unsigned int num_slots;
|
||||
int irq_line;
|
||||
struct gpio_desc *rdy_gpiod;
|
||||
int irq_line;
|
||||
bool status_appended;
|
||||
/* map slots to channels in order to know what to expect from devices */
|
||||
unsigned int *slots;
|
||||
@ -178,8 +183,7 @@ int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
|
||||
int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
|
||||
unsigned int size, unsigned int *val);
|
||||
|
||||
int ad_sd_reset(struct ad_sigma_delta *sigma_delta,
|
||||
unsigned int reset_length);
|
||||
int ad_sd_reset(struct ad_sigma_delta *sigma_delta);
|
||||
|
||||
int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan, int *val);
|
||||
|
@ -418,7 +418,7 @@ unsigned int iio_get_channel_ext_info_count(struct iio_channel *chan);
|
||||
* @chan: The channel being queried.
|
||||
* @attr: The ext_info attribute to read.
|
||||
* @buf: Where to store the attribute value. Assumed to hold
|
||||
* at least PAGE_SIZE bytes.
|
||||
* at least PAGE_SIZE bytes and to be aligned at PAGE_SIZE.
|
||||
*
|
||||
* Returns the number of bytes written to buf (perhaps w/o zero termination;
|
||||
* it need not even be a string), or an error code.
|
||||
@ -445,7 +445,7 @@ ssize_t iio_write_channel_ext_info(struct iio_channel *chan, const char *attr,
|
||||
* iio_read_channel_label() - read label for a given channel
|
||||
* @chan: The channel being queried.
|
||||
* @buf: Where to store the attribute value. Assumed to hold
|
||||
* at least PAGE_SIZE bytes.
|
||||
* at least PAGE_SIZE bytes and to be aligned at PAGE_SIZE.
|
||||
*
|
||||
* Returns the number of bytes written to buf, or an error code.
|
||||
*/
|
||||
|
@ -28,7 +28,7 @@
|
||||
* @groupcounter: index of next attribute group
|
||||
* @legacy_scan_el_group: attribute group for legacy scan elements attribute group
|
||||
* @legacy_buffer_group: attribute group for legacy buffer attributes group
|
||||
* @bounce_buffer: for devices that call iio_push_to_buffers_with_timestamp_unaligned()
|
||||
* @bounce_buffer: for devices that call iio_push_to_buffers_with_ts_unaligned()
|
||||
* @bounce_buffer_size: size of currently allocate bounce buffer
|
||||
* @scan_index_timestamp: cache of the index to the timestamp
|
||||
* @clock_id: timestamping clock posix identifier
|
||||
|
@ -99,7 +99,6 @@ struct adis_data {
|
||||
* @spi: Reference to SPI device which owns this ADIS IIO device
|
||||
* @trig: IIO trigger object data
|
||||
* @data: ADIS chip variant specific data
|
||||
* @burst: ADIS burst transfer information
|
||||
* @burst_extra_len: Burst extra length. Should only be used by devices that can
|
||||
* dynamically change their burst mode length.
|
||||
* @state_lock: Lock used by the device to protect state
|
||||
|
Loading…
Reference in New Issue
Block a user