mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-19 02:04:19 +08:00
Third set of IIO new device support cleanups and fixes for the 5.5 cycle.
New device support * ad5446 - Support the ad5600 DAC (id only needed). * ad7292 ADC DAC etc - New driver plus dt-bindings. * veml6030 ambient light sensor - New driver plus dt-bindings and sysfs docs. Features * mpu6050 - Explicit VDD control. * stm32-adc - Allow limiting of max clock frequency from devicetree to ensure it's suitable for external circuitry. yaml binding conversions * ltc1660 * mcp3911 Fixes * adis16480 - Fix wrong scale factors. - Fix debugfs reg access by providing the callback. * cros_ec_baro - Fixing missing mask entry to make available sample frequencies visible in sysfs. * st_lsm6dsx - Explicitly handle different ODR table sizes. - Handle restrictions between slave ODR and accel ODR when both are enabled. - Allow ODR to be expressed more accurately by using miliHz. * tools - Fix an issue with parallel builds. Cleanups and warning fixes * adis16136, adis16400, adis16460, adis-lib - Change some checks on return values to be for 0 rather than strictly negative. Avoids some fiddly issues with the compiler concluding some variables are initialized due to a mixture of error checks. - Assign values only on success of 'read' operations - avoiding any chance the compiler will falsly suggest they might be used uninitialized. - Whitespace and simlar cleanups. * aspeed adc - devm_platfom_ioremap_resource to reduce boilerplate. * bcm-iproc-adc - Stray semicolon removal. * cc10001 - devm_platfom_ioremap_resource to reduce boilerplate. * dln2-adc - Reorganise the buffered mode setup and tear down. Part of moving towards being able to refactor this area of the IIO core. * hdc100x - Reorganise the buffered mode setup and tear down. * ingenic-adc - devm_platfom_ioremap_resource to reduce boilerplate. * lpc18xx-adc - devm_platfom_ioremap_resource to reduce boilerplate. * lpc18xx-dac - devm_platfom_ioremap_resource to reduce boilerplate. * mt6577 - devm_platfom_ioremap_resource to reduce boilerplate. * npcm - devm_platfom_ioremap_resource to reduce boilerplate. * rcar-gyroadc - devm_platfom_ioremap_resource to reduce boilerplate. * spear-adc - devm_platfom_ioremap_resource to reduce boilerplate. * vf610-adc - devm_platfom_ioremap_resource to reduce boilerplate. * vf610-dac - devm_platfom_ioremap_resource to reduce boilerplate. -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEEbilms4eEBlKRJoGxVIU0mcT0FogFAl3JsAoRHGppYzIzQGtl cm5lbC5vcmcACgkQVIU0mcT0Foiw0w//Qpe9IxW4kdiMZB0vMr0mz74Aa6niS1Rm c/vMEv7x/0cHjNBJWZiI4VQqScadVMMk2nD/KHAMt+9ZgZg+/r9d7PkVsrEIydZw XBFf8qwFYoxL6jAgWinuCWuWAE3o9aKVqqGj/aosloUwzZDBXUpmCSnRpBFOhEyp hbNNYZJo4Sbrg/xOYqyIaGJFTes0u+n8OuiS53dLN71lGW6BbGyJQtPzb/7rkOV/ z7zL0nbIfXszRrFQc17eBlblZvWl3QtHY08aiem8gcTkQbzTOTVWgLxyg+aZwBB2 XkCeeI21gLjVh2rxAcqBTs7OWObyGUjVES0+fAGBqIGEslq9nruMPrVrlTqkUHxJ +vMPPA2VqvAqLI6cBz8oG9HsO/TUTQaRV3tHMF5WnoX9mDEzu9A8V4Cd7pg15lc1 aEvDXq5UU+aocKOofvyZJ8LqBi0ZmxJpohMGHHyDPmdtlL/HuWWsn9FyzsSgdBuc EiGH+GKlUnG4mNOibr2L+TOBZwyelL+wGu40Xld3+KTyHyaysvQ2puP6wHTVf1da ME0e6sFDPk4k+JTmsT9vYljgEfW3IMuTzI0BePlsfsx3/SbMZqdYLkijIHM1mpyE yhaP/00u4aDFOlE1Ct0iwakUJ4Myxw0UeOz6deNKdTHcOExy28c8AIG6dqZhAJ9S ohWETBDIDzI= =ckQz -----END PGP SIGNATURE----- Merge tag 'iio-for-5.5c' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next Jonathan writes: Third set of IIO new device support cleanups and fixes for the 5.5 cycle. New device support * ad5446 - Support the ad5600 DAC (id only needed). * ad7292 ADC DAC etc - New driver plus dt-bindings. * veml6030 ambient light sensor - New driver plus dt-bindings and sysfs docs. Features * mpu6050 - Explicit VDD control. * stm32-adc - Allow limiting of max clock frequency from devicetree to ensure it's suitable for external circuitry. yaml binding conversions * ltc1660 * mcp3911 Fixes * adis16480 - Fix wrong scale factors. - Fix debugfs reg access by providing the callback. * cros_ec_baro - Fixing missing mask entry to make available sample frequencies visible in sysfs. * st_lsm6dsx - Explicitly handle different ODR table sizes. - Handle restrictions between slave ODR and accel ODR when both are enabled. - Allow ODR to be expressed more accurately by using miliHz. * tools - Fix an issue with parallel builds. Cleanups and warning fixes * adis16136, adis16400, adis16460, adis-lib - Change some checks on return values to be for 0 rather than strictly negative. Avoids some fiddly issues with the compiler concluding some variables are initialized due to a mixture of error checks. - Assign values only on success of 'read' operations - avoiding any chance the compiler will falsly suggest they might be used uninitialized. - Whitespace and simlar cleanups. * aspeed adc - devm_platfom_ioremap_resource to reduce boilerplate. * bcm-iproc-adc - Stray semicolon removal. * cc10001 - devm_platfom_ioremap_resource to reduce boilerplate. * dln2-adc - Reorganise the buffered mode setup and tear down. Part of moving towards being able to refactor this area of the IIO core. * hdc100x - Reorganise the buffered mode setup and tear down. * ingenic-adc - devm_platfom_ioremap_resource to reduce boilerplate. * lpc18xx-adc - devm_platfom_ioremap_resource to reduce boilerplate. * lpc18xx-dac - devm_platfom_ioremap_resource to reduce boilerplate. * mt6577 - devm_platfom_ioremap_resource to reduce boilerplate. * npcm - devm_platfom_ioremap_resource to reduce boilerplate. * rcar-gyroadc - devm_platfom_ioremap_resource to reduce boilerplate. * spear-adc - devm_platfom_ioremap_resource to reduce boilerplate. * vf610-adc - devm_platfom_ioremap_resource to reduce boilerplate. * vf610-dac - devm_platfom_ioremap_resource to reduce boilerplate. * tag 'iio-for-5.5c' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (43 commits) iio: adis16480: Add debugfs_reg_access entry iio: adis16480: Fix scales factors tools: iio: Correctly add make dependency for iio_utils iio: adc: Add driver support for AD7292 dt-bindings: iio: adc: Add dt-schema for AD7292 dt-bindings: iio: adc: Migrate MCP3911 documentation to yaml iio: imu: mpu6050: Add support for vdd-supply regulator dt-bindings: iio: imu: mpu6050: add vdd-supply iio: cros_ec_baro: set info_mask_shared_by_all_available field iio: dac: ad5446: Add support for new AD5600 DAC dt-bindings: iio: dac: Migrate LTC1660 documentation to yaml iio: documentation: light: Add veml6030 sysfs documentation dt-bindings: iio: light: add veml6030 ALS bindings iio: light: add driver for veml6030 ambient light sensor iio: imu: st_lsm6dsx: express odr in mHZ iio: imu: st_lsm6dsx: fix ODR check in st_lsm6dsx_write_raw iio: imu: st_lsm6dsx: explicitly define odr table size iio: adc: stm32: allow to tune analog clock dt-bindings: iio: stm32-adc: add max clock rate property iio: dac: vf610: Use devm_platform_ioremap_resource ...
This commit is contained in:
commit
8bde9f3d2a
@ -753,6 +753,8 @@ What: /sys/.../events/in_illuminance0_thresh_falling_value
|
||||
what: /sys/.../events/in_illuminance0_thresh_rising_value
|
||||
what: /sys/.../events/in_proximity0_thresh_falling_value
|
||||
what: /sys/.../events/in_proximity0_thresh_rising_value
|
||||
What: /sys/.../events/in_illuminance_thresh_rising_value
|
||||
What: /sys/.../events/in_illuminance_thresh_falling_value
|
||||
KernelVersion: 2.6.37
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
@ -972,6 +974,7 @@ What: /sys/.../events/in_activity_jogging_thresh_rising_period
|
||||
What: /sys/.../events/in_activity_jogging_thresh_falling_period
|
||||
What: /sys/.../events/in_activity_running_thresh_rising_period
|
||||
What: /sys/.../events/in_activity_running_thresh_falling_period
|
||||
What: /sys/.../events/in_illuminance_thresh_either_period
|
||||
KernelVersion: 2.6.37
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
@ -1715,3 +1718,11 @@ Description:
|
||||
Mass concentration reading of particulate matter in ug / m3.
|
||||
pmX consists of particles with aerodynamic diameter less or
|
||||
equal to X micrometers.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/events/in_illuminance_period_available
|
||||
Date: November 2019
|
||||
KernelVersion: 5.4
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
List of valid periods (in seconds) for which the light intensity
|
||||
must be above the threshold level before interrupt is asserted.
|
||||
|
104
Documentation/devicetree/bindings/iio/adc/adi,ad7292.yaml
Normal file
104
Documentation/devicetree/bindings/iio/adc/adi,ad7292.yaml
Normal file
@ -0,0 +1,104 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/adi,ad7292.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices AD7292 10-Bit Monitor and Control System
|
||||
|
||||
maintainers:
|
||||
- Marcelo Schmitt <marcelo.schmitt1@gmail.com>
|
||||
|
||||
description: |
|
||||
Analog Devices AD7292 10-Bit Monitor and Control System with ADC, DACs,
|
||||
Temperature Sensor, and GPIOs
|
||||
|
||||
Specifications about the part can be found at:
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7292.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,ad7292
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vref-supply:
|
||||
description: |
|
||||
The regulator supply for ADC and DAC reference voltage.
|
||||
|
||||
spi-cpha: true
|
||||
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- spi-cpha
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-7]$":
|
||||
type: object
|
||||
description: |
|
||||
Represents the external channels which are connected to the ADC.
|
||||
See Documentation/devicetree/bindings/iio/adc/adc.txt.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
description: |
|
||||
The channel number. It can have up to 8 channels numbered from 0 to 7.
|
||||
items:
|
||||
maximum: 7
|
||||
|
||||
diff-channels:
|
||||
description: see Documentation/devicetree/bindings/iio/adc/adc.txt
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
examples:
|
||||
- |
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ad7292: adc@0 {
|
||||
compatible = "adi,ad7292";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <25000000>;
|
||||
vref-supply = <&adc_vref>;
|
||||
spi-cpha;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
channel@0 {
|
||||
reg = <0>;
|
||||
diff-channels = <0 1>;
|
||||
};
|
||||
channel@2 {
|
||||
reg = <2>;
|
||||
};
|
||||
channel@3 {
|
||||
reg = <3>;
|
||||
};
|
||||
channel@4 {
|
||||
reg = <4>;
|
||||
};
|
||||
channel@5 {
|
||||
reg = <5>;
|
||||
};
|
||||
channel@6 {
|
||||
reg = <6>;
|
||||
};
|
||||
channel@7 {
|
||||
reg = <7>;
|
||||
};
|
||||
};
|
||||
};
|
@ -1,30 +0,0 @@
|
||||
* Microchip MCP3911 Dual channel analog front end (ADC)
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "microchip,mcp3911"
|
||||
- reg: SPI chip select number for the device
|
||||
|
||||
Recommended properties:
|
||||
- spi-max-frequency: Definition as per
|
||||
Documentation/devicetree/bindings/spi/spi-bus.txt.
|
||||
Max frequency for this chip is 20MHz.
|
||||
|
||||
Optional properties:
|
||||
- clocks: Phandle and clock identifier for sampling clock
|
||||
- interrupt-parent: Phandle to the parent interrupt controller
|
||||
- interrupts: IRQ line for the ADC
|
||||
- microchip,device-addr: Device address when multiple MCP3911 chips are present on the
|
||||
same SPI bus. Valid values are 0-3. Defaults to 0.
|
||||
- vref-supply: Phandle to the external reference voltage supply.
|
||||
|
||||
Example:
|
||||
adc@0 {
|
||||
compatible = "microchip,mcp3911";
|
||||
reg = <0>;
|
||||
interrupt-parent = <&gpio5>;
|
||||
interrupts = <15 IRQ_TYPE_EDGE_RISING>;
|
||||
spi-max-frequency = <20000000>;
|
||||
microchip,device-addr = <0>;
|
||||
vref-supply = <&vref_reg>;
|
||||
clocks = <&xtal>;
|
||||
};
|
@ -0,0 +1,71 @@
|
||||
# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
|
||||
# Copyright 2019 Marcus Folkesson <marcus.folkesson@gmail.com>
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/bindings/iio/adc/microchip,mcp3911.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Microchip MCP3911 Dual channel analog front end (ADC)
|
||||
|
||||
maintainers:
|
||||
- Marcus Folkesson <marcus.folkesson@gmail.com>
|
||||
- Kent Gustavsson <nedo80@gmail.com>
|
||||
|
||||
description: |
|
||||
Bindings for the Microchip MCP3911 Dual channel ADC device. Datasheet can be
|
||||
found here: https://ww1.microchip.com/downloads/en/DeviceDoc/20002286C.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- microchip,mcp3911
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
spi-max-frequency:
|
||||
maximum: 20000000
|
||||
|
||||
clocks:
|
||||
description: |
|
||||
Phandle and clock identifier for external sampling clock.
|
||||
If not specified, the internal crystal oscillator will be used.
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
description: IRQ line of the ADC
|
||||
maxItems: 1
|
||||
|
||||
microchip,device-addr:
|
||||
description: Device address when multiple MCP3911 chips are present on the same SPI bus.
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
- enum: [0, 1, 2, 3]
|
||||
- default: 0
|
||||
|
||||
vref-supply:
|
||||
description: |
|
||||
Phandle to the external reference voltage supply.
|
||||
If not specified, the internal voltage reference (1.2V) will be used.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
examples:
|
||||
- |
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
adc@0 {
|
||||
compatible = "microchip,mcp3911";
|
||||
reg = <0>;
|
||||
interrupt-parent = <&gpio5>;
|
||||
interrupts = <15 2>;
|
||||
spi-max-frequency = <20000000>;
|
||||
microchip,device-addr = <0>;
|
||||
vref-supply = <&vref_reg>;
|
||||
clocks = <&xtal>;
|
||||
};
|
||||
};
|
@ -53,6 +53,8 @@ Optional properties:
|
||||
analog input switches on stm32mp1.
|
||||
- st,syscfg: Phandle to system configuration controller. It can be used to
|
||||
control the analog circuitry on stm32mp1.
|
||||
- st,max-clk-rate-hz: Allow to specify desired max clock rate used by analog
|
||||
circuitry.
|
||||
|
||||
Contents of a stm32 adc child node:
|
||||
-----------------------------------
|
||||
|
49
Documentation/devicetree/bindings/iio/dac/lltc,ltc1660.yaml
Normal file
49
Documentation/devicetree/bindings/iio/dac/lltc,ltc1660.yaml
Normal file
@ -0,0 +1,49 @@
|
||||
# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
|
||||
# Copyright 2019 Marcus Folkesson <marcus.folkesson@gmail.com>
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/bindings/iio/dac/lltc,ltc1660.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Linear Technology Micropower octal 8-Bit and 10-Bit DACs
|
||||
|
||||
maintainers:
|
||||
- Marcus Folkesson <marcus.folkesson@gmail.com>
|
||||
|
||||
description: |
|
||||
Bindings for the Linear Technology Micropower octal 8-Bit and 10-Bit DAC.
|
||||
Datasheet can be found here: https://www.analog.com/media/en/technical-documentation/data-sheets/166560fa.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- lltc,ltc1660
|
||||
- lltc,ltc1665
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
spi-max-frequency:
|
||||
maximum: 5000000
|
||||
|
||||
vref-supply:
|
||||
description: Phandle to the external reference voltage supply.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vref-supply
|
||||
|
||||
examples:
|
||||
- |
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
dac@0 {
|
||||
compatible = "lltc,ltc1660";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <5000000>;
|
||||
vref-supply = <&vref_reg>;
|
||||
};
|
||||
};
|
@ -1,21 +0,0 @@
|
||||
* Linear Technology Micropower octal 8-Bit and 10-Bit DACs
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be one of the following:
|
||||
"lltc,ltc1660"
|
||||
"lltc,ltc1665"
|
||||
- reg: SPI chip select number for the device
|
||||
- vref-supply: Phandle to the voltage reference supply
|
||||
|
||||
Recommended properties:
|
||||
- spi-max-frequency: Definition as per
|
||||
Documentation/devicetree/bindings/spi/spi-bus.txt.
|
||||
Max frequency for this chip is 5 MHz.
|
||||
|
||||
Example:
|
||||
dac@0 {
|
||||
compatible = "lltc,ltc1660";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <5000000>;
|
||||
vref-supply = <&vref_reg>;
|
||||
};
|
@ -21,6 +21,7 @@ Required properties:
|
||||
bindings.
|
||||
|
||||
Optional properties:
|
||||
- vdd-supply: regulator phandle for VDD supply
|
||||
- vddio-supply: regulator phandle for VDDIO supply
|
||||
- mount-matrix: an optional 3x3 mounting rotation matrix
|
||||
- i2c-gate node. These devices also support an auxiliary i2c bus. This is
|
||||
|
62
Documentation/devicetree/bindings/iio/light/veml6030.yaml
Normal file
62
Documentation/devicetree/bindings/iio/light/veml6030.yaml
Normal file
@ -0,0 +1,62 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/light/veml6030.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: VEML6030 Ambient Light Sensor (ALS)
|
||||
|
||||
maintainers:
|
||||
- Rishi Gupta <gupt21@gmail.com>
|
||||
|
||||
description: |
|
||||
Bindings for the ambient light sensor veml6030 from Vishay
|
||||
Semiconductors over an i2c interface.
|
||||
|
||||
Irrespective of whether interrupt is used or not, application
|
||||
can get the ALS and White channel reading from IIO raw interface.
|
||||
|
||||
If the interrupts are used, application will receive an IIO event
|
||||
whenever configured threshold is crossed.
|
||||
|
||||
Specifications about the sensor can be found at:
|
||||
https://www.vishay.com/docs/84366/veml6030.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- vishay,veml6030
|
||||
|
||||
reg:
|
||||
description:
|
||||
I2C address of the device.
|
||||
enum:
|
||||
- 0x10 # ADDR pin pulled down
|
||||
- 0x48 # ADDR pin pulled up
|
||||
|
||||
interrupts:
|
||||
description:
|
||||
interrupt mapping for IRQ. Configure with IRQ_TYPE_LEVEL_LOW.
|
||||
Refer to interrupt-controller/interrupts.txt for generic
|
||||
interrupt client node bindings.
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
light-sensor@10 {
|
||||
compatible = "vishay,veml6030";
|
||||
reg = <0x10>;
|
||||
interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
|
||||
};
|
||||
};
|
||||
...
|
12
MAINTAINERS
12
MAINTAINERS
@ -901,6 +901,14 @@ S: Supported
|
||||
F: drivers/iio/adc/ad7124.c
|
||||
F: Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml
|
||||
|
||||
ANALOG DEVICES INC AD7292 DRIVER
|
||||
M: Marcelo Schmitt <marcelo.schmitt1@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
W: http://ez.analog.com/community/linux-device-drivers
|
||||
S: Supported
|
||||
F: drivers/iio/adc/ad7292.c
|
||||
F: Documentation/devicetree/bindings/iio/adc/adi,ad7292.yaml
|
||||
|
||||
ANALOG DEVICES INC AD7606 DRIVER
|
||||
M: Stefan Popa <stefan.popa@analog.com>
|
||||
M: Beniamin Bia <beniamin.bia@analog.com>
|
||||
@ -9622,7 +9630,7 @@ LTC1660 DAC DRIVER
|
||||
M: Marcus Folkesson <marcus.folkesson@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/dac/ltc1660.txt
|
||||
F: Documentation/devicetree/bindings/iio/dac/lltc,ltc1660.yaml
|
||||
F: drivers/iio/dac/ltc1660.c
|
||||
|
||||
LTC2983 IIO TEMPERATURE DRIVER
|
||||
@ -10738,7 +10746,7 @@ M: Kent Gustavsson <kent@minoris.se>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/iio/adc/mcp3911.c
|
||||
F: Documentation/devicetree/bindings/iio/adc/mcp3911.txt
|
||||
F: Documentation/devicetree/bindings/iio/adc/microchip,mcp3911.yaml
|
||||
|
||||
MICROCHIP NAND DRIVER
|
||||
M: Tudor Ambarus <tudor.ambarus@microchip.com>
|
||||
|
@ -55,6 +55,16 @@ config AD7291
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ad7291.
|
||||
|
||||
config AD7292
|
||||
tristate "Analog Devices AD7292 ADC driver"
|
||||
depends on SPI
|
||||
help
|
||||
Say yes here to build support for Analog Devices AD7292
|
||||
8 Channel ADC with temperature sensor.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ad7292.
|
||||
|
||||
config AD7298
|
||||
tristate "Analog Devices AD7298 ADC driver"
|
||||
depends on SPI
|
||||
|
@ -9,6 +9,7 @@ obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
|
||||
obj-$(CONFIG_AD7124) += ad7124.o
|
||||
obj-$(CONFIG_AD7266) += ad7266.o
|
||||
obj-$(CONFIG_AD7291) += ad7291.o
|
||||
obj-$(CONFIG_AD7292) += ad7292.o
|
||||
obj-$(CONFIG_AD7298) += ad7298.o
|
||||
obj-$(CONFIG_AD7923) += ad7923.o
|
||||
obj-$(CONFIG_AD7476) += ad7476.o
|
||||
|
350
drivers/iio/adc/ad7292.c
Normal file
350
drivers/iio/adc/ad7292.c
Normal file
@ -0,0 +1,350 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Analog Devices AD7292 SPI ADC driver
|
||||
*
|
||||
* Copyright 2019 Analog Devices Inc.
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
|
||||
#define ADI_VENDOR_ID 0x0018
|
||||
|
||||
/* AD7292 registers definition */
|
||||
#define AD7292_REG_VENDOR_ID 0x00
|
||||
#define AD7292_REG_CONF_BANK 0x05
|
||||
#define AD7292_REG_CONV_COMM 0x0E
|
||||
#define AD7292_REG_ADC_CH(x) (0x10 + (x))
|
||||
|
||||
/* AD7292 configuration bank subregisters definition */
|
||||
#define AD7292_BANK_REG_VIN_RNG0 0x10
|
||||
#define AD7292_BANK_REG_VIN_RNG1 0x11
|
||||
#define AD7292_BANK_REG_SAMP_MODE 0x12
|
||||
|
||||
#define AD7292_RD_FLAG_MSK(x) (BIT(7) | ((x) & 0x3F))
|
||||
|
||||
/* AD7292_REG_ADC_CONVERSION */
|
||||
#define AD7292_ADC_DATA_MASK GENMASK(15, 6)
|
||||
#define AD7292_ADC_DATA(x) FIELD_GET(AD7292_ADC_DATA_MASK, x)
|
||||
|
||||
/* AD7292_CHANNEL_SAMPLING_MODE */
|
||||
#define AD7292_CH_SAMP_MODE(reg, ch) (((reg) >> 8) & BIT(ch))
|
||||
|
||||
/* AD7292_CHANNEL_VIN_RANGE */
|
||||
#define AD7292_CH_VIN_RANGE(reg, ch) ((reg) & BIT(ch))
|
||||
|
||||
#define AD7292_VOLTAGE_CHAN(_chan) \
|
||||
{ \
|
||||
.type = IIO_VOLTAGE, \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||
BIT(IIO_CHAN_INFO_SCALE), \
|
||||
.indexed = 1, \
|
||||
.channel = _chan, \
|
||||
}
|
||||
|
||||
static const struct iio_chan_spec ad7292_channels[] = {
|
||||
AD7292_VOLTAGE_CHAN(0),
|
||||
AD7292_VOLTAGE_CHAN(1),
|
||||
AD7292_VOLTAGE_CHAN(2),
|
||||
AD7292_VOLTAGE_CHAN(3),
|
||||
AD7292_VOLTAGE_CHAN(4),
|
||||
AD7292_VOLTAGE_CHAN(5),
|
||||
AD7292_VOLTAGE_CHAN(6),
|
||||
AD7292_VOLTAGE_CHAN(7)
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec ad7292_channels_diff[] = {
|
||||
{
|
||||
.type = IIO_VOLTAGE,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
||||
.indexed = 1,
|
||||
.differential = 1,
|
||||
.channel = 0,
|
||||
.channel2 = 1,
|
||||
},
|
||||
AD7292_VOLTAGE_CHAN(2),
|
||||
AD7292_VOLTAGE_CHAN(3),
|
||||
AD7292_VOLTAGE_CHAN(4),
|
||||
AD7292_VOLTAGE_CHAN(5),
|
||||
AD7292_VOLTAGE_CHAN(6),
|
||||
AD7292_VOLTAGE_CHAN(7)
|
||||
};
|
||||
|
||||
struct ad7292_state {
|
||||
struct spi_device *spi;
|
||||
struct regulator *reg;
|
||||
unsigned short vref_mv;
|
||||
|
||||
__be16 d16 ____cacheline_aligned;
|
||||
u8 d8[2];
|
||||
};
|
||||
|
||||
static int ad7292_spi_reg_read(struct ad7292_state *st, unsigned int addr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
st->d8[0] = AD7292_RD_FLAG_MSK(addr);
|
||||
|
||||
ret = spi_write_then_read(st->spi, st->d8, 1, &st->d16, 2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return be16_to_cpu(st->d16);
|
||||
}
|
||||
|
||||
static int ad7292_spi_subreg_read(struct ad7292_state *st, unsigned int addr,
|
||||
unsigned int sub_addr, unsigned int len)
|
||||
{
|
||||
unsigned int shift = 16 - (8 * len);
|
||||
int ret;
|
||||
|
||||
st->d8[0] = AD7292_RD_FLAG_MSK(addr);
|
||||
st->d8[1] = sub_addr;
|
||||
|
||||
ret = spi_write_then_read(st->spi, st->d8, 2, &st->d16, len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return (be16_to_cpu(st->d16) >> shift);
|
||||
}
|
||||
|
||||
static int ad7292_single_conversion(struct ad7292_state *st,
|
||||
unsigned int chan_addr)
|
||||
{
|
||||
int ret;
|
||||
|
||||
struct spi_transfer t[] = {
|
||||
{
|
||||
.tx_buf = &st->d8,
|
||||
.len = 4,
|
||||
.delay_usecs = 6,
|
||||
}, {
|
||||
.rx_buf = &st->d16,
|
||||
.len = 2,
|
||||
},
|
||||
};
|
||||
|
||||
st->d8[0] = chan_addr;
|
||||
st->d8[1] = AD7292_RD_FLAG_MSK(AD7292_REG_CONV_COMM);
|
||||
|
||||
ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return be16_to_cpu(st->d16);
|
||||
}
|
||||
|
||||
static int ad7292_vin_range_multiplier(struct ad7292_state *st, int channel)
|
||||
{
|
||||
int samp_mode, range0, range1, factor = 1;
|
||||
|
||||
/*
|
||||
* Every AD7292 ADC channel may have its input range adjusted according
|
||||
* to the settings at the ADC sampling mode and VIN range subregisters.
|
||||
* For a given channel, the minimum input range is equal to Vref, and it
|
||||
* may be increased by a multiplier factor of 2 or 4 according to the
|
||||
* following rule:
|
||||
* If channel is being sampled with respect to AGND:
|
||||
* factor = 4 if VIN range0 and VIN range1 equal 0
|
||||
* factor = 2 if only one of VIN ranges equal 1
|
||||
* factor = 1 if both VIN range0 and VIN range1 equal 1
|
||||
* If channel is being sampled with respect to AVDD:
|
||||
* factor = 4 if VIN range0 and VIN range1 equal 0
|
||||
* Behavior is undefined if any of VIN range doesn't equal 0
|
||||
*/
|
||||
|
||||
samp_mode = ad7292_spi_subreg_read(st, AD7292_REG_CONF_BANK,
|
||||
AD7292_BANK_REG_SAMP_MODE, 2);
|
||||
|
||||
if (samp_mode < 0)
|
||||
return samp_mode;
|
||||
|
||||
range0 = ad7292_spi_subreg_read(st, AD7292_REG_CONF_BANK,
|
||||
AD7292_BANK_REG_VIN_RNG0, 2);
|
||||
|
||||
if (range0 < 0)
|
||||
return range0;
|
||||
|
||||
range1 = ad7292_spi_subreg_read(st, AD7292_REG_CONF_BANK,
|
||||
AD7292_BANK_REG_VIN_RNG1, 2);
|
||||
|
||||
if (range1 < 0)
|
||||
return range1;
|
||||
|
||||
if (AD7292_CH_SAMP_MODE(samp_mode, channel)) {
|
||||
/* Sampling with respect to AGND */
|
||||
if (!AD7292_CH_VIN_RANGE(range0, channel))
|
||||
factor *= 2;
|
||||
|
||||
if (!AD7292_CH_VIN_RANGE(range1, channel))
|
||||
factor *= 2;
|
||||
|
||||
} else {
|
||||
/* Sampling with respect to AVDD */
|
||||
if (AD7292_CH_VIN_RANGE(range0, channel) ||
|
||||
AD7292_CH_VIN_RANGE(range1, channel))
|
||||
return -EPERM;
|
||||
|
||||
factor = 4;
|
||||
}
|
||||
|
||||
return factor;
|
||||
}
|
||||
|
||||
static int ad7292_read_raw(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
int *val, int *val2, long info)
|
||||
{
|
||||
struct ad7292_state *st = iio_priv(indio_dev);
|
||||
unsigned int ch_addr;
|
||||
int ret;
|
||||
|
||||
switch (info) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
ch_addr = AD7292_REG_ADC_CH(chan->channel);
|
||||
ret = ad7292_single_conversion(st, ch_addr);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*val = AD7292_ADC_DATA(ret);
|
||||
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
/*
|
||||
* To convert a raw value to standard units, the IIO defines
|
||||
* this formula: Scaled value = (raw + offset) * scale.
|
||||
* For the scale to be a correct multiplier for (raw + offset),
|
||||
* it must be calculated as the input range divided by the
|
||||
* number of possible distinct input values. Given the ADC data
|
||||
* is 10 bit long, it may assume 2^10 distinct values.
|
||||
* Hence, scale = range / 2^10. The IIO_VAL_FRACTIONAL_LOG2
|
||||
* return type indicates to the IIO API to divide *val by 2 to
|
||||
* the power of *val2 when returning from read_raw.
|
||||
*/
|
||||
|
||||
ret = ad7292_vin_range_multiplier(st, chan->channel);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*val = st->vref_mv * ret;
|
||||
*val2 = 10;
|
||||
return IIO_VAL_FRACTIONAL_LOG2;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct iio_info ad7292_info = {
|
||||
.read_raw = ad7292_read_raw,
|
||||
};
|
||||
|
||||
static void ad7292_regulator_disable(void *data)
|
||||
{
|
||||
struct ad7292_state *st = data;
|
||||
|
||||
regulator_disable(st->reg);
|
||||
}
|
||||
|
||||
static int ad7292_probe(struct spi_device *spi)
|
||||
{
|
||||
struct ad7292_state *st;
|
||||
struct iio_dev *indio_dev;
|
||||
struct device_node *child;
|
||||
bool diff_channels = 0;
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
st->spi = spi;
|
||||
|
||||
ret = ad7292_spi_reg_read(st, AD7292_REG_VENDOR_ID);
|
||||
if (ret != ADI_VENDOR_ID) {
|
||||
dev_err(&spi->dev, "Wrong vendor id 0x%x\n", ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spi_set_drvdata(spi, indio_dev);
|
||||
|
||||
st->reg = devm_regulator_get_optional(&spi->dev, "vref");
|
||||
if (!IS_ERR(st->reg)) {
|
||||
ret = regulator_enable(st->reg);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev,
|
||||
"Failed to enable external vref supply\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_add_action_or_reset(&spi->dev,
|
||||
ad7292_regulator_disable, st);
|
||||
if (ret) {
|
||||
regulator_disable(st->reg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regulator_get_voltage(st->reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
st->vref_mv = ret / 1000;
|
||||
} else {
|
||||
/* Use the internal voltage reference. */
|
||||
st->vref_mv = 1250;
|
||||
}
|
||||
|
||||
indio_dev->dev.parent = &spi->dev;
|
||||
indio_dev->name = spi_get_device_id(spi)->name;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->info = &ad7292_info;
|
||||
|
||||
for_each_available_child_of_node(spi->dev.of_node, child) {
|
||||
diff_channels = of_property_read_bool(child, "diff-channels");
|
||||
if (diff_channels)
|
||||
break;
|
||||
}
|
||||
|
||||
if (diff_channels) {
|
||||
indio_dev->num_channels = ARRAY_SIZE(ad7292_channels_diff);
|
||||
indio_dev->channels = ad7292_channels_diff;
|
||||
} else {
|
||||
indio_dev->num_channels = ARRAY_SIZE(ad7292_channels);
|
||||
indio_dev->channels = ad7292_channels;
|
||||
}
|
||||
|
||||
return devm_iio_device_register(&spi->dev, indio_dev);
|
||||
}
|
||||
|
||||
static const struct spi_device_id ad7292_id_table[] = {
|
||||
{ "ad7292", 0 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, ad7292_id_table);
|
||||
|
||||
static const struct of_device_id ad7292_of_match[] = {
|
||||
{ .compatible = "adi,ad7292" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ad7292_of_match);
|
||||
|
||||
static struct spi_driver ad7292_driver = {
|
||||
.driver = {
|
||||
.name = "ad7292",
|
||||
.of_match_table = ad7292_of_match,
|
||||
},
|
||||
.probe = ad7292_probe,
|
||||
.id_table = ad7292_id_table,
|
||||
};
|
||||
module_spi_driver(ad7292_driver);
|
||||
|
||||
MODULE_AUTHOR("Marcelo Schmitt <marcelo.schmitt1@gmail.com>");
|
||||
MODULE_DESCRIPTION("Analog Devices AD7292 ADC driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -173,7 +173,6 @@ static int aspeed_adc_probe(struct platform_device *pdev)
|
||||
struct iio_dev *indio_dev;
|
||||
struct aspeed_adc_data *data;
|
||||
const struct aspeed_adc_model_data *model_data;
|
||||
struct resource *res;
|
||||
const char *clk_parent_name;
|
||||
int ret;
|
||||
u32 adc_engine_control_reg_val;
|
||||
@ -185,8 +184,7 @@ static int aspeed_adc_probe(struct platform_device *pdev)
|
||||
data = iio_priv(indio_dev);
|
||||
data->dev = &pdev->dev;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
data->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
data->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(data->base))
|
||||
return PTR_ERR(data->base);
|
||||
|
||||
|
@ -308,7 +308,7 @@ static int iproc_adc_do_read(struct iio_dev *indio_dev,
|
||||
"IntMask set failed. Read will likely fail.");
|
||||
read_len = -EIO;
|
||||
goto adc_err;
|
||||
};
|
||||
}
|
||||
}
|
||||
regmap_read(adc_priv->regmap, IPROC_INTERRUPT_MASK, &val_check);
|
||||
|
||||
|
@ -310,7 +310,6 @@ static int cc10001_adc_probe(struct platform_device *pdev)
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct cc10001_adc_device *adc_dev;
|
||||
unsigned long adc_clk_rate;
|
||||
struct resource *res;
|
||||
struct iio_dev *indio_dev;
|
||||
unsigned long channel_map;
|
||||
int ret;
|
||||
@ -340,8 +339,7 @@ static int cc10001_adc_probe(struct platform_device *pdev)
|
||||
indio_dev->info = &cc10001_adc_info;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
adc_dev->reg_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
adc_dev->reg_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(adc_dev->reg_base)) {
|
||||
ret = PTR_ERR(adc_dev->reg_base);
|
||||
goto err_disable_reg;
|
||||
|
@ -524,6 +524,10 @@ static int dln2_adc_triggered_buffer_postenable(struct iio_dev *indio_dev)
|
||||
u16 conflict;
|
||||
unsigned int trigger_chan;
|
||||
|
||||
ret = iio_triggered_buffer_postenable(indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&dln2->mutex);
|
||||
|
||||
/* Enable ADC */
|
||||
@ -537,6 +541,7 @@ static int dln2_adc_triggered_buffer_postenable(struct iio_dev *indio_dev)
|
||||
(int)conflict);
|
||||
ret = -EBUSY;
|
||||
}
|
||||
iio_triggered_buffer_predisable(indio_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -550,6 +555,7 @@ static int dln2_adc_triggered_buffer_postenable(struct iio_dev *indio_dev)
|
||||
mutex_unlock(&dln2->mutex);
|
||||
if (ret < 0) {
|
||||
dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__);
|
||||
iio_triggered_buffer_predisable(indio_dev);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
@ -557,12 +563,12 @@ static int dln2_adc_triggered_buffer_postenable(struct iio_dev *indio_dev)
|
||||
mutex_unlock(&dln2->mutex);
|
||||
}
|
||||
|
||||
return iio_triggered_buffer_postenable(indio_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dln2_adc_triggered_buffer_predisable(struct iio_dev *indio_dev)
|
||||
{
|
||||
int ret;
|
||||
int ret, ret2;
|
||||
struct dln2_adc *dln2 = iio_priv(indio_dev);
|
||||
|
||||
mutex_lock(&dln2->mutex);
|
||||
@ -577,12 +583,14 @@ static int dln2_adc_triggered_buffer_predisable(struct iio_dev *indio_dev)
|
||||
ret = dln2_adc_set_port_enabled(dln2, false, NULL);
|
||||
|
||||
mutex_unlock(&dln2->mutex);
|
||||
if (ret < 0) {
|
||||
if (ret < 0)
|
||||
dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return iio_triggered_buffer_predisable(indio_dev);
|
||||
ret2 = iio_triggered_buffer_predisable(indio_dev);
|
||||
if (ret == 0)
|
||||
ret = ret2;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct iio_buffer_setup_ops dln2_adc_buffer_setup_ops = {
|
||||
|
@ -428,7 +428,6 @@ static int ingenic_adc_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct iio_dev *iio_dev;
|
||||
struct ingenic_adc *adc;
|
||||
struct resource *mem_base;
|
||||
const struct ingenic_adc_soc_data *soc_data;
|
||||
int ret;
|
||||
|
||||
@ -445,8 +444,7 @@ static int ingenic_adc_probe(struct platform_device *pdev)
|
||||
mutex_init(&adc->aux_lock);
|
||||
adc->soc_data = soc_data;
|
||||
|
||||
mem_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
adc->base = devm_ioremap_resource(dev, mem_base);
|
||||
adc->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(adc->base))
|
||||
return PTR_ERR(adc->base);
|
||||
|
||||
|
@ -119,7 +119,6 @@ static int lpc18xx_adc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct iio_dev *indio_dev;
|
||||
struct lpc18xx_adc *adc;
|
||||
struct resource *res;
|
||||
unsigned int clkdiv;
|
||||
unsigned long rate;
|
||||
int ret;
|
||||
@ -133,8 +132,7 @@ static int lpc18xx_adc_probe(struct platform_device *pdev)
|
||||
adc->dev = &pdev->dev;
|
||||
mutex_init(&adc->lock);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
adc->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
adc->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(adc->base))
|
||||
return PTR_ERR(adc->base);
|
||||
|
||||
|
@ -237,7 +237,6 @@ static int mt6577_auxadc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct mt6577_auxadc_device *adc_dev;
|
||||
unsigned long adc_clk_rate;
|
||||
struct resource *res;
|
||||
struct iio_dev *indio_dev;
|
||||
int ret;
|
||||
|
||||
@ -253,8 +252,7 @@ static int mt6577_auxadc_probe(struct platform_device *pdev)
|
||||
indio_dev->channels = mt6577_auxadc_iio_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(mt6577_auxadc_iio_channels);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
adc_dev->reg_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
adc_dev->reg_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(adc_dev->reg_base)) {
|
||||
dev_err(&pdev->dev, "failed to get auxadc base address\n");
|
||||
return PTR_ERR(adc_dev->reg_base);
|
||||
|
@ -183,7 +183,6 @@ static int npcm_adc_probe(struct platform_device *pdev)
|
||||
int irq;
|
||||
u32 div;
|
||||
u32 reg_con;
|
||||
struct resource *res;
|
||||
struct npcm_adc *info;
|
||||
struct iio_dev *indio_dev;
|
||||
struct device *dev = &pdev->dev;
|
||||
@ -196,8 +195,7 @@ static int npcm_adc_probe(struct platform_device *pdev)
|
||||
|
||||
info->dev = &pdev->dev;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
info->regs = devm_ioremap_resource(&pdev->dev, res);
|
||||
info->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(info->regs))
|
||||
return PTR_ERR(info->regs);
|
||||
|
||||
|
@ -481,7 +481,6 @@ static int rcar_gyroadc_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct rcar_gyroadc *priv;
|
||||
struct iio_dev *indio_dev;
|
||||
struct resource *mem;
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
|
||||
@ -491,8 +490,7 @@ static int rcar_gyroadc_probe(struct platform_device *pdev)
|
||||
priv = iio_priv(indio_dev);
|
||||
priv->dev = dev;
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
priv->regs = devm_ioremap_resource(dev, mem);
|
||||
priv->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(priv->regs))
|
||||
return PTR_ERR(priv->regs);
|
||||
|
||||
|
@ -260,7 +260,6 @@ static int spear_adc_probe(struct platform_device *pdev)
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct spear_adc_state *st;
|
||||
struct resource *res;
|
||||
struct iio_dev *indio_dev = NULL;
|
||||
int ret = -ENODEV;
|
||||
int irq;
|
||||
@ -279,8 +278,7 @@ static int spear_adc_probe(struct platform_device *pdev)
|
||||
* (e.g. SPEAr3xx). Let's provide two register base addresses
|
||||
* to support multi-arch kernels.
|
||||
*/
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
st->adc_base_spear6xx = devm_ioremap_resource(&pdev->dev, res);
|
||||
st->adc_base_spear6xx = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(st->adc_base_spear6xx))
|
||||
return PTR_ERR(st->adc_base_spear6xx);
|
||||
|
||||
|
@ -79,6 +79,7 @@ struct stm32_adc_priv_cfg {
|
||||
* @domain: irq domain reference
|
||||
* @aclk: clock reference for the analog circuitry
|
||||
* @bclk: bus clock common for all ADCs, depends on part used
|
||||
* @max_clk_rate: desired maximum clock rate
|
||||
* @booster: booster supply reference
|
||||
* @vdd: vdd supply reference
|
||||
* @vdda: vdda analog supply reference
|
||||
@ -95,6 +96,7 @@ struct stm32_adc_priv {
|
||||
struct irq_domain *domain;
|
||||
struct clk *aclk;
|
||||
struct clk *bclk;
|
||||
u32 max_clk_rate;
|
||||
struct regulator *booster;
|
||||
struct regulator *vdd;
|
||||
struct regulator *vdda;
|
||||
@ -141,7 +143,7 @@ static int stm32f4_adc_clk_sel(struct platform_device *pdev,
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) {
|
||||
if ((rate / stm32f4_pclk_div[i]) <= priv->cfg->max_clk_rate_hz)
|
||||
if ((rate / stm32f4_pclk_div[i]) <= priv->max_clk_rate)
|
||||
break;
|
||||
}
|
||||
if (i >= ARRAY_SIZE(stm32f4_pclk_div)) {
|
||||
@ -230,7 +232,7 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev,
|
||||
if (ckmode)
|
||||
continue;
|
||||
|
||||
if ((rate / div) <= priv->cfg->max_clk_rate_hz)
|
||||
if ((rate / div) <= priv->max_clk_rate)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@ -250,7 +252,7 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev,
|
||||
if (!ckmode)
|
||||
continue;
|
||||
|
||||
if ((rate / div) <= priv->cfg->max_clk_rate_hz)
|
||||
if ((rate / div) <= priv->max_clk_rate)
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -655,6 +657,7 @@ static int stm32_adc_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct resource *res;
|
||||
u32 max_rate;
|
||||
int ret;
|
||||
|
||||
if (!pdev->dev.of_node)
|
||||
@ -731,6 +734,13 @@ static int stm32_adc_probe(struct platform_device *pdev)
|
||||
priv->common.vref_mv = ret / 1000;
|
||||
dev_dbg(&pdev->dev, "vref+=%dmV\n", priv->common.vref_mv);
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node, "st,max-clk-rate-hz",
|
||||
&max_rate);
|
||||
if (!ret)
|
||||
priv->max_clk_rate = min(max_rate, priv->cfg->max_clk_rate_hz);
|
||||
else
|
||||
priv->max_clk_rate = priv->cfg->max_clk_rate_hz;
|
||||
|
||||
ret = priv->cfg->clk_sel(pdev, priv);
|
||||
if (ret < 0)
|
||||
goto err_hw_stop;
|
||||
|
@ -802,7 +802,6 @@ static int vf610_adc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct vf610_adc *info;
|
||||
struct iio_dev *indio_dev;
|
||||
struct resource *mem;
|
||||
int irq;
|
||||
int ret;
|
||||
|
||||
@ -815,8 +814,7 @@ static int vf610_adc_probe(struct platform_device *pdev)
|
||||
info = iio_priv(indio_dev);
|
||||
info->dev = &pdev->dev;
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
info->regs = devm_ioremap_resource(&pdev->dev, mem);
|
||||
info->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(info->regs))
|
||||
return PTR_ERR(info->regs);
|
||||
|
||||
|
@ -60,8 +60,8 @@ config AD5446
|
||||
help
|
||||
Say yes here to build support for Analog Devices AD5300, AD5301, AD5310,
|
||||
AD5311, AD5320, AD5321, AD5444, AD5446, AD5450, AD5451, AD5452, AD5453,
|
||||
AD5512A, AD5541A, AD5542A, AD5543, AD5553, AD5601, AD5602, AD5611, AD5612,
|
||||
AD5620, AD5621, AD5622, AD5640, AD5641, AD5660, AD5662 DACs
|
||||
AD5512A, AD5541A, AD5542A, AD5543, AD5553, AD5600, AD5601, AD5602, AD5611,
|
||||
AD5612, AD5620, AD5621, AD5622, AD5640, AD5641, AD5660, AD5662 DACs
|
||||
as well as Texas Instruments DAC081S101, DAC101S101, DAC121S101.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
|
@ -327,6 +327,7 @@ enum ad5446_supported_spi_device_ids {
|
||||
ID_AD5541A,
|
||||
ID_AD5512A,
|
||||
ID_AD5553,
|
||||
ID_AD5600,
|
||||
ID_AD5601,
|
||||
ID_AD5611,
|
||||
ID_AD5621,
|
||||
@ -381,6 +382,10 @@ static const struct ad5446_chip_info ad5446_spi_chip_info[] = {
|
||||
.channel = AD5446_CHANNEL(14, 16, 0),
|
||||
.write = ad5446_write,
|
||||
},
|
||||
[ID_AD5600] = {
|
||||
.channel = AD5446_CHANNEL(16, 16, 0),
|
||||
.write = ad5446_write,
|
||||
},
|
||||
[ID_AD5601] = {
|
||||
.channel = AD5446_CHANNEL_POWERDOWN(8, 16, 6),
|
||||
.write = ad5446_write,
|
||||
@ -448,6 +453,7 @@ static const struct spi_device_id ad5446_spi_ids[] = {
|
||||
{"ad5542a", ID_AD5541A}, /* ad5541a and ad5542a are compatible */
|
||||
{"ad5543", ID_AD5541A}, /* ad5541a and ad5543 are compatible */
|
||||
{"ad5553", ID_AD5553},
|
||||
{"ad5600", ID_AD5600},
|
||||
{"ad5601", ID_AD5601},
|
||||
{"ad5611", ID_AD5611},
|
||||
{"ad5621", ID_AD5621},
|
||||
|
@ -106,7 +106,6 @@ static int lpc18xx_dac_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct iio_dev *indio_dev;
|
||||
struct lpc18xx_dac *dac;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*dac));
|
||||
@ -117,8 +116,7 @@ static int lpc18xx_dac_probe(struct platform_device *pdev)
|
||||
dac = iio_priv(indio_dev);
|
||||
mutex_init(&dac->lock);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
dac->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
dac->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(dac->base))
|
||||
return PTR_ERR(dac->base);
|
||||
|
||||
|
@ -172,7 +172,6 @@ static int vf610_dac_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct iio_dev *indio_dev;
|
||||
struct vf610_dac *info;
|
||||
struct resource *mem;
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev,
|
||||
@ -185,8 +184,7 @@ static int vf610_dac_probe(struct platform_device *pdev)
|
||||
info = iio_priv(indio_dev);
|
||||
info->dev = &pdev->dev;
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
info->regs = devm_ioremap_resource(&pdev->dev, mem);
|
||||
info->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(info->regs))
|
||||
return PTR_ERR(info->regs);
|
||||
|
||||
|
@ -80,19 +80,19 @@ static ssize_t adis16136_show_serial(struct file *file,
|
||||
|
||||
ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_SERIAL_NUM,
|
||||
&serial);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT1, &lot1);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT2, &lot2);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT3, &lot3);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
len = snprintf(buf, sizeof(buf), "%.4x%.4x%.4x-%.4x\n", lot1, lot2,
|
||||
@ -116,7 +116,7 @@ static int adis16136_show_product_id(void *arg, u64 *val)
|
||||
|
||||
ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_PROD_ID,
|
||||
&prod_id);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = prod_id;
|
||||
@ -134,7 +134,7 @@ static int adis16136_show_flash_count(void *arg, u64 *val)
|
||||
|
||||
ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_FLASH_CNT,
|
||||
&flash_count);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = flash_count;
|
||||
@ -191,7 +191,7 @@ static int adis16136_get_freq(struct adis16136 *adis16136, unsigned int *freq)
|
||||
int ret;
|
||||
|
||||
ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_SMPL_PRD, &t);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*freq = 32768 / (t + 1);
|
||||
@ -228,7 +228,7 @@ static ssize_t adis16136_read_frequency(struct device *dev,
|
||||
int ret;
|
||||
|
||||
ret = adis16136_get_freq(adis16136, &freq);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%d\n", freq);
|
||||
@ -256,7 +256,7 @@ static int adis16136_set_filter(struct iio_dev *indio_dev, int val)
|
||||
int i, ret;
|
||||
|
||||
ret = adis16136_get_freq(adis16136, &freq);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = ARRAY_SIZE(adis16136_3db_divisors) - 1; i >= 1; i--) {
|
||||
@ -277,11 +277,11 @@ static int adis16136_get_filter(struct iio_dev *indio_dev, int *val)
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
|
||||
ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, &val16);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
goto err_unlock;
|
||||
|
||||
ret = adis16136_get_freq(adis16136, &freq);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
goto err_unlock;
|
||||
|
||||
*val = freq / adis16136_3db_divisors[val16 & 0x07];
|
||||
@ -318,7 +318,7 @@ static int adis16136_read_raw(struct iio_dev *indio_dev,
|
||||
case IIO_CHAN_INFO_CALIBBIAS:
|
||||
ret = adis_read_reg_32(&adis16136->adis,
|
||||
ADIS16136_REG_GYRO_OFF2, &val32);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = sign_extend32(val32, 31);
|
||||
|
@ -278,31 +278,34 @@ static int hdc100x_buffer_postenable(struct iio_dev *indio_dev)
|
||||
struct hdc100x_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
ret = iio_triggered_buffer_postenable(indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Buffer is enabled. First set ACQ Mode, then attach poll func */
|
||||
mutex_lock(&data->lock);
|
||||
ret = hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE,
|
||||
HDC100X_REG_CONFIG_ACQ_MODE);
|
||||
mutex_unlock(&data->lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
iio_triggered_buffer_predisable(indio_dev);
|
||||
|
||||
return iio_triggered_buffer_postenable(indio_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hdc100x_buffer_predisable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct hdc100x_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
/* First detach poll func, then reset ACQ mode. OK to disable buffer */
|
||||
ret = iio_triggered_buffer_predisable(indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
int ret, ret2;
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
ret = hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE, 0);
|
||||
mutex_unlock(&data->lock);
|
||||
|
||||
ret2 = iio_triggered_buffer_predisable(indio_dev);
|
||||
if (ret == 0)
|
||||
ret = ret2;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -229,7 +229,8 @@ int adis_debugfs_reg_access(struct iio_dev *indio_dev,
|
||||
int ret;
|
||||
|
||||
ret = adis_read_reg_16(adis, reg, &val16);
|
||||
*readval = val16;
|
||||
if (ret == 0)
|
||||
*readval = val16;
|
||||
|
||||
return ret;
|
||||
} else {
|
||||
@ -286,7 +287,7 @@ int adis_check_status(struct adis *adis)
|
||||
int i;
|
||||
|
||||
ret = adis_read_reg_16(adis, adis->data->diag_stat_reg, &status);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
status &= adis->data->status_error_mask;
|
||||
|
@ -217,16 +217,16 @@ static ssize_t adis16400_show_serial_number(struct file *file,
|
||||
int ret;
|
||||
|
||||
ret = adis_read_reg_16(&st->adis, ADIS16334_LOT_ID1, &lot1);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = adis_read_reg_16(&st->adis, ADIS16334_LOT_ID2, &lot2);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = adis_read_reg_16(&st->adis, ADIS16334_SERIAL_NUMBER,
|
||||
&serial_number);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
len = snprintf(buf, sizeof(buf), "%.4x-%.4x-%.4x\n", lot1, lot2,
|
||||
@ -249,7 +249,7 @@ static int adis16400_show_product_id(void *arg, u64 *val)
|
||||
int ret;
|
||||
|
||||
ret = adis_read_reg_16(&st->adis, ADIS16400_PRODUCT_ID, &prod_id);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = prod_id;
|
||||
@ -266,7 +266,7 @@ static int adis16400_show_flash_count(void *arg, u64 *val)
|
||||
int ret;
|
||||
|
||||
ret = adis_read_reg_16(&st->adis, ADIS16400_FLASH_CNT, &flash_count);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = flash_count;
|
||||
@ -327,7 +327,7 @@ static int adis16334_get_freq(struct adis16400_state *st)
|
||||
uint16_t t;
|
||||
|
||||
ret = adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
t >>= ADIS16334_RATE_DIV_SHIFT;
|
||||
@ -359,7 +359,7 @@ static int adis16400_get_freq(struct adis16400_state *st)
|
||||
uint16_t t;
|
||||
|
||||
ret = adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
sps = (t & ADIS16400_SMPL_PRD_TIME_BASE) ? 52851 : 1638404;
|
||||
@ -416,7 +416,7 @@ static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val)
|
||||
}
|
||||
|
||||
ret = adis_read_reg_16(&st->adis, ADIS16400_SENS_AVG, &val16);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = adis_write_reg_16(&st->adis, ADIS16400_SENS_AVG,
|
||||
@ -615,7 +615,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
|
||||
ret = adis_read_reg_16(&st->adis,
|
||||
ADIS16400_SENS_AVG,
|
||||
&val16);
|
||||
if (ret < 0) {
|
||||
if (ret) {
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
return ret;
|
||||
}
|
||||
@ -626,12 +626,12 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
|
||||
*val2 = (ret % 1000) * 1000;
|
||||
}
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
ret = st->variant->get_freq(st);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
*val = ret / 1000;
|
||||
*val2 = (ret % 1000) * 1000;
|
||||
|
@ -80,7 +80,7 @@ static int adis16460_show_serial_number(void *arg, u64 *val)
|
||||
|
||||
ret = adis_read_reg_16(&adis16460->adis, ADIS16460_REG_SERIAL_NUM,
|
||||
&serial);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = serial;
|
||||
@ -98,7 +98,7 @@ static int adis16460_show_product_id(void *arg, u64 *val)
|
||||
|
||||
ret = adis_read_reg_16(&adis16460->adis, ADIS16460_REG_PROD_ID,
|
||||
&prod_id);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = prod_id;
|
||||
@ -116,7 +116,7 @@ static int adis16460_show_flash_count(void *arg, u64 *val)
|
||||
|
||||
ret = adis_read_reg_32(&adis16460->adis, ADIS16460_REG_FLASH_CNT,
|
||||
&flash_count);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = flash_count;
|
||||
@ -176,7 +176,7 @@ static int adis16460_get_freq(struct iio_dev *indio_dev, int *val, int *val2)
|
||||
unsigned int freq;
|
||||
|
||||
ret = adis_read_reg_16(&st->adis, ADIS16460_REG_DEC_RATE, &t);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
freq = 2048000 / (t + 1);
|
||||
|
@ -181,7 +181,7 @@ static ssize_t adis16480_show_firmware_revision(struct file *file,
|
||||
int ret;
|
||||
|
||||
ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_FIRM_REV, &rev);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
len = scnprintf(buf, sizeof(buf), "%x.%x\n", rev >> 8, rev & 0xff);
|
||||
@ -206,11 +206,11 @@ static ssize_t adis16480_show_firmware_date(struct file *file,
|
||||
int ret;
|
||||
|
||||
ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_FIRM_Y, &year);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_FIRM_DM, &md);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
len = snprintf(buf, sizeof(buf), "%.2x-%.2x-%.4x\n",
|
||||
@ -234,7 +234,7 @@ static int adis16480_show_serial_number(void *arg, u64 *val)
|
||||
|
||||
ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_SERIAL_NUM,
|
||||
&serial);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = serial;
|
||||
@ -252,7 +252,7 @@ static int adis16480_show_product_id(void *arg, u64 *val)
|
||||
|
||||
ret = adis_read_reg_16(&adis16480->adis, ADIS16480_REG_PROD_ID,
|
||||
&prod_id);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = prod_id;
|
||||
@ -270,7 +270,7 @@ static int adis16480_show_flash_count(void *arg, u64 *val)
|
||||
|
||||
ret = adis_read_reg_32(&adis16480->adis, ADIS16480_REG_FLASH_CNT,
|
||||
&flash_count);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = flash_count;
|
||||
@ -353,7 +353,7 @@ static int adis16480_get_freq(struct iio_dev *indio_dev, int *val, int *val2)
|
||||
struct adis16480 *st = iio_priv(indio_dev);
|
||||
uint16_t t;
|
||||
int ret;
|
||||
unsigned freq;
|
||||
unsigned int freq;
|
||||
unsigned int reg;
|
||||
|
||||
if (st->clk_mode == ADIS16480_CLK_PPS)
|
||||
@ -362,7 +362,7 @@ static int adis16480_get_freq(struct iio_dev *indio_dev, int *val, int *val2)
|
||||
reg = ADIS16480_REG_DEC_RATE;
|
||||
|
||||
ret = adis_read_reg_16(&st->adis, reg, &t);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
@ -454,18 +454,20 @@ static int adis16480_get_calibbias(struct iio_dev *indio_dev,
|
||||
case IIO_MAGN:
|
||||
case IIO_PRESSURE:
|
||||
ret = adis_read_reg_16(&st->adis, reg, &val16);
|
||||
*bias = sign_extend32(val16, 15);
|
||||
if (ret == 0)
|
||||
*bias = sign_extend32(val16, 15);
|
||||
break;
|
||||
case IIO_ANGL_VEL:
|
||||
case IIO_ACCEL:
|
||||
ret = adis_read_reg_32(&st->adis, reg, &val32);
|
||||
*bias = sign_extend32(val32, 31);
|
||||
if (ret == 0)
|
||||
*bias = sign_extend32(val32, 31);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return IIO_VAL_INT;
|
||||
@ -492,7 +494,7 @@ static int adis16480_get_calibscale(struct iio_dev *indio_dev,
|
||||
int ret;
|
||||
|
||||
ret = adis_read_reg_16(&st->adis, reg, &val16);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*scale = sign_extend32(val16, 15);
|
||||
@ -538,7 +540,7 @@ static int adis16480_get_filter_freq(struct iio_dev *indio_dev,
|
||||
enable_mask = BIT(offset + 2);
|
||||
|
||||
ret = adis_read_reg_16(&st->adis, reg, &val);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!(val & enable_mask))
|
||||
@ -564,7 +566,7 @@ static int adis16480_set_filter_freq(struct iio_dev *indio_dev,
|
||||
enable_mask = BIT(offset + 2);
|
||||
|
||||
ret = adis_read_reg_16(&st->adis, reg, &val);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (freq == 0) {
|
||||
@ -623,9 +625,13 @@ static int adis16480_read_raw(struct iio_dev *indio_dev,
|
||||
*val2 = (st->chip_info->temp_scale % 1000) * 1000;
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
case IIO_PRESSURE:
|
||||
*val = 0;
|
||||
*val2 = 4000; /* 40ubar = 0.004 kPa */
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
/*
|
||||
* max scale is 1310 mbar
|
||||
* max raw value is 32767 shifted for 32bits
|
||||
*/
|
||||
*val = 131; /* 1310mbar = 131 kPa */
|
||||
*val2 = 32767 << 16;
|
||||
return IIO_VAL_FRACTIONAL;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -786,13 +792,14 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
|
||||
.channels = adis16485_channels,
|
||||
.num_channels = ARRAY_SIZE(adis16485_channels),
|
||||
/*
|
||||
* storing the value in rad/degree and the scale in degree
|
||||
* gives us the result in rad and better precession than
|
||||
* storing the scale directly in rad.
|
||||
* Typically we do IIO_RAD_TO_DEGREE in the denominator, which
|
||||
* is exactly the same as IIO_DEGREE_TO_RAD in numerator, since
|
||||
* it gives better approximation. However, in this case we
|
||||
* cannot do it since it would not fit in a 32bit variable.
|
||||
*/
|
||||
.gyro_max_val = IIO_RAD_TO_DEGREE(22887),
|
||||
.gyro_max_scale = 300,
|
||||
.accel_max_val = IIO_M_S_2_TO_G(21973),
|
||||
.gyro_max_val = 22887 << 16,
|
||||
.gyro_max_scale = IIO_DEGREE_TO_RAD(300),
|
||||
.accel_max_val = IIO_M_S_2_TO_G(21973 << 16),
|
||||
.accel_max_scale = 18,
|
||||
.temp_scale = 5650, /* 5.65 milli degree Celsius */
|
||||
.int_clk = 2460000,
|
||||
@ -802,9 +809,9 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
|
||||
[ADIS16480] = {
|
||||
.channels = adis16480_channels,
|
||||
.num_channels = ARRAY_SIZE(adis16480_channels),
|
||||
.gyro_max_val = IIO_RAD_TO_DEGREE(22500),
|
||||
.gyro_max_scale = 450,
|
||||
.accel_max_val = IIO_M_S_2_TO_G(12500),
|
||||
.gyro_max_val = 22500 << 16,
|
||||
.gyro_max_scale = IIO_DEGREE_TO_RAD(450),
|
||||
.accel_max_val = IIO_M_S_2_TO_G(12500 << 16),
|
||||
.accel_max_scale = 10,
|
||||
.temp_scale = 5650, /* 5.65 milli degree Celsius */
|
||||
.int_clk = 2460000,
|
||||
@ -814,9 +821,9 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
|
||||
[ADIS16485] = {
|
||||
.channels = adis16485_channels,
|
||||
.num_channels = ARRAY_SIZE(adis16485_channels),
|
||||
.gyro_max_val = IIO_RAD_TO_DEGREE(22500),
|
||||
.gyro_max_scale = 450,
|
||||
.accel_max_val = IIO_M_S_2_TO_G(20000),
|
||||
.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 */
|
||||
.int_clk = 2460000,
|
||||
@ -826,9 +833,9 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
|
||||
[ADIS16488] = {
|
||||
.channels = adis16480_channels,
|
||||
.num_channels = ARRAY_SIZE(adis16480_channels),
|
||||
.gyro_max_val = IIO_RAD_TO_DEGREE(22500),
|
||||
.gyro_max_scale = 450,
|
||||
.accel_max_val = IIO_M_S_2_TO_G(22500),
|
||||
.gyro_max_val = 22500 << 16,
|
||||
.gyro_max_scale = IIO_DEGREE_TO_RAD(450),
|
||||
.accel_max_val = IIO_M_S_2_TO_G(22500 << 16),
|
||||
.accel_max_scale = 18,
|
||||
.temp_scale = 5650, /* 5.65 milli degree Celsius */
|
||||
.int_clk = 2460000,
|
||||
@ -838,9 +845,9 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
|
||||
[ADIS16495_1] = {
|
||||
.channels = adis16485_channels,
|
||||
.num_channels = ARRAY_SIZE(adis16485_channels),
|
||||
.gyro_max_val = IIO_RAD_TO_DEGREE(20000),
|
||||
.gyro_max_scale = 125,
|
||||
.accel_max_val = IIO_M_S_2_TO_G(32000),
|
||||
.gyro_max_val = 20000 << 16,
|
||||
.gyro_max_scale = IIO_DEGREE_TO_RAD(125),
|
||||
.accel_max_val = IIO_M_S_2_TO_G(32000 << 16),
|
||||
.accel_max_scale = 8,
|
||||
.temp_scale = 12500, /* 12.5 milli degree Celsius */
|
||||
.int_clk = 4250000,
|
||||
@ -851,9 +858,9 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
|
||||
[ADIS16495_2] = {
|
||||
.channels = adis16485_channels,
|
||||
.num_channels = ARRAY_SIZE(adis16485_channels),
|
||||
.gyro_max_val = IIO_RAD_TO_DEGREE(18000),
|
||||
.gyro_max_scale = 450,
|
||||
.accel_max_val = IIO_M_S_2_TO_G(32000),
|
||||
.gyro_max_val = 18000 << 16,
|
||||
.gyro_max_scale = IIO_DEGREE_TO_RAD(450),
|
||||
.accel_max_val = IIO_M_S_2_TO_G(32000 << 16),
|
||||
.accel_max_scale = 8,
|
||||
.temp_scale = 12500, /* 12.5 milli degree Celsius */
|
||||
.int_clk = 4250000,
|
||||
@ -864,9 +871,9 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
|
||||
[ADIS16495_3] = {
|
||||
.channels = adis16485_channels,
|
||||
.num_channels = ARRAY_SIZE(adis16485_channels),
|
||||
.gyro_max_val = IIO_RAD_TO_DEGREE(20000),
|
||||
.gyro_max_scale = 2000,
|
||||
.accel_max_val = IIO_M_S_2_TO_G(32000),
|
||||
.gyro_max_val = 20000 << 16,
|
||||
.gyro_max_scale = IIO_DEGREE_TO_RAD(2000),
|
||||
.accel_max_val = IIO_M_S_2_TO_G(32000 << 16),
|
||||
.accel_max_scale = 8,
|
||||
.temp_scale = 12500, /* 12.5 milli degree Celsius */
|
||||
.int_clk = 4250000,
|
||||
@ -877,9 +884,9 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
|
||||
[ADIS16497_1] = {
|
||||
.channels = adis16485_channels,
|
||||
.num_channels = ARRAY_SIZE(adis16485_channels),
|
||||
.gyro_max_val = IIO_RAD_TO_DEGREE(20000),
|
||||
.gyro_max_scale = 125,
|
||||
.accel_max_val = IIO_M_S_2_TO_G(32000),
|
||||
.gyro_max_val = 20000 << 16,
|
||||
.gyro_max_scale = IIO_DEGREE_TO_RAD(125),
|
||||
.accel_max_val = IIO_M_S_2_TO_G(32000 << 16),
|
||||
.accel_max_scale = 40,
|
||||
.temp_scale = 12500, /* 12.5 milli degree Celsius */
|
||||
.int_clk = 4250000,
|
||||
@ -890,9 +897,9 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
|
||||
[ADIS16497_2] = {
|
||||
.channels = adis16485_channels,
|
||||
.num_channels = ARRAY_SIZE(adis16485_channels),
|
||||
.gyro_max_val = IIO_RAD_TO_DEGREE(18000),
|
||||
.gyro_max_scale = 450,
|
||||
.accel_max_val = IIO_M_S_2_TO_G(32000),
|
||||
.gyro_max_val = 18000 << 16,
|
||||
.gyro_max_scale = IIO_DEGREE_TO_RAD(450),
|
||||
.accel_max_val = IIO_M_S_2_TO_G(32000 << 16),
|
||||
.accel_max_scale = 40,
|
||||
.temp_scale = 12500, /* 12.5 milli degree Celsius */
|
||||
.int_clk = 4250000,
|
||||
@ -903,9 +910,9 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
|
||||
[ADIS16497_3] = {
|
||||
.channels = adis16485_channels,
|
||||
.num_channels = ARRAY_SIZE(adis16485_channels),
|
||||
.gyro_max_val = IIO_RAD_TO_DEGREE(20000),
|
||||
.gyro_max_scale = 2000,
|
||||
.accel_max_val = IIO_M_S_2_TO_G(32000),
|
||||
.gyro_max_val = 20000 << 16,
|
||||
.gyro_max_scale = IIO_DEGREE_TO_RAD(2000),
|
||||
.accel_max_val = IIO_M_S_2_TO_G(32000 << 16),
|
||||
.accel_max_scale = 40,
|
||||
.temp_scale = 12500, /* 12.5 milli degree Celsius */
|
||||
.int_clk = 4250000,
|
||||
@ -919,6 +926,7 @@ static const struct iio_info adis16480_info = {
|
||||
.read_raw = &adis16480_read_raw,
|
||||
.write_raw = &adis16480_write_raw,
|
||||
.update_scan_mode = adis_update_scan_mode,
|
||||
.debugfs_reg_access = adis_debugfs_reg_access,
|
||||
};
|
||||
|
||||
static int adis16480_stop_device(struct iio_dev *indio_dev)
|
||||
@ -940,7 +948,7 @@ static int adis16480_enable_irq(struct adis *adis, bool enable)
|
||||
int ret;
|
||||
|
||||
ret = adis_read_reg_16(adis, ADIS16480_REG_FNCTIO_CTRL, &val);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val &= ~ADIS16480_DRDY_EN_MSK;
|
||||
@ -1118,7 +1126,7 @@ static int adis16480_ext_clk_config(struct adis16480 *st,
|
||||
int ret;
|
||||
|
||||
ret = adis_read_reg_16(&st->adis, ADIS16480_REG_FNCTIO_CTRL, &val);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pin = adis16480_of_get_ext_clk_pin(st, of_node);
|
||||
@ -1144,7 +1152,7 @@ static int adis16480_ext_clk_config(struct adis16480 *st,
|
||||
val |= mode;
|
||||
|
||||
ret = adis_write_reg_16(&st->adis, ADIS16480_REG_FNCTIO_CTRL, val);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return clk_prepare_enable(st->ext_clk);
|
||||
|
@ -1149,14 +1149,14 @@ error_power_off:
|
||||
return result;
|
||||
}
|
||||
|
||||
static int inv_mpu_core_enable_regulator(struct inv_mpu6050_state *st)
|
||||
static int inv_mpu_core_enable_regulator_vddio(struct inv_mpu6050_state *st)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = regulator_enable(st->vddio_supply);
|
||||
if (result) {
|
||||
dev_err(regmap_get_device(st->map),
|
||||
"Failed to enable regulator: %d\n", result);
|
||||
"Failed to enable vddio regulator: %d\n", result);
|
||||
} else {
|
||||
/* Give the device a little bit of time to start up. */
|
||||
usleep_range(35000, 70000);
|
||||
@ -1165,21 +1165,29 @@ static int inv_mpu_core_enable_regulator(struct inv_mpu6050_state *st)
|
||||
return result;
|
||||
}
|
||||
|
||||
static int inv_mpu_core_disable_regulator(struct inv_mpu6050_state *st)
|
||||
static int inv_mpu_core_disable_regulator_vddio(struct inv_mpu6050_state *st)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = regulator_disable(st->vddio_supply);
|
||||
if (result)
|
||||
dev_err(regmap_get_device(st->map),
|
||||
"Failed to disable regulator: %d\n", result);
|
||||
"Failed to disable vddio regulator: %d\n", result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void inv_mpu_core_disable_regulator_action(void *_data)
|
||||
{
|
||||
inv_mpu_core_disable_regulator(_data);
|
||||
struct inv_mpu6050_state *st = _data;
|
||||
int result;
|
||||
|
||||
result = regulator_disable(st->vdd_supply);
|
||||
if (result)
|
||||
dev_err(regmap_get_device(st->map),
|
||||
"Failed to disable vdd regulator: %d\n", result);
|
||||
|
||||
inv_mpu_core_disable_regulator_vddio(st);
|
||||
}
|
||||
|
||||
int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
|
||||
@ -1248,6 +1256,15 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
st->vdd_supply = devm_regulator_get(dev, "vdd");
|
||||
if (IS_ERR(st->vdd_supply)) {
|
||||
if (PTR_ERR(st->vdd_supply) != -EPROBE_DEFER)
|
||||
dev_err(dev, "Failed to get vdd regulator %d\n",
|
||||
(int)PTR_ERR(st->vdd_supply));
|
||||
|
||||
return PTR_ERR(st->vdd_supply);
|
||||
}
|
||||
|
||||
st->vddio_supply = devm_regulator_get(dev, "vddio");
|
||||
if (IS_ERR(st->vddio_supply)) {
|
||||
if (PTR_ERR(st->vddio_supply) != -EPROBE_DEFER)
|
||||
@ -1257,9 +1274,17 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
|
||||
return PTR_ERR(st->vddio_supply);
|
||||
}
|
||||
|
||||
result = inv_mpu_core_enable_regulator(st);
|
||||
if (result)
|
||||
result = regulator_enable(st->vdd_supply);
|
||||
if (result) {
|
||||
dev_err(dev, "Failed to enable vdd regulator: %d\n", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = inv_mpu_core_enable_regulator_vddio(st);
|
||||
if (result) {
|
||||
regulator_disable(st->vdd_supply);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = devm_add_action_or_reset(dev, inv_mpu_core_disable_regulator_action,
|
||||
st);
|
||||
@ -1361,7 +1386,7 @@ static int inv_mpu_resume(struct device *dev)
|
||||
int result;
|
||||
|
||||
mutex_lock(&st->lock);
|
||||
result = inv_mpu_core_enable_regulator(st);
|
||||
result = inv_mpu_core_enable_regulator_vddio(st);
|
||||
if (result)
|
||||
goto out_unlock;
|
||||
|
||||
@ -1379,7 +1404,7 @@ static int inv_mpu_suspend(struct device *dev)
|
||||
|
||||
mutex_lock(&st->lock);
|
||||
result = inv_mpu6050_set_power_itg(st, false);
|
||||
inv_mpu_core_disable_regulator(st);
|
||||
inv_mpu_core_disable_regulator_vddio(st);
|
||||
mutex_unlock(&st->lock);
|
||||
|
||||
return result;
|
||||
|
@ -132,7 +132,8 @@ struct inv_mpu6050_hw {
|
||||
* @chip_period: chip internal period estimation (~1kHz).
|
||||
* @it_timestamp: timestamp from previous interrupt.
|
||||
* @data_timestamp: timestamp for next data sample.
|
||||
* @vddio_supply voltage regulator for the chip.
|
||||
* @vdd_supply: VDD voltage regulator for the chip.
|
||||
* @vddio_supply I/O voltage regulator for the chip.
|
||||
* @magn_disabled: magnetometer disabled for backward compatibility reason.
|
||||
* @magn_raw_to_gauss: coefficient to convert mag raw value to Gauss.
|
||||
* @magn_orient: magnetometer sensor chip orientation if available.
|
||||
@ -156,6 +157,7 @@ struct inv_mpu6050_state {
|
||||
s64 chip_period;
|
||||
s64 it_timestamp;
|
||||
s64 data_timestamp;
|
||||
struct regulator *vdd_supply;
|
||||
struct regulator *vddio_supply;
|
||||
bool magn_disabled;
|
||||
s32 magn_raw_to_gauss[3];
|
||||
|
@ -106,14 +106,16 @@ struct st_lsm6dsx_sensor;
|
||||
struct st_lsm6dsx_hw;
|
||||
|
||||
struct st_lsm6dsx_odr {
|
||||
u16 hz;
|
||||
u32 milli_hz;
|
||||
u8 val;
|
||||
};
|
||||
|
||||
#define ST_LSM6DSX_ODR_LIST_SIZE 6
|
||||
struct st_lsm6dsx_odr_table_entry {
|
||||
struct st_lsm6dsx_reg reg;
|
||||
|
||||
struct st_lsm6dsx_odr odr_avl[ST_LSM6DSX_ODR_LIST_SIZE];
|
||||
int odr_len;
|
||||
};
|
||||
|
||||
struct st_lsm6dsx_fs {
|
||||
@ -328,7 +330,7 @@ struct st_lsm6dsx_sensor {
|
||||
struct st_lsm6dsx_hw *hw;
|
||||
|
||||
u32 gain;
|
||||
u16 odr;
|
||||
u32 odr;
|
||||
|
||||
u16 watermark;
|
||||
u8 sip;
|
||||
@ -413,7 +415,7 @@ int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw,
|
||||
enum st_lsm6dsx_fifo_mode fifo_mode);
|
||||
int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw);
|
||||
int st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw);
|
||||
int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u16 odr, u8 *val);
|
||||
int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u32 odr, u8 *val);
|
||||
int st_lsm6dsx_shub_probe(struct st_lsm6dsx_hw *hw, const char *name);
|
||||
int st_lsm6dsx_shub_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable);
|
||||
int st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable);
|
||||
|
@ -91,7 +91,7 @@ static int st_lsm6dsx_get_decimator_val(u8 val)
|
||||
}
|
||||
|
||||
static void st_lsm6dsx_get_max_min_odr(struct st_lsm6dsx_hw *hw,
|
||||
u16 *max_odr, u16 *min_odr)
|
||||
u32 *max_odr, u32 *min_odr)
|
||||
{
|
||||
struct st_lsm6dsx_sensor *sensor;
|
||||
int i;
|
||||
@ -106,16 +106,17 @@ static void st_lsm6dsx_get_max_min_odr(struct st_lsm6dsx_hw *hw,
|
||||
if (!(hw->enable_mask & BIT(sensor->id)))
|
||||
continue;
|
||||
|
||||
*max_odr = max_t(u16, *max_odr, sensor->odr);
|
||||
*min_odr = min_t(u16, *min_odr, sensor->odr);
|
||||
*max_odr = max_t(u32, *max_odr, sensor->odr);
|
||||
*min_odr = min_t(u32, *min_odr, sensor->odr);
|
||||
}
|
||||
}
|
||||
|
||||
static int st_lsm6dsx_update_decimators(struct st_lsm6dsx_hw *hw)
|
||||
{
|
||||
u16 max_odr, min_odr, sip = 0, ts_sip = 0;
|
||||
const struct st_lsm6dsx_reg *ts_dec_reg;
|
||||
struct st_lsm6dsx_sensor *sensor;
|
||||
u16 sip = 0, ts_sip = 0;
|
||||
u32 max_odr, min_odr;
|
||||
int err = 0, i;
|
||||
u8 data;
|
||||
|
||||
|
@ -127,24 +127,26 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
|
||||
.addr = 0x20,
|
||||
.mask = GENMASK(7, 5),
|
||||
},
|
||||
.odr_avl[0] = { 10, 0x01 },
|
||||
.odr_avl[1] = { 50, 0x02 },
|
||||
.odr_avl[2] = { 119, 0x03 },
|
||||
.odr_avl[3] = { 238, 0x04 },
|
||||
.odr_avl[4] = { 476, 0x05 },
|
||||
.odr_avl[5] = { 952, 0x06 },
|
||||
.odr_avl[0] = { 10000, 0x01 },
|
||||
.odr_avl[1] = { 50000, 0x02 },
|
||||
.odr_avl[2] = { 119000, 0x03 },
|
||||
.odr_avl[3] = { 238000, 0x04 },
|
||||
.odr_avl[4] = { 476000, 0x05 },
|
||||
.odr_avl[5] = { 952000, 0x06 },
|
||||
.odr_len = 6,
|
||||
},
|
||||
[ST_LSM6DSX_ID_GYRO] = {
|
||||
.reg = {
|
||||
.addr = 0x10,
|
||||
.mask = GENMASK(7, 5),
|
||||
},
|
||||
.odr_avl[0] = { 15, 0x01 },
|
||||
.odr_avl[1] = { 60, 0x02 },
|
||||
.odr_avl[2] = { 119, 0x03 },
|
||||
.odr_avl[3] = { 238, 0x04 },
|
||||
.odr_avl[4] = { 476, 0x05 },
|
||||
.odr_avl[5] = { 952, 0x06 },
|
||||
.odr_avl[0] = { 14900, 0x01 },
|
||||
.odr_avl[1] = { 59500, 0x02 },
|
||||
.odr_avl[2] = { 119000, 0x03 },
|
||||
.odr_avl[3] = { 238000, 0x04 },
|
||||
.odr_avl[4] = { 476000, 0x05 },
|
||||
.odr_avl[5] = { 952000, 0x06 },
|
||||
.odr_len = 6,
|
||||
},
|
||||
},
|
||||
.fs_table = {
|
||||
@ -227,24 +229,26 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
|
||||
.addr = 0x10,
|
||||
.mask = GENMASK(7, 4),
|
||||
},
|
||||
.odr_avl[0] = { 13, 0x01 },
|
||||
.odr_avl[1] = { 26, 0x02 },
|
||||
.odr_avl[2] = { 52, 0x03 },
|
||||
.odr_avl[3] = { 104, 0x04 },
|
||||
.odr_avl[4] = { 208, 0x05 },
|
||||
.odr_avl[5] = { 416, 0x06 },
|
||||
.odr_avl[0] = { 12500, 0x01 },
|
||||
.odr_avl[1] = { 26000, 0x02 },
|
||||
.odr_avl[2] = { 52000, 0x03 },
|
||||
.odr_avl[3] = { 104000, 0x04 },
|
||||
.odr_avl[4] = { 208000, 0x05 },
|
||||
.odr_avl[5] = { 416000, 0x06 },
|
||||
.odr_len = 6,
|
||||
},
|
||||
[ST_LSM6DSX_ID_GYRO] = {
|
||||
.reg = {
|
||||
.addr = 0x11,
|
||||
.mask = GENMASK(7, 4),
|
||||
},
|
||||
.odr_avl[0] = { 13, 0x01 },
|
||||
.odr_avl[1] = { 26, 0x02 },
|
||||
.odr_avl[2] = { 52, 0x03 },
|
||||
.odr_avl[3] = { 104, 0x04 },
|
||||
.odr_avl[4] = { 208, 0x05 },
|
||||
.odr_avl[5] = { 416, 0x06 },
|
||||
.odr_avl[0] = { 12500, 0x01 },
|
||||
.odr_avl[1] = { 26000, 0x02 },
|
||||
.odr_avl[2] = { 52000, 0x03 },
|
||||
.odr_avl[3] = { 104000, 0x04 },
|
||||
.odr_avl[4] = { 208000, 0x05 },
|
||||
.odr_avl[5] = { 416000, 0x06 },
|
||||
.odr_len = 6,
|
||||
},
|
||||
},
|
||||
.fs_table = {
|
||||
@ -391,24 +395,26 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
|
||||
.addr = 0x10,
|
||||
.mask = GENMASK(7, 4),
|
||||
},
|
||||
.odr_avl[0] = { 13, 0x01 },
|
||||
.odr_avl[1] = { 26, 0x02 },
|
||||
.odr_avl[2] = { 52, 0x03 },
|
||||
.odr_avl[3] = { 104, 0x04 },
|
||||
.odr_avl[4] = { 208, 0x05 },
|
||||
.odr_avl[5] = { 416, 0x06 },
|
||||
.odr_avl[0] = { 12500, 0x01 },
|
||||
.odr_avl[1] = { 26000, 0x02 },
|
||||
.odr_avl[2] = { 52000, 0x03 },
|
||||
.odr_avl[3] = { 104000, 0x04 },
|
||||
.odr_avl[4] = { 208000, 0x05 },
|
||||
.odr_avl[5] = { 416000, 0x06 },
|
||||
.odr_len = 6,
|
||||
},
|
||||
[ST_LSM6DSX_ID_GYRO] = {
|
||||
.reg = {
|
||||
.addr = 0x11,
|
||||
.mask = GENMASK(7, 4),
|
||||
},
|
||||
.odr_avl[0] = { 13, 0x01 },
|
||||
.odr_avl[1] = { 26, 0x02 },
|
||||
.odr_avl[2] = { 52, 0x03 },
|
||||
.odr_avl[3] = { 104, 0x04 },
|
||||
.odr_avl[4] = { 208, 0x05 },
|
||||
.odr_avl[5] = { 416, 0x06 },
|
||||
.odr_avl[0] = { 12500, 0x01 },
|
||||
.odr_avl[1] = { 26000, 0x02 },
|
||||
.odr_avl[2] = { 52000, 0x03 },
|
||||
.odr_avl[3] = { 104000, 0x04 },
|
||||
.odr_avl[4] = { 208000, 0x05 },
|
||||
.odr_avl[5] = { 416000, 0x06 },
|
||||
.odr_len = 6,
|
||||
},
|
||||
},
|
||||
.fs_table = {
|
||||
@ -564,24 +570,26 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
|
||||
.addr = 0x10,
|
||||
.mask = GENMASK(7, 4),
|
||||
},
|
||||
.odr_avl[0] = { 13, 0x01 },
|
||||
.odr_avl[1] = { 26, 0x02 },
|
||||
.odr_avl[2] = { 52, 0x03 },
|
||||
.odr_avl[3] = { 104, 0x04 },
|
||||
.odr_avl[4] = { 208, 0x05 },
|
||||
.odr_avl[5] = { 416, 0x06 },
|
||||
.odr_avl[0] = { 12500, 0x01 },
|
||||
.odr_avl[1] = { 26000, 0x02 },
|
||||
.odr_avl[2] = { 52000, 0x03 },
|
||||
.odr_avl[3] = { 104000, 0x04 },
|
||||
.odr_avl[4] = { 208000, 0x05 },
|
||||
.odr_avl[5] = { 416000, 0x06 },
|
||||
.odr_len = 6,
|
||||
},
|
||||
[ST_LSM6DSX_ID_GYRO] = {
|
||||
.reg = {
|
||||
.addr = 0x11,
|
||||
.mask = GENMASK(7, 4),
|
||||
},
|
||||
.odr_avl[0] = { 13, 0x01 },
|
||||
.odr_avl[1] = { 26, 0x02 },
|
||||
.odr_avl[2] = { 52, 0x03 },
|
||||
.odr_avl[3] = { 104, 0x04 },
|
||||
.odr_avl[4] = { 208, 0x05 },
|
||||
.odr_avl[5] = { 416, 0x06 },
|
||||
.odr_avl[0] = { 12500, 0x01 },
|
||||
.odr_avl[1] = { 26000, 0x02 },
|
||||
.odr_avl[2] = { 52000, 0x03 },
|
||||
.odr_avl[3] = { 104000, 0x04 },
|
||||
.odr_avl[4] = { 208000, 0x05 },
|
||||
.odr_avl[5] = { 416000, 0x06 },
|
||||
.odr_len = 6,
|
||||
},
|
||||
},
|
||||
.fs_table = {
|
||||
@ -739,24 +747,26 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
|
||||
.addr = 0x10,
|
||||
.mask = GENMASK(7, 4),
|
||||
},
|
||||
.odr_avl[0] = { 13, 0x01 },
|
||||
.odr_avl[1] = { 26, 0x02 },
|
||||
.odr_avl[2] = { 52, 0x03 },
|
||||
.odr_avl[3] = { 104, 0x04 },
|
||||
.odr_avl[4] = { 208, 0x05 },
|
||||
.odr_avl[5] = { 416, 0x06 },
|
||||
.odr_avl[0] = { 12500, 0x01 },
|
||||
.odr_avl[1] = { 26000, 0x02 },
|
||||
.odr_avl[2] = { 52000, 0x03 },
|
||||
.odr_avl[3] = { 104000, 0x04 },
|
||||
.odr_avl[4] = { 208000, 0x05 },
|
||||
.odr_avl[5] = { 416000, 0x06 },
|
||||
.odr_len = 6,
|
||||
},
|
||||
[ST_LSM6DSX_ID_GYRO] = {
|
||||
.reg = {
|
||||
.addr = 0x11,
|
||||
.mask = GENMASK(7, 4),
|
||||
},
|
||||
.odr_avl[0] = { 13, 0x01 },
|
||||
.odr_avl[1] = { 26, 0x02 },
|
||||
.odr_avl[2] = { 52, 0x03 },
|
||||
.odr_avl[3] = { 104, 0x04 },
|
||||
.odr_avl[4] = { 208, 0x05 },
|
||||
.odr_avl[5] = { 416, 0x06 },
|
||||
.odr_avl[0] = { 12500, 0x01 },
|
||||
.odr_avl[1] = { 26000, 0x02 },
|
||||
.odr_avl[2] = { 52000, 0x03 },
|
||||
.odr_avl[3] = { 104000, 0x04 },
|
||||
.odr_avl[4] = { 208000, 0x05 },
|
||||
.odr_avl[5] = { 416000, 0x06 },
|
||||
.odr_len = 6,
|
||||
},
|
||||
},
|
||||
.fs_table = {
|
||||
@ -934,24 +944,26 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
|
||||
.addr = 0x10,
|
||||
.mask = GENMASK(7, 4),
|
||||
},
|
||||
.odr_avl[0] = { 13, 0x01 },
|
||||
.odr_avl[1] = { 26, 0x02 },
|
||||
.odr_avl[2] = { 52, 0x03 },
|
||||
.odr_avl[3] = { 104, 0x04 },
|
||||
.odr_avl[4] = { 208, 0x05 },
|
||||
.odr_avl[5] = { 416, 0x06 },
|
||||
.odr_avl[0] = { 12500, 0x01 },
|
||||
.odr_avl[1] = { 26000, 0x02 },
|
||||
.odr_avl[2] = { 52000, 0x03 },
|
||||
.odr_avl[3] = { 104000, 0x04 },
|
||||
.odr_avl[4] = { 208000, 0x05 },
|
||||
.odr_avl[5] = { 416000, 0x06 },
|
||||
.odr_len = 6,
|
||||
},
|
||||
[ST_LSM6DSX_ID_GYRO] = {
|
||||
.reg = {
|
||||
.addr = 0x11,
|
||||
.mask = GENMASK(7, 4),
|
||||
},
|
||||
.odr_avl[0] = { 13, 0x01 },
|
||||
.odr_avl[1] = { 26, 0x02 },
|
||||
.odr_avl[2] = { 52, 0x03 },
|
||||
.odr_avl[3] = { 104, 0x04 },
|
||||
.odr_avl[4] = { 208, 0x05 },
|
||||
.odr_avl[5] = { 416, 0x06 },
|
||||
.odr_avl[0] = { 12500, 0x01 },
|
||||
.odr_avl[1] = { 26000, 0x02 },
|
||||
.odr_avl[2] = { 52000, 0x03 },
|
||||
.odr_avl[3] = { 104000, 0x04 },
|
||||
.odr_avl[4] = { 208000, 0x05 },
|
||||
.odr_avl[5] = { 416000, 0x06 },
|
||||
.odr_len = 6,
|
||||
},
|
||||
},
|
||||
.fs_table = {
|
||||
@ -1109,24 +1121,26 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
|
||||
.addr = 0x10,
|
||||
.mask = GENMASK(7, 4),
|
||||
},
|
||||
.odr_avl[0] = { 13, 0x01 },
|
||||
.odr_avl[1] = { 26, 0x02 },
|
||||
.odr_avl[2] = { 52, 0x03 },
|
||||
.odr_avl[3] = { 104, 0x04 },
|
||||
.odr_avl[4] = { 208, 0x05 },
|
||||
.odr_avl[5] = { 416, 0x06 },
|
||||
.odr_avl[0] = { 12500, 0x01 },
|
||||
.odr_avl[1] = { 26000, 0x02 },
|
||||
.odr_avl[2] = { 52000, 0x03 },
|
||||
.odr_avl[3] = { 104000, 0x04 },
|
||||
.odr_avl[4] = { 208000, 0x05 },
|
||||
.odr_avl[5] = { 416000, 0x06 },
|
||||
.odr_len = 6,
|
||||
},
|
||||
[ST_LSM6DSX_ID_GYRO] = {
|
||||
.reg = {
|
||||
.addr = 0x11,
|
||||
.mask = GENMASK(7, 4),
|
||||
},
|
||||
.odr_avl[0] = { 13, 0x01 },
|
||||
.odr_avl[1] = { 26, 0x02 },
|
||||
.odr_avl[2] = { 52, 0x03 },
|
||||
.odr_avl[3] = { 104, 0x04 },
|
||||
.odr_avl[4] = { 208, 0x05 },
|
||||
.odr_avl[5] = { 416, 0x06 },
|
||||
.odr_avl[0] = { 12500, 0x01 },
|
||||
.odr_avl[1] = { 26000, 0x02 },
|
||||
.odr_avl[2] = { 52000, 0x03 },
|
||||
.odr_avl[3] = { 104000, 0x04 },
|
||||
.odr_avl[4] = { 208000, 0x05 },
|
||||
.odr_avl[5] = { 416000, 0x06 },
|
||||
.odr_len = 6,
|
||||
},
|
||||
},
|
||||
.fs_table = {
|
||||
@ -1344,36 +1358,37 @@ static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u16 odr, u8 *val)
|
||||
int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u32 odr, u8 *val)
|
||||
{
|
||||
const struct st_lsm6dsx_odr_table_entry *odr_table;
|
||||
int i;
|
||||
|
||||
odr_table = &sensor->hw->settings->odr_table[sensor->id];
|
||||
for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++)
|
||||
for (i = 0; i < odr_table->odr_len; i++) {
|
||||
/*
|
||||
* ext devices can run at different odr respect to
|
||||
* accel sensor
|
||||
*/
|
||||
if (odr_table->odr_avl[i].hz >= odr)
|
||||
if (odr_table->odr_avl[i].milli_hz >= odr)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ST_LSM6DSX_ODR_LIST_SIZE)
|
||||
if (i == odr_table->odr_len)
|
||||
return -EINVAL;
|
||||
|
||||
*val = odr_table->odr_avl[i].val;
|
||||
|
||||
return 0;
|
||||
return odr_table->odr_avl[i].milli_hz;
|
||||
}
|
||||
|
||||
static u16 st_lsm6dsx_check_odr_dependency(struct st_lsm6dsx_hw *hw, u16 odr,
|
||||
enum st_lsm6dsx_sensor_id id)
|
||||
static int
|
||||
st_lsm6dsx_check_odr_dependency(struct st_lsm6dsx_hw *hw, u32 odr,
|
||||
enum st_lsm6dsx_sensor_id id)
|
||||
{
|
||||
struct st_lsm6dsx_sensor *ref = iio_priv(hw->iio_devs[id]);
|
||||
|
||||
if (odr > 0) {
|
||||
if (hw->enable_mask & BIT(id))
|
||||
return max_t(u16, ref->odr, odr);
|
||||
return max_t(u32, ref->odr, odr);
|
||||
else
|
||||
return odr;
|
||||
} else {
|
||||
@ -1381,7 +1396,8 @@ static u16 st_lsm6dsx_check_odr_dependency(struct st_lsm6dsx_hw *hw, u16 odr,
|
||||
}
|
||||
}
|
||||
|
||||
static int st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u16 req_odr)
|
||||
static int
|
||||
st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u32 req_odr)
|
||||
{
|
||||
struct st_lsm6dsx_sensor *ref_sensor = sensor;
|
||||
struct st_lsm6dsx_hw *hw = sensor->hw;
|
||||
@ -1395,7 +1411,7 @@ static int st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u16 req_odr)
|
||||
case ST_LSM6DSX_ID_EXT1:
|
||||
case ST_LSM6DSX_ID_EXT2:
|
||||
case ST_LSM6DSX_ID_ACC: {
|
||||
u16 odr;
|
||||
u32 odr;
|
||||
int i;
|
||||
|
||||
/*
|
||||
@ -1435,7 +1451,7 @@ int st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor,
|
||||
bool enable)
|
||||
{
|
||||
struct st_lsm6dsx_hw *hw = sensor->hw;
|
||||
u16 odr = enable ? sensor->odr : 0;
|
||||
u32 odr = enable ? sensor->odr : 0;
|
||||
int err;
|
||||
|
||||
err = st_lsm6dsx_set_odr(sensor, odr);
|
||||
@ -1461,7 +1477,7 @@ static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
delay = 1000000 / sensor->odr;
|
||||
delay = 1000000000 / sensor->odr;
|
||||
usleep_range(delay, 2 * delay);
|
||||
|
||||
err = st_lsm6dsx_read_locked(hw, addr, &data, sizeof(data));
|
||||
@ -1493,8 +1509,9 @@ static int st_lsm6dsx_read_raw(struct iio_dev *iio_dev,
|
||||
iio_device_release_direct_mode(iio_dev);
|
||||
break;
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
*val = sensor->odr;
|
||||
ret = IIO_VAL_INT;
|
||||
*val = sensor->odr / 1000;
|
||||
*val2 = (sensor->odr % 1000) * 1000;
|
||||
ret = IIO_VAL_INT_PLUS_MICRO;
|
||||
break;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
*val = 0;
|
||||
@ -1527,8 +1544,11 @@ static int st_lsm6dsx_write_raw(struct iio_dev *iio_dev,
|
||||
case IIO_CHAN_INFO_SAMP_FREQ: {
|
||||
u8 data;
|
||||
|
||||
err = st_lsm6dsx_check_odr(sensor, val, &data);
|
||||
if (!err)
|
||||
val = val * 1000 + val2 / 1000;
|
||||
val = st_lsm6dsx_check_odr(sensor, val, &data);
|
||||
if (val < 0)
|
||||
err = val;
|
||||
else
|
||||
sensor->odr = val;
|
||||
break;
|
||||
}
|
||||
@ -1709,13 +1729,14 @@ st_lsm6dsx_sysfs_sampling_frequency_avail(struct device *dev,
|
||||
char *buf)
|
||||
{
|
||||
struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev));
|
||||
enum st_lsm6dsx_sensor_id id = sensor->id;
|
||||
struct st_lsm6dsx_hw *hw = sensor->hw;
|
||||
const struct st_lsm6dsx_odr_table_entry *odr_table;
|
||||
int i, len = 0;
|
||||
|
||||
for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++)
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len, "%d ",
|
||||
hw->settings->odr_table[id].odr_avl[i].hz);
|
||||
odr_table = &sensor->hw->settings->odr_table[sensor->id];
|
||||
for (i = 0; i < odr_table->odr_len; i++)
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%03d ",
|
||||
odr_table->odr_avl[i].milli_hz / 1000,
|
||||
odr_table->odr_avl[i].milli_hz % 1000);
|
||||
buf[len - 1] = '\n';
|
||||
|
||||
return len;
|
||||
@ -2021,7 +2042,7 @@ static struct iio_dev *st_lsm6dsx_alloc_iiodev(struct st_lsm6dsx_hw *hw,
|
||||
sensor = iio_priv(iio_dev);
|
||||
sensor->id = id;
|
||||
sensor->hw = hw;
|
||||
sensor->odr = hw->settings->odr_table[id].odr_avl[0].hz;
|
||||
sensor->odr = hw->settings->odr_table[id].odr_avl[0].milli_hz;
|
||||
sensor->gain = hw->settings->fs_table[id].fs_avl[0].gain;
|
||||
sensor->watermark = 1;
|
||||
|
||||
|
@ -51,10 +51,11 @@ static const struct st_lsm6dsx_ext_dev_settings st_lsm6dsx_ext_dev_table[] = {
|
||||
.addr = 0x60,
|
||||
.mask = GENMASK(3, 2),
|
||||
},
|
||||
.odr_avl[0] = { 10, 0x0 },
|
||||
.odr_avl[1] = { 20, 0x1 },
|
||||
.odr_avl[2] = { 50, 0x2 },
|
||||
.odr_avl[3] = { 100, 0x3 },
|
||||
.odr_avl[0] = { 10000, 0x0 },
|
||||
.odr_avl[1] = { 20000, 0x1 },
|
||||
.odr_avl[2] = { 50000, 0x2 },
|
||||
.odr_avl[3] = { 100000, 0x3 },
|
||||
.odr_len = 4,
|
||||
},
|
||||
.fs_table = {
|
||||
.fs_avl[0] = {
|
||||
@ -93,11 +94,11 @@ static const struct st_lsm6dsx_ext_dev_settings st_lsm6dsx_ext_dev_table[] = {
|
||||
static void st_lsm6dsx_shub_wait_complete(struct st_lsm6dsx_hw *hw)
|
||||
{
|
||||
struct st_lsm6dsx_sensor *sensor;
|
||||
u16 odr;
|
||||
u32 odr;
|
||||
|
||||
sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]);
|
||||
odr = (hw->enable_mask & BIT(ST_LSM6DSX_ID_ACC)) ? sensor->odr : 13;
|
||||
msleep((2000U / odr) + 1);
|
||||
odr = (hw->enable_mask & BIT(ST_LSM6DSX_ID_ACC)) ? sensor->odr : 12500;
|
||||
msleep((2000000U / odr) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -317,17 +318,18 @@ st_lsm6dsx_shub_write_with_mask(struct st_lsm6dsx_sensor *sensor,
|
||||
|
||||
static int
|
||||
st_lsm6dsx_shub_get_odr_val(struct st_lsm6dsx_sensor *sensor,
|
||||
u16 odr, u16 *val)
|
||||
u32 odr, u16 *val)
|
||||
{
|
||||
const struct st_lsm6dsx_ext_dev_settings *settings;
|
||||
int i;
|
||||
|
||||
settings = sensor->ext_info.settings;
|
||||
for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++)
|
||||
if (settings->odr_table.odr_avl[i].hz == odr)
|
||||
for (i = 0; i < settings->odr_table.odr_len; i++) {
|
||||
if (settings->odr_table.odr_avl[i].milli_hz == odr)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ST_LSM6DSX_ODR_LIST_SIZE)
|
||||
if (i == settings->odr_table.odr_len)
|
||||
return -EINVAL;
|
||||
|
||||
*val = settings->odr_table.odr_avl[i].val;
|
||||
@ -335,7 +337,7 @@ st_lsm6dsx_shub_get_odr_val(struct st_lsm6dsx_sensor *sensor,
|
||||
}
|
||||
|
||||
static int
|
||||
st_lsm6dsx_shub_set_odr(struct st_lsm6dsx_sensor *sensor, u16 odr)
|
||||
st_lsm6dsx_shub_set_odr(struct st_lsm6dsx_sensor *sensor, u32 odr)
|
||||
{
|
||||
const struct st_lsm6dsx_ext_dev_settings *settings;
|
||||
u16 val;
|
||||
@ -440,7 +442,7 @@ st_lsm6dsx_shub_read_oneshot(struct st_lsm6dsx_sensor *sensor,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
delay = 1000000 / sensor->odr;
|
||||
delay = 1000000000 / sensor->odr;
|
||||
usleep_range(delay, 2 * delay);
|
||||
|
||||
len = min_t(int, sizeof(data), ch->scan_type.realbits >> 3);
|
||||
@ -480,8 +482,9 @@ st_lsm6dsx_shub_read_raw(struct iio_dev *iio_dev,
|
||||
iio_device_release_direct_mode(iio_dev);
|
||||
break;
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
*val = sensor->odr;
|
||||
ret = IIO_VAL_INT;
|
||||
*val = sensor->odr / 1000;
|
||||
*val2 = (sensor->odr % 1000) * 1000;
|
||||
ret = IIO_VAL_INT_PLUS_MICRO;
|
||||
break;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
*val = 0;
|
||||
@ -512,6 +515,7 @@ st_lsm6dsx_shub_write_raw(struct iio_dev *iio_dev,
|
||||
case IIO_CHAN_INFO_SAMP_FREQ: {
|
||||
u16 data;
|
||||
|
||||
val = val * 1000 + val2 / 1000;
|
||||
err = st_lsm6dsx_shub_get_odr_val(sensor, val, &data);
|
||||
if (!err)
|
||||
sensor->odr = val;
|
||||
@ -537,12 +541,11 @@ st_lsm6dsx_shub_sampling_freq_avail(struct device *dev,
|
||||
int i, len = 0;
|
||||
|
||||
settings = sensor->ext_info.settings;
|
||||
for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++) {
|
||||
u16 val = settings->odr_table.odr_avl[i].hz;
|
||||
for (i = 0; i < settings->odr_table.odr_len; i++) {
|
||||
u32 val = settings->odr_table.odr_avl[i].milli_hz;
|
||||
|
||||
if (val > 0)
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len, "%d ",
|
||||
val);
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%03d ",
|
||||
val / 1000, val % 1000);
|
||||
}
|
||||
buf[len - 1] = '\n';
|
||||
|
||||
@ -607,7 +610,7 @@ st_lsm6dsx_shub_alloc_iiodev(struct st_lsm6dsx_hw *hw,
|
||||
sensor = iio_priv(iio_dev);
|
||||
sensor->id = id;
|
||||
sensor->hw = hw;
|
||||
sensor->odr = info->odr_table.odr_avl[0].hz;
|
||||
sensor->odr = info->odr_table.odr_avl[0].milli_hz;
|
||||
sensor->gain = info->fs_table.fs_avl[0].gain;
|
||||
sensor->ext_info.settings = info;
|
||||
sensor->ext_info.addr = i2c_addr;
|
||||
|
@ -507,6 +507,17 @@ config VCNL4035
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called vcnl4035.
|
||||
|
||||
config VEML6030
|
||||
tristate "VEML6030 ambient light sensor"
|
||||
select REGMAP_I2C
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here if you want to build a driver for the Vishay VEML6030
|
||||
ambient light sensor (ALS).
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called veml6030.
|
||||
|
||||
config VEML6070
|
||||
tristate "VEML6070 UV A light sensor"
|
||||
depends on I2C
|
||||
|
@ -49,6 +49,7 @@ obj-$(CONFIG_TSL4531) += tsl4531.o
|
||||
obj-$(CONFIG_US5182D) += us5182d.o
|
||||
obj-$(CONFIG_VCNL4000) += vcnl4000.o
|
||||
obj-$(CONFIG_VCNL4035) += vcnl4035.o
|
||||
obj-$(CONFIG_VEML6030) += veml6030.o
|
||||
obj-$(CONFIG_VEML6070) += veml6070.o
|
||||
obj-$(CONFIG_VL6180) += vl6180.o
|
||||
obj-$(CONFIG_ZOPT2201) += zopt2201.o
|
||||
|
908
drivers/iio/light/veml6030.c
Normal file
908
drivers/iio/light/veml6030.c
Normal file
@ -0,0 +1,908 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* VEML6030 Ambient Light Sensor
|
||||
*
|
||||
* Copyright (c) 2019, Rishi Gupta <gupt21@gmail.com>
|
||||
*
|
||||
* Datasheet: https://www.vishay.com/docs/84366/veml6030.pdf
|
||||
* Appnote-84367: https://www.vishay.com/docs/84367/designingveml6030.pdf
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/events.h>
|
||||
|
||||
/* Device registers */
|
||||
#define VEML6030_REG_ALS_CONF 0x00
|
||||
#define VEML6030_REG_ALS_WH 0x01
|
||||
#define VEML6030_REG_ALS_WL 0x02
|
||||
#define VEML6030_REG_ALS_PSM 0x03
|
||||
#define VEML6030_REG_ALS_DATA 0x04
|
||||
#define VEML6030_REG_WH_DATA 0x05
|
||||
#define VEML6030_REG_ALS_INT 0x06
|
||||
|
||||
/* Bit masks for specific functionality */
|
||||
#define VEML6030_ALS_IT GENMASK(9, 6)
|
||||
#define VEML6030_PSM GENMASK(2, 1)
|
||||
#define VEML6030_ALS_PERS GENMASK(5, 4)
|
||||
#define VEML6030_ALS_GAIN GENMASK(12, 11)
|
||||
#define VEML6030_PSM_EN BIT(0)
|
||||
#define VEML6030_INT_TH_LOW BIT(15)
|
||||
#define VEML6030_INT_TH_HIGH BIT(14)
|
||||
#define VEML6030_ALS_INT_EN BIT(1)
|
||||
#define VEML6030_ALS_SD BIT(0)
|
||||
|
||||
/*
|
||||
* The resolution depends on both gain and integration time. The
|
||||
* cur_resolution stores one of the resolution mentioned in the
|
||||
* table during startup and gets updated whenever integration time
|
||||
* or gain is changed.
|
||||
*
|
||||
* Table 'resolution and maximum detection range' in appnote 84367
|
||||
* is visualized as a 2D array. The cur_gain stores index of gain
|
||||
* in this table (0-3) while the cur_integration_time holds index
|
||||
* of integration time (0-5).
|
||||
*/
|
||||
struct veml6030_data {
|
||||
struct i2c_client *client;
|
||||
struct regmap *regmap;
|
||||
int cur_resolution;
|
||||
int cur_gain;
|
||||
int cur_integration_time;
|
||||
};
|
||||
|
||||
/* Integration time available in seconds */
|
||||
static IIO_CONST_ATTR(in_illuminance_integration_time_available,
|
||||
"0.025 0.05 0.1 0.2 0.4 0.8");
|
||||
|
||||
/*
|
||||
* Scale is 1/gain. Value 0.125 is ALS gain x (1/8), 0.25 is
|
||||
* ALS gain x (1/4), 1.0 = ALS gain x 1 and 2.0 is ALS gain x 2.
|
||||
*/
|
||||
static IIO_CONST_ATTR(in_illuminance_scale_available,
|
||||
"0.125 0.25 1.0 2.0");
|
||||
|
||||
static struct attribute *veml6030_attributes[] = {
|
||||
&iio_const_attr_in_illuminance_integration_time_available.dev_attr.attr,
|
||||
&iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group veml6030_attr_group = {
|
||||
.attrs = veml6030_attributes,
|
||||
};
|
||||
|
||||
/*
|
||||
* Persistence = 1/2/4/8 x integration time
|
||||
* Minimum time for which light readings must stay above configured
|
||||
* threshold to assert the interrupt.
|
||||
*/
|
||||
static const char * const period_values[] = {
|
||||
"0.1 0.2 0.4 0.8",
|
||||
"0.2 0.4 0.8 1.6",
|
||||
"0.4 0.8 1.6 3.2",
|
||||
"0.8 1.6 3.2 6.4",
|
||||
"0.05 0.1 0.2 0.4",
|
||||
"0.025 0.050 0.1 0.2"
|
||||
};
|
||||
|
||||
/*
|
||||
* Return list of valid period values in seconds corresponding to
|
||||
* the currently active integration time.
|
||||
*/
|
||||
static ssize_t in_illuminance_period_available_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int ret, reg, x;
|
||||
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
|
||||
struct veml6030_data *data = iio_priv(indio_dev);
|
||||
|
||||
ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, ®);
|
||||
if (ret) {
|
||||
dev_err(&data->client->dev,
|
||||
"can't read als conf register %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ((reg >> 6) & 0xF);
|
||||
switch (ret) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
x = ret;
|
||||
break;
|
||||
case 8:
|
||||
x = 4;
|
||||
break;
|
||||
case 12:
|
||||
x = 5;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", period_values[x]);
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR_RO(in_illuminance_period_available, 0);
|
||||
|
||||
static struct attribute *veml6030_event_attributes[] = {
|
||||
&iio_dev_attr_in_illuminance_period_available.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group veml6030_event_attr_group = {
|
||||
.attrs = veml6030_event_attributes,
|
||||
};
|
||||
|
||||
static int veml6030_als_pwr_on(struct veml6030_data *data)
|
||||
{
|
||||
return regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
|
||||
VEML6030_ALS_SD, 0);
|
||||
}
|
||||
|
||||
static int veml6030_als_shut_down(struct veml6030_data *data)
|
||||
{
|
||||
return regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
|
||||
VEML6030_ALS_SD, 1);
|
||||
}
|
||||
|
||||
static void veml6030_als_shut_down_action(void *data)
|
||||
{
|
||||
veml6030_als_shut_down(data);
|
||||
}
|
||||
|
||||
static const struct iio_event_spec veml6030_event_spec[] = {
|
||||
{
|
||||
.type = IIO_EV_TYPE_THRESH,
|
||||
.dir = IIO_EV_DIR_RISING,
|
||||
.mask_separate = BIT(IIO_EV_INFO_VALUE),
|
||||
}, {
|
||||
.type = IIO_EV_TYPE_THRESH,
|
||||
.dir = IIO_EV_DIR_FALLING,
|
||||
.mask_separate = BIT(IIO_EV_INFO_VALUE),
|
||||
}, {
|
||||
.type = IIO_EV_TYPE_THRESH,
|
||||
.dir = IIO_EV_DIR_EITHER,
|
||||
.mask_separate = BIT(IIO_EV_INFO_PERIOD) |
|
||||
BIT(IIO_EV_INFO_ENABLE),
|
||||
},
|
||||
};
|
||||
|
||||
/* Channel number */
|
||||
enum veml6030_chan {
|
||||
CH_ALS,
|
||||
CH_WHITE,
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec veml6030_channels[] = {
|
||||
{
|
||||
.type = IIO_LIGHT,
|
||||
.channel = CH_ALS,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
|
||||
BIT(IIO_CHAN_INFO_PROCESSED) |
|
||||
BIT(IIO_CHAN_INFO_INT_TIME) |
|
||||
BIT(IIO_CHAN_INFO_SCALE),
|
||||
.event_spec = veml6030_event_spec,
|
||||
.num_event_specs = ARRAY_SIZE(veml6030_event_spec),
|
||||
},
|
||||
{
|
||||
.type = IIO_INTENSITY,
|
||||
.channel = CH_WHITE,
|
||||
.modified = 1,
|
||||
.channel2 = IIO_MOD_LIGHT_BOTH,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
|
||||
BIT(IIO_CHAN_INFO_PROCESSED),
|
||||
},
|
||||
};
|
||||
|
||||
static const struct regmap_config veml6030_regmap_config = {
|
||||
.name = "veml6030_regmap",
|
||||
.reg_bits = 8,
|
||||
.val_bits = 16,
|
||||
.max_register = VEML6030_REG_ALS_INT,
|
||||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
};
|
||||
|
||||
static int veml6030_get_intgrn_tm(struct iio_dev *indio_dev,
|
||||
int *val, int *val2)
|
||||
{
|
||||
int ret, reg;
|
||||
struct veml6030_data *data = iio_priv(indio_dev);
|
||||
|
||||
ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, ®);
|
||||
if (ret) {
|
||||
dev_err(&data->client->dev,
|
||||
"can't read als conf register %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch ((reg >> 6) & 0xF) {
|
||||
case 0:
|
||||
*val2 = 100000;
|
||||
break;
|
||||
case 1:
|
||||
*val2 = 200000;
|
||||
break;
|
||||
case 2:
|
||||
*val2 = 400000;
|
||||
break;
|
||||
case 3:
|
||||
*val2 = 800000;
|
||||
break;
|
||||
case 8:
|
||||
*val2 = 50000;
|
||||
break;
|
||||
case 12:
|
||||
*val2 = 25000;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*val = 0;
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
}
|
||||
|
||||
static int veml6030_set_intgrn_tm(struct iio_dev *indio_dev,
|
||||
int val, int val2)
|
||||
{
|
||||
int ret, new_int_time, int_idx;
|
||||
struct veml6030_data *data = iio_priv(indio_dev);
|
||||
|
||||
if (val)
|
||||
return -EINVAL;
|
||||
|
||||
switch (val2) {
|
||||
case 25000:
|
||||
new_int_time = 0x300;
|
||||
int_idx = 5;
|
||||
break;
|
||||
case 50000:
|
||||
new_int_time = 0x200;
|
||||
int_idx = 4;
|
||||
break;
|
||||
case 100000:
|
||||
new_int_time = 0x00;
|
||||
int_idx = 3;
|
||||
break;
|
||||
case 200000:
|
||||
new_int_time = 0x40;
|
||||
int_idx = 2;
|
||||
break;
|
||||
case 400000:
|
||||
new_int_time = 0x80;
|
||||
int_idx = 1;
|
||||
break;
|
||||
case 800000:
|
||||
new_int_time = 0xC0;
|
||||
int_idx = 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
|
||||
VEML6030_ALS_IT, new_int_time);
|
||||
if (ret) {
|
||||
dev_err(&data->client->dev,
|
||||
"can't update als integration time %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cache current integration time and update resolution. For every
|
||||
* increase in integration time to next level, resolution is halved
|
||||
* and vice-versa.
|
||||
*/
|
||||
if (data->cur_integration_time < int_idx)
|
||||
data->cur_resolution <<= int_idx - data->cur_integration_time;
|
||||
else if (data->cur_integration_time > int_idx)
|
||||
data->cur_resolution >>= data->cur_integration_time - int_idx;
|
||||
|
||||
data->cur_integration_time = int_idx;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int veml6030_read_persistence(struct iio_dev *indio_dev,
|
||||
int *val, int *val2)
|
||||
{
|
||||
int ret, reg, period, x, y;
|
||||
struct veml6030_data *data = iio_priv(indio_dev);
|
||||
|
||||
ret = veml6030_get_intgrn_tm(indio_dev, &x, &y);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, ®);
|
||||
if (ret) {
|
||||
dev_err(&data->client->dev,
|
||||
"can't read als conf register %d\n", ret);
|
||||
}
|
||||
|
||||
/* integration time multiplied by 1/2/4/8 */
|
||||
period = y * (1 << ((reg >> 4) & 0x03));
|
||||
|
||||
*val = period / 1000000;
|
||||
*val2 = period % 1000000;
|
||||
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
}
|
||||
|
||||
static int veml6030_write_persistence(struct iio_dev *indio_dev,
|
||||
int val, int val2)
|
||||
{
|
||||
int ret, period, x, y;
|
||||
struct veml6030_data *data = iio_priv(indio_dev);
|
||||
|
||||
ret = veml6030_get_intgrn_tm(indio_dev, &x, &y);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!val) {
|
||||
period = val2 / y;
|
||||
} else {
|
||||
if ((val == 1) && (val2 == 600000))
|
||||
period = 1600000 / y;
|
||||
else if ((val == 3) && (val2 == 200000))
|
||||
period = 3200000 / y;
|
||||
else if ((val == 6) && (val2 == 400000))
|
||||
period = 6400000 / y;
|
||||
else
|
||||
period = -1;
|
||||
}
|
||||
|
||||
if (period <= 0 || period > 8 || hweight8(period) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
|
||||
VEML6030_ALS_PERS, (ffs(period) - 1) << 4);
|
||||
if (ret)
|
||||
dev_err(&data->client->dev,
|
||||
"can't set persistence value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int veml6030_set_als_gain(struct iio_dev *indio_dev,
|
||||
int val, int val2)
|
||||
{
|
||||
int ret, new_gain, gain_idx;
|
||||
struct veml6030_data *data = iio_priv(indio_dev);
|
||||
|
||||
if (val == 0 && val2 == 125000) {
|
||||
new_gain = 0x1000; /* 0x02 << 11 */
|
||||
gain_idx = 3;
|
||||
} else if (val == 0 && val2 == 250000) {
|
||||
new_gain = 0x1800;
|
||||
gain_idx = 2;
|
||||
} else if (val == 1 && val2 == 0) {
|
||||
new_gain = 0x00;
|
||||
gain_idx = 1;
|
||||
} else if (val == 2 && val2 == 0) {
|
||||
new_gain = 0x800;
|
||||
gain_idx = 0;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
|
||||
VEML6030_ALS_GAIN, new_gain);
|
||||
if (ret) {
|
||||
dev_err(&data->client->dev,
|
||||
"can't set als gain %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cache currently set gain & update resolution. For every
|
||||
* increase in the gain to next level, resolution is halved
|
||||
* and vice-versa.
|
||||
*/
|
||||
if (data->cur_gain < gain_idx)
|
||||
data->cur_resolution <<= gain_idx - data->cur_gain;
|
||||
else if (data->cur_gain > gain_idx)
|
||||
data->cur_resolution >>= data->cur_gain - gain_idx;
|
||||
|
||||
data->cur_gain = gain_idx;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int veml6030_get_als_gain(struct iio_dev *indio_dev,
|
||||
int *val, int *val2)
|
||||
{
|
||||
int ret, reg;
|
||||
struct veml6030_data *data = iio_priv(indio_dev);
|
||||
|
||||
ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, ®);
|
||||
if (ret) {
|
||||
dev_err(&data->client->dev,
|
||||
"can't read als conf register %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch ((reg >> 11) & 0x03) {
|
||||
case 0:
|
||||
*val = 1;
|
||||
*val2 = 0;
|
||||
break;
|
||||
case 1:
|
||||
*val = 2;
|
||||
*val2 = 0;
|
||||
break;
|
||||
case 2:
|
||||
*val = 0;
|
||||
*val2 = 125000;
|
||||
break;
|
||||
case 3:
|
||||
*val = 0;
|
||||
*val2 = 250000;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
}
|
||||
|
||||
static int veml6030_read_thresh(struct iio_dev *indio_dev,
|
||||
int *val, int *val2, int dir)
|
||||
{
|
||||
int ret, reg;
|
||||
struct veml6030_data *data = iio_priv(indio_dev);
|
||||
|
||||
if (dir == IIO_EV_DIR_RISING)
|
||||
ret = regmap_read(data->regmap, VEML6030_REG_ALS_WH, ®);
|
||||
else
|
||||
ret = regmap_read(data->regmap, VEML6030_REG_ALS_WL, ®);
|
||||
if (ret) {
|
||||
dev_err(&data->client->dev,
|
||||
"can't read als threshold value %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*val = reg & 0xffff;
|
||||
return IIO_VAL_INT;
|
||||
}
|
||||
|
||||
static int veml6030_write_thresh(struct iio_dev *indio_dev,
|
||||
int val, int val2, int dir)
|
||||
{
|
||||
int ret;
|
||||
struct veml6030_data *data = iio_priv(indio_dev);
|
||||
|
||||
if (val > 0xFFFF || val < 0 || val2)
|
||||
return -EINVAL;
|
||||
|
||||
if (dir == IIO_EV_DIR_RISING) {
|
||||
ret = regmap_write(data->regmap, VEML6030_REG_ALS_WH, val);
|
||||
if (ret)
|
||||
dev_err(&data->client->dev,
|
||||
"can't set high threshold %d\n", ret);
|
||||
} else {
|
||||
ret = regmap_write(data->regmap, VEML6030_REG_ALS_WL, val);
|
||||
if (ret)
|
||||
dev_err(&data->client->dev,
|
||||
"can't set low threshold %d\n", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Provide both raw as well as light reading in lux.
|
||||
* light (in lux) = resolution * raw reading
|
||||
*/
|
||||
static int veml6030_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan, int *val,
|
||||
int *val2, long mask)
|
||||
{
|
||||
int ret, reg;
|
||||
struct veml6030_data *data = iio_priv(indio_dev);
|
||||
struct regmap *regmap = data->regmap;
|
||||
struct device *dev = &data->client->dev;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
case IIO_CHAN_INFO_PROCESSED:
|
||||
switch (chan->type) {
|
||||
case IIO_LIGHT:
|
||||
ret = regmap_read(regmap, VEML6030_REG_ALS_DATA, ®);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "can't read als data %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (mask == IIO_CHAN_INFO_PROCESSED) {
|
||||
*val = (reg * data->cur_resolution) / 10000;
|
||||
*val2 = (reg * data->cur_resolution) % 10000;
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
}
|
||||
*val = reg;
|
||||
return IIO_VAL_INT;
|
||||
case IIO_INTENSITY:
|
||||
ret = regmap_read(regmap, VEML6030_REG_WH_DATA, ®);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "can't read white data %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (mask == IIO_CHAN_INFO_PROCESSED) {
|
||||
*val = (reg * data->cur_resolution) / 10000;
|
||||
*val2 = (reg * data->cur_resolution) % 10000;
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
}
|
||||
*val = reg;
|
||||
return IIO_VAL_INT;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
case IIO_CHAN_INFO_INT_TIME:
|
||||
if (chan->type == IIO_LIGHT)
|
||||
return veml6030_get_intgrn_tm(indio_dev, val, val2);
|
||||
return -EINVAL;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
if (chan->type == IIO_LIGHT)
|
||||
return veml6030_get_als_gain(indio_dev, val, val2);
|
||||
return -EINVAL;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int veml6030_write_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int val, int val2, long mask)
|
||||
{
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_INT_TIME:
|
||||
switch (chan->type) {
|
||||
case IIO_LIGHT:
|
||||
return veml6030_set_intgrn_tm(indio_dev, val, val2);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
switch (chan->type) {
|
||||
case IIO_LIGHT:
|
||||
return veml6030_set_als_gain(indio_dev, val, val2);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int veml6030_read_event_val(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan, enum iio_event_type type,
|
||||
enum iio_event_direction dir, enum iio_event_info info,
|
||||
int *val, int *val2)
|
||||
{
|
||||
switch (info) {
|
||||
case IIO_EV_INFO_VALUE:
|
||||
switch (dir) {
|
||||
case IIO_EV_DIR_RISING:
|
||||
case IIO_EV_DIR_FALLING:
|
||||
return veml6030_read_thresh(indio_dev, val, val2, dir);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case IIO_EV_INFO_PERIOD:
|
||||
return veml6030_read_persistence(indio_dev, val, val2);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int veml6030_write_event_val(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan, enum iio_event_type type,
|
||||
enum iio_event_direction dir, enum iio_event_info info,
|
||||
int val, int val2)
|
||||
{
|
||||
switch (info) {
|
||||
case IIO_EV_INFO_VALUE:
|
||||
return veml6030_write_thresh(indio_dev, val, val2, dir);
|
||||
case IIO_EV_INFO_PERIOD:
|
||||
return veml6030_write_persistence(indio_dev, val, val2);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int veml6030_read_interrupt_config(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan, enum iio_event_type type,
|
||||
enum iio_event_direction dir)
|
||||
{
|
||||
int ret, reg;
|
||||
struct veml6030_data *data = iio_priv(indio_dev);
|
||||
|
||||
ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, ®);
|
||||
if (ret) {
|
||||
dev_err(&data->client->dev,
|
||||
"can't read als conf register %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (reg & VEML6030_ALS_INT_EN)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sensor should not be measuring light when interrupt is configured.
|
||||
* Therefore correct sequence to configure interrupt functionality is:
|
||||
* shut down -> enable/disable interrupt -> power on
|
||||
*
|
||||
* state = 1 enables interrupt, state = 0 disables interrupt
|
||||
*/
|
||||
static int veml6030_write_interrupt_config(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan, enum iio_event_type type,
|
||||
enum iio_event_direction dir, int state)
|
||||
{
|
||||
int ret;
|
||||
struct veml6030_data *data = iio_priv(indio_dev);
|
||||
|
||||
if (state < 0 || state > 1)
|
||||
return -EINVAL;
|
||||
|
||||
ret = veml6030_als_shut_down(data);
|
||||
if (ret < 0) {
|
||||
dev_err(&data->client->dev,
|
||||
"can't disable als to configure interrupt %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* enable interrupt + power on */
|
||||
ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
|
||||
VEML6030_ALS_INT_EN | VEML6030_ALS_SD, state << 1);
|
||||
if (ret)
|
||||
dev_err(&data->client->dev,
|
||||
"can't enable interrupt & poweron als %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct iio_info veml6030_info = {
|
||||
.read_raw = veml6030_read_raw,
|
||||
.write_raw = veml6030_write_raw,
|
||||
.read_event_value = veml6030_read_event_val,
|
||||
.write_event_value = veml6030_write_event_val,
|
||||
.read_event_config = veml6030_read_interrupt_config,
|
||||
.write_event_config = veml6030_write_interrupt_config,
|
||||
.attrs = &veml6030_attr_group,
|
||||
.event_attrs = &veml6030_event_attr_group,
|
||||
};
|
||||
|
||||
static const struct iio_info veml6030_info_no_irq = {
|
||||
.read_raw = veml6030_read_raw,
|
||||
.write_raw = veml6030_write_raw,
|
||||
.attrs = &veml6030_attr_group,
|
||||
};
|
||||
|
||||
static irqreturn_t veml6030_event_handler(int irq, void *private)
|
||||
{
|
||||
int ret, reg, evtdir;
|
||||
struct iio_dev *indio_dev = private;
|
||||
struct veml6030_data *data = iio_priv(indio_dev);
|
||||
|
||||
ret = regmap_read(data->regmap, VEML6030_REG_ALS_INT, ®);
|
||||
if (ret) {
|
||||
dev_err(&data->client->dev,
|
||||
"can't read als interrupt register %d\n", ret);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/* Spurious interrupt handling */
|
||||
if (!(reg & (VEML6030_INT_TH_HIGH | VEML6030_INT_TH_LOW)))
|
||||
return IRQ_NONE;
|
||||
|
||||
if (reg & VEML6030_INT_TH_HIGH)
|
||||
evtdir = IIO_EV_DIR_RISING;
|
||||
else
|
||||
evtdir = IIO_EV_DIR_FALLING;
|
||||
|
||||
iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_INTENSITY,
|
||||
0, IIO_EV_TYPE_THRESH, evtdir),
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set ALS gain to 1/8, integration time to 100 ms, PSM to mode 2,
|
||||
* persistence to 1 x integration time and the threshold
|
||||
* interrupt disabled by default. First shutdown the sensor,
|
||||
* update registers and then power on the sensor.
|
||||
*/
|
||||
static int veml6030_hw_init(struct iio_dev *indio_dev)
|
||||
{
|
||||
int ret, val;
|
||||
struct veml6030_data *data = iio_priv(indio_dev);
|
||||
struct i2c_client *client = data->client;
|
||||
|
||||
ret = veml6030_als_shut_down(data);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "can't shutdown als %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_write(data->regmap, VEML6030_REG_ALS_CONF, 0x1001);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "can't setup als configs %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_PSM,
|
||||
VEML6030_PSM | VEML6030_PSM_EN, 0x03);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "can't setup default PSM %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_write(data->regmap, VEML6030_REG_ALS_WH, 0xFFFF);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "can't setup high threshold %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_write(data->regmap, VEML6030_REG_ALS_WL, 0x0000);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "can't setup low threshold %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = veml6030_als_pwr_on(data);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "can't poweron als %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Wait 4 ms to let processor & oscillator start correctly */
|
||||
usleep_range(4000, 4002);
|
||||
|
||||
/* Clear stale interrupt status bits if any during start */
|
||||
ret = regmap_read(data->regmap, VEML6030_REG_ALS_INT, &val);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev,
|
||||
"can't clear als interrupt status %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Cache currently active measurement parameters */
|
||||
data->cur_gain = 3;
|
||||
data->cur_resolution = 4608;
|
||||
data->cur_integration_time = 3;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int veml6030_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
struct veml6030_data *data;
|
||||
struct iio_dev *indio_dev;
|
||||
struct regmap *regmap;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
|
||||
dev_err(&client->dev, "i2c adapter doesn't support plain i2c\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
regmap = devm_regmap_init_i2c(client, &veml6030_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&client->dev, "can't setup regmap\n");
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
data = iio_priv(indio_dev);
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
data->client = client;
|
||||
data->regmap = regmap;
|
||||
|
||||
indio_dev->dev.parent = &client->dev;
|
||||
indio_dev->name = "veml6030";
|
||||
indio_dev->channels = veml6030_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(veml6030_channels);
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
if (client->irq) {
|
||||
ret = devm_request_threaded_irq(&client->dev, client->irq,
|
||||
NULL, veml6030_event_handler,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
"veml6030", indio_dev);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev,
|
||||
"irq %d request failed\n", client->irq);
|
||||
return ret;
|
||||
}
|
||||
indio_dev->info = &veml6030_info;
|
||||
} else {
|
||||
indio_dev->info = &veml6030_info_no_irq;
|
||||
}
|
||||
|
||||
ret = veml6030_hw_init(indio_dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(&client->dev,
|
||||
veml6030_als_shut_down_action, data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return devm_iio_device_register(&client->dev, indio_dev);
|
||||
}
|
||||
|
||||
static int __maybe_unused veml6030_runtime_suspend(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
|
||||
struct veml6030_data *data = iio_priv(indio_dev);
|
||||
|
||||
ret = veml6030_als_shut_down(data);
|
||||
if (ret < 0)
|
||||
dev_err(&data->client->dev, "can't suspend als %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __maybe_unused veml6030_runtime_resume(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
|
||||
struct veml6030_data *data = iio_priv(indio_dev);
|
||||
|
||||
ret = veml6030_als_pwr_on(data);
|
||||
if (ret < 0)
|
||||
dev_err(&data->client->dev, "can't resume als %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops veml6030_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
SET_RUNTIME_PM_OPS(veml6030_runtime_suspend,
|
||||
veml6030_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static const struct of_device_id veml6030_of_match[] = {
|
||||
{ .compatible = "vishay,veml6030" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, veml6030_of_match);
|
||||
|
||||
static const struct i2c_device_id veml6030_id[] = {
|
||||
{ "veml6030", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, veml6030_id);
|
||||
|
||||
static struct i2c_driver veml6030_driver = {
|
||||
.driver = {
|
||||
.name = "veml6030",
|
||||
.of_match_table = veml6030_of_match,
|
||||
.pm = &veml6030_pm_ops,
|
||||
},
|
||||
.probe = veml6030_probe,
|
||||
.id_table = veml6030_id,
|
||||
};
|
||||
module_i2c_driver(veml6030_driver);
|
||||
|
||||
MODULE_AUTHOR("Rishi Gupta <gupt21@gmail.com>");
|
||||
MODULE_DESCRIPTION("VEML6030 Ambient Light Sensor");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -114,6 +114,7 @@ static int cros_ec_baro_write(struct iio_dev *indio_dev,
|
||||
static const struct iio_info cros_ec_baro_info = {
|
||||
.read_raw = &cros_ec_baro_read,
|
||||
.write_raw = &cros_ec_baro_write,
|
||||
.read_avail = &cros_ec_sensors_core_read_avail,
|
||||
};
|
||||
|
||||
static int cros_ec_baro_probe(struct platform_device *pdev)
|
||||
@ -149,6 +150,8 @@ static int cros_ec_baro_probe(struct platform_device *pdev)
|
||||
BIT(IIO_CHAN_INFO_SCALE) |
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ) |
|
||||
BIT(IIO_CHAN_INFO_FREQUENCY);
|
||||
channel->info_mask_shared_by_all_available =
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ);
|
||||
channel->scan_type.realbits = CROS_EC_SENSOR_BITS;
|
||||
channel->scan_type.storagebits = CROS_EC_SENSOR_BITS;
|
||||
channel->scan_type.shift = 0;
|
||||
|
@ -129,7 +129,8 @@ static inline int adis_read_reg_16(struct adis *adis, unsigned int reg,
|
||||
int ret;
|
||||
|
||||
ret = adis_read_reg(adis, reg, &tmp, 2);
|
||||
*val = tmp;
|
||||
if (ret == 0)
|
||||
*val = tmp;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -147,7 +148,8 @@ static inline int adis_read_reg_32(struct adis *adis, unsigned int reg,
|
||||
int ret;
|
||||
|
||||
ret = adis_read_reg(adis, reg, &tmp, 4);
|
||||
*val = tmp;
|
||||
if (ret == 0)
|
||||
*val = tmp;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
iio_utils-y += iio_utils.o
|
||||
lsiio-y += lsiio.o iio_utils.o
|
||||
iio_event_monitor-y += iio_event_monitor.o iio_utils.o
|
||||
iio_generic_buffer-y += iio_generic_buffer.o iio_utils.o
|
||||
|
@ -32,20 +32,24 @@ $(OUTPUT)include/linux/iio: ../../include/uapi/linux/iio
|
||||
|
||||
prepare: $(OUTPUT)include/linux/iio
|
||||
|
||||
IIO_UTILS_IN := $(OUTPUT)iio_utils-in.o
|
||||
$(IIO_UTILS_IN): prepare FORCE
|
||||
$(Q)$(MAKE) $(build)=iio_utils
|
||||
|
||||
LSIIO_IN := $(OUTPUT)lsiio-in.o
|
||||
$(LSIIO_IN): prepare FORCE
|
||||
$(LSIIO_IN): prepare FORCE $(OUTPUT)iio_utils-in.o
|
||||
$(Q)$(MAKE) $(build)=lsiio
|
||||
$(OUTPUT)lsiio: $(LSIIO_IN)
|
||||
$(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
|
||||
|
||||
IIO_EVENT_MONITOR_IN := $(OUTPUT)iio_event_monitor-in.o
|
||||
$(IIO_EVENT_MONITOR_IN): prepare FORCE
|
||||
$(IIO_EVENT_MONITOR_IN): prepare FORCE $(OUTPUT)iio_utils-in.o
|
||||
$(Q)$(MAKE) $(build)=iio_event_monitor
|
||||
$(OUTPUT)iio_event_monitor: $(IIO_EVENT_MONITOR_IN)
|
||||
$(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
|
||||
|
||||
IIO_GENERIC_BUFFER_IN := $(OUTPUT)iio_generic_buffer-in.o
|
||||
$(IIO_GENERIC_BUFFER_IN): prepare FORCE
|
||||
$(IIO_GENERIC_BUFFER_IN): prepare FORCE $(OUTPUT)iio_utils-in.o
|
||||
$(Q)$(MAKE) $(build)=iio_generic_buffer
|
||||
$(OUTPUT)iio_generic_buffer: $(IIO_GENERIC_BUFFER_IN)
|
||||
$(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
|
||||
|
Loading…
Reference in New Issue
Block a user