mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 12:42:02 +00:00
First set of new IIO device support, features and cleanup for the 5.8 cycle
Usual mix of new drivers, new support in old drivers and lots of minor cleanup. Yaml conversions also continue to trickle in (plenty more to go!) New device support * ad7476 - Add ad7091 support (ID only) * ad9467 - New driver for this 200/250 MSPS adi-axi-adc and SPI attached ADC. * adi-axi-adc - New driver to support ADIs generic AXI ADC IP core, used to provide high speed interfaces to ADCs (JESD204B/C or parallel interfaces). Usually paired with a device using a slow configuration interface (spi etc) Includes DT bindings and some fixes for fpga headers. * bmg160 - Add support for BMI088 (ID only) * max1241 - New driver for this ADC. * st_sensors - Add support for LIS2HH12 accelerometer * sx9310 - New driver supporting sx9310 and sx9311 proximity sensors. Yaml DT binding conversions * rockchip-saradc (including adding some missing parts) * stm32-dac * tsl2563 * vcnl4000 Features * st_lsm6dsx - Add LIS3MDL as a possible sensor hub device. * vcnl4000 - Add new concept of near level (from DT) to provide to userspace which often needs to have some calibrated concept of 'near'. Cleanups, minor fixes etc. * core - Use snprintf for functions where strings are built and there is potential for overflow. - Correct docs to indicate mlock should not be used directly by drivers. - Fix up accidental dropping of a patch to use bitmap_zalloc. - Stop allowing enabling of buffers with no channels enabled. - Drop unused 'stufftoread' from iio_buffer. - Drop scan_el_attrs form iio_buffer as unused. - Reorder sanity checks in __iio_device_register to fail earlier. - Drop all the devm_ runregister / free functions from IIO as they were never used and encourage poor design. * dma-buffer - Tidy up includes. * dma-engine-buffer - Provide dev-managed allocator. - Fix an issue with printing a size_t * cross subsystem (kxsd9, bmg160, mpu3050, bmi160, mpu6050, bmc150) - Replace some unnecessary casts of error ptrs and whilst there. use the %pe printf parameter to print them in a more useful fashion. * cross subsystem - Drop casts in calls to regmap_bulk_read as they make no sense. - Use devm_platform_ioremap_resource to reduce boilerplate. - Fix typos in Analog Devices. * counters/104-quad - Add Syed Nayyar Waris as an additional maintainer. * ad7476 - Generate CONVST signal internally rather than requiring external trigger. Add sysfs read back as can now do so. - use devm_add_action_or_reset to tidy up error and remove handling. * ad7793 - Switch to read_avail from explicit attribute. Mostly done to avoid confusing people with a - sign (without surounding spaces) that was correct but checkpatch didn't like. * adis library - Add missing newlines at end of error messages. * adis16400 - Use DEFINE_DEBUGS_ATTRIBUTE rather than DEFINE_SIMPLE_ATTR. * adis16460 - Use DEFINE_DEBUGS_ATTRIBUTE rather than DEFINE_SIMPLE_ATTR. * ad_sigma_delta - Move some channel definitions into individual drivers to avoid having to deal with complex options. * ak8974 - Silence an error on deffered probe. * bmp280 - Harden against IRQ before registration. - Convert to read_avail instead of opencoding the equivalent. - Explicitly mark GPIO as optional. - Cleanup casts. - Remove line breaks from strings. * htts221 - Replace direct access to platform_data with dev_get_platdata(). - Use device properties rather than device tree ones to allow ACPI probing. - Casting cleanups. * intel_mrfld_adc - Don't use unaligned accessor for aligned data. * isl29125 - Reorder buer pre and post hooks to allow for coming core rework. * ltc2983 - Remove comp to bool. * max1363 - Stop using mlock from the iio_dev directly in favour of a local lock with clearly defined scope. * max30100 - Use generic device properties to allow ACPI probe. * mpu6050 - Convert to i2c_new_client_device. - Add debugfs register access. * st_lsm6dsx - Provide means of configuring full scale on slave device if supported. - Drop include of st_sensors header to get one value. Its not otherwise used by this driver. * st-sensors - Replace direct access to platform_data with dev_get_platdata(). - Casting cleanups. - Avoid splitting strings. * st_uvis25 - Casting cleanups. * tsl2563 - Typo fix. * tsl2772 - scnprintf in a non obvious string building usecase. Note also 'fixes' a wrong calculation of remaining space that couldn't actually cause any trouble as there was lots of room. * xilinx-xadc - Fix Lars-Peter spelling his own name wrong :) + additional typos. -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEEbilms4eEBlKRJoGxVIU0mcT0FogFAl6gicARHGppYzIzQGtl cm5lbC5vcmcACgkQVIU0mcT0Foj3ig//XRAAHRSfzXFpvYxITVKDIGwP/giYdp91 OflGw/0aOZFExr72ENLmCArXZPOT2qAZyNNoDNvuJ9SkcVDf4bT3w9gYwWtJ1sd7 Hhh+1JpPspSo6vS85FMjm37UDfSbmYqB6wC57cZ5pKQIiJwi6W2hGsyOoOXmfLLc 57d3mlg4g3KLl9Hl4UTU84gE1ushKQgNxVH21Y71pOTa8p+xbWWcspWjR2Jf+kVZ qPr2+2rP/AjeAVLu9SKfdBiczYQCNR3uFWKkOKsBE9fq3sbcN6NT5DktrSJUH+qU zfUGmShCEP908/9fARazXQZcTOX1tIUOnrpHG9l54GNPh3S2Qk9xGaZxvQy5sguC AmC4p+MaIMrMcgWMk9po+nE5INJq7HBV/0jnADG307wEhFrKrjh/2PtP4f9k/Mcv sHB7K1+dcJAUwFb5gccdDBfmKMnwfnGS8OFGLXZZKBIDqSvptmIs/pmavjEPgqhV GwGTDPyZKeyDnyhTXGafxii03Q2I62Zte5l4jcZ+q8Q4UMxQovEkX6IvUpXwA0Kk eoxedbgdvzxrDNiNrXa0k6CLzqSQW+aVHgJG+HEig4IXQse8zXb11HCs35zq5r4j JI2UjLk3zUHLiNR/Ir9fKAbPwWSWv3IWkfmFEEUWvUFjM+Xot1Hg+61vBTFKo4iK EIqqPZmd5Mk= =DyTF -----END PGP SIGNATURE----- Merge tag 'iio-for-5.8a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next Jonathan writes: First set of new IIO device support, features and cleanup for the 5.8 cycle Usual mix of new drivers, new support in old drivers and lots of minor cleanup. Yaml conversions also continue to trickle in (plenty more to go!) New device support * ad7476 - Add ad7091 support (ID only) * ad9467 - New driver for this 200/250 MSPS adi-axi-adc and SPI attached ADC. * adi-axi-adc - New driver to support ADIs generic AXI ADC IP core, used to provide high speed interfaces to ADCs (JESD204B/C or parallel interfaces). Usually paired with a device using a slow configuration interface (spi etc) Includes DT bindings and some fixes for fpga headers. * bmg160 - Add support for BMI088 (ID only) * max1241 - New driver for this ADC. * st_sensors - Add support for LIS2HH12 accelerometer * sx9310 - New driver supporting sx9310 and sx9311 proximity sensors. Yaml DT binding conversions * rockchip-saradc (including adding some missing parts) * stm32-dac * tsl2563 * vcnl4000 Features * st_lsm6dsx - Add LIS3MDL as a possible sensor hub device. * vcnl4000 - Add new concept of near level (from DT) to provide to userspace which often needs to have some calibrated concept of 'near'. Cleanups, minor fixes etc. * core - Use snprintf for functions where strings are built and there is potential for overflow. - Correct docs to indicate mlock should not be used directly by drivers. - Fix up accidental dropping of a patch to use bitmap_zalloc. - Stop allowing enabling of buffers with no channels enabled. - Drop unused 'stufftoread' from iio_buffer. - Drop scan_el_attrs form iio_buffer as unused. - Reorder sanity checks in __iio_device_register to fail earlier. - Drop all the devm_ runregister / free functions from IIO as they were never used and encourage poor design. * dma-buffer - Tidy up includes. * dma-engine-buffer - Provide dev-managed allocator. - Fix an issue with printing a size_t * cross subsystem (kxsd9, bmg160, mpu3050, bmi160, mpu6050, bmc150) - Replace some unnecessary casts of error ptrs and whilst there. use the %pe printf parameter to print them in a more useful fashion. * cross subsystem - Drop casts in calls to regmap_bulk_read as they make no sense. - Use devm_platform_ioremap_resource to reduce boilerplate. - Fix typos in Analog Devices. * counters/104-quad - Add Syed Nayyar Waris as an additional maintainer. * ad7476 - Generate CONVST signal internally rather than requiring external trigger. Add sysfs read back as can now do so. - use devm_add_action_or_reset to tidy up error and remove handling. * ad7793 - Switch to read_avail from explicit attribute. Mostly done to avoid confusing people with a - sign (without surounding spaces) that was correct but checkpatch didn't like. * adis library - Add missing newlines at end of error messages. * adis16400 - Use DEFINE_DEBUGS_ATTRIBUTE rather than DEFINE_SIMPLE_ATTR. * adis16460 - Use DEFINE_DEBUGS_ATTRIBUTE rather than DEFINE_SIMPLE_ATTR. * ad_sigma_delta - Move some channel definitions into individual drivers to avoid having to deal with complex options. * ak8974 - Silence an error on deffered probe. * bmp280 - Harden against IRQ before registration. - Convert to read_avail instead of opencoding the equivalent. - Explicitly mark GPIO as optional. - Cleanup casts. - Remove line breaks from strings. * htts221 - Replace direct access to platform_data with dev_get_platdata(). - Use device properties rather than device tree ones to allow ACPI probing. - Casting cleanups. * intel_mrfld_adc - Don't use unaligned accessor for aligned data. * isl29125 - Reorder buer pre and post hooks to allow for coming core rework. * ltc2983 - Remove comp to bool. * max1363 - Stop using mlock from the iio_dev directly in favour of a local lock with clearly defined scope. * max30100 - Use generic device properties to allow ACPI probe. * mpu6050 - Convert to i2c_new_client_device. - Add debugfs register access. * st_lsm6dsx - Provide means of configuring full scale on slave device if supported. - Drop include of st_sensors header to get one value. Its not otherwise used by this driver. * st-sensors - Replace direct access to platform_data with dev_get_platdata(). - Casting cleanups. - Avoid splitting strings. * st_uvis25 - Casting cleanups. * tsl2563 - Typo fix. * tsl2772 - scnprintf in a non obvious string building usecase. Note also 'fixes' a wrong calculation of remaining space that couldn't actually cause any trouble as there was lots of room. * xilinx-xadc - Fix Lars-Peter spelling his own name wrong :) + additional typos. * tag 'iio-for-5.8a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (101 commits) iio: magnetometer: ak8974: Silence deferred-probe error Documentation: ABI: document IIO in_proximity_nearlevel file iio: vcnl4000: Export near level property for proximity sensor dt-bindings: iio: light: vcnl4000: Add proximity-near-level dt-bindings: iio: Introduce common properties for iio sensors dt-bindings: iio: vcnl4000: convert bindings to YAML format iio: Fix misspellings of "Analog Devices" iio: light: isl29125: fix iio_triggered_buffer_{predisable,postenable} positions iio: adc: fsl-imx25-gcq: Use devm_platform_ioremap_resource iio: adc: at91-adc: Use devm_platform_ioremap_resource iio: adc: sun4i-gpadc-iio: Use devm_platform_ioremap_resource iio:light:ltr501: Drop unnecessary cast of parameter in regmap_bulk_read iio:magn:mmc35240: Drop unnecessary casts of val parameter in regmap_bulk* iio:imu:mpu6050: Tidy up parameters to regmap_bulk functions. iio:chemical:bme680: Tidy up parameters to regmap_bulk_read iio:chemical:atlas-sensor: Drop unnecessary explicit casts in regmap_bulk_read calls iio:accel:mxc4005: Drop unnecessary explicit casts in regmap_bulk_read calls iio: imu: st_lsm6dsx: drop huge include in sensor-hub driver iio: buffer: drop devm_iio_kfifo_free() API call iio: buffer: drop devm_iio_hw_consumer_free() API call ...
This commit is contained in:
commit
4e1d96306d
10
Documentation/ABI/testing/sysfs-bus-iio-proximity
Normal file
10
Documentation/ABI/testing/sysfs-bus-iio-proximity
Normal file
@ -0,0 +1,10 @@
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_proximity_nearlevel
|
||||
Date: March 2020
|
||||
KernelVersion: 5.7
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Near level for proximity sensors. This is a single integer
|
||||
value that tells user space when an object should be
|
||||
considered close to the device. If the value read from the
|
||||
sensor is above or equal to the value in this file an object
|
||||
should typically be considered near.
|
10
Documentation/ABI/testing/sysfs-bus-iio-sx9310
Normal file
10
Documentation/ABI/testing/sysfs-bus-iio-sx9310
Normal file
@ -0,0 +1,10 @@
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_proximity3_comb_raw
|
||||
Date: February 2019
|
||||
KernelVersion: 5.6
|
||||
Contact: Daniel Campello <campello@chromium.org>
|
||||
Description:
|
||||
Proximity measurement indicating that some object is
|
||||
near the combined sensor. The combined sensor presents
|
||||
proximity measurements constructed by hardware by
|
||||
combining measurements taken from a given set of
|
||||
physical sensors.
|
65
Documentation/devicetree/bindings/iio/adc/adi,ad9467.yaml
Normal file
65
Documentation/devicetree/bindings/iio/adc/adi,ad9467.yaml
Normal file
@ -0,0 +1,65 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/adi,ad9467.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices AD9467 High-Speed ADC
|
||||
|
||||
maintainers:
|
||||
- Michael Hennerich <michael.hennerich@analog.com>
|
||||
- Alexandru Ardelean <alexandru.ardelean@analog.com>
|
||||
|
||||
description: |
|
||||
The AD9467 is a 16-bit, monolithic, IF sampling analog-to-digital
|
||||
converter (ADC).
|
||||
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/AD9467.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,ad9467
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: adc-clk
|
||||
|
||||
powerdown-gpios:
|
||||
description:
|
||||
Pin that controls the powerdown mode of the device.
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description:
|
||||
Reset pin for the device.
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
adc@0 {
|
||||
compatible = "adi,ad9467";
|
||||
reg = <0>;
|
||||
clocks = <&adc_clk>;
|
||||
clock-names = "adc-clk";
|
||||
};
|
||||
};
|
||||
...
|
62
Documentation/devicetree/bindings/iio/adc/adi,axi-adc.yaml
Normal file
62
Documentation/devicetree/bindings/iio/adc/adi,axi-adc.yaml
Normal file
@ -0,0 +1,62 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/adi,axi-adc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices AXI ADC IP core
|
||||
|
||||
maintainers:
|
||||
- Michael Hennerich <michael.hennerich@analog.com>
|
||||
- Alexandru Ardelean <alexandru.ardelean@analog.com>
|
||||
|
||||
description: |
|
||||
Analog Devices Generic AXI ADC IP core for interfacing an ADC device
|
||||
with a high speed serial (JESD204B/C) or source synchronous parallel
|
||||
interface (LVDS/CMOS).
|
||||
Usually, some other interface type (i.e SPI) is used as a control
|
||||
interface for the actual ADC, while this IP core will interface
|
||||
to the data-lines of the ADC and handle the streaming of data into
|
||||
memory via DMA.
|
||||
|
||||
https://wiki.analog.com/resources/fpga/docs/axi_adc_ip
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,axi-adc-10.0.a
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
dmas:
|
||||
maxItems: 1
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: rx
|
||||
|
||||
adi,adc-dev:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
A reference to a the actual ADC to which this FPGA ADC interfaces to.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- dmas
|
||||
- reg
|
||||
- adi,adc-dev
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
axi-adc@44a00000 {
|
||||
compatible = "adi,axi-adc-10.0.a";
|
||||
reg = <0x44a00000 0x10000>;
|
||||
dmas = <&rx_dma 0>;
|
||||
dma-names = "rx";
|
||||
|
||||
adi,adc-dev = <&spi_adc>;
|
||||
};
|
||||
...
|
63
Documentation/devicetree/bindings/iio/adc/maxim,max1241.yaml
Normal file
63
Documentation/devicetree/bindings/iio/adc/maxim,max1241.yaml
Normal file
@ -0,0 +1,63 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
# Copyright 2020 Alexandru Lazar
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/maxim,max1241.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Maxim MAX1241 12-bit, single-channel analog to digital converter
|
||||
|
||||
maintainers:
|
||||
- Alexandru Lazar <alazar@startmail.com>
|
||||
|
||||
description: |
|
||||
Bindings for the max1241 12-bit, single-channel ADC device. Datasheet
|
||||
can be found at:
|
||||
https://datasheets.maximintegrated.com/en/ds/MAX1240-MAX1241.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- maxim,max1241
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply:
|
||||
description:
|
||||
Device tree identifier of the regulator that powers the ADC.
|
||||
|
||||
vref-supply:
|
||||
description:
|
||||
Device tree identifier of the regulator that provides the external
|
||||
reference voltage.
|
||||
|
||||
shutdown-gpios:
|
||||
description:
|
||||
GPIO spec for the GPIO pin connected to the ADC's /SHDN pin. If
|
||||
specified, the /SHDN pin will be asserted between conversions,
|
||||
thus enabling power-down mode.
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
- vref-supply
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
adc@0 {
|
||||
compatible = "maxim,max1241";
|
||||
reg = <0>;
|
||||
vdd-supply = <&adc_vdd>;
|
||||
vref-supply = <&adc_vref>;
|
||||
spi-max-frequency = <1000000>;
|
||||
shutdown-gpios = <&gpio 26 1>;
|
||||
};
|
||||
};
|
@ -1,37 +0,0 @@
|
||||
Rockchip Successive Approximation Register (SAR) A/D Converter bindings
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "rockchip,<name>-saradc" or "rockchip,rk3066-tsadc"
|
||||
- "rockchip,saradc": for rk3188, rk3288
|
||||
- "rockchip,rk3066-tsadc": for rk3036
|
||||
- "rockchip,rk3328-saradc", "rockchip,rk3399-saradc": for rk3328
|
||||
- "rockchip,rk3399-saradc": for rk3399
|
||||
- "rockchip,rv1108-saradc", "rockchip,rk3399-saradc": for rv1108
|
||||
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- interrupts: The interrupt number to the cpu. The interrupt specifier format
|
||||
depends on the interrupt controller.
|
||||
- clocks: Must contain an entry for each entry in clock-names.
|
||||
- clock-names: Shall be "saradc" for the converter-clock, and "apb_pclk" for
|
||||
the peripheral clock.
|
||||
- vref-supply: The regulator supply ADC reference voltage.
|
||||
- #io-channel-cells: Should be 1, see ../iio-bindings.txt
|
||||
|
||||
Optional properties:
|
||||
- resets: Must contain an entry for each entry in reset-names if need support
|
||||
this option. See ../reset/reset.txt for details.
|
||||
- reset-names: Must include the name "saradc-apb".
|
||||
|
||||
Example:
|
||||
saradc: saradc@2006c000 {
|
||||
compatible = "rockchip,saradc";
|
||||
reg = <0x2006c000 0x100>;
|
||||
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>;
|
||||
clock-names = "saradc", "apb_pclk";
|
||||
resets = <&cru SRST_SARADC>;
|
||||
reset-names = "saradc-apb";
|
||||
#io-channel-cells = <1>;
|
||||
vref-supply = <&vcc18>;
|
||||
};
|
@ -0,0 +1,80 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/rockchip-saradc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Rockchip Successive Approximation Register (SAR) A/D Converter
|
||||
|
||||
maintainers:
|
||||
- Heiko Stuebner <heiko@sntech.de>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: rockchip,saradc
|
||||
- const: rockchip,rk3066-tsadc
|
||||
- const: rockchip,rk3399-saradc
|
||||
- items:
|
||||
- enum:
|
||||
- rockchip,px30-saradc
|
||||
- rockchip,rk3308-saradc
|
||||
- rockchip,rk3328-saradc
|
||||
- rockchip,rv1108-saradc
|
||||
- const: rockchip,rk3399-saradc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: converter clock
|
||||
- description: peripheral clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: saradc
|
||||
- const: apb_pclk
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
reset-names:
|
||||
const: saradc-apb
|
||||
|
||||
vref-supply:
|
||||
description:
|
||||
The regulator supply for the ADC reference voltage.
|
||||
|
||||
"#io-channel-cells":
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- vref-supply
|
||||
- "#io-channel-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/rk3288-cru.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
saradc: saradc@2006c000 {
|
||||
compatible = "rockchip,saradc";
|
||||
reg = <0x2006c000 0x100>;
|
||||
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>;
|
||||
clock-names = "saradc", "apb_pclk";
|
||||
resets = <&cru SRST_SARADC>;
|
||||
reset-names = "saradc-apb";
|
||||
vref-supply = <&vcc18>;
|
||||
#io-channel-cells = <1>;
|
||||
};
|
35
Documentation/devicetree/bindings/iio/common.yaml
Normal file
35
Documentation/devicetree/bindings/iio/common.yaml
Normal file
@ -0,0 +1,35 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/common.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Common properties for iio sensors
|
||||
|
||||
maintainers:
|
||||
- Jonathan Cameron <jic23@kernel.org>
|
||||
- Guido Günther <agx@sigxcpu.org>
|
||||
|
||||
description: |
|
||||
This document defines device tree properties common to several iio
|
||||
sensors. It doesn't constitue a device tree binding specification by itself but
|
||||
is meant to be referenced by device tree bindings.
|
||||
|
||||
When referenced from sensor tree bindings the properties defined in this
|
||||
document are defined as follows. The sensor tree bindings are responsible for
|
||||
defining whether each property is required or optional.
|
||||
|
||||
properties:
|
||||
proximity-near-level:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |
|
||||
For proximity sensors whether an object can be considered near to the
|
||||
device depends on parameters like sensor position, covering glass and
|
||||
aperture. This value gives an indication to userspace for which
|
||||
sensor readings this is the case.
|
||||
|
||||
Raw proximity values equal or above this level should be
|
||||
considered 'near' to the device (an object is near to the
|
||||
sensor).
|
||||
|
||||
...
|
@ -1,63 +0,0 @@
|
||||
STMicroelectronics STM32 DAC
|
||||
|
||||
The STM32 DAC is a 12-bit voltage output digital-to-analog converter. The DAC
|
||||
may be configured in 8 or 12-bit mode. It has two output channels, each with
|
||||
its own converter.
|
||||
It has built-in noise and triangle waveform generator and supports external
|
||||
triggers for conversions. The DAC's output buffer allows a high drive output
|
||||
current.
|
||||
|
||||
Contents of a stm32 dac root node:
|
||||
-----------------------------------
|
||||
Required properties:
|
||||
- compatible: Should be one of:
|
||||
"st,stm32f4-dac-core"
|
||||
"st,stm32h7-dac-core"
|
||||
- reg: Offset and length of the device's register set.
|
||||
- clocks: Must contain an entry for pclk (which feeds the peripheral bus
|
||||
interface)
|
||||
- clock-names: Must be "pclk".
|
||||
- vref-supply: Phandle to the vref+ input analog reference supply.
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <0>;
|
||||
|
||||
Optional properties:
|
||||
- resets: Must contain the phandle to the reset controller.
|
||||
- A pinctrl state named "default" for each DAC channel may be defined to set
|
||||
DAC_OUTx pin in mode of operation for analog output on external pin.
|
||||
|
||||
Contents of a stm32 dac child node:
|
||||
-----------------------------------
|
||||
DAC core node should contain at least one subnode, representing a
|
||||
DAC instance/channel available on the machine.
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be "st,stm32-dac".
|
||||
- reg: Must be either 1 or 2, to define (single) channel in use
|
||||
- #io-channel-cells = <1>: See the IIO bindings section "IIO consumers" in
|
||||
Documentation/devicetree/bindings/iio/iio-bindings.txt
|
||||
|
||||
Example:
|
||||
dac: dac@40007400 {
|
||||
compatible = "st,stm32h7-dac-core";
|
||||
reg = <0x40007400 0x400>;
|
||||
clocks = <&clk>;
|
||||
clock-names = "pclk";
|
||||
vref-supply = <®_vref>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&dac_out1 &dac_out2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
dac1: dac@1 {
|
||||
compatible = "st,stm32-dac";
|
||||
#io-channels-cells = <1>;
|
||||
reg = <1>;
|
||||
};
|
||||
|
||||
dac2: dac@2 {
|
||||
compatible = "st,stm32-dac";
|
||||
#io-channels-cells = <1>;
|
||||
reg = <2>;
|
||||
};
|
||||
};
|
110
Documentation/devicetree/bindings/iio/dac/st,stm32-dac.yaml
Normal file
110
Documentation/devicetree/bindings/iio/dac/st,stm32-dac.yaml
Normal file
@ -0,0 +1,110 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/iio/dac/st,stm32-dac.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: STMicroelectronics STM32 DAC bindings
|
||||
|
||||
description: |
|
||||
The STM32 DAC is a 12-bit voltage output digital-to-analog converter. The DAC
|
||||
may be configured in 8 or 12-bit mode. It has two output channels, each with
|
||||
its own converter.
|
||||
It has built-in noise and triangle waveform generator and supports external
|
||||
triggers for conversions. The DAC's output buffer allows a high drive output
|
||||
current.
|
||||
|
||||
maintainers:
|
||||
- Fabrice Gasnier <fabrice.gasnier@st.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- st,stm32f4-dac-core
|
||||
- st,stm32h7-dac-core
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: pclk
|
||||
|
||||
vref-supply:
|
||||
description: Phandle to the vref input analog reference voltage.
|
||||
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- vref-supply
|
||||
- '#address-cells'
|
||||
- '#size-cells'
|
||||
|
||||
patternProperties:
|
||||
"^dac@[1-2]+$":
|
||||
type: object
|
||||
description:
|
||||
A DAC block node should contain at least one subnode, representing an
|
||||
DAC instance/channel available on the machine.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: st,stm32-dac
|
||||
|
||||
reg:
|
||||
description: Must be either 1 or 2, to define (single) channel in use
|
||||
enum: [1, 2]
|
||||
|
||||
'#io-channel-cells':
|
||||
const: 1
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- '#io-channel-cells'
|
||||
|
||||
examples:
|
||||
- |
|
||||
// Example on stm32mp157c
|
||||
#include <dt-bindings/clock/stm32mp1-clks.h>
|
||||
dac: dac@40017000 {
|
||||
compatible = "st,stm32h7-dac-core";
|
||||
reg = <0x40017000 0x400>;
|
||||
clocks = <&rcc DAC12>;
|
||||
clock-names = "pclk";
|
||||
vref-supply = <&vref>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
dac@1 {
|
||||
compatible = "st,stm32-dac";
|
||||
#io-channel-cells = <1>;
|
||||
reg = <1>;
|
||||
};
|
||||
|
||||
dac@2 {
|
||||
compatible = "st,stm32-dac";
|
||||
#io-channel-cells = <1>;
|
||||
reg = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -2,7 +2,7 @@
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : should be "bosch,bmg160" or "bosch,bmi055_gyro"
|
||||
- compatible : should be "bosch,bmg160", "bosch,bmi055_gyro" or "bosch,bmi088_gyro"
|
||||
- reg : the I2C address of the sensor (0x69)
|
||||
|
||||
Optional properties:
|
||||
|
@ -0,0 +1,49 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/light/amstaos,tsl2563.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: AMS TAOS TSL2563 ambient light sensor
|
||||
|
||||
maintainers:
|
||||
- Sebastian Reichel <sre@kernel.org>
|
||||
|
||||
description: |
|
||||
Ambient light sensor with an i2c interface.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- amstaos,tsl2560
|
||||
- amstaos,tsl2561
|
||||
- amstaos,tsl2562
|
||||
- amstaos,tsl2563
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
amstaos,cover-comp-gain:
|
||||
description: Multiplier for gain compensation
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
- enum: [1, 16]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
light-sensor@29 {
|
||||
compatible = "amstaos,tsl2563";
|
||||
reg = <0x29>;
|
||||
amstaos,cover-comp-gain = <16>;
|
||||
};
|
||||
};
|
||||
...
|
@ -1,19 +0,0 @@
|
||||
* AMS TAOS TSL2563 ambient light sensor
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : should be "amstaos,tsl2563"
|
||||
- reg : the I2C address of the sensor
|
||||
|
||||
Optional properties:
|
||||
|
||||
- amstaos,cover-comp-gain : integer used as multiplier for gain
|
||||
compensation (default = 1)
|
||||
|
||||
Example:
|
||||
|
||||
tsl2563@29 {
|
||||
compatible = "amstaos,tsl2563";
|
||||
reg = <0x29>;
|
||||
amstaos,cover-comp-gain = <16>;
|
||||
};
|
@ -1,24 +0,0 @@
|
||||
VISHAY VCNL4000 - Ambient Light and proximity sensor
|
||||
|
||||
This driver supports the VCNL4000/10/20/40 and VCNL4200 chips
|
||||
|
||||
Required properties:
|
||||
|
||||
-compatible: must be one of :
|
||||
vishay,vcnl4000
|
||||
vishay,vcnl4010
|
||||
vishay,vcnl4020
|
||||
vishay,vcnl4040
|
||||
vishay,vcnl4200
|
||||
|
||||
-reg: I2C address of the sensor, should be one from below based on the model:
|
||||
0x13
|
||||
0x51
|
||||
0x60
|
||||
|
||||
Example:
|
||||
|
||||
light-sensor@51 {
|
||||
compatible = "vishay,vcnl4200";
|
||||
reg = <0x51>;
|
||||
};
|
@ -0,0 +1,50 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/light/vishay,vcnl4000.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: VISHAY VCNL4000 ambient light and proximity sensor
|
||||
|
||||
maintainers:
|
||||
- Peter Meerwald <pmeerw@pmeerw.net>
|
||||
|
||||
description: |
|
||||
Ambient light sensing with proximity detection over an i2c
|
||||
interface.
|
||||
|
||||
allOf:
|
||||
- $ref: ../common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- vishay,vcnl4000
|
||||
- vishay,vcnl4010
|
||||
- vishay,vcnl4020
|
||||
- vishay,vcnl4040
|
||||
- vishay,vcnl4200
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
proximity-near-level: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
light-sensor@51 {
|
||||
compatible = "vishay,vcnl4200";
|
||||
reg = <0x51>;
|
||||
proximity-near-level = <220>;
|
||||
};
|
||||
};
|
||||
...
|
@ -50,6 +50,7 @@ Accelerometers:
|
||||
- st,lis3dhh
|
||||
- st,lis3de
|
||||
- st,lis2de12
|
||||
- st,lis2hh12
|
||||
|
||||
Gyroscopes:
|
||||
- st,l3g4200d-gyro
|
||||
|
@ -284,21 +284,13 @@ I2C
|
||||
|
||||
IIO
|
||||
devm_iio_device_alloc()
|
||||
devm_iio_device_free()
|
||||
devm_iio_device_register()
|
||||
devm_iio_device_unregister()
|
||||
devm_iio_kfifo_allocate()
|
||||
devm_iio_kfifo_free()
|
||||
devm_iio_triggered_buffer_setup()
|
||||
devm_iio_triggered_buffer_cleanup()
|
||||
devm_iio_trigger_alloc()
|
||||
devm_iio_trigger_free()
|
||||
devm_iio_trigger_register()
|
||||
devm_iio_trigger_unregister()
|
||||
devm_iio_channel_get()
|
||||
devm_iio_channel_release()
|
||||
devm_iio_channel_get_all()
|
||||
devm_iio_channel_release_all()
|
||||
|
||||
INPUT
|
||||
devm_input_allocate_device()
|
||||
|
@ -4,9 +4,7 @@ Triggers
|
||||
|
||||
* struct :c:type:`iio_trigger` — industrial I/O trigger device
|
||||
* :c:func:`devm_iio_trigger_alloc` — Resource-managed iio_trigger_alloc
|
||||
* :c:func:`devm_iio_trigger_free` — Resource-managed iio_trigger_free
|
||||
* :c:func:`devm_iio_trigger_register` — Resource-managed iio_trigger_register
|
||||
* :c:func:`devm_iio_trigger_unregister` — Resource-managed
|
||||
iio_trigger_unregister
|
||||
* :c:func:`iio_trigger_validate_own_device` — Check if a trigger and IIO
|
||||
device belong to the same device
|
||||
|
@ -294,6 +294,7 @@ F: drivers/gpio/gpio-104-idio-16.c
|
||||
|
||||
ACCES 104-QUAD-8 DRIVER
|
||||
M: William Breathitt Gray <vilhelm.gray@gmail.com>
|
||||
M: Syed Nayyar Waris <syednwaris@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/ABI/testing/sysfs-bus-counter-104-quad-8
|
||||
|
@ -238,7 +238,7 @@ config IIO_ST_ACCEL_3AXIS
|
||||
Say yes here to build support for STMicroelectronics accelerometers:
|
||||
LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC,
|
||||
LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12, H3LIS331DL,
|
||||
LNG2DM, LIS3DE, LIS2DE12
|
||||
LNG2DM, LIS3DE, LIS2DE12, LIS2HH12
|
||||
|
||||
This driver can also be built as a module. If so, these modules
|
||||
will be created:
|
||||
|
@ -21,8 +21,8 @@ static int kxsd9_i2c_probe(struct i2c_client *i2c,
|
||||
|
||||
regmap = devm_regmap_init_i2c(i2c, &config);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&i2c->dev, "Failed to register i2c regmap %d\n",
|
||||
(int)PTR_ERR(regmap));
|
||||
dev_err(&i2c->dev, "Failed to register i2c regmap: %pe\n",
|
||||
regmap);
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,7 @@ static int mxc4005_read_xyz(struct mxc4005_data *data)
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, MXC4005_REG_XOUT_UPPER,
|
||||
(u8 *) data->buffer, sizeof(data->buffer));
|
||||
data->buffer, sizeof(data->buffer));
|
||||
if (ret < 0) {
|
||||
dev_err(data->dev, "failed to read axes\n");
|
||||
return ret;
|
||||
@ -150,7 +150,7 @@ static int mxc4005_read_axis(struct mxc4005_data *data,
|
||||
__be16 reg;
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, addr, (u8 *) ®, sizeof(reg));
|
||||
ret = regmap_bulk_read(data->regmap, addr, ®, sizeof(reg));
|
||||
if (ret < 0) {
|
||||
dev_err(data->dev, "failed to read reg %02x\n", addr);
|
||||
return ret;
|
||||
|
@ -35,6 +35,7 @@ enum st_accel_type {
|
||||
LIS2DW12,
|
||||
LIS3DHH,
|
||||
LIS2DE12,
|
||||
LIS2HH12,
|
||||
ST_ACCEL_MAX,
|
||||
};
|
||||
|
||||
@ -59,6 +60,7 @@ enum st_accel_type {
|
||||
#define LIS3DHH_ACCEL_DEV_NAME "lis3dhh"
|
||||
#define LIS3DE_ACCEL_DEV_NAME "lis3de"
|
||||
#define LIS2DE12_ACCEL_DEV_NAME "lis2de12"
|
||||
#define LIS2HH12_ACCEL_DEV_NAME "lis2hh12"
|
||||
|
||||
/**
|
||||
* struct st_sensors_platform_data - default accel platform data
|
||||
|
@ -37,8 +37,7 @@ static int st_accel_buffer_postenable(struct iio_dev *indio_dev)
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = st_sensors_set_axis_enable(indio_dev,
|
||||
(u8)indio_dev->active_scan_mask[0]);
|
||||
err = st_sensors_set_axis_enable(indio_dev, indio_dev->active_scan_mask[0]);
|
||||
if (err < 0)
|
||||
goto st_accel_buffer_predisable;
|
||||
|
||||
|
@ -904,6 +904,83 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
|
||||
.multi_read_bit = true,
|
||||
.bootime = 2,
|
||||
},
|
||||
{
|
||||
.wai = 0x41,
|
||||
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
|
||||
.sensors_supported = {
|
||||
[0] = LIS2HH12_ACCEL_DEV_NAME,
|
||||
},
|
||||
.ch = (struct iio_chan_spec *)st_accel_16bit_channels,
|
||||
.odr = {
|
||||
.addr = 0x20,
|
||||
.mask = 0x70,
|
||||
.odr_avl = {
|
||||
{ .hz = 10, .value = 0x01, },
|
||||
{ .hz = 50, .value = 0x02, },
|
||||
{ .hz = 100, .value = 0x03, },
|
||||
{ .hz = 200, .value = 0x04, },
|
||||
{ .hz = 400, .value = 0x05, },
|
||||
{ .hz = 800, .value = 0x06, },
|
||||
},
|
||||
},
|
||||
.pw = {
|
||||
.addr = 0x20,
|
||||
.mask = 0x70,
|
||||
.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
|
||||
},
|
||||
.enable_axis = {
|
||||
.addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
|
||||
.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
|
||||
},
|
||||
.fs = {
|
||||
.addr = 0x23,
|
||||
.mask = 0x30,
|
||||
.fs_avl = {
|
||||
[0] = {
|
||||
.num = ST_ACCEL_FS_AVL_2G,
|
||||
.value = 0x00,
|
||||
.gain = IIO_G_TO_M_S_2(61),
|
||||
},
|
||||
[1] = {
|
||||
.num = ST_ACCEL_FS_AVL_4G,
|
||||
.value = 0x02,
|
||||
.gain = IIO_G_TO_M_S_2(122),
|
||||
},
|
||||
[2] = {
|
||||
.num = ST_ACCEL_FS_AVL_8G,
|
||||
.value = 0x03,
|
||||
.gain = IIO_G_TO_M_S_2(244),
|
||||
},
|
||||
},
|
||||
},
|
||||
.bdu = {
|
||||
.addr = 0x20,
|
||||
.mask = 0x08,
|
||||
},
|
||||
.drdy_irq = {
|
||||
.int1 = {
|
||||
.addr = 0x22,
|
||||
.mask = 0x01,
|
||||
},
|
||||
.int2 = {
|
||||
.addr = 0x25,
|
||||
.mask = 0x01,
|
||||
},
|
||||
.addr_ihl = 0x24,
|
||||
.mask_ihl = 0x02,
|
||||
.stat_drdy = {
|
||||
.addr = ST_SENSORS_DEFAULT_STAT_ADDR,
|
||||
.mask = 0x07,
|
||||
},
|
||||
},
|
||||
.sim = {
|
||||
.addr = 0x23,
|
||||
.value = BIT(0),
|
||||
},
|
||||
.multi_read_bit = true,
|
||||
.bootime = 2,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static int st_accel_read_raw(struct iio_dev *indio_dev,
|
||||
@ -1170,8 +1247,7 @@ EXPORT_SYMBOL(st_accel_get_settings);
|
||||
int st_accel_common_probe(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct st_sensor_data *adata = iio_priv(indio_dev);
|
||||
struct st_sensors_platform_data *pdata =
|
||||
(struct st_sensors_platform_data *)adata->dev->platform_data;
|
||||
struct st_sensors_platform_data *pdata = dev_get_platdata(adata->dev);
|
||||
struct iio_chan_spec *channels;
|
||||
size_t channels_size;
|
||||
int err;
|
||||
@ -1204,8 +1280,7 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
|
||||
"failed to apply ACPI orientation data: %d\n", err);
|
||||
|
||||
indio_dev->channels = channels;
|
||||
adata->current_fullscale = (struct st_sensor_fullscale_avl *)
|
||||
&adata->sensor_settings->fs.fs_avl[0];
|
||||
adata->current_fullscale = &adata->sensor_settings->fs.fs_avl[0];
|
||||
adata->odr = adata->sensor_settings->odr.odr_avl[0].hz;
|
||||
|
||||
if (!pdata)
|
||||
|
@ -104,6 +104,10 @@ static const struct of_device_id st_accel_of_match[] = {
|
||||
.compatible = "st,lis2de12",
|
||||
.data = LIS2DE12_ACCEL_DEV_NAME,
|
||||
},
|
||||
{
|
||||
.compatible = "st,lis2hh12",
|
||||
.data = LIS2HH12_ACCEL_DEV_NAME,
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, st_accel_of_match);
|
||||
@ -138,6 +142,7 @@ static const struct i2c_device_id st_accel_id_table[] = {
|
||||
{ LIS2DW12_ACCEL_DEV_NAME },
|
||||
{ LIS3DE_ACCEL_DEV_NAME },
|
||||
{ LIS2DE12_ACCEL_DEV_NAME },
|
||||
{ LIS2HH12_ACCEL_DEV_NAME },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
|
||||
|
@ -246,6 +246,41 @@ config AD799X
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
called ad799x.
|
||||
|
||||
config AD9467
|
||||
tristate "Analog Devices AD9467 High Speed ADC driver"
|
||||
depends on SPI
|
||||
select ADI_AXI_ADC
|
||||
help
|
||||
Say yes here to build support for Analog Devices:
|
||||
* AD9467 16-Bit, 200 MSPS/250 MSPS Analog-to-Digital Converter
|
||||
|
||||
The driver requires the assistance of the AXI ADC IP core to operate,
|
||||
since SPI is used for configuration only, while data has to be
|
||||
streamed into memory via DMA.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
called ad9467.
|
||||
|
||||
config ADI_AXI_ADC
|
||||
tristate "Analog Devices Generic AXI ADC IP core driver"
|
||||
select IIO_BUFFER
|
||||
select IIO_BUFFER_HW_CONSUMER
|
||||
select IIO_BUFFER_DMAENGINE
|
||||
help
|
||||
Say yes here to build support for Analog Devices Generic
|
||||
AXI ADC IP core. The IP core is used for interfacing with
|
||||
analog-to-digital (ADC) converters that require either a high-speed
|
||||
serial interface (JESD204B/C) or a source synchronous parallel
|
||||
interface (LVDS/CMOS).
|
||||
Typically (for such devices) SPI will be used for configuration only,
|
||||
while this IP core handles the streaming of data into memory via DMA.
|
||||
|
||||
Link: https://wiki.analog.com/resources/fpga/docs/axi_adc_ip
|
||||
If unsure, say N (but it's safe to say "Y").
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called adi-axi-adc.
|
||||
|
||||
config ASPEED_ADC
|
||||
tristate "Aspeed ADC"
|
||||
depends on ARCH_ASPEED || COMPILE_TEST
|
||||
@ -595,6 +630,16 @@ config MAX1118
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
called max1118.
|
||||
|
||||
config MAX1241
|
||||
tristate "Maxim max1241 ADC driver"
|
||||
depends on SPI_MASTER
|
||||
help
|
||||
Say yes here to build support for Maxim max1241 12-bit, single-channel
|
||||
ADC.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
called max1241.
|
||||
|
||||
config MAX1363
|
||||
tristate "Maxim max1363 ADC driver"
|
||||
depends on I2C
|
||||
|
@ -26,6 +26,8 @@ obj-$(CONFIG_AD7793) += ad7793.o
|
||||
obj-$(CONFIG_AD7887) += ad7887.o
|
||||
obj-$(CONFIG_AD7949) += ad7949.o
|
||||
obj-$(CONFIG_AD799X) += ad799x.o
|
||||
obj-$(CONFIG_AD9467) += ad9467.o
|
||||
obj-$(CONFIG_ADI_AXI_ADC) += adi-axi-adc.o
|
||||
obj-$(CONFIG_ASPEED_ADC) += aspeed_adc.o
|
||||
obj-$(CONFIG_AT91_ADC) += at91_adc.o
|
||||
obj-$(CONFIG_AT91_SAMA5D2_ADC) += at91-sama5d2_adc.o
|
||||
@ -57,6 +59,7 @@ obj-$(CONFIG_LTC2497) += ltc2497.o ltc2497-core.o
|
||||
obj-$(CONFIG_MAX1027) += max1027.o
|
||||
obj-$(CONFIG_MAX11100) += max11100.o
|
||||
obj-$(CONFIG_MAX1118) += max1118.o
|
||||
obj-$(CONFIG_MAX1241) += max1241.o
|
||||
obj-$(CONFIG_MAX1363) += max1363.o
|
||||
obj-$(CONFIG_MAX9611) += max9611.o
|
||||
obj-$(CONFIG_MCP320X) += mcp320x.o
|
||||
|
@ -12,9 +12,11 @@
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
@ -27,6 +29,8 @@ struct ad7476_state;
|
||||
struct ad7476_chip_info {
|
||||
unsigned int int_vref_uv;
|
||||
struct iio_chan_spec channel[2];
|
||||
/* channels used when convst gpio is defined */
|
||||
struct iio_chan_spec convst_channel[2];
|
||||
void (*reset)(struct ad7476_state *);
|
||||
};
|
||||
|
||||
@ -34,6 +38,7 @@ struct ad7476_state {
|
||||
struct spi_device *spi;
|
||||
const struct ad7476_chip_info *chip_info;
|
||||
struct regulator *reg;
|
||||
struct gpio_desc *convst_gpio;
|
||||
struct spi_transfer xfer;
|
||||
struct spi_message msg;
|
||||
/*
|
||||
@ -64,6 +69,17 @@ enum ad7476_supported_device_ids {
|
||||
ID_ADS7868,
|
||||
};
|
||||
|
||||
static void ad7091_convst(struct ad7476_state *st)
|
||||
{
|
||||
if (!st->convst_gpio)
|
||||
return;
|
||||
|
||||
gpiod_set_value(st->convst_gpio, 0);
|
||||
udelay(1); /* CONVST pulse width: 10 ns min */
|
||||
gpiod_set_value(st->convst_gpio, 1);
|
||||
udelay(1); /* Conversion time: 650 ns max */
|
||||
}
|
||||
|
||||
static irqreturn_t ad7476_trigger_handler(int irq, void *p)
|
||||
{
|
||||
struct iio_poll_func *pf = p;
|
||||
@ -71,6 +87,8 @@ static irqreturn_t ad7476_trigger_handler(int irq, void *p)
|
||||
struct ad7476_state *st = iio_priv(indio_dev);
|
||||
int b_sent;
|
||||
|
||||
ad7091_convst(st);
|
||||
|
||||
b_sent = spi_sync(st->spi, &st->msg);
|
||||
if (b_sent < 0)
|
||||
goto done;
|
||||
@ -93,6 +111,8 @@ static int ad7476_scan_direct(struct ad7476_state *st)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ad7091_convst(st);
|
||||
|
||||
ret = spi_sync(st->spi, &st->msg);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -160,6 +180,8 @@ static int ad7476_read_raw(struct iio_dev *indio_dev,
|
||||
#define AD7940_CHAN(bits) _AD7476_CHAN((bits), 15 - (bits), \
|
||||
BIT(IIO_CHAN_INFO_RAW))
|
||||
#define AD7091R_CHAN(bits) _AD7476_CHAN((bits), 16 - (bits), 0)
|
||||
#define AD7091R_CONVST_CHAN(bits) _AD7476_CHAN((bits), 16 - (bits), \
|
||||
BIT(IIO_CHAN_INFO_RAW))
|
||||
#define ADS786X_CHAN(bits) _AD7476_CHAN((bits), 12 - (bits), \
|
||||
BIT(IIO_CHAN_INFO_RAW))
|
||||
|
||||
@ -167,6 +189,8 @@ static const struct ad7476_chip_info ad7476_chip_info_tbl[] = {
|
||||
[ID_AD7091R] = {
|
||||
.channel[0] = AD7091R_CHAN(12),
|
||||
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
|
||||
.convst_channel[0] = AD7091R_CONVST_CHAN(12),
|
||||
.convst_channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
|
||||
.reset = ad7091_reset,
|
||||
},
|
||||
[ID_AD7276] = {
|
||||
@ -232,6 +256,13 @@ static const struct iio_info ad7476_info = {
|
||||
.read_raw = &ad7476_read_raw,
|
||||
};
|
||||
|
||||
static void ad7476_reg_disable(void *data)
|
||||
{
|
||||
struct ad7476_state *st = data;
|
||||
|
||||
regulator_disable(st->reg);
|
||||
}
|
||||
|
||||
static int ad7476_probe(struct spi_device *spi)
|
||||
{
|
||||
struct ad7476_state *st;
|
||||
@ -254,6 +285,17 @@ static int ad7476_probe(struct spi_device *spi)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(&spi->dev, ad7476_reg_disable,
|
||||
st);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
st->convst_gpio = devm_gpiod_get_optional(&spi->dev,
|
||||
"adi,conversion-start",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(st->convst_gpio))
|
||||
return PTR_ERR(st->convst_gpio);
|
||||
|
||||
spi_set_drvdata(spi, indio_dev);
|
||||
|
||||
st->spi = spi;
|
||||
@ -266,6 +308,9 @@ static int ad7476_probe(struct spi_device *spi)
|
||||
indio_dev->channels = st->chip_info->channel;
|
||||
indio_dev->num_channels = 2;
|
||||
indio_dev->info = &ad7476_info;
|
||||
|
||||
if (st->convst_gpio && st->chip_info->convst_channel)
|
||||
indio_dev->channels = st->chip_info->convst_channel;
|
||||
/* Setup default message */
|
||||
|
||||
st->xfer.rx_buf = &st->data;
|
||||
@ -295,19 +340,8 @@ error_disable_reg:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ad7476_remove(struct spi_device *spi)
|
||||
{
|
||||
struct iio_dev *indio_dev = spi_get_drvdata(spi);
|
||||
struct ad7476_state *st = iio_priv(indio_dev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
regulator_disable(st->reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct spi_device_id ad7476_id[] = {
|
||||
{"ad7091", ID_AD7091R},
|
||||
{"ad7091r", ID_AD7091R},
|
||||
{"ad7273", ID_AD7277},
|
||||
{"ad7274", ID_AD7276},
|
||||
@ -343,7 +377,6 @@ static struct spi_driver ad7476_driver = {
|
||||
.name = "ad7476",
|
||||
},
|
||||
.probe = ad7476_probe,
|
||||
.remove = ad7476_remove,
|
||||
.id_table = ad7476_id,
|
||||
};
|
||||
module_spi_driver(ad7476_driver);
|
||||
|
@ -206,10 +206,29 @@ static const struct ad_sigma_delta_info ad7780_sigma_delta_info = {
|
||||
.irq_flags = IRQF_TRIGGER_LOW,
|
||||
};
|
||||
|
||||
#define AD7780_CHANNEL(bits, wordsize) \
|
||||
AD_SD_CHANNEL(1, 0, 0, bits, 32, (wordsize) - (bits))
|
||||
#define AD7170_CHANNEL(bits, wordsize) \
|
||||
AD_SD_CHANNEL_NO_SAMP_FREQ(1, 0, 0, bits, 32, (wordsize) - (bits))
|
||||
#define _AD7780_CHANNEL(_bits, _wordsize, _mask_all) \
|
||||
{ \
|
||||
.type = IIO_VOLTAGE, \
|
||||
.indexed = 1, \
|
||||
.channel = 0, \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||
BIT(IIO_CHAN_INFO_OFFSET), \
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
||||
.info_mask_shared_by_all = _mask_all, \
|
||||
.scan_index = 1, \
|
||||
.scan_type = { \
|
||||
.sign = 'u', \
|
||||
.realbits = (_bits), \
|
||||
.storagebits = 32, \
|
||||
.shift = (_wordsize) - (_bits), \
|
||||
.endianness = IIO_BE, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define AD7780_CHANNEL(_bits, _wordsize) \
|
||||
_AD7780_CHANNEL(_bits, _wordsize, BIT(IIO_CHAN_INFO_SAMP_FREQ))
|
||||
#define AD7170_CHANNEL(_bits, _wordsize) \
|
||||
_AD7780_CHANNEL(_bits, _wordsize, 0)
|
||||
|
||||
static const struct ad7780_chip_info ad7780_chip_info_tbl[] = {
|
||||
[ID_AD7170] = {
|
||||
|
@ -64,25 +64,73 @@
|
||||
#define AD7791_MODE_SEL_MASK (0x3 << 6)
|
||||
#define AD7791_MODE_SEL(x) ((x) << 6)
|
||||
|
||||
#define __AD7991_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
|
||||
_storagebits, _shift, _extend_name, _type, _mask_all) \
|
||||
{ \
|
||||
.type = (_type), \
|
||||
.differential = (_channel2 == -1 ? 0 : 1), \
|
||||
.indexed = 1, \
|
||||
.channel = (_channel1), \
|
||||
.channel2 = (_channel2), \
|
||||
.address = (_address), \
|
||||
.extend_name = (_extend_name), \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||
BIT(IIO_CHAN_INFO_OFFSET), \
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
||||
.info_mask_shared_by_all = _mask_all, \
|
||||
.scan_index = (_si), \
|
||||
.scan_type = { \
|
||||
.sign = 'u', \
|
||||
.realbits = (_bits), \
|
||||
.storagebits = (_storagebits), \
|
||||
.shift = (_shift), \
|
||||
.endianness = IIO_BE, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define AD7991_SHORTED_CHANNEL(_si, _channel, _address, _bits, \
|
||||
_storagebits, _shift) \
|
||||
__AD7991_CHANNEL(_si, _channel, _channel, _address, _bits, \
|
||||
_storagebits, _shift, "shorted", IIO_VOLTAGE, \
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ))
|
||||
|
||||
#define AD7991_CHANNEL(_si, _channel, _address, _bits, \
|
||||
_storagebits, _shift) \
|
||||
__AD7991_CHANNEL(_si, _channel, -1, _address, _bits, \
|
||||
_storagebits, _shift, NULL, IIO_VOLTAGE, \
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ))
|
||||
|
||||
#define AD7991_DIFF_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
|
||||
_storagebits, _shift) \
|
||||
__AD7991_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
|
||||
_storagebits, _shift, NULL, IIO_VOLTAGE, \
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ))
|
||||
|
||||
#define AD7991_SUPPLY_CHANNEL(_si, _channel, _address, _bits, _storagebits, \
|
||||
_shift) \
|
||||
__AD7991_CHANNEL(_si, _channel, -1, _address, _bits, \
|
||||
_storagebits, _shift, "supply", IIO_VOLTAGE, \
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ))
|
||||
|
||||
#define DECLARE_AD7787_CHANNELS(name, bits, storagebits) \
|
||||
const struct iio_chan_spec name[] = { \
|
||||
AD_SD_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \
|
||||
AD7991_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \
|
||||
(bits), (storagebits), 0), \
|
||||
AD_SD_CHANNEL(1, 1, AD7791_CH_AIN2, (bits), (storagebits), 0), \
|
||||
AD_SD_SHORTED_CHANNEL(2, 0, AD7791_CH_AIN1N_AIN1N, \
|
||||
AD7991_CHANNEL(1, 1, AD7791_CH_AIN2, (bits), (storagebits), 0), \
|
||||
AD7991_SHORTED_CHANNEL(2, 0, AD7791_CH_AIN1N_AIN1N, \
|
||||
(bits), (storagebits), 0), \
|
||||
AD_SD_SUPPLY_CHANNEL(3, 2, AD7791_CH_AVDD_MONITOR, \
|
||||
AD7991_SUPPLY_CHANNEL(3, 2, AD7791_CH_AVDD_MONITOR, \
|
||||
(bits), (storagebits), 0), \
|
||||
IIO_CHAN_SOFT_TIMESTAMP(4), \
|
||||
}
|
||||
|
||||
#define DECLARE_AD7791_CHANNELS(name, bits, storagebits) \
|
||||
const struct iio_chan_spec name[] = { \
|
||||
AD_SD_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \
|
||||
AD7991_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \
|
||||
(bits), (storagebits), 0), \
|
||||
AD_SD_SHORTED_CHANNEL(1, 0, AD7791_CH_AIN1N_AIN1N, \
|
||||
AD7991_SHORTED_CHANNEL(1, 0, AD7791_CH_AIN1N_AIN1N, \
|
||||
(bits), (storagebits), 0), \
|
||||
AD_SD_SUPPLY_CHANNEL(2, 1, AD7791_CH_AVDD_MONITOR, \
|
||||
AD7991_SUPPLY_CHANNEL(2, 1, AD7791_CH_AVDD_MONITOR, \
|
||||
(bits), (storagebits), 0), \
|
||||
IIO_CHAN_SOFT_TIMESTAMP(3), \
|
||||
}
|
||||
@ -444,5 +492,5 @@ static struct spi_driver ad7791_driver = {
|
||||
module_spi_driver(ad7791_driver);
|
||||
|
||||
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
|
||||
MODULE_DESCRIPTION("Analog Device AD7787/AD7788/AD7789/AD7790/AD7791 ADC driver");
|
||||
MODULE_DESCRIPTION("Analog Devices AD7787/AD7788/AD7789/AD7790/AD7791 ADC driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -354,29 +354,28 @@ static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
|
||||
static IIO_CONST_ATTR_NAMED(sampling_frequency_available_ad7797,
|
||||
sampling_frequency_available, "123 62 50 33 17 16 12 10 8 6 4");
|
||||
|
||||
static ssize_t ad7793_show_scale_available(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static int ad7793_read_avail(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
const int **vals, int *type, int *length,
|
||||
long mask)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct ad7793_state *st = iio_priv(indio_dev);
|
||||
int i, len = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++)
|
||||
len += sprintf(buf + len, "%d.%09u ", st->scale_avail[i][0],
|
||||
st->scale_avail[i][1]);
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
*vals = (int *)st->scale_avail;
|
||||
*type = IIO_VAL_INT_PLUS_NANO;
|
||||
/* Values are stored in a 2D matrix */
|
||||
*length = ARRAY_SIZE(st->scale_avail) * 2;
|
||||
|
||||
len += sprintf(buf + len, "\n");
|
||||
|
||||
return len;
|
||||
return IIO_AVAIL_LIST;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR_NAMED(in_m_in_scale_available,
|
||||
in_voltage-voltage_scale_available, S_IRUGO,
|
||||
ad7793_show_scale_available, NULL, 0);
|
||||
|
||||
static struct attribute *ad7793_attributes[] = {
|
||||
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
|
||||
&iio_dev_attr_in_m_in_scale_available.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -534,6 +533,7 @@ static const struct iio_info ad7793_info = {
|
||||
.read_raw = &ad7793_read_raw,
|
||||
.write_raw = &ad7793_write_raw,
|
||||
.write_raw_get_fmt = &ad7793_write_raw_get_fmt,
|
||||
.read_avail = ad7793_read_avail,
|
||||
.attrs = &ad7793_attribute_group,
|
||||
.validate_trigger = ad_sd_validate_trigger,
|
||||
};
|
||||
@ -546,47 +546,113 @@ static const struct iio_info ad7797_info = {
|
||||
.validate_trigger = ad_sd_validate_trigger,
|
||||
};
|
||||
|
||||
#define __AD7793_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
|
||||
_storagebits, _shift, _extend_name, _type, _mask_type_av, _mask_all) \
|
||||
{ \
|
||||
.type = (_type), \
|
||||
.differential = (_channel2 == -1 ? 0 : 1), \
|
||||
.indexed = 1, \
|
||||
.channel = (_channel1), \
|
||||
.channel2 = (_channel2), \
|
||||
.address = (_address), \
|
||||
.extend_name = (_extend_name), \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||
BIT(IIO_CHAN_INFO_OFFSET), \
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
||||
.info_mask_shared_by_type_available = (_mask_type_av), \
|
||||
.info_mask_shared_by_all = _mask_all, \
|
||||
.scan_index = (_si), \
|
||||
.scan_type = { \
|
||||
.sign = 'u', \
|
||||
.realbits = (_bits), \
|
||||
.storagebits = (_storagebits), \
|
||||
.shift = (_shift), \
|
||||
.endianness = IIO_BE, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define AD7793_DIFF_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
|
||||
_storagebits, _shift) \
|
||||
__AD7793_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
|
||||
_storagebits, _shift, NULL, IIO_VOLTAGE, \
|
||||
BIT(IIO_CHAN_INFO_SCALE), \
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ))
|
||||
|
||||
#define AD7793_SHORTED_CHANNEL(_si, _channel, _address, _bits, \
|
||||
_storagebits, _shift) \
|
||||
__AD7793_CHANNEL(_si, _channel, _channel, _address, _bits, \
|
||||
_storagebits, _shift, "shorted", IIO_VOLTAGE, \
|
||||
BIT(IIO_CHAN_INFO_SCALE), \
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ))
|
||||
|
||||
#define AD7793_TEMP_CHANNEL(_si, _address, _bits, _storagebits, _shift) \
|
||||
__AD7793_CHANNEL(_si, 0, -1, _address, _bits, \
|
||||
_storagebits, _shift, NULL, IIO_TEMP, \
|
||||
0, \
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ))
|
||||
|
||||
#define AD7793_SUPPLY_CHANNEL(_si, _channel, _address, _bits, _storagebits, \
|
||||
_shift) \
|
||||
__AD7793_CHANNEL(_si, _channel, -1, _address, _bits, \
|
||||
_storagebits, _shift, "supply", IIO_VOLTAGE, \
|
||||
0, \
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ))
|
||||
|
||||
#define AD7797_DIFF_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
|
||||
_storagebits, _shift) \
|
||||
__AD7793_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
|
||||
_storagebits, _shift, NULL, IIO_VOLTAGE, \
|
||||
0, \
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ))
|
||||
|
||||
#define AD7797_SHORTED_CHANNEL(_si, _channel, _address, _bits, \
|
||||
_storagebits, _shift) \
|
||||
__AD7793_CHANNEL(_si, _channel, _channel, _address, _bits, \
|
||||
_storagebits, _shift, "shorted", IIO_VOLTAGE, \
|
||||
0, \
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ))
|
||||
|
||||
#define DECLARE_AD7793_CHANNELS(_name, _b, _sb, _s) \
|
||||
const struct iio_chan_spec _name##_channels[] = { \
|
||||
AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), (_s)), \
|
||||
AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), (_s)), \
|
||||
AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), (_s)), \
|
||||
AD_SD_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), (_s)), \
|
||||
AD_SD_TEMP_CHANNEL(4, AD7793_CH_TEMP, (_b), (_sb), (_s)), \
|
||||
AD_SD_SUPPLY_CHANNEL(5, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), (_s)), \
|
||||
AD7793_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), (_s)), \
|
||||
AD7793_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), (_s)), \
|
||||
AD7793_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), (_s)), \
|
||||
AD7793_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), (_s)), \
|
||||
AD7793_TEMP_CHANNEL(4, AD7793_CH_TEMP, (_b), (_sb), (_s)), \
|
||||
AD7793_SUPPLY_CHANNEL(5, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), (_s)), \
|
||||
IIO_CHAN_SOFT_TIMESTAMP(6), \
|
||||
}
|
||||
|
||||
#define DECLARE_AD7795_CHANNELS(_name, _b, _sb) \
|
||||
const struct iio_chan_spec _name##_channels[] = { \
|
||||
AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
|
||||
AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \
|
||||
AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \
|
||||
AD_SD_DIFF_CHANNEL(3, 3, 3, AD7795_CH_AIN4P_AIN4M, (_b), (_sb), 0), \
|
||||
AD_SD_DIFF_CHANNEL(4, 4, 4, AD7795_CH_AIN5P_AIN5M, (_b), (_sb), 0), \
|
||||
AD_SD_DIFF_CHANNEL(5, 5, 5, AD7795_CH_AIN6P_AIN6M, (_b), (_sb), 0), \
|
||||
AD_SD_SHORTED_CHANNEL(6, 0, AD7795_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
|
||||
AD_SD_TEMP_CHANNEL(7, AD7793_CH_TEMP, (_b), (_sb), 0), \
|
||||
AD_SD_SUPPLY_CHANNEL(8, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
|
||||
AD7793_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
|
||||
AD7793_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \
|
||||
AD7793_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \
|
||||
AD7793_DIFF_CHANNEL(3, 3, 3, AD7795_CH_AIN4P_AIN4M, (_b), (_sb), 0), \
|
||||
AD7793_DIFF_CHANNEL(4, 4, 4, AD7795_CH_AIN5P_AIN5M, (_b), (_sb), 0), \
|
||||
AD7793_DIFF_CHANNEL(5, 5, 5, AD7795_CH_AIN6P_AIN6M, (_b), (_sb), 0), \
|
||||
AD7793_SHORTED_CHANNEL(6, 0, AD7795_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
|
||||
AD7793_TEMP_CHANNEL(7, AD7793_CH_TEMP, (_b), (_sb), 0), \
|
||||
AD7793_SUPPLY_CHANNEL(8, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
|
||||
IIO_CHAN_SOFT_TIMESTAMP(9), \
|
||||
}
|
||||
|
||||
#define DECLARE_AD7797_CHANNELS(_name, _b, _sb) \
|
||||
const struct iio_chan_spec _name##_channels[] = { \
|
||||
AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
|
||||
AD_SD_SHORTED_CHANNEL(1, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
|
||||
AD_SD_TEMP_CHANNEL(2, AD7793_CH_TEMP, (_b), (_sb), 0), \
|
||||
AD_SD_SUPPLY_CHANNEL(3, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
|
||||
AD7797_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
|
||||
AD7797_SHORTED_CHANNEL(1, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
|
||||
AD7793_TEMP_CHANNEL(2, AD7793_CH_TEMP, (_b), (_sb), 0), \
|
||||
AD7793_SUPPLY_CHANNEL(3, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
|
||||
IIO_CHAN_SOFT_TIMESTAMP(4), \
|
||||
}
|
||||
|
||||
#define DECLARE_AD7799_CHANNELS(_name, _b, _sb) \
|
||||
const struct iio_chan_spec _name##_channels[] = { \
|
||||
AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
|
||||
AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \
|
||||
AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \
|
||||
AD_SD_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
|
||||
AD_SD_SUPPLY_CHANNEL(4, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
|
||||
AD7793_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
|
||||
AD7793_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \
|
||||
AD7793_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \
|
||||
AD7793_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
|
||||
AD7793_SUPPLY_CHANNEL(4, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
|
||||
IIO_CHAN_SOFT_TIMESTAMP(5), \
|
||||
}
|
||||
|
||||
|
422
drivers/iio/adc/ad9467.c
Normal file
422
drivers/iio/adc/ad9467.c
Normal file
@ -0,0 +1,422 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Analog Devices AD9467 SPI ADC driver
|
||||
*
|
||||
* Copyright 2012-2020 Analog Devices Inc.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include <linux/iio/adc/adi-axi-adc.h>
|
||||
|
||||
/*
|
||||
* ADI High-Speed ADC common spi interface registers
|
||||
* See Application-Note AN-877:
|
||||
* https://www.analog.com/media/en/technical-documentation/application-notes/AN-877.pdf
|
||||
*/
|
||||
|
||||
#define AN877_ADC_REG_CHIP_PORT_CONF 0x00
|
||||
#define AN877_ADC_REG_CHIP_ID 0x01
|
||||
#define AN877_ADC_REG_CHIP_GRADE 0x02
|
||||
#define AN877_ADC_REG_CHAN_INDEX 0x05
|
||||
#define AN877_ADC_REG_TRANSFER 0xFF
|
||||
#define AN877_ADC_REG_MODES 0x08
|
||||
#define AN877_ADC_REG_TEST_IO 0x0D
|
||||
#define AN877_ADC_REG_ADC_INPUT 0x0F
|
||||
#define AN877_ADC_REG_OFFSET 0x10
|
||||
#define AN877_ADC_REG_OUTPUT_MODE 0x14
|
||||
#define AN877_ADC_REG_OUTPUT_ADJUST 0x15
|
||||
#define AN877_ADC_REG_OUTPUT_PHASE 0x16
|
||||
#define AN877_ADC_REG_OUTPUT_DELAY 0x17
|
||||
#define AN877_ADC_REG_VREF 0x18
|
||||
#define AN877_ADC_REG_ANALOG_INPUT 0x2C
|
||||
|
||||
/* AN877_ADC_REG_TEST_IO */
|
||||
#define AN877_ADC_TESTMODE_OFF 0x0
|
||||
#define AN877_ADC_TESTMODE_MIDSCALE_SHORT 0x1
|
||||
#define AN877_ADC_TESTMODE_POS_FULLSCALE 0x2
|
||||
#define AN877_ADC_TESTMODE_NEG_FULLSCALE 0x3
|
||||
#define AN877_ADC_TESTMODE_ALT_CHECKERBOARD 0x4
|
||||
#define AN877_ADC_TESTMODE_PN23_SEQ 0x5
|
||||
#define AN877_ADC_TESTMODE_PN9_SEQ 0x6
|
||||
#define AN877_ADC_TESTMODE_ONE_ZERO_TOGGLE 0x7
|
||||
#define AN877_ADC_TESTMODE_USER 0x8
|
||||
#define AN877_ADC_TESTMODE_BIT_TOGGLE 0x9
|
||||
#define AN877_ADC_TESTMODE_SYNC 0xA
|
||||
#define AN877_ADC_TESTMODE_ONE_BIT_HIGH 0xB
|
||||
#define AN877_ADC_TESTMODE_MIXED_BIT_FREQUENCY 0xC
|
||||
#define AN877_ADC_TESTMODE_RAMP 0xF
|
||||
|
||||
/* AN877_ADC_REG_TRANSFER */
|
||||
#define AN877_ADC_TRANSFER_SYNC 0x1
|
||||
|
||||
/* AN877_ADC_REG_OUTPUT_MODE */
|
||||
#define AN877_ADC_OUTPUT_MODE_OFFSET_BINARY 0x0
|
||||
#define AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT 0x1
|
||||
#define AN877_ADC_OUTPUT_MODE_GRAY_CODE 0x2
|
||||
|
||||
/* AN877_ADC_REG_OUTPUT_PHASE */
|
||||
#define AN877_ADC_OUTPUT_EVEN_ODD_MODE_EN 0x20
|
||||
#define AN877_ADC_INVERT_DCO_CLK 0x80
|
||||
|
||||
/* AN877_ADC_REG_OUTPUT_DELAY */
|
||||
#define AN877_ADC_DCO_DELAY_ENABLE 0x80
|
||||
|
||||
/*
|
||||
* Analog Devices AD9467 16-Bit, 200/250 MSPS ADC
|
||||
*/
|
||||
|
||||
#define CHIPID_AD9467 0x50
|
||||
#define AD9467_DEF_OUTPUT_MODE 0x08
|
||||
#define AD9467_REG_VREF_MASK 0x0F
|
||||
|
||||
enum {
|
||||
ID_AD9467,
|
||||
};
|
||||
|
||||
struct ad9467_state {
|
||||
struct spi_device *spi;
|
||||
struct clk *clk;
|
||||
unsigned int output_mode;
|
||||
|
||||
struct gpio_desc *pwrdown_gpio;
|
||||
struct gpio_desc *reset_gpio;
|
||||
};
|
||||
|
||||
static int ad9467_spi_read(struct spi_device *spi, unsigned int reg)
|
||||
{
|
||||
unsigned char tbuf[2], rbuf[1];
|
||||
int ret;
|
||||
|
||||
tbuf[0] = 0x80 | (reg >> 8);
|
||||
tbuf[1] = reg & 0xFF;
|
||||
|
||||
ret = spi_write_then_read(spi,
|
||||
tbuf, ARRAY_SIZE(tbuf),
|
||||
rbuf, ARRAY_SIZE(rbuf));
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return rbuf[0];
|
||||
}
|
||||
|
||||
static int ad9467_spi_write(struct spi_device *spi, unsigned int reg,
|
||||
unsigned int val)
|
||||
{
|
||||
unsigned char buf[3];
|
||||
|
||||
buf[0] = reg >> 8;
|
||||
buf[1] = reg & 0xFF;
|
||||
buf[2] = val;
|
||||
|
||||
return spi_write(spi, buf, ARRAY_SIZE(buf));
|
||||
}
|
||||
|
||||
static int ad9467_reg_access(struct adi_axi_adc_conv *conv, unsigned int reg,
|
||||
unsigned int writeval, unsigned int *readval)
|
||||
{
|
||||
struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
|
||||
struct spi_device *spi = st->spi;
|
||||
int ret;
|
||||
|
||||
if (readval == NULL) {
|
||||
ret = ad9467_spi_write(spi, reg, writeval);
|
||||
ad9467_spi_write(spi, AN877_ADC_REG_TRANSFER,
|
||||
AN877_ADC_TRANSFER_SYNC);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ad9467_spi_read(spi, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*readval = ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const unsigned int ad9467_scale_table[][2] = {
|
||||
{2000, 0}, {2100, 6}, {2200, 7},
|
||||
{2300, 8}, {2400, 9}, {2500, 10},
|
||||
};
|
||||
|
||||
static void __ad9467_get_scale(struct adi_axi_adc_conv *conv, int index,
|
||||
unsigned int *val, unsigned int *val2)
|
||||
{
|
||||
const struct adi_axi_adc_chip_info *info = conv->chip_info;
|
||||
const struct iio_chan_spec *chan = &info->channels[0];
|
||||
unsigned int tmp;
|
||||
|
||||
tmp = (info->scale_table[index][0] * 1000000ULL) >>
|
||||
chan->scan_type.realbits;
|
||||
*val = tmp / 1000000;
|
||||
*val2 = tmp % 1000000;
|
||||
}
|
||||
|
||||
#define AD9467_CHAN(_chan, _si, _bits, _sign) \
|
||||
{ \
|
||||
.type = IIO_VOLTAGE, \
|
||||
.indexed = 1, \
|
||||
.channel = _chan, \
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ), \
|
||||
.scan_index = _si, \
|
||||
.scan_type = { \
|
||||
.sign = _sign, \
|
||||
.realbits = _bits, \
|
||||
.storagebits = 16, \
|
||||
}, \
|
||||
}
|
||||
|
||||
static const struct iio_chan_spec ad9467_channels[] = {
|
||||
AD9467_CHAN(0, 0, 16, 'S'),
|
||||
};
|
||||
|
||||
static const struct adi_axi_adc_chip_info ad9467_chip_tbl[] = {
|
||||
[ID_AD9467] = {
|
||||
.id = CHIPID_AD9467,
|
||||
.max_rate = 250000000UL,
|
||||
.scale_table = ad9467_scale_table,
|
||||
.num_scales = ARRAY_SIZE(ad9467_scale_table),
|
||||
.channels = ad9467_channels,
|
||||
.num_channels = ARRAY_SIZE(ad9467_channels),
|
||||
},
|
||||
};
|
||||
|
||||
static int ad9467_get_scale(struct adi_axi_adc_conv *conv, int *val, int *val2)
|
||||
{
|
||||
const struct adi_axi_adc_chip_info *info = conv->chip_info;
|
||||
struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
|
||||
unsigned int i, vref_val, vref_mask;
|
||||
|
||||
vref_val = ad9467_spi_read(st->spi, AN877_ADC_REG_VREF);
|
||||
|
||||
switch (info->id) {
|
||||
case CHIPID_AD9467:
|
||||
vref_mask = AD9467_REG_VREF_MASK;
|
||||
break;
|
||||
default:
|
||||
vref_mask = 0xFFFF;
|
||||
break;
|
||||
}
|
||||
|
||||
vref_val &= vref_mask;
|
||||
|
||||
for (i = 0; i < info->num_scales; i++) {
|
||||
if (vref_val == info->scale_table[i][1])
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == info->num_scales)
|
||||
return -ERANGE;
|
||||
|
||||
__ad9467_get_scale(conv, i, val, val2);
|
||||
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
}
|
||||
|
||||
static int ad9467_set_scale(struct adi_axi_adc_conv *conv, int val, int val2)
|
||||
{
|
||||
const struct adi_axi_adc_chip_info *info = conv->chip_info;
|
||||
struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
|
||||
unsigned int scale_val[2];
|
||||
unsigned int i;
|
||||
|
||||
if (val != 0)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < info->num_scales; i++) {
|
||||
__ad9467_get_scale(conv, i, &scale_val[0], &scale_val[1]);
|
||||
if (scale_val[0] != val || scale_val[1] != val2)
|
||||
continue;
|
||||
|
||||
ad9467_spi_write(st->spi, AN877_ADC_REG_VREF,
|
||||
info->scale_table[i][1]);
|
||||
ad9467_spi_write(st->spi, AN877_ADC_REG_TRANSFER,
|
||||
AN877_ADC_TRANSFER_SYNC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ad9467_read_raw(struct adi_axi_adc_conv *conv,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val, int *val2, long m)
|
||||
{
|
||||
struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
|
||||
|
||||
switch (m) {
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
return ad9467_get_scale(conv, val, val2);
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
*val = clk_get_rate(st->clk);
|
||||
|
||||
return IIO_VAL_INT;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int ad9467_write_raw(struct adi_axi_adc_conv *conv,
|
||||
struct iio_chan_spec const *chan,
|
||||
int val, int val2, long mask)
|
||||
{
|
||||
const struct adi_axi_adc_chip_info *info = conv->chip_info;
|
||||
struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
|
||||
long r_clk;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
return ad9467_set_scale(conv, val, val2);
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
r_clk = clk_round_rate(st->clk, val);
|
||||
if (r_clk < 0 || r_clk > info->max_rate) {
|
||||
dev_warn(&st->spi->dev,
|
||||
"Error setting ADC sample rate %ld", r_clk);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return clk_set_rate(st->clk, r_clk);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int ad9467_outputmode_set(struct spi_device *spi, unsigned int mode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ad9467_spi_write(spi, AN877_ADC_REG_OUTPUT_MODE, mode);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return ad9467_spi_write(spi, AN877_ADC_REG_TRANSFER,
|
||||
AN877_ADC_TRANSFER_SYNC);
|
||||
}
|
||||
|
||||
static int ad9467_preenable_setup(struct adi_axi_adc_conv *conv)
|
||||
{
|
||||
struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
|
||||
|
||||
return ad9467_outputmode_set(st->spi, st->output_mode);
|
||||
}
|
||||
|
||||
static int ad9467_setup(struct ad9467_state *st, unsigned int chip_id)
|
||||
{
|
||||
switch (chip_id) {
|
||||
case CHIPID_AD9467:
|
||||
st->output_mode = AD9467_DEF_OUTPUT_MODE |
|
||||
AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT;
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static void ad9467_clk_disable(void *data)
|
||||
{
|
||||
struct ad9467_state *st = data;
|
||||
|
||||
clk_disable_unprepare(st->clk);
|
||||
}
|
||||
|
||||
static int ad9467_probe(struct spi_device *spi)
|
||||
{
|
||||
const struct adi_axi_adc_chip_info *info;
|
||||
struct adi_axi_adc_conv *conv;
|
||||
struct ad9467_state *st;
|
||||
unsigned int id;
|
||||
int ret;
|
||||
|
||||
info = of_device_get_match_data(&spi->dev);
|
||||
if (!info)
|
||||
return -ENODEV;
|
||||
|
||||
conv = devm_adi_axi_adc_conv_register(&spi->dev, sizeof(*st));
|
||||
if (IS_ERR(conv))
|
||||
return PTR_ERR(conv);
|
||||
|
||||
st = adi_axi_adc_conv_priv(conv);
|
||||
st->spi = spi;
|
||||
|
||||
st->clk = devm_clk_get(&spi->dev, "adc-clk");
|
||||
if (IS_ERR(st->clk))
|
||||
return PTR_ERR(st->clk);
|
||||
|
||||
ret = clk_prepare_enable(st->clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(&spi->dev, ad9467_clk_disable, st);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
st->pwrdown_gpio = devm_gpiod_get_optional(&spi->dev, "powerdown",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(st->pwrdown_gpio))
|
||||
return PTR_ERR(st->pwrdown_gpio);
|
||||
|
||||
st->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(st->reset_gpio))
|
||||
return PTR_ERR(st->reset_gpio);
|
||||
|
||||
if (st->reset_gpio) {
|
||||
udelay(1);
|
||||
ret = gpiod_direction_output(st->reset_gpio, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
mdelay(10);
|
||||
}
|
||||
|
||||
spi_set_drvdata(spi, st);
|
||||
|
||||
conv->chip_info = info;
|
||||
|
||||
id = ad9467_spi_read(spi, AN877_ADC_REG_CHIP_ID);
|
||||
if (id != conv->chip_info->id) {
|
||||
dev_err(&spi->dev, "Unrecognized CHIP_ID 0x%X\n", id);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
conv->reg_access = ad9467_reg_access;
|
||||
conv->write_raw = ad9467_write_raw;
|
||||
conv->read_raw = ad9467_read_raw;
|
||||
conv->preenable_setup = ad9467_preenable_setup;
|
||||
|
||||
return ad9467_setup(st, id);
|
||||
}
|
||||
|
||||
static const struct of_device_id ad9467_of_match[] = {
|
||||
{ .compatible = "adi,ad9467", .data = &ad9467_chip_tbl[ID_AD9467], },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ad9467_of_match);
|
||||
|
||||
static struct spi_driver ad9467_driver = {
|
||||
.driver = {
|
||||
.name = "ad9467",
|
||||
.of_match_table = ad9467_of_match,
|
||||
},
|
||||
.probe = ad9467_probe,
|
||||
};
|
||||
module_spi_driver(ad9467_driver);
|
||||
|
||||
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
|
||||
MODULE_DESCRIPTION("Analog Devices AD9467 ADC driver");
|
||||
MODULE_LICENSE("GPL v2");
|
482
drivers/iio/adc/adi-axi-adc.c
Normal file
482
drivers/iio/adc/adi-axi-adc.c
Normal file
@ -0,0 +1,482 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Analog Devices Generic AXI ADC IP core
|
||||
* Link: https://wiki.analog.com/resources/fpga/docs/axi_adc_ip
|
||||
*
|
||||
* Copyright 2012-2020 Analog Devices Inc.
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/buffer-dmaengine.h>
|
||||
|
||||
#include <linux/fpga/adi-axi-common.h>
|
||||
#include <linux/iio/adc/adi-axi-adc.h>
|
||||
|
||||
/**
|
||||
* Register definitions:
|
||||
* https://wiki.analog.com/resources/fpga/docs/axi_adc_ip#register_map
|
||||
*/
|
||||
|
||||
/* ADC controls */
|
||||
|
||||
#define ADI_AXI_REG_RSTN 0x0040
|
||||
#define ADI_AXI_REG_RSTN_CE_N BIT(2)
|
||||
#define ADI_AXI_REG_RSTN_MMCM_RSTN BIT(1)
|
||||
#define ADI_AXI_REG_RSTN_RSTN BIT(0)
|
||||
|
||||
/* ADC Channel controls */
|
||||
|
||||
#define ADI_AXI_REG_CHAN_CTRL(c) (0x0400 + (c) * 0x40)
|
||||
#define ADI_AXI_REG_CHAN_CTRL_LB_OWR BIT(11)
|
||||
#define ADI_AXI_REG_CHAN_CTRL_PN_SEL_OWR BIT(10)
|
||||
#define ADI_AXI_REG_CHAN_CTRL_IQCOR_EN BIT(9)
|
||||
#define ADI_AXI_REG_CHAN_CTRL_DCFILT_EN BIT(8)
|
||||
#define ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT BIT(6)
|
||||
#define ADI_AXI_REG_CHAN_CTRL_FMT_TYPE BIT(5)
|
||||
#define ADI_AXI_REG_CHAN_CTRL_FMT_EN BIT(4)
|
||||
#define ADI_AXI_REG_CHAN_CTRL_PN_TYPE_OWR BIT(1)
|
||||
#define ADI_AXI_REG_CHAN_CTRL_ENABLE BIT(0)
|
||||
|
||||
#define ADI_AXI_REG_CHAN_CTRL_DEFAULTS \
|
||||
(ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT | \
|
||||
ADI_AXI_REG_CHAN_CTRL_FMT_EN | \
|
||||
ADI_AXI_REG_CHAN_CTRL_ENABLE)
|
||||
|
||||
struct adi_axi_adc_core_info {
|
||||
unsigned int version;
|
||||
};
|
||||
|
||||
struct adi_axi_adc_state {
|
||||
struct mutex lock;
|
||||
|
||||
struct adi_axi_adc_client *client;
|
||||
void __iomem *regs;
|
||||
};
|
||||
|
||||
struct adi_axi_adc_client {
|
||||
struct list_head entry;
|
||||
struct adi_axi_adc_conv conv;
|
||||
struct adi_axi_adc_state *state;
|
||||
struct device *dev;
|
||||
const struct adi_axi_adc_core_info *info;
|
||||
};
|
||||
|
||||
static LIST_HEAD(registered_clients);
|
||||
static DEFINE_MUTEX(registered_clients_lock);
|
||||
|
||||
static struct adi_axi_adc_client *conv_to_client(struct adi_axi_adc_conv *conv)
|
||||
{
|
||||
return container_of(conv, struct adi_axi_adc_client, conv);
|
||||
}
|
||||
|
||||
void *adi_axi_adc_conv_priv(struct adi_axi_adc_conv *conv)
|
||||
{
|
||||
struct adi_axi_adc_client *cl = conv_to_client(conv);
|
||||
|
||||
return (char *)cl + ALIGN(sizeof(struct adi_axi_adc_client), IIO_ALIGN);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(adi_axi_adc_conv_priv);
|
||||
|
||||
static void adi_axi_adc_write(struct adi_axi_adc_state *st,
|
||||
unsigned int reg,
|
||||
unsigned int val)
|
||||
{
|
||||
iowrite32(val, st->regs + reg);
|
||||
}
|
||||
|
||||
static unsigned int adi_axi_adc_read(struct adi_axi_adc_state *st,
|
||||
unsigned int reg)
|
||||
{
|
||||
return ioread32(st->regs + reg);
|
||||
}
|
||||
|
||||
static int adi_axi_adc_config_dma_buffer(struct device *dev,
|
||||
struct iio_dev *indio_dev)
|
||||
{
|
||||
struct iio_buffer *buffer;
|
||||
const char *dma_name;
|
||||
|
||||
if (!device_property_present(dev, "dmas"))
|
||||
return 0;
|
||||
|
||||
if (device_property_read_string(dev, "dma-names", &dma_name))
|
||||
dma_name = "rx";
|
||||
|
||||
buffer = devm_iio_dmaengine_buffer_alloc(indio_dev->dev.parent,
|
||||
dma_name);
|
||||
if (IS_ERR(buffer))
|
||||
return PTR_ERR(buffer);
|
||||
|
||||
indio_dev->modes |= INDIO_BUFFER_HARDWARE;
|
||||
iio_device_attach_buffer(indio_dev, buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adi_axi_adc_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val, int *val2, long mask)
|
||||
{
|
||||
struct adi_axi_adc_state *st = iio_priv(indio_dev);
|
||||
struct adi_axi_adc_conv *conv = &st->client->conv;
|
||||
|
||||
if (!conv->read_raw)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return conv->read_raw(conv, chan, val, val2, mask);
|
||||
}
|
||||
|
||||
static int adi_axi_adc_write_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int val, int val2, long mask)
|
||||
{
|
||||
struct adi_axi_adc_state *st = iio_priv(indio_dev);
|
||||
struct adi_axi_adc_conv *conv = &st->client->conv;
|
||||
|
||||
if (!conv->write_raw)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return conv->write_raw(conv, chan, val, val2, mask);
|
||||
}
|
||||
|
||||
static int adi_axi_adc_update_scan_mode(struct iio_dev *indio_dev,
|
||||
const unsigned long *scan_mask)
|
||||
{
|
||||
struct adi_axi_adc_state *st = iio_priv(indio_dev);
|
||||
struct adi_axi_adc_conv *conv = &st->client->conv;
|
||||
unsigned int i, ctrl;
|
||||
|
||||
for (i = 0; i < conv->chip_info->num_channels; i++) {
|
||||
ctrl = adi_axi_adc_read(st, ADI_AXI_REG_CHAN_CTRL(i));
|
||||
|
||||
if (test_bit(i, scan_mask))
|
||||
ctrl |= ADI_AXI_REG_CHAN_CTRL_ENABLE;
|
||||
else
|
||||
ctrl &= ~ADI_AXI_REG_CHAN_CTRL_ENABLE;
|
||||
|
||||
adi_axi_adc_write(st, ADI_AXI_REG_CHAN_CTRL(i), ctrl);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct adi_axi_adc_conv *adi_axi_adc_conv_register(struct device *dev,
|
||||
size_t sizeof_priv)
|
||||
{
|
||||
struct adi_axi_adc_client *cl;
|
||||
size_t alloc_size;
|
||||
|
||||
alloc_size = ALIGN(sizeof(struct adi_axi_adc_client), IIO_ALIGN);
|
||||
if (sizeof_priv)
|
||||
alloc_size += ALIGN(sizeof_priv, IIO_ALIGN);
|
||||
|
||||
cl = kzalloc(alloc_size, GFP_KERNEL);
|
||||
if (!cl)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
mutex_lock(®istered_clients_lock);
|
||||
|
||||
cl->dev = get_device(dev);
|
||||
|
||||
list_add_tail(&cl->entry, ®istered_clients);
|
||||
|
||||
mutex_unlock(®istered_clients_lock);
|
||||
|
||||
return &cl->conv;
|
||||
}
|
||||
|
||||
static void adi_axi_adc_conv_unregister(struct adi_axi_adc_conv *conv)
|
||||
{
|
||||
struct adi_axi_adc_client *cl = conv_to_client(conv);
|
||||
|
||||
mutex_lock(®istered_clients_lock);
|
||||
|
||||
list_del(&cl->entry);
|
||||
put_device(cl->dev);
|
||||
|
||||
mutex_unlock(®istered_clients_lock);
|
||||
|
||||
kfree(cl);
|
||||
}
|
||||
|
||||
static void devm_adi_axi_adc_conv_release(struct device *dev, void *res)
|
||||
{
|
||||
adi_axi_adc_conv_unregister(*(struct adi_axi_adc_conv **)res);
|
||||
}
|
||||
|
||||
struct adi_axi_adc_conv *devm_adi_axi_adc_conv_register(struct device *dev,
|
||||
size_t sizeof_priv)
|
||||
{
|
||||
struct adi_axi_adc_conv **ptr, *conv;
|
||||
|
||||
ptr = devres_alloc(devm_adi_axi_adc_conv_release, sizeof(*ptr),
|
||||
GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
conv = adi_axi_adc_conv_register(dev, sizeof_priv);
|
||||
if (IS_ERR(conv)) {
|
||||
devres_free(ptr);
|
||||
return ERR_CAST(conv);
|
||||
}
|
||||
|
||||
*ptr = conv;
|
||||
devres_add(dev, ptr);
|
||||
|
||||
return conv;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_adi_axi_adc_conv_register);
|
||||
|
||||
static ssize_t in_voltage_scale_available_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct adi_axi_adc_state *st = iio_priv(indio_dev);
|
||||
struct adi_axi_adc_conv *conv = &st->client->conv;
|
||||
size_t len = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < conv->chip_info->num_scales; i++) {
|
||||
const unsigned int *s = conv->chip_info->scale_table[i];
|
||||
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len,
|
||||
"%u.%06u ", s[0], s[1]);
|
||||
}
|
||||
buf[len - 1] = '\n';
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR_RO(in_voltage_scale_available, 0);
|
||||
|
||||
enum {
|
||||
ADI_AXI_ATTR_SCALE_AVAIL,
|
||||
};
|
||||
|
||||
#define ADI_AXI_ATTR(_en_, _file_) \
|
||||
[ADI_AXI_ATTR_##_en_] = &iio_dev_attr_##_file_.dev_attr.attr
|
||||
|
||||
static struct attribute *adi_axi_adc_attributes[] = {
|
||||
ADI_AXI_ATTR(SCALE_AVAIL, in_voltage_scale_available),
|
||||
NULL
|
||||
};
|
||||
|
||||
static umode_t axi_adc_attr_is_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int n)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct adi_axi_adc_state *st = iio_priv(indio_dev);
|
||||
struct adi_axi_adc_conv *conv = &st->client->conv;
|
||||
|
||||
switch (n) {
|
||||
case ADI_AXI_ATTR_SCALE_AVAIL:
|
||||
if (!conv->chip_info->num_scales)
|
||||
return 0;
|
||||
return attr->mode;
|
||||
default:
|
||||
return attr->mode;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct attribute_group adi_axi_adc_attribute_group = {
|
||||
.attrs = adi_axi_adc_attributes,
|
||||
.is_visible = axi_adc_attr_is_visible,
|
||||
};
|
||||
|
||||
static const struct iio_info adi_axi_adc_info = {
|
||||
.read_raw = &adi_axi_adc_read_raw,
|
||||
.write_raw = &adi_axi_adc_write_raw,
|
||||
.attrs = &adi_axi_adc_attribute_group,
|
||||
.update_scan_mode = &adi_axi_adc_update_scan_mode,
|
||||
};
|
||||
|
||||
static const struct adi_axi_adc_core_info adi_axi_adc_10_0_a_info = {
|
||||
.version = ADI_AXI_PCORE_VER(10, 0, 'a'),
|
||||
};
|
||||
|
||||
static struct adi_axi_adc_client *adi_axi_adc_attach_client(struct device *dev)
|
||||
{
|
||||
const struct adi_axi_adc_core_info *info;
|
||||
struct adi_axi_adc_client *cl;
|
||||
struct device_node *cln;
|
||||
|
||||
info = of_device_get_match_data(dev);
|
||||
if (!info)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
cln = of_parse_phandle(dev->of_node, "adi,adc-dev", 0);
|
||||
if (!cln) {
|
||||
dev_err(dev, "No 'adi,adc-dev' node defined\n");
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
mutex_lock(®istered_clients_lock);
|
||||
|
||||
list_for_each_entry(cl, ®istered_clients, entry) {
|
||||
if (!cl->dev)
|
||||
continue;
|
||||
|
||||
if (cl->dev->of_node != cln)
|
||||
continue;
|
||||
|
||||
if (!try_module_get(dev->driver->owner)) {
|
||||
mutex_unlock(®istered_clients_lock);
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
get_device(dev);
|
||||
cl->info = info;
|
||||
mutex_unlock(®istered_clients_lock);
|
||||
return cl;
|
||||
}
|
||||
|
||||
mutex_unlock(®istered_clients_lock);
|
||||
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
static int adi_axi_adc_setup_channels(struct device *dev,
|
||||
struct adi_axi_adc_state *st)
|
||||
{
|
||||
struct adi_axi_adc_conv *conv = &st->client->conv;
|
||||
int i, ret;
|
||||
|
||||
if (conv->preenable_setup) {
|
||||
ret = conv->preenable_setup(conv);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < conv->chip_info->num_channels; i++) {
|
||||
adi_axi_adc_write(st, ADI_AXI_REG_CHAN_CTRL(i),
|
||||
ADI_AXI_REG_CHAN_CTRL_DEFAULTS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void axi_adc_reset(struct adi_axi_adc_state *st)
|
||||
{
|
||||
adi_axi_adc_write(st, ADI_AXI_REG_RSTN, 0);
|
||||
mdelay(10);
|
||||
adi_axi_adc_write(st, ADI_AXI_REG_RSTN, ADI_AXI_REG_RSTN_MMCM_RSTN);
|
||||
mdelay(10);
|
||||
adi_axi_adc_write(st, ADI_AXI_REG_RSTN,
|
||||
ADI_AXI_REG_RSTN_RSTN | ADI_AXI_REG_RSTN_MMCM_RSTN);
|
||||
}
|
||||
|
||||
static void adi_axi_adc_cleanup(void *data)
|
||||
{
|
||||
struct adi_axi_adc_client *cl = data;
|
||||
|
||||
put_device(cl->dev);
|
||||
module_put(cl->dev->driver->owner);
|
||||
}
|
||||
|
||||
static int adi_axi_adc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct adi_axi_adc_conv *conv;
|
||||
struct iio_dev *indio_dev;
|
||||
struct adi_axi_adc_client *cl;
|
||||
struct adi_axi_adc_state *st;
|
||||
unsigned int ver;
|
||||
int ret;
|
||||
|
||||
cl = adi_axi_adc_attach_client(&pdev->dev);
|
||||
if (IS_ERR(cl))
|
||||
return PTR_ERR(cl);
|
||||
|
||||
ret = devm_add_action_or_reset(&pdev->dev, adi_axi_adc_cleanup, cl);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
st->client = cl;
|
||||
cl->state = st;
|
||||
mutex_init(&st->lock);
|
||||
|
||||
st->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(st->regs))
|
||||
return PTR_ERR(st->regs);
|
||||
|
||||
conv = &st->client->conv;
|
||||
|
||||
axi_adc_reset(st);
|
||||
|
||||
ver = adi_axi_adc_read(st, ADI_AXI_REG_VERSION);
|
||||
|
||||
if (cl->info->version > ver) {
|
||||
dev_err(&pdev->dev,
|
||||
"IP core version is too old. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",
|
||||
ADI_AXI_PCORE_VER_MAJOR(cl->info->version),
|
||||
ADI_AXI_PCORE_VER_MINOR(cl->info->version),
|
||||
ADI_AXI_PCORE_VER_PATCH(cl->info->version),
|
||||
ADI_AXI_PCORE_VER_MAJOR(ver),
|
||||
ADI_AXI_PCORE_VER_MINOR(ver),
|
||||
ADI_AXI_PCORE_VER_PATCH(ver));
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
indio_dev->info = &adi_axi_adc_info;
|
||||
indio_dev->dev.parent = &pdev->dev;
|
||||
indio_dev->name = "adi-axi-adc";
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->num_channels = conv->chip_info->num_channels;
|
||||
indio_dev->channels = conv->chip_info->channels;
|
||||
|
||||
ret = adi_axi_adc_config_dma_buffer(&pdev->dev, indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = adi_axi_adc_setup_channels(&pdev->dev, st);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_iio_device_register(&pdev->dev, indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev_info(&pdev->dev, "AXI ADC IP core (%d.%.2d.%c) probed\n",
|
||||
ADI_AXI_PCORE_VER_MAJOR(ver),
|
||||
ADI_AXI_PCORE_VER_MINOR(ver),
|
||||
ADI_AXI_PCORE_VER_PATCH(ver));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Match table for of_platform binding */
|
||||
static const struct of_device_id adi_axi_adc_of_match[] = {
|
||||
{ .compatible = "adi,axi-adc-10.0.a", .data = &adi_axi_adc_10_0_a_info },
|
||||
{ /* end of list */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, adi_axi_adc_of_match);
|
||||
|
||||
static struct platform_driver adi_axi_adc_driver = {
|
||||
.driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.of_match_table = adi_axi_adc_of_match,
|
||||
},
|
||||
.probe = adi_axi_adc_probe,
|
||||
};
|
||||
module_platform_driver(adi_axi_adc_driver);
|
||||
|
||||
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
|
||||
MODULE_DESCRIPTION("Analog Devices Generic AXI ADC IP core driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -1152,7 +1152,6 @@ static int at91_adc_probe(struct platform_device *pdev)
|
||||
int ret;
|
||||
struct iio_dev *idev;
|
||||
struct at91_adc_state *st;
|
||||
struct resource *res;
|
||||
u32 reg;
|
||||
|
||||
idev = devm_iio_device_alloc(&pdev->dev, sizeof(struct at91_adc_state));
|
||||
@ -1182,9 +1181,7 @@ static int at91_adc_probe(struct platform_device *pdev)
|
||||
if (st->irq < 0)
|
||||
return -ENODEV;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
||||
st->reg_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
st->reg_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(st->reg_base))
|
||||
return PTR_ERR(st->reg_base);
|
||||
|
||||
|
@ -294,7 +294,6 @@ static int mx25_gcq_probe(struct platform_device *pdev)
|
||||
struct mx25_gcq_priv *priv;
|
||||
struct mx25_tsadc *tsadc = dev_get_drvdata(pdev->dev.parent);
|
||||
struct device *dev = &pdev->dev;
|
||||
struct resource *res;
|
||||
void __iomem *mem;
|
||||
int ret;
|
||||
int i;
|
||||
@ -305,8 +304,7 @@ static int mx25_gcq_probe(struct platform_device *pdev)
|
||||
|
||||
priv = iio_priv(indio_dev);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
mem = devm_ioremap_resource(dev, res);
|
||||
mem = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(mem))
|
||||
return PTR_ERR(mem);
|
||||
|
||||
|
@ -75,7 +75,7 @@ static int mrfld_adc_single_conv(struct iio_dev *indio_dev,
|
||||
struct regmap *regmap = adc->regmap;
|
||||
unsigned int req;
|
||||
long timeout;
|
||||
u8 buf[2];
|
||||
__be16 value;
|
||||
int ret;
|
||||
|
||||
reinit_completion(&adc->completion);
|
||||
@ -105,11 +105,11 @@ static int mrfld_adc_single_conv(struct iio_dev *indio_dev,
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = regmap_bulk_read(regmap, chan->address, buf, 2);
|
||||
ret = regmap_bulk_read(regmap, chan->address, &value, sizeof(value));
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
*result = get_unaligned_be16(buf);
|
||||
*result = be16_to_cpu(value);
|
||||
ret = IIO_VAL_INT;
|
||||
|
||||
done:
|
||||
|
227
drivers/iio/adc/max1241.c
Normal file
227
drivers/iio/adc/max1241.c
Normal file
@ -0,0 +1,227 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* MAX1241 low-power, 12-bit serial ADC
|
||||
*
|
||||
* Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX1240-MAX1241.pdf
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#define MAX1241_VAL_MASK GENMASK(11, 0)
|
||||
#define MAX1241_SHUTDOWN_DELAY_USEC 4
|
||||
|
||||
enum max1241_id {
|
||||
max1241,
|
||||
};
|
||||
|
||||
struct max1241 {
|
||||
struct spi_device *spi;
|
||||
struct mutex lock;
|
||||
struct regulator *vdd;
|
||||
struct regulator *vref;
|
||||
struct gpio_desc *shutdown;
|
||||
|
||||
__be16 data ____cacheline_aligned;
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec max1241_channels[] = {
|
||||
{
|
||||
.type = IIO_VOLTAGE,
|
||||
.indexed = 1,
|
||||
.channel = 0,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
|
||||
BIT(IIO_CHAN_INFO_SCALE),
|
||||
},
|
||||
};
|
||||
|
||||
static int max1241_read(struct max1241 *adc)
|
||||
{
|
||||
struct spi_transfer xfers[] = {
|
||||
/*
|
||||
* Begin conversion by bringing /CS low for at least
|
||||
* tconv us.
|
||||
*/
|
||||
{
|
||||
.len = 0,
|
||||
.delay.value = 8,
|
||||
.delay.unit = SPI_DELAY_UNIT_USECS,
|
||||
},
|
||||
/*
|
||||
* Then read two bytes of data in our RX buffer.
|
||||
*/
|
||||
{
|
||||
.rx_buf = &adc->data,
|
||||
.len = 2,
|
||||
},
|
||||
};
|
||||
|
||||
return spi_sync_transfer(adc->spi, xfers, ARRAY_SIZE(xfers));
|
||||
}
|
||||
|
||||
static int max1241_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val, int *val2, long mask)
|
||||
{
|
||||
int ret, vref_uV;
|
||||
struct max1241 *adc = iio_priv(indio_dev);
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
mutex_lock(&adc->lock);
|
||||
|
||||
if (adc->shutdown) {
|
||||
gpiod_set_value(adc->shutdown, 0);
|
||||
udelay(MAX1241_SHUTDOWN_DELAY_USEC);
|
||||
ret = max1241_read(adc);
|
||||
gpiod_set_value(adc->shutdown, 1);
|
||||
} else
|
||||
ret = max1241_read(adc);
|
||||
|
||||
if (ret) {
|
||||
mutex_unlock(&adc->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*val = (be16_to_cpu(adc->data) >> 3) & MAX1241_VAL_MASK;
|
||||
|
||||
mutex_unlock(&adc->lock);
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
vref_uV = regulator_get_voltage(adc->vref);
|
||||
|
||||
if (vref_uV < 0)
|
||||
return vref_uV;
|
||||
|
||||
*val = vref_uV / 1000;
|
||||
*val2 = 12;
|
||||
|
||||
return IIO_VAL_FRACTIONAL_LOG2;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct iio_info max1241_info = {
|
||||
.read_raw = max1241_read_raw,
|
||||
};
|
||||
|
||||
static void max1241_disable_vdd_action(void *data)
|
||||
{
|
||||
struct max1241 *adc = data;
|
||||
struct device *dev = &adc->spi->dev;
|
||||
int err;
|
||||
|
||||
err = regulator_disable(adc->vdd);
|
||||
if (err)
|
||||
dev_err(dev, "could not disable vdd regulator.\n");
|
||||
}
|
||||
|
||||
static void max1241_disable_vref_action(void *data)
|
||||
{
|
||||
struct max1241 *adc = data;
|
||||
struct device *dev = &adc->spi->dev;
|
||||
int err;
|
||||
|
||||
err = regulator_disable(adc->vref);
|
||||
if (err)
|
||||
dev_err(dev, "could not disable vref regulator.\n");
|
||||
}
|
||||
|
||||
static int max1241_probe(struct spi_device *spi)
|
||||
{
|
||||
struct device *dev = &spi->dev;
|
||||
struct iio_dev *indio_dev;
|
||||
struct max1241 *adc;
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*adc));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
adc = iio_priv(indio_dev);
|
||||
adc->spi = spi;
|
||||
mutex_init(&adc->lock);
|
||||
|
||||
spi_set_drvdata(spi, indio_dev);
|
||||
|
||||
adc->vdd = devm_regulator_get(dev, "vdd");
|
||||
if (IS_ERR(adc->vdd)) {
|
||||
dev_err(dev, "failed to get vdd regulator\n");
|
||||
return PTR_ERR(adc->vdd);
|
||||
}
|
||||
|
||||
ret = regulator_enable(adc->vdd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, max1241_disable_vdd_action, adc);
|
||||
if (ret) {
|
||||
dev_err(dev, "could not set up vdd regulator cleanup action\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
adc->vref = devm_regulator_get(dev, "vref");
|
||||
if (IS_ERR(adc->vref)) {
|
||||
dev_err(dev, "failed to get vref regulator\n");
|
||||
return PTR_ERR(adc->vref);
|
||||
}
|
||||
|
||||
ret = regulator_enable(adc->vref);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, max1241_disable_vref_action, adc);
|
||||
if (ret) {
|
||||
dev_err(dev, "could not set up vref regulator cleanup action\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
adc->shutdown = devm_gpiod_get_optional(dev, "shutdown",
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(adc->shutdown))
|
||||
return PTR_ERR(adc->shutdown);
|
||||
|
||||
if (adc->shutdown)
|
||||
dev_dbg(dev, "shutdown pin passed, low-power mode enabled");
|
||||
else
|
||||
dev_dbg(dev, "no shutdown pin passed, low-power mode disabled");
|
||||
|
||||
indio_dev->name = spi_get_device_id(spi)->name;
|
||||
indio_dev->dev.parent = dev;
|
||||
indio_dev->info = &max1241_info;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->channels = max1241_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(max1241_channels);
|
||||
|
||||
return devm_iio_device_register(dev, indio_dev);
|
||||
}
|
||||
|
||||
static const struct spi_device_id max1241_id[] = {
|
||||
{ "max1241", max1241 },
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct of_device_id max1241_dt_ids[] = {
|
||||
{ .compatible = "maxim,max1241" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, max1241_dt_ids);
|
||||
|
||||
static struct spi_driver max1241_spi_driver = {
|
||||
.driver = {
|
||||
.name = "max1241",
|
||||
.of_match_table = max1241_dt_ids,
|
||||
},
|
||||
.probe = max1241_probe,
|
||||
.id_table = max1241_id,
|
||||
};
|
||||
module_spi_driver(max1241_spi_driver);
|
||||
|
||||
MODULE_AUTHOR("Alexandru Lazar <alazar@startmail.com>");
|
||||
MODULE_DESCRIPTION("MAX1241 ADC driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -150,6 +150,7 @@ struct max1363_chip_info {
|
||||
* @current_mode: the scan mode of this chip
|
||||
* @requestedmask: a valid requested set of channels
|
||||
* @reg: supply regulator
|
||||
* @lock lock to ensure state is consistent
|
||||
* @monitor_on: whether monitor mode is enabled
|
||||
* @monitor_speed: parameter corresponding to device monitor speed setting
|
||||
* @mask_high: bitmask for enabled high thresholds
|
||||
@ -169,6 +170,7 @@ struct max1363_state {
|
||||
const struct max1363_mode *current_mode;
|
||||
u32 requestedmask;
|
||||
struct regulator *reg;
|
||||
struct mutex lock;
|
||||
|
||||
/* Using monitor modes and buffer at the same time is
|
||||
currently not supported */
|
||||
@ -364,7 +366,11 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev,
|
||||
struct max1363_state *st = iio_priv(indio_dev);
|
||||
struct i2c_client *client = st->client;
|
||||
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
ret = iio_device_claim_direct_mode(indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
mutex_lock(&st->lock);
|
||||
|
||||
/*
|
||||
* If monitor mode is enabled, the method for reading a single
|
||||
* channel will have to be rather different and has not yet
|
||||
@ -372,7 +378,7 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev,
|
||||
*
|
||||
* Also, cannot read directly if buffered capture enabled.
|
||||
*/
|
||||
if (st->monitor_on || iio_buffer_enabled(indio_dev)) {
|
||||
if (st->monitor_on) {
|
||||
ret = -EBUSY;
|
||||
goto error_ret;
|
||||
}
|
||||
@ -404,8 +410,10 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev,
|
||||
data = rxbuf[0];
|
||||
}
|
||||
*val = data;
|
||||
|
||||
error_ret:
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
mutex_unlock(&st->lock);
|
||||
iio_device_release_direct_mode(indio_dev);
|
||||
return ret;
|
||||
|
||||
}
|
||||
@ -705,9 +713,9 @@ static ssize_t max1363_monitor_store_freq(struct device *dev,
|
||||
if (!found)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
mutex_lock(&st->lock);
|
||||
st->monitor_speed = i;
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
mutex_unlock(&st->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -810,12 +818,12 @@ static int max1363_read_event_config(struct iio_dev *indio_dev,
|
||||
int val;
|
||||
int number = chan->channel;
|
||||
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
mutex_lock(&st->lock);
|
||||
if (dir == IIO_EV_DIR_FALLING)
|
||||
val = (1 << number) & st->mask_low;
|
||||
else
|
||||
val = (1 << number) & st->mask_high;
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
mutex_unlock(&st->lock);
|
||||
|
||||
return val;
|
||||
}
|
||||
@ -962,7 +970,11 @@ static int max1363_write_event_config(struct iio_dev *indio_dev,
|
||||
u16 unifiedmask;
|
||||
int number = chan->channel;
|
||||
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
ret = iio_device_claim_direct_mode(indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
mutex_lock(&st->lock);
|
||||
|
||||
unifiedmask = st->mask_low | st->mask_high;
|
||||
if (dir == IIO_EV_DIR_FALLING) {
|
||||
|
||||
@ -989,7 +1001,8 @@ static int max1363_write_event_config(struct iio_dev *indio_dev,
|
||||
|
||||
max1363_monitor_mode_update(st, !!(st->mask_high | st->mask_low));
|
||||
error_ret:
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
mutex_unlock(&st->lock);
|
||||
iio_device_release_direct_mode(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1587,6 +1600,7 @@ static int max1363_probe(struct i2c_client *client,
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
|
||||
mutex_init(&st->lock);
|
||||
st->reg = devm_regulator_get(&client->dev, "vcc");
|
||||
if (IS_ERR(st->reg)) {
|
||||
ret = PTR_ERR(st->reg);
|
||||
|
@ -496,7 +496,6 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev,
|
||||
struct iio_dev *indio_dev)
|
||||
{
|
||||
struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
|
||||
struct resource *mem;
|
||||
void __iomem *base;
|
||||
int ret;
|
||||
|
||||
@ -508,8 +507,7 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev,
|
||||
indio_dev->num_channels = ARRAY_SIZE(sun8i_a33_gpadc_channels);
|
||||
indio_dev->channels = sun8i_a33_gpadc_channels;
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
base = devm_ioremap_resource(&pdev->dev, mem);
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Xilinx XADC driver
|
||||
*
|
||||
* Copyright 2013-2014 Analog Devices Inc.
|
||||
* Author: Lars-Peter Clauen <lars@metafoo.de>
|
||||
* Author: Lars-Peter Clausen <lars@metafoo.de>
|
||||
*
|
||||
* Documentation for the parts can be found at:
|
||||
* - XADC hardmacro: Xilinx UG480
|
||||
@ -653,7 +653,7 @@ static int xadc_trigger_set_state(struct iio_trigger *trigger, bool state)
|
||||
mutex_lock(&xadc->mutex);
|
||||
|
||||
if (state) {
|
||||
/* Only one of the two triggers can be active at the a time. */
|
||||
/* Only one of the two triggers can be active at a time. */
|
||||
if (xadc->trigger != NULL) {
|
||||
ret = -EBUSY;
|
||||
goto err_out;
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Xilinx XADC driver
|
||||
*
|
||||
* Copyright 2013 Analog Devices Inc.
|
||||
* Author: Lars-Peter Clauen <lars@metafoo.de>
|
||||
* Author: Lars-Peter Clausen <lars@metafoo.de>
|
||||
*/
|
||||
|
||||
#include <linux/iio/events.h>
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Xilinx XADC driver
|
||||
*
|
||||
* Copyright 2013 Analog Devices Inc.
|
||||
* Author: Lars-Peter Clauen <lars@metafoo.de>
|
||||
* Author: Lars-Peter Clausen <lars@metafoo.de>
|
||||
*/
|
||||
|
||||
#ifndef __IIO_XILINX_XADC__
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/buffer_impl.h>
|
||||
#include <linux/iio/buffer-dma.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
@ -134,7 +134,7 @@ static ssize_t iio_dmaengine_buffer_get_length_align(struct device *dev,
|
||||
struct dmaengine_buffer *dmaengine_buffer =
|
||||
iio_buffer_to_dmaengine_buffer(indio_dev->buffer);
|
||||
|
||||
return sprintf(buf, "%u\n", dmaengine_buffer->align);
|
||||
return sprintf(buf, "%zu\n", dmaengine_buffer->align);
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(length_align_bytes, 0444,
|
||||
@ -229,6 +229,45 @@ void iio_dmaengine_buffer_free(struct iio_buffer *buffer)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iio_dmaengine_buffer_free);
|
||||
|
||||
static void __devm_iio_dmaengine_buffer_free(struct device *dev, void *res)
|
||||
{
|
||||
iio_dmaengine_buffer_free(*(struct iio_buffer **)res);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_iio_dmaengine_buffer_alloc() - Resource-managed iio_dmaengine_buffer_alloc()
|
||||
* @dev: Parent device for the buffer
|
||||
* @channel: DMA channel name, typically "rx".
|
||||
*
|
||||
* This allocates a new IIO buffer which internally uses the DMAengine framework
|
||||
* to perform its transfers. The parent device will be used to request the DMA
|
||||
* channel.
|
||||
*
|
||||
* The buffer will be automatically de-allocated once the device gets destroyed.
|
||||
*/
|
||||
struct iio_buffer *devm_iio_dmaengine_buffer_alloc(struct device *dev,
|
||||
const char *channel)
|
||||
{
|
||||
struct iio_buffer **bufferp, *buffer;
|
||||
|
||||
bufferp = devres_alloc(__devm_iio_dmaengine_buffer_free,
|
||||
sizeof(*bufferp), GFP_KERNEL);
|
||||
if (!bufferp)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
buffer = iio_dmaengine_buffer_alloc(dev, channel);
|
||||
if (IS_ERR(buffer)) {
|
||||
devres_free(bufferp);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
*bufferp = buffer;
|
||||
devres_add(dev, bufferp);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_iio_dmaengine_buffer_alloc);
|
||||
|
||||
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
|
||||
MODULE_DESCRIPTION("DMA buffer for the IIO framework");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -142,17 +142,6 @@ static void devm_iio_hw_consumer_release(struct device *dev, void *res)
|
||||
iio_hw_consumer_free(*(struct iio_hw_consumer **)res);
|
||||
}
|
||||
|
||||
static int devm_iio_hw_consumer_match(struct device *dev, void *res, void *data)
|
||||
{
|
||||
struct iio_hw_consumer **r = res;
|
||||
|
||||
if (!r || !*r) {
|
||||
WARN_ON(!r || !*r);
|
||||
return 0;
|
||||
}
|
||||
return *r == data;
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_iio_hw_consumer_alloc - Resource-managed iio_hw_consumer_alloc()
|
||||
* @dev: Pointer to consumer device.
|
||||
@ -160,9 +149,6 @@ static int devm_iio_hw_consumer_match(struct device *dev, void *res, void *data)
|
||||
* Managed iio_hw_consumer_alloc. iio_hw_consumer allocated with this function
|
||||
* is automatically freed on driver detach.
|
||||
*
|
||||
* If an iio_hw_consumer allocated with this function needs to be freed
|
||||
* separately, devm_iio_hw_consumer_free() must be used.
|
||||
*
|
||||
* returns pointer to allocated iio_hw_consumer on success, NULL on failure.
|
||||
*/
|
||||
struct iio_hw_consumer *devm_iio_hw_consumer_alloc(struct device *dev)
|
||||
@ -186,23 +172,6 @@ struct iio_hw_consumer *devm_iio_hw_consumer_alloc(struct device *dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_iio_hw_consumer_alloc);
|
||||
|
||||
/**
|
||||
* devm_iio_hw_consumer_free - Resource-managed iio_hw_consumer_free()
|
||||
* @dev: Pointer to consumer device.
|
||||
* @hwc: iio_hw_consumer to free.
|
||||
*
|
||||
* Free iio_hw_consumer allocated with devm_iio_hw_consumer_alloc().
|
||||
*/
|
||||
void devm_iio_hw_consumer_free(struct device *dev, struct iio_hw_consumer *hwc)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = devres_release(dev, devm_iio_hw_consumer_release,
|
||||
devm_iio_hw_consumer_match, hwc);
|
||||
WARN_ON(rc);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_iio_hw_consumer_free);
|
||||
|
||||
/**
|
||||
* iio_hw_consumer_enable() - Enable IIO hardware consumer
|
||||
* @hwc: iio_hw_consumer to enable.
|
||||
|
@ -126,17 +126,6 @@ int devm_iio_triggered_buffer_setup(struct device *dev,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_iio_triggered_buffer_setup);
|
||||
|
||||
void devm_iio_triggered_buffer_cleanup(struct device *dev,
|
||||
struct iio_dev *indio_dev)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = devres_release(dev, devm_iio_triggered_buffer_clean,
|
||||
devm_iio_device_match, indio_dev);
|
||||
WARN_ON(rc);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_iio_triggered_buffer_cleanup);
|
||||
|
||||
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
|
||||
MODULE_DESCRIPTION("IIO helper functions for setting up triggered buffers");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -179,16 +179,6 @@ static void devm_iio_kfifo_release(struct device *dev, void *res)
|
||||
iio_kfifo_free(*(struct iio_buffer **)res);
|
||||
}
|
||||
|
||||
static int devm_iio_kfifo_match(struct device *dev, void *res, void *data)
|
||||
{
|
||||
struct iio_buffer **r = res;
|
||||
|
||||
if (WARN_ON(!r || !*r))
|
||||
return 0;
|
||||
|
||||
return *r == data;
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_iio_fifo_allocate - Resource-managed iio_kfifo_allocate()
|
||||
* @dev: Device to allocate kfifo buffer for
|
||||
@ -216,16 +206,4 @@ struct iio_buffer *devm_iio_kfifo_allocate(struct device *dev)
|
||||
}
|
||||
EXPORT_SYMBOL(devm_iio_kfifo_allocate);
|
||||
|
||||
/**
|
||||
* devm_iio_fifo_free - Resource-managed iio_kfifo_free()
|
||||
* @dev: Device the buffer belongs to
|
||||
* @r: The buffer associated with the device
|
||||
*/
|
||||
void devm_iio_kfifo_free(struct device *dev, struct iio_buffer *r)
|
||||
{
|
||||
WARN_ON(devres_release(dev, devm_iio_kfifo_release,
|
||||
devm_iio_kfifo_match, r));
|
||||
}
|
||||
EXPORT_SYMBOL(devm_iio_kfifo_free);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -426,8 +426,7 @@ static irqreturn_t atlas_trigger_handler(int irq, void *private)
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, data->chip->data_reg,
|
||||
(u8 *) &data->buffer,
|
||||
sizeof(__be32) * channels);
|
||||
&data->buffer, sizeof(__be32) * channels);
|
||||
|
||||
if (!ret)
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
|
||||
@ -463,7 +462,7 @@ static int atlas_read_measurement(struct atlas_data *data, int reg, __be32 *val)
|
||||
if (suspended)
|
||||
msleep(data->chip->delay);
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, reg, (u8 *) val, sizeof(*val));
|
||||
ret = regmap_bulk_read(data->regmap, reg, val, sizeof(*val));
|
||||
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
@ -485,7 +484,7 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
|
||||
switch (chan->type) {
|
||||
case IIO_TEMP:
|
||||
ret = regmap_bulk_read(data->regmap, chan->address,
|
||||
(u8 *) ®, sizeof(reg));
|
||||
®, sizeof(reg));
|
||||
break;
|
||||
case IIO_PH:
|
||||
case IIO_CONCENTRATION:
|
||||
|
@ -114,14 +114,16 @@ static int bme680_read_calib(struct bme680_data *data,
|
||||
__le16 buf;
|
||||
|
||||
/* Temperature related coefficients */
|
||||
ret = regmap_bulk_read(data->regmap, BME680_T1_LSB_REG, (u8 *) &buf, 2);
|
||||
ret = regmap_bulk_read(data->regmap, BME680_T1_LSB_REG,
|
||||
&buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to read BME680_T1_LSB_REG\n");
|
||||
return ret;
|
||||
}
|
||||
calib->par_t1 = le16_to_cpu(buf);
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BME680_T2_LSB_REG, (u8 *) &buf, 2);
|
||||
ret = regmap_bulk_read(data->regmap, BME680_T2_LSB_REG,
|
||||
&buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to read BME680_T2_LSB_REG\n");
|
||||
return ret;
|
||||
@ -136,14 +138,16 @@ static int bme680_read_calib(struct bme680_data *data,
|
||||
calib->par_t3 = tmp;
|
||||
|
||||
/* Pressure related coefficients */
|
||||
ret = regmap_bulk_read(data->regmap, BME680_P1_LSB_REG, (u8 *) &buf, 2);
|
||||
ret = regmap_bulk_read(data->regmap, BME680_P1_LSB_REG,
|
||||
&buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to read BME680_P1_LSB_REG\n");
|
||||
return ret;
|
||||
}
|
||||
calib->par_p1 = le16_to_cpu(buf);
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BME680_P2_LSB_REG, (u8 *) &buf, 2);
|
||||
ret = regmap_bulk_read(data->regmap, BME680_P2_LSB_REG,
|
||||
&buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to read BME680_P2_LSB_REG\n");
|
||||
return ret;
|
||||
@ -157,14 +161,16 @@ static int bme680_read_calib(struct bme680_data *data,
|
||||
}
|
||||
calib->par_p3 = tmp;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BME680_P4_LSB_REG, (u8 *) &buf, 2);
|
||||
ret = regmap_bulk_read(data->regmap, BME680_P4_LSB_REG,
|
||||
&buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to read BME680_P4_LSB_REG\n");
|
||||
return ret;
|
||||
}
|
||||
calib->par_p4 = le16_to_cpu(buf);
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BME680_P5_LSB_REG, (u8 *) &buf, 2);
|
||||
ret = regmap_bulk_read(data->regmap, BME680_P5_LSB_REG,
|
||||
&buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to read BME680_P5_LSB_REG\n");
|
||||
return ret;
|
||||
@ -185,14 +191,16 @@ static int bme680_read_calib(struct bme680_data *data,
|
||||
}
|
||||
calib->par_p7 = tmp;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BME680_P8_LSB_REG, (u8 *) &buf, 2);
|
||||
ret = regmap_bulk_read(data->regmap, BME680_P8_LSB_REG,
|
||||
&buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to read BME680_P8_LSB_REG\n");
|
||||
return ret;
|
||||
}
|
||||
calib->par_p8 = le16_to_cpu(buf);
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BME680_P9_LSB_REG, (u8 *) &buf, 2);
|
||||
ret = regmap_bulk_read(data->regmap, BME680_P9_LSB_REG,
|
||||
&buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to read BME680_P9_LSB_REG\n");
|
||||
return ret;
|
||||
@ -276,8 +284,8 @@ static int bme680_read_calib(struct bme680_data *data,
|
||||
}
|
||||
calib->par_gh1 = tmp;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BME680_GH2_LSB_REG, (u8 *) &buf,
|
||||
2);
|
||||
ret = regmap_bulk_read(data->regmap, BME680_GH2_LSB_REG,
|
||||
&buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to read BME680_GH2_LSB_REG\n");
|
||||
return ret;
|
||||
@ -615,7 +623,7 @@ static int bme680_read_temp(struct bme680_data *data, int *val)
|
||||
return ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BME680_REG_TEMP_MSB,
|
||||
(u8 *) &tmp, 3);
|
||||
&tmp, 3);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to read temperature\n");
|
||||
return ret;
|
||||
@ -656,7 +664,7 @@ static int bme680_read_press(struct bme680_data *data,
|
||||
return ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BME680_REG_PRESS_MSB,
|
||||
(u8 *) &tmp, 3);
|
||||
&tmp, 3);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to read pressure\n");
|
||||
return ret;
|
||||
@ -689,7 +697,7 @@ static int bme680_read_humid(struct bme680_data *data,
|
||||
return ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BM6880_REG_HUMIDITY_MSB,
|
||||
(u8 *) &tmp, 2);
|
||||
&tmp, sizeof(tmp));
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to read humidity\n");
|
||||
return ret;
|
||||
@ -754,7 +762,7 @@ static int bme680_read_gas(struct bme680_data *data,
|
||||
}
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BME680_REG_GAS_MSB,
|
||||
(u8 *) &tmp, 2);
|
||||
&tmp, sizeof(tmp));
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to read gas resistance\n");
|
||||
return ret;
|
||||
|
@ -150,8 +150,7 @@ static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs)
|
||||
if (err < 0)
|
||||
goto st_accel_set_fullscale_error;
|
||||
|
||||
sdata->current_fullscale = (struct st_sensor_fullscale_avl *)
|
||||
&sdata->sensor_settings->fs.fs_avl[i];
|
||||
sdata->current_fullscale = &sdata->sensor_settings->fs.fs_avl[i];
|
||||
return err;
|
||||
|
||||
st_accel_set_fullscale_error:
|
||||
@ -278,8 +277,7 @@ static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev,
|
||||
!sdata->sensor_settings->drdy_irq.int2.addr) {
|
||||
if (pdata->drdy_int_pin)
|
||||
dev_info(&indio_dev->dev,
|
||||
"DRDY on pin INT%d specified, but sensor "
|
||||
"does not support interrupts\n",
|
||||
"DRDY on pin INT%d specified, but sensor does not support interrupts\n",
|
||||
pdata->drdy_int_pin);
|
||||
return 0;
|
||||
}
|
||||
|
@ -49,8 +49,8 @@ int st_sensors_i2c_configure(struct iio_dev *indio_dev,
|
||||
|
||||
sdata->regmap = devm_regmap_init_i2c(client, config);
|
||||
if (IS_ERR(sdata->regmap)) {
|
||||
dev_err(&client->dev, "Failed to register i2c regmap (%d)\n",
|
||||
(int)PTR_ERR(sdata->regmap));
|
||||
dev_err(&client->dev, "Failed to register i2c regmap (%ld)\n",
|
||||
PTR_ERR(sdata->regmap));
|
||||
return PTR_ERR(sdata->regmap);
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ static bool st_sensors_is_spi_3_wire(struct spi_device *spi)
|
||||
if (device_property_read_bool(dev, "spi-3wire"))
|
||||
return true;
|
||||
|
||||
pdata = (struct st_sensors_platform_data *)dev->platform_data;
|
||||
pdata = dev_get_platdata(dev);
|
||||
if (pdata && pdata->spi_3wire)
|
||||
return true;
|
||||
|
||||
@ -101,8 +101,8 @@ int st_sensors_spi_configure(struct iio_dev *indio_dev,
|
||||
|
||||
sdata->regmap = devm_regmap_init_spi(spi, config);
|
||||
if (IS_ERR(sdata->regmap)) {
|
||||
dev_err(&spi->dev, "Failed to register spi regmap (%d)\n",
|
||||
(int)PTR_ERR(sdata->regmap));
|
||||
dev_err(&spi->dev, "Failed to register spi regmap (%ld)\n",
|
||||
PTR_ERR(sdata->regmap));
|
||||
return PTR_ERR(sdata->regmap);
|
||||
}
|
||||
|
||||
|
@ -44,8 +44,7 @@ static int st_sensors_new_samples_available(struct iio_dev *indio_dev,
|
||||
sdata->sensor_settings->drdy_irq.stat_drdy.addr,
|
||||
&status);
|
||||
if (ret < 0) {
|
||||
dev_err(sdata->dev,
|
||||
"error checking samples available\n");
|
||||
dev_err(sdata->dev, "error checking samples available\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -148,9 +147,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
|
||||
case IRQF_TRIGGER_LOW:
|
||||
if (!sdata->sensor_settings->drdy_irq.addr_ihl) {
|
||||
dev_err(&indio_dev->dev,
|
||||
"falling/low specified for IRQ "
|
||||
"but hardware supports only rising/high: "
|
||||
"will request rising/high\n");
|
||||
"falling/low specified for IRQ but hardware supports only rising/high: will request rising/high\n");
|
||||
if (irq_trig == IRQF_TRIGGER_FALLING)
|
||||
irq_trig = IRQF_TRIGGER_RISING;
|
||||
if (irq_trig == IRQF_TRIGGER_LOW)
|
||||
@ -163,8 +160,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
|
||||
if (err < 0)
|
||||
goto iio_trigger_free;
|
||||
dev_info(&indio_dev->dev,
|
||||
"interrupts on the falling edge or "
|
||||
"active low level\n");
|
||||
"interrupts on the falling edge or active low level\n");
|
||||
}
|
||||
break;
|
||||
case IRQF_TRIGGER_RISING:
|
||||
@ -178,8 +174,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
|
||||
default:
|
||||
/* This is the most preferred mode, if possible */
|
||||
dev_err(&indio_dev->dev,
|
||||
"unsupported IRQ trigger specified (%lx), enforce "
|
||||
"rising edge\n", irq_trig);
|
||||
"unsupported IRQ trigger specified (%lx), enforce rising edge\n", irq_trig);
|
||||
irq_trig = IRQF_TRIGGER_RISING;
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ config BMG160
|
||||
help
|
||||
Say yes here to build support for BOSCH BMG160 Tri-axis Gyro Sensor
|
||||
driver connected via I2C or SPI. This driver also supports BMI055
|
||||
gyroscope.
|
||||
and BMI088 gyroscope.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called bmg160_i2c or bmg160_spi.
|
||||
|
@ -21,8 +21,8 @@ static int bmg160_i2c_probe(struct i2c_client *client,
|
||||
|
||||
regmap = devm_regmap_init_i2c(client, &bmg160_regmap_i2c_conf);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&client->dev, "Failed to register i2c regmap %d\n",
|
||||
(int)PTR_ERR(regmap));
|
||||
dev_err(&client->dev, "Failed to register i2c regmap: %pe\n",
|
||||
regmap);
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
@ -42,6 +42,7 @@ static int bmg160_i2c_remove(struct i2c_client *client)
|
||||
static const struct acpi_device_id bmg160_acpi_match[] = {
|
||||
{"BMG0160", 0},
|
||||
{"BMI055B", 0},
|
||||
{"BMI088B", 0},
|
||||
{},
|
||||
};
|
||||
|
||||
@ -50,6 +51,7 @@ MODULE_DEVICE_TABLE(acpi, bmg160_acpi_match);
|
||||
static const struct i2c_device_id bmg160_i2c_id[] = {
|
||||
{"bmg160", 0},
|
||||
{"bmi055_gyro", 0},
|
||||
{"bmi088_gyro", 0},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -19,8 +19,8 @@ static int bmg160_spi_probe(struct spi_device *spi)
|
||||
|
||||
regmap = devm_regmap_init_spi(spi, &bmg160_regmap_spi_conf);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&spi->dev, "Failed to register spi regmap %d\n",
|
||||
(int)PTR_ERR(regmap));
|
||||
dev_err(&spi->dev, "Failed to register spi regmap: %pe\n",
|
||||
regmap);
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
@ -37,6 +37,7 @@ static int bmg160_spi_remove(struct spi_device *spi)
|
||||
static const struct spi_device_id bmg160_spi_id[] = {
|
||||
{"bmg160", 0},
|
||||
{"bmi055_gyro", 0},
|
||||
{"bmi088_gyro", 0},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -51,8 +51,8 @@ static int mpu3050_i2c_probe(struct i2c_client *client,
|
||||
|
||||
regmap = devm_regmap_init_i2c(client, &mpu3050_i2c_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&client->dev, "Failed to register i2c regmap %d\n",
|
||||
(int)PTR_ERR(regmap));
|
||||
dev_err(&client->dev, "Failed to register i2c regmap: %pe\n",
|
||||
regmap);
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
|
@ -37,8 +37,7 @@ static int st_gyro_buffer_postenable(struct iio_dev *indio_dev)
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = st_sensors_set_axis_enable(indio_dev,
|
||||
(u8)indio_dev->active_scan_mask[0]);
|
||||
err = st_sensors_set_axis_enable(indio_dev, indio_dev->active_scan_mask[0]);
|
||||
if (err < 0)
|
||||
goto st_gyro_buffer_predisable;
|
||||
|
||||
|
@ -460,6 +460,7 @@ EXPORT_SYMBOL(st_gyro_get_settings);
|
||||
int st_gyro_common_probe(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct st_sensor_data *gdata = iio_priv(indio_dev);
|
||||
struct st_sensors_platform_data *pdata;
|
||||
int err;
|
||||
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
@ -477,12 +478,12 @@ int st_gyro_common_probe(struct iio_dev *indio_dev)
|
||||
indio_dev->channels = gdata->sensor_settings->ch;
|
||||
indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
|
||||
|
||||
gdata->current_fullscale = (struct st_sensor_fullscale_avl *)
|
||||
&gdata->sensor_settings->fs.fs_avl[0];
|
||||
gdata->current_fullscale = &gdata->sensor_settings->fs.fs_avl[0];
|
||||
gdata->odr = gdata->sensor_settings->odr.odr_avl[0].hz;
|
||||
|
||||
err = st_sensors_init_sensor(indio_dev,
|
||||
(struct st_sensors_platform_data *)&gyro_pdata);
|
||||
pdata = (struct st_sensors_platform_data *)&gyro_pdata;
|
||||
|
||||
err = st_sensors_init_sensor(indio_dev, pdata);
|
||||
if (err < 0)
|
||||
goto st_gyro_power_off;
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include <linux/irq.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
@ -267,11 +267,10 @@ static int max30100_get_current_idx(unsigned int val, int *reg)
|
||||
static int max30100_led_init(struct max30100_data *data)
|
||||
{
|
||||
struct device *dev = &data->client->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
unsigned int val[2];
|
||||
int reg, ret;
|
||||
|
||||
ret = of_property_read_u32_array(np, "maxim,led-current-microamp",
|
||||
ret = device_property_read_u32_array(dev, "maxim,led-current-microamp",
|
||||
(unsigned int *) &val, 2);
|
||||
if (ret) {
|
||||
/* Default to 24 mA RED LED, 50 mA IR LED */
|
||||
@ -502,7 +501,7 @@ MODULE_DEVICE_TABLE(of, max30100_dt_ids);
|
||||
static struct i2c_driver max30100_driver = {
|
||||
.driver = {
|
||||
.name = MAX30100_DRV_NAME,
|
||||
.of_match_table = of_match_ptr(max30100_dt_ids),
|
||||
.of_match_table = max30100_dt_ids,
|
||||
},
|
||||
.probe = max30100_probe,
|
||||
.remove = max30100_remove,
|
||||
|
@ -74,10 +74,9 @@ static irqreturn_t hts221_trigger_handler_thread(int irq, void *private)
|
||||
|
||||
int hts221_allocate_trigger(struct hts221_hw *hw)
|
||||
{
|
||||
struct st_sensors_platform_data *pdata = dev_get_platdata(hw->dev);
|
||||
struct iio_dev *iio_dev = iio_priv_to_dev(hw);
|
||||
bool irq_active_low = false, open_drain = false;
|
||||
struct device_node *np = hw->dev->of_node;
|
||||
struct st_sensors_platform_data *pdata;
|
||||
unsigned long irq_type;
|
||||
int err;
|
||||
|
||||
@ -106,8 +105,7 @@ int hts221_allocate_trigger(struct hts221_hw *hw)
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
pdata = (struct st_sensors_platform_data *)hw->dev->platform_data;
|
||||
if ((np && of_property_read_bool(np, "drive-open-drain")) ||
|
||||
if (device_property_read_bool(hw->dev, "drive-open-drain") ||
|
||||
(pdata && pdata->open_drain)) {
|
||||
irq_type |= IRQF_SHARED;
|
||||
open_drain = true;
|
||||
|
@ -32,8 +32,8 @@ static int hts221_i2c_probe(struct i2c_client *client,
|
||||
|
||||
regmap = devm_regmap_init_i2c(client, &hts221_i2c_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&client->dev, "Failed to register i2c regmap %d\n",
|
||||
(int)PTR_ERR(regmap));
|
||||
dev_err(&client->dev, "Failed to register i2c regmap %ld\n",
|
||||
PTR_ERR(regmap));
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
@ -63,7 +63,7 @@ static struct i2c_driver hts221_driver = {
|
||||
.driver = {
|
||||
.name = "hts221_i2c",
|
||||
.pm = &hts221_pm_ops,
|
||||
.of_match_table = of_match_ptr(hts221_i2c_of_match),
|
||||
.of_match_table = hts221_i2c_of_match,
|
||||
.acpi_match_table = ACPI_PTR(hts221_acpi_match),
|
||||
},
|
||||
.probe = hts221_i2c_probe,
|
||||
|
@ -31,8 +31,8 @@ static int hts221_spi_probe(struct spi_device *spi)
|
||||
|
||||
regmap = devm_regmap_init_spi(spi, &hts221_spi_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&spi->dev, "Failed to register spi regmap %d\n",
|
||||
(int)PTR_ERR(regmap));
|
||||
dev_err(&spi->dev, "Failed to register spi regmap %ld\n",
|
||||
PTR_ERR(regmap));
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ static struct spi_driver hts221_driver = {
|
||||
.driver = {
|
||||
.name = "hts221_spi",
|
||||
.pm = &hts221_pm_ops,
|
||||
.of_match_table = of_match_ptr(hts221_spi_of_match),
|
||||
.of_match_table = hts221_spi_of_match,
|
||||
},
|
||||
.probe = hts221_spi_probe,
|
||||
.id_table = hts221_spi_id_table,
|
||||
|
@ -419,7 +419,7 @@ int __adis_initial_startup(struct adis *adis)
|
||||
|
||||
if (prod_id != adis->data->prod_id)
|
||||
dev_warn(&adis->spi->dev,
|
||||
"Device ID(%u) and product ID(%u) do not match.",
|
||||
"Device ID(%u) and product ID(%u) do not match.\n",
|
||||
adis->data->prod_id, prod_id);
|
||||
|
||||
return 0;
|
||||
|
@ -258,7 +258,7 @@ static int adis16400_show_product_id(void *arg, u64 *val)
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SIMPLE_ATTRIBUTE(adis16400_product_id_fops,
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(adis16400_product_id_fops,
|
||||
adis16400_show_product_id, NULL, "%lld\n");
|
||||
|
||||
static int adis16400_show_flash_count(void *arg, u64 *val)
|
||||
@ -275,7 +275,7 @@ static int adis16400_show_flash_count(void *arg, u64 *val)
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SIMPLE_ATTRIBUTE(adis16400_flash_count_fops,
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(adis16400_flash_count_fops,
|
||||
adis16400_show_flash_count, NULL, "%lld\n");
|
||||
|
||||
static int adis16400_debugfs_init(struct iio_dev *indio_dev)
|
||||
@ -283,15 +283,16 @@ static int adis16400_debugfs_init(struct iio_dev *indio_dev)
|
||||
struct adis16400_state *st = iio_priv(indio_dev);
|
||||
|
||||
if (st->variant->flags & ADIS16400_HAS_SERIAL_NUMBER)
|
||||
debugfs_create_file("serial_number", 0400,
|
||||
indio_dev->debugfs_dentry, st,
|
||||
&adis16400_serial_number_fops);
|
||||
debugfs_create_file_unsafe("serial_number", 0400,
|
||||
indio_dev->debugfs_dentry, st,
|
||||
&adis16400_serial_number_fops);
|
||||
if (st->variant->flags & ADIS16400_HAS_PROD_ID)
|
||||
debugfs_create_file("product_id", 0400,
|
||||
debugfs_create_file_unsafe("product_id", 0400,
|
||||
indio_dev->debugfs_dentry, st,
|
||||
&adis16400_product_id_fops);
|
||||
debugfs_create_file_unsafe("flash_count", 0400,
|
||||
indio_dev->debugfs_dentry, st,
|
||||
&adis16400_product_id_fops);
|
||||
debugfs_create_file("flash_count", 0400, indio_dev->debugfs_dentry,
|
||||
st, &adis16400_flash_count_fops);
|
||||
&adis16400_flash_count_fops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -87,8 +87,8 @@ static int adis16460_show_serial_number(void *arg, u64 *val)
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SIMPLE_ATTRIBUTE(adis16460_serial_number_fops,
|
||||
adis16460_show_serial_number, NULL, "0x%.4llx\n");
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(adis16460_serial_number_fops,
|
||||
adis16460_show_serial_number, NULL, "0x%.4llx\n");
|
||||
|
||||
static int adis16460_show_product_id(void *arg, u64 *val)
|
||||
{
|
||||
@ -105,8 +105,8 @@ static int adis16460_show_product_id(void *arg, u64 *val)
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SIMPLE_ATTRIBUTE(adis16460_product_id_fops,
|
||||
adis16460_show_product_id, NULL, "%llu\n");
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(adis16460_product_id_fops,
|
||||
adis16460_show_product_id, NULL, "%llu\n");
|
||||
|
||||
static int adis16460_show_flash_count(void *arg, u64 *val)
|
||||
{
|
||||
@ -123,19 +123,22 @@ static int adis16460_show_flash_count(void *arg, u64 *val)
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SIMPLE_ATTRIBUTE(adis16460_flash_count_fops,
|
||||
adis16460_show_flash_count, NULL, "%lld\n");
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(adis16460_flash_count_fops,
|
||||
adis16460_show_flash_count, NULL, "%lld\n");
|
||||
|
||||
static int adis16460_debugfs_init(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct adis16460 *adis16460 = iio_priv(indio_dev);
|
||||
|
||||
debugfs_create_file("serial_number", 0400, indio_dev->debugfs_dentry,
|
||||
adis16460, &adis16460_serial_number_fops);
|
||||
debugfs_create_file("product_id", 0400, indio_dev->debugfs_dentry,
|
||||
adis16460, &adis16460_product_id_fops);
|
||||
debugfs_create_file("flash_count", 0400, indio_dev->debugfs_dentry,
|
||||
adis16460, &adis16460_flash_count_fops);
|
||||
debugfs_create_file_unsafe("serial_number", 0400,
|
||||
indio_dev->debugfs_dentry, adis16460,
|
||||
&adis16460_serial_number_fops);
|
||||
debugfs_create_file_unsafe("product_id", 0400,
|
||||
indio_dev->debugfs_dentry, adis16460,
|
||||
&adis16460_product_id_fops);
|
||||
debugfs_create_file_unsafe("flash_count", 0400,
|
||||
indio_dev->debugfs_dentry, adis16460,
|
||||
&adis16460_flash_count_fops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -24,8 +24,8 @@ static int bmi160_i2c_probe(struct i2c_client *client,
|
||||
|
||||
regmap = devm_regmap_init_i2c(client, &bmi160_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&client->dev, "Failed to register i2c regmap %d\n",
|
||||
(int)PTR_ERR(regmap));
|
||||
dev_err(&client->dev, "Failed to register i2c regmap: %pe\n",
|
||||
regmap);
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
|
@ -20,8 +20,8 @@ static int bmi160_spi_probe(struct spi_device *spi)
|
||||
|
||||
regmap = devm_regmap_init_spi(spi, &bmi160_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&spi->dev, "Failed to register spi regmap %d\n",
|
||||
(int)PTR_ERR(regmap));
|
||||
dev_err(&spi->dev, "Failed to register spi regmap: %pe\n",
|
||||
regmap);
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
return bmi160_core_probe(&spi->dev, regmap, id->name, true);
|
||||
|
@ -135,6 +135,7 @@ int inv_mpu_acpi_create_mux_client(struct i2c_client *client)
|
||||
st->mux_client = NULL;
|
||||
if (ACPI_HANDLE(&client->dev)) {
|
||||
struct i2c_board_info info;
|
||||
struct i2c_client *mux_client;
|
||||
struct acpi_device *adev;
|
||||
int ret = -1;
|
||||
|
||||
@ -172,9 +173,10 @@ int inv_mpu_acpi_create_mux_client(struct i2c_client *client)
|
||||
} else
|
||||
return 0; /* no secondary addr, which is OK */
|
||||
}
|
||||
st->mux_client = i2c_new_device(st->muxc->adapter[0], &info);
|
||||
if (!st->mux_client)
|
||||
return -ENODEV;
|
||||
mux_client = i2c_new_client_device(st->muxc->adapter[0], &info);
|
||||
if (IS_ERR(mux_client))
|
||||
return PTR_ERR(mux_client);
|
||||
st->mux_client = mux_client;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -526,7 +526,7 @@ static int inv_mpu6050_sensor_set(struct inv_mpu6050_state *st, int reg,
|
||||
__be16 d = cpu_to_be16(val);
|
||||
|
||||
ind = (axis - IIO_MOD_X) * 2;
|
||||
result = regmap_bulk_write(st->map, reg + ind, (u8 *)&d, 2);
|
||||
result = regmap_bulk_write(st->map, reg + ind, &d, sizeof(d));
|
||||
if (result)
|
||||
return -EINVAL;
|
||||
|
||||
@ -540,7 +540,7 @@ static int inv_mpu6050_sensor_show(struct inv_mpu6050_state *st, int reg,
|
||||
__be16 d;
|
||||
|
||||
ind = (axis - IIO_MOD_X) * 2;
|
||||
result = regmap_bulk_read(st->map, reg + ind, (u8 *)&d, 2);
|
||||
result = regmap_bulk_read(st->map, reg + ind, &d, sizeof(d));
|
||||
if (result)
|
||||
return -EINVAL;
|
||||
*val = (short)be16_to_cpup(&d);
|
||||
@ -1248,12 +1248,31 @@ static const struct attribute_group inv_attribute_group = {
|
||||
.attrs = inv_attributes
|
||||
};
|
||||
|
||||
static int inv_mpu6050_reg_access(struct iio_dev *indio_dev,
|
||||
unsigned int reg,
|
||||
unsigned int writeval,
|
||||
unsigned int *readval)
|
||||
{
|
||||
struct inv_mpu6050_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&st->lock);
|
||||
if (readval)
|
||||
ret = regmap_read(st->map, reg, readval);
|
||||
else
|
||||
ret = regmap_write(st->map, reg, writeval);
|
||||
mutex_unlock(&st->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct iio_info mpu_info = {
|
||||
.read_raw = &inv_mpu6050_read_raw,
|
||||
.write_raw = &inv_mpu6050_write_raw,
|
||||
.write_raw_get_fmt = &inv_write_raw_get_fmt,
|
||||
.attrs = &inv_attribute_group,
|
||||
.validate_trigger = inv_mpu6050_validate_trigger,
|
||||
.debugfs_reg_access = &inv_mpu6050_reg_access,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -122,8 +122,8 @@ static int inv_mpu_probe(struct i2c_client *client,
|
||||
|
||||
regmap = devm_regmap_init_i2c(client, &inv_mpu_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&client->dev, "Failed to register i2c regmap %d\n",
|
||||
(int)PTR_ERR(regmap));
|
||||
dev_err(&client->dev, "Failed to register i2c regmap: %pe\n",
|
||||
regmap);
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
|
@ -53,8 +53,8 @@ static int inv_mpu_probe(struct spi_device *spi)
|
||||
|
||||
regmap = devm_regmap_init_spi(spi, &inv_mpu_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&spi->dev, "Failed to register spi regmap %d\n",
|
||||
(int)PTR_ERR(regmap));
|
||||
dev_err(&spi->dev, "Failed to register spi regmap: %pe\n",
|
||||
regmap);
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ struct st_lsm6dsx_odr {
|
||||
u8 val;
|
||||
};
|
||||
|
||||
#define ST_LSM6DSX_ODR_LIST_SIZE 6
|
||||
#define ST_LSM6DSX_ODR_LIST_SIZE 8
|
||||
struct st_lsm6dsx_odr_table_entry {
|
||||
struct st_lsm6dsx_reg reg;
|
||||
|
||||
|
@ -88,6 +88,69 @@ static const struct st_lsm6dsx_ext_dev_settings st_lsm6dsx_ext_dev_table[] = {
|
||||
.len = 6,
|
||||
},
|
||||
},
|
||||
/* LIS3MDL */
|
||||
{
|
||||
.i2c_addr = { 0x1e },
|
||||
.wai = {
|
||||
.addr = 0x0f,
|
||||
.val = 0x3d,
|
||||
},
|
||||
.id = ST_LSM6DSX_ID_MAGN,
|
||||
.odr_table = {
|
||||
.reg = {
|
||||
.addr = 0x20,
|
||||
.mask = GENMASK(4, 2),
|
||||
},
|
||||
.odr_avl[0] = { 1000, 0x0 },
|
||||
.odr_avl[1] = { 2000, 0x1 },
|
||||
.odr_avl[2] = { 3000, 0x2 },
|
||||
.odr_avl[3] = { 5000, 0x3 },
|
||||
.odr_avl[4] = { 10000, 0x4 },
|
||||
.odr_avl[5] = { 20000, 0x5 },
|
||||
.odr_avl[6] = { 40000, 0x6 },
|
||||
.odr_avl[7] = { 80000, 0x7 },
|
||||
.odr_len = 8,
|
||||
},
|
||||
.fs_table = {
|
||||
.reg = {
|
||||
.addr = 0x21,
|
||||
.mask = GENMASK(6, 5),
|
||||
},
|
||||
.fs_avl[0] = {
|
||||
.gain = 146,
|
||||
.val = 0x00,
|
||||
}, /* 4000 uG/LSB */
|
||||
.fs_avl[1] = {
|
||||
.gain = 292,
|
||||
.val = 0x01,
|
||||
}, /* 8000 uG/LSB */
|
||||
.fs_avl[2] = {
|
||||
.gain = 438,
|
||||
.val = 0x02,
|
||||
}, /* 12000 uG/LSB */
|
||||
.fs_avl[3] = {
|
||||
.gain = 584,
|
||||
.val = 0x03,
|
||||
}, /* 16000 uG/LSB */
|
||||
.fs_len = 4,
|
||||
},
|
||||
.pwr_table = {
|
||||
.reg = {
|
||||
.addr = 0x22,
|
||||
.mask = GENMASK(1, 0),
|
||||
},
|
||||
.off_val = 0x2,
|
||||
.on_val = 0x0,
|
||||
},
|
||||
.bdu = {
|
||||
.addr = 0x24,
|
||||
.mask = BIT(6),
|
||||
},
|
||||
.out = {
|
||||
.addr = 0x28,
|
||||
.len = 6,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static void st_lsm6dsx_shub_wait_complete(struct st_lsm6dsx_hw *hw)
|
||||
@ -517,6 +580,36 @@ st_lsm6dsx_shub_read_raw(struct iio_dev *iio_dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
st_lsm6dsx_shub_set_full_scale(struct st_lsm6dsx_sensor *sensor,
|
||||
u32 gain)
|
||||
{
|
||||
const struct st_lsm6dsx_fs_table_entry *fs_table;
|
||||
int i, err;
|
||||
|
||||
fs_table = &sensor->ext_info.settings->fs_table;
|
||||
if (!fs_table->reg.addr)
|
||||
return -ENOTSUPP;
|
||||
|
||||
for (i = 0; i < fs_table->fs_len; i++) {
|
||||
if (fs_table->fs_avl[i].gain == gain)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == fs_table->fs_len)
|
||||
return -EINVAL;
|
||||
|
||||
err = st_lsm6dsx_shub_write_with_mask(sensor, fs_table->reg.addr,
|
||||
fs_table->reg.mask,
|
||||
fs_table->fs_avl[i].val);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
sensor->gain = gain;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
st_lsm6dsx_shub_write_raw(struct iio_dev *iio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
@ -539,6 +632,9 @@ st_lsm6dsx_shub_write_raw(struct iio_dev *iio_dev,
|
||||
sensor->odr = val;
|
||||
break;
|
||||
}
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
err = st_lsm6dsx_shub_set_full_scale(sensor, val2);
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
break;
|
||||
|
@ -316,8 +316,7 @@ static int iio_scan_mask_set(struct iio_dev *indio_dev,
|
||||
const unsigned long *mask;
|
||||
unsigned long *trialmask;
|
||||
|
||||
trialmask = kcalloc(BITS_TO_LONGS(indio_dev->masklength),
|
||||
sizeof(*trialmask), GFP_KERNEL);
|
||||
trialmask = bitmap_zalloc(indio_dev->masklength, GFP_KERNEL);
|
||||
if (trialmask == NULL)
|
||||
return -ENOMEM;
|
||||
if (!indio_dev->masklength) {
|
||||
@ -687,6 +686,13 @@ static int iio_verify_update(struct iio_dev *indio_dev,
|
||||
bool scan_timestamp;
|
||||
unsigned int modes;
|
||||
|
||||
if (insert_buffer &&
|
||||
bitmap_empty(insert_buffer->scan_mask, indio_dev->masklength)) {
|
||||
dev_dbg(&indio_dev->dev,
|
||||
"At least one scan element must be enabled first\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(config, 0, sizeof(*config));
|
||||
config->watermark = ~0;
|
||||
|
||||
@ -1277,11 +1283,6 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
|
||||
|
||||
indio_dev->groups[indio_dev->groupcounter++] = &buffer->buffer_group;
|
||||
|
||||
if (buffer->scan_el_attrs != NULL) {
|
||||
attr = buffer->scan_el_attrs->attrs;
|
||||
while (*attr++ != NULL)
|
||||
attrcount_orig++;
|
||||
}
|
||||
attrcount = attrcount_orig;
|
||||
INIT_LIST_HEAD(&buffer->scan_el_dev_attr_list);
|
||||
channels = indio_dev->channels;
|
||||
@ -1319,9 +1320,6 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
|
||||
ret = -ENOMEM;
|
||||
goto error_free_scan_mask;
|
||||
}
|
||||
if (buffer->scan_el_attrs)
|
||||
memcpy(buffer->scan_el_group.attrs, buffer->scan_el_attrs,
|
||||
sizeof(buffer->scan_el_group.attrs[0])*attrcount_orig);
|
||||
attrn = attrcount_orig;
|
||||
|
||||
list_for_each_entry(p, &buffer->scan_el_dev_attr_list, l)
|
||||
|
@ -572,46 +572,46 @@ static ssize_t __iio_format_value(char *buf, size_t len, unsigned int type,
|
||||
|
||||
switch (type) {
|
||||
case IIO_VAL_INT:
|
||||
return snprintf(buf, len, "%d", vals[0]);
|
||||
return scnprintf(buf, len, "%d", vals[0]);
|
||||
case IIO_VAL_INT_PLUS_MICRO_DB:
|
||||
scale_db = true;
|
||||
/* fall through */
|
||||
case IIO_VAL_INT_PLUS_MICRO:
|
||||
if (vals[1] < 0)
|
||||
return snprintf(buf, len, "-%d.%06u%s", abs(vals[0]),
|
||||
return scnprintf(buf, len, "-%d.%06u%s", abs(vals[0]),
|
||||
-vals[1], scale_db ? " dB" : "");
|
||||
else
|
||||
return snprintf(buf, len, "%d.%06u%s", vals[0], vals[1],
|
||||
return scnprintf(buf, len, "%d.%06u%s", vals[0], vals[1],
|
||||
scale_db ? " dB" : "");
|
||||
case IIO_VAL_INT_PLUS_NANO:
|
||||
if (vals[1] < 0)
|
||||
return snprintf(buf, len, "-%d.%09u", abs(vals[0]),
|
||||
return scnprintf(buf, len, "-%d.%09u", abs(vals[0]),
|
||||
-vals[1]);
|
||||
else
|
||||
return snprintf(buf, len, "%d.%09u", vals[0], vals[1]);
|
||||
return scnprintf(buf, len, "%d.%09u", vals[0], vals[1]);
|
||||
case IIO_VAL_FRACTIONAL:
|
||||
tmp = div_s64((s64)vals[0] * 1000000000LL, vals[1]);
|
||||
tmp1 = vals[1];
|
||||
tmp0 = (int)div_s64_rem(tmp, 1000000000, &tmp1);
|
||||
return snprintf(buf, len, "%d.%09u", tmp0, abs(tmp1));
|
||||
return scnprintf(buf, len, "%d.%09u", tmp0, abs(tmp1));
|
||||
case IIO_VAL_FRACTIONAL_LOG2:
|
||||
tmp = shift_right((s64)vals[0] * 1000000000LL, vals[1]);
|
||||
tmp0 = (int)div_s64_rem(tmp, 1000000000LL, &tmp1);
|
||||
return snprintf(buf, len, "%d.%09u", tmp0, abs(tmp1));
|
||||
return scnprintf(buf, len, "%d.%09u", tmp0, abs(tmp1));
|
||||
case IIO_VAL_INT_MULTIPLE:
|
||||
{
|
||||
int i;
|
||||
int l = 0;
|
||||
|
||||
for (i = 0; i < size; ++i) {
|
||||
l += snprintf(&buf[l], len - l, "%d ", vals[i]);
|
||||
l += scnprintf(&buf[l], len - l, "%d ", vals[i]);
|
||||
if (l >= len)
|
||||
break;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
case IIO_VAL_CHAR:
|
||||
return snprintf(buf, len, "%c", (char)vals[0]);
|
||||
return scnprintf(buf, len, "%c", (char)vals[0]);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -682,10 +682,10 @@ static ssize_t iio_format_avail_list(char *buf, const int *vals,
|
||||
if (len >= PAGE_SIZE)
|
||||
return -EFBIG;
|
||||
if (i < length - 1)
|
||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len,
|
||||
" ");
|
||||
else
|
||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len,
|
||||
"\n");
|
||||
if (len >= PAGE_SIZE)
|
||||
return -EFBIG;
|
||||
@ -698,10 +698,10 @@ static ssize_t iio_format_avail_list(char *buf, const int *vals,
|
||||
if (len >= PAGE_SIZE)
|
||||
return -EFBIG;
|
||||
if (i < length / 2 - 1)
|
||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len,
|
||||
" ");
|
||||
else
|
||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len,
|
||||
"\n");
|
||||
if (len >= PAGE_SIZE)
|
||||
return -EFBIG;
|
||||
@ -725,10 +725,10 @@ static ssize_t iio_format_avail_range(char *buf, const int *vals, int type)
|
||||
if (len >= PAGE_SIZE)
|
||||
return -EFBIG;
|
||||
if (i < 2)
|
||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len,
|
||||
" ");
|
||||
else
|
||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len,
|
||||
"]\n");
|
||||
if (len >= PAGE_SIZE)
|
||||
return -EFBIG;
|
||||
@ -741,10 +741,10 @@ static ssize_t iio_format_avail_range(char *buf, const int *vals, int type)
|
||||
if (len >= PAGE_SIZE)
|
||||
return -EFBIG;
|
||||
if (i < 2)
|
||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len,
|
||||
" ");
|
||||
else
|
||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len,
|
||||
"]\n");
|
||||
if (len >= PAGE_SIZE)
|
||||
return -EFBIG;
|
||||
@ -1552,17 +1552,6 @@ static void devm_iio_device_release(struct device *dev, void *res)
|
||||
iio_device_free(*(struct iio_dev **)res);
|
||||
}
|
||||
|
||||
int devm_iio_device_match(struct device *dev, void *res, void *data)
|
||||
{
|
||||
struct iio_dev **r = res;
|
||||
if (!r || !*r) {
|
||||
WARN_ON(!r || !*r);
|
||||
return 0;
|
||||
}
|
||||
return *r == data;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_iio_device_match);
|
||||
|
||||
/**
|
||||
* devm_iio_device_alloc - Resource-managed iio_device_alloc()
|
||||
* @dev: Device to allocate iio_dev for
|
||||
@ -1571,9 +1560,6 @@ EXPORT_SYMBOL_GPL(devm_iio_device_match);
|
||||
* Managed iio_device_alloc. iio_dev allocated with this function is
|
||||
* automatically freed on driver detach.
|
||||
*
|
||||
* If an iio_dev allocated with this function needs to be freed separately,
|
||||
* devm_iio_device_free() must be used.
|
||||
*
|
||||
* RETURNS:
|
||||
* Pointer to allocated iio_dev on success, NULL on failure.
|
||||
*/
|
||||
@ -1598,23 +1584,6 @@ struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_iio_device_alloc);
|
||||
|
||||
/**
|
||||
* devm_iio_device_free - Resource-managed iio_device_free()
|
||||
* @dev: Device this iio_dev belongs to
|
||||
* @iio_dev: the iio_dev associated with the device
|
||||
*
|
||||
* Free iio_dev allocated with devm_iio_device_alloc().
|
||||
*/
|
||||
void devm_iio_device_free(struct device *dev, struct iio_dev *iio_dev)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = devres_release(dev, devm_iio_device_release,
|
||||
devm_iio_device_match, iio_dev);
|
||||
WARN_ON(rc);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_iio_device_free);
|
||||
|
||||
/**
|
||||
* iio_chrdev_open() - chrdev file open for buffer access and ioctls
|
||||
* @inode: Inode structure for identifying the device in the file system
|
||||
@ -1717,6 +1686,9 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!indio_dev->info)
|
||||
return -EINVAL;
|
||||
|
||||
indio_dev->driver_module = this_mod;
|
||||
/* If the calling driver did not initialize of_node, do it here */
|
||||
if (!indio_dev->dev.of_node && indio_dev->dev.parent)
|
||||
@ -1729,9 +1701,6 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!indio_dev->info)
|
||||
return -EINVAL;
|
||||
|
||||
/* configure elements for the chrdev */
|
||||
indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id);
|
||||
|
||||
@ -1836,23 +1805,6 @@ int __devm_iio_device_register(struct device *dev, struct iio_dev *indio_dev,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__devm_iio_device_register);
|
||||
|
||||
/**
|
||||
* devm_iio_device_unregister - Resource-managed iio_device_unregister()
|
||||
* @dev: Device this iio_dev belongs to
|
||||
* @indio_dev: the iio_dev associated with the device
|
||||
*
|
||||
* Unregister iio_dev registered with devm_iio_device_register().
|
||||
*/
|
||||
void devm_iio_device_unregister(struct device *dev, struct iio_dev *indio_dev)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = devres_release(dev, devm_iio_device_unreg,
|
||||
devm_iio_device_match, indio_dev);
|
||||
WARN_ON(rc);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_iio_device_unregister);
|
||||
|
||||
/**
|
||||
* iio_device_claim_direct_mode - Keep device in direct mode
|
||||
* @indio_dev: the iio_dev associated with the device
|
||||
|
@ -585,18 +585,6 @@ static void devm_iio_trigger_release(struct device *dev, void *res)
|
||||
iio_trigger_free(*(struct iio_trigger **)res);
|
||||
}
|
||||
|
||||
static int devm_iio_trigger_match(struct device *dev, void *res, void *data)
|
||||
{
|
||||
struct iio_trigger **r = res;
|
||||
|
||||
if (!r || !*r) {
|
||||
WARN_ON(!r || !*r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return *r == data;
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_iio_trigger_alloc - Resource-managed iio_trigger_alloc()
|
||||
* @dev: Device to allocate iio_trigger for
|
||||
@ -608,9 +596,6 @@ static int devm_iio_trigger_match(struct device *dev, void *res, void *data)
|
||||
* Managed iio_trigger_alloc. iio_trigger allocated with this function is
|
||||
* automatically freed on driver detach.
|
||||
*
|
||||
* If an iio_trigger allocated with this function needs to be freed separately,
|
||||
* devm_iio_trigger_free() must be used.
|
||||
*
|
||||
* RETURNS:
|
||||
* Pointer to allocated iio_trigger on success, NULL on failure.
|
||||
*/
|
||||
@ -640,23 +625,6 @@ struct iio_trigger *devm_iio_trigger_alloc(struct device *dev,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_iio_trigger_alloc);
|
||||
|
||||
/**
|
||||
* devm_iio_trigger_free - Resource-managed iio_trigger_free()
|
||||
* @dev: Device this iio_dev belongs to
|
||||
* @iio_trig: the iio_trigger associated with the device
|
||||
*
|
||||
* Free iio_trigger allocated with devm_iio_trigger_alloc().
|
||||
*/
|
||||
void devm_iio_trigger_free(struct device *dev, struct iio_trigger *iio_trig)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = devres_release(dev, devm_iio_trigger_release,
|
||||
devm_iio_trigger_match, iio_trig);
|
||||
WARN_ON(rc);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_iio_trigger_free);
|
||||
|
||||
static void devm_iio_trigger_unreg(struct device *dev, void *res)
|
||||
{
|
||||
iio_trigger_unregister(*(struct iio_trigger **)res);
|
||||
@ -673,9 +641,6 @@ static void devm_iio_trigger_unreg(struct device *dev, void *res)
|
||||
* calls iio_trigger_register() internally. Refer to that function for more
|
||||
* information.
|
||||
*
|
||||
* If an iio_trigger registered with this function needs to be unregistered
|
||||
* separately, devm_iio_trigger_unregister() must be used.
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, negative error number on failure.
|
||||
*/
|
||||
@ -701,24 +666,6 @@ int __devm_iio_trigger_register(struct device *dev,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__devm_iio_trigger_register);
|
||||
|
||||
/**
|
||||
* devm_iio_trigger_unregister - Resource-managed iio_trigger_unregister()
|
||||
* @dev: device this iio_trigger belongs to
|
||||
* @trig_info: the trigger associated with the device
|
||||
*
|
||||
* Unregister trigger registered with devm_iio_trigger_register().
|
||||
*/
|
||||
void devm_iio_trigger_unregister(struct device *dev,
|
||||
struct iio_trigger *trig_info)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = devres_release(dev, devm_iio_trigger_unreg, devm_iio_trigger_match,
|
||||
trig_info);
|
||||
WARN_ON(rc);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_iio_trigger_unregister);
|
||||
|
||||
bool iio_trigger_using_own(struct iio_dev *indio_dev)
|
||||
{
|
||||
return indio_dev->trig->attached_own_device;
|
||||
|
@ -360,18 +360,6 @@ static void devm_iio_channel_free(struct device *dev, void *res)
|
||||
iio_channel_release(channel);
|
||||
}
|
||||
|
||||
static int devm_iio_channel_match(struct device *dev, void *res, void *data)
|
||||
{
|
||||
struct iio_channel **r = res;
|
||||
|
||||
if (!r || !*r) {
|
||||
WARN_ON(!r || !*r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return *r == data;
|
||||
}
|
||||
|
||||
struct iio_channel *devm_iio_channel_get(struct device *dev,
|
||||
const char *channel_name)
|
||||
{
|
||||
@ -394,13 +382,6 @@ struct iio_channel *devm_iio_channel_get(struct device *dev,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_iio_channel_get);
|
||||
|
||||
void devm_iio_channel_release(struct device *dev, struct iio_channel *channel)
|
||||
{
|
||||
WARN_ON(devres_release(dev, devm_iio_channel_free,
|
||||
devm_iio_channel_match, channel));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_iio_channel_release);
|
||||
|
||||
struct iio_channel *iio_channel_get_all(struct device *dev)
|
||||
{
|
||||
const char *name;
|
||||
@ -514,14 +495,6 @@ struct iio_channel *devm_iio_channel_get_all(struct device *dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_iio_channel_get_all);
|
||||
|
||||
void devm_iio_channel_release_all(struct device *dev,
|
||||
struct iio_channel *channels)
|
||||
{
|
||||
WARN_ON(devres_release(dev, devm_iio_channel_free_all,
|
||||
devm_iio_channel_match, channels));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_iio_channel_release_all);
|
||||
|
||||
static int iio_channel_read(struct iio_channel *chan, int *val, int *val2,
|
||||
enum iio_chan_info_enum info)
|
||||
{
|
||||
|
@ -213,13 +213,24 @@ static const struct iio_info isl29125_info = {
|
||||
.attrs = &isl29125_attribute_group,
|
||||
};
|
||||
|
||||
static int isl29125_buffer_preenable(struct iio_dev *indio_dev)
|
||||
static int isl29125_buffer_postenable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct isl29125_data *data = iio_priv(indio_dev);
|
||||
int err;
|
||||
|
||||
err = iio_triggered_buffer_postenable(indio_dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
data->conf1 |= ISL29125_MODE_RGB;
|
||||
return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
|
||||
err = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
|
||||
data->conf1);
|
||||
if (err) {
|
||||
iio_triggered_buffer_predisable(indio_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int isl29125_buffer_predisable(struct iio_dev *indio_dev)
|
||||
@ -227,19 +238,18 @@ static int isl29125_buffer_predisable(struct iio_dev *indio_dev)
|
||||
struct isl29125_data *data = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
ret = iio_triggered_buffer_predisable(indio_dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
data->conf1 &= ~ISL29125_MODE_MASK;
|
||||
data->conf1 |= ISL29125_MODE_PD;
|
||||
return i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
|
||||
ret = i2c_smbus_write_byte_data(data->client, ISL29125_CONF1,
|
||||
data->conf1);
|
||||
|
||||
iio_triggered_buffer_predisable(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct iio_buffer_setup_ops isl29125_buffer_setup_ops = {
|
||||
.preenable = isl29125_buffer_preenable,
|
||||
.postenable = &iio_triggered_buffer_postenable,
|
||||
.postenable = isl29125_buffer_postenable,
|
||||
.predisable = isl29125_buffer_predisable,
|
||||
};
|
||||
|
||||
|
@ -1263,7 +1263,7 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p)
|
||||
|
||||
if (mask & LTR501_STATUS_ALS_RDY) {
|
||||
ret = regmap_bulk_read(data->regmap, LTR501_ALS_DATA1,
|
||||
(u8 *)als_buf, sizeof(als_buf));
|
||||
als_buf, sizeof(als_buf));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (test_bit(0, indio_dev->active_scan_mask))
|
||||
|
@ -31,8 +31,8 @@ static int st_uvis25_i2c_probe(struct i2c_client *client,
|
||||
|
||||
regmap = devm_regmap_init_i2c(client, &st_uvis25_i2c_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&client->dev, "Failed to register i2c regmap %d\n",
|
||||
(int)PTR_ERR(regmap));
|
||||
dev_err(&client->dev, "Failed to register i2c regmap %ld\n",
|
||||
PTR_ERR(regmap));
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
|
@ -31,8 +31,8 @@ static int st_uvis25_spi_probe(struct spi_device *spi)
|
||||
|
||||
regmap = devm_regmap_init_spi(spi, &st_uvis25_spi_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&spi->dev, "Failed to register spi regmap %d\n",
|
||||
(int)PTR_ERR(regmap));
|
||||
dev_err(&spi->dev, "Failed to register spi regmap %ld\n",
|
||||
PTR_ERR(regmap));
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@
|
||||
#define TSL2563_TIMING_GAIN16 0x10
|
||||
#define TSL2563_TIMING_GAIN1 0x00
|
||||
|
||||
#define TSL2563_INT_DISBLED 0x00
|
||||
#define TSL2563_INT_DISABLED 0x00
|
||||
#define TSL2563_INT_LEVEL 0x10
|
||||
#define TSL2563_INT_PERSIST(n) ((n) & 0x0F)
|
||||
|
||||
|
@ -932,7 +932,7 @@ static ssize_t in_illuminance0_target_input_show(struct device *dev,
|
||||
{
|
||||
struct tsl2772_chip *chip = iio_priv(dev_to_iio_dev(dev));
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", chip->settings.als_cal_target);
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", chip->settings.als_cal_target);
|
||||
}
|
||||
|
||||
static ssize_t in_illuminance0_target_input_store(struct device *dev,
|
||||
@ -986,7 +986,7 @@ static ssize_t in_illuminance0_lux_table_show(struct device *dev,
|
||||
int offset = 0;
|
||||
|
||||
while (i < TSL2772_MAX_LUX_TABLE_SIZE) {
|
||||
offset += snprintf(buf + offset, PAGE_SIZE, "%u,%u,",
|
||||
offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%u,%u,",
|
||||
chip->tsl2772_device_lux[i].ch0,
|
||||
chip->tsl2772_device_lux[i].ch1);
|
||||
if (chip->tsl2772_device_lux[i].ch0 == 0) {
|
||||
@ -1000,7 +1000,7 @@ static ssize_t in_illuminance0_lux_table_show(struct device *dev,
|
||||
i++;
|
||||
}
|
||||
|
||||
offset += snprintf(buf + offset, PAGE_SIZE, "\n");
|
||||
offset += scnprintf(buf + offset, PAGE_SIZE - offset, "\n");
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
@ -83,6 +83,7 @@ struct vcnl4000_data {
|
||||
struct mutex vcnl4000_lock;
|
||||
struct vcnl4200_channel vcnl4200_al;
|
||||
struct vcnl4200_channel vcnl4200_ps;
|
||||
uint32_t near_level;
|
||||
};
|
||||
|
||||
struct vcnl4000_chip_spec {
|
||||
@ -343,6 +344,25 @@ static const struct vcnl4000_chip_spec vcnl4000_chip_spec_cfg[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static ssize_t vcnl4000_read_near_level(struct iio_dev *indio_dev,
|
||||
uintptr_t priv,
|
||||
const struct iio_chan_spec *chan,
|
||||
char *buf)
|
||||
{
|
||||
struct vcnl4000_data *data = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%u\n", data->near_level);
|
||||
}
|
||||
|
||||
static const struct iio_chan_spec_ext_info vcnl4000_ext_info[] = {
|
||||
{
|
||||
.name = "nearlevel",
|
||||
.shared = IIO_SEPARATE,
|
||||
.read = vcnl4000_read_near_level,
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec vcnl4000_channels[] = {
|
||||
{
|
||||
.type = IIO_LIGHT,
|
||||
@ -351,6 +371,7 @@ static const struct iio_chan_spec vcnl4000_channels[] = {
|
||||
}, {
|
||||
.type = IIO_PROXIMITY,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
||||
.ext_info = vcnl4000_ext_info,
|
||||
}
|
||||
};
|
||||
|
||||
@ -440,6 +461,10 @@ static int vcnl4000_probe(struct i2c_client *client,
|
||||
dev_dbg(&client->dev, "%s Ambient light/proximity sensor, Rev: %02x\n",
|
||||
data->chip_spec->prod, data->rev);
|
||||
|
||||
if (device_property_read_u32(&client->dev, "proximity-near-level",
|
||||
&data->near_level))
|
||||
data->near_level = 0;
|
||||
|
||||
indio_dev->dev.parent = &client->dev;
|
||||
indio_dev->info = &vcnl4000_info;
|
||||
indio_dev->channels = vcnl4000_channels;
|
||||
|
@ -746,7 +746,12 @@ static int ak8974_probe(struct i2c_client *i2c,
|
||||
ARRAY_SIZE(ak8974->regs),
|
||||
ak8974->regs);
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c->dev, "cannot get regulators\n");
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(&i2c->dev, "cannot get regulators: %d\n", ret);
|
||||
else
|
||||
dev_dbg(&i2c->dev,
|
||||
"regulators unavailable, deferring probe\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -22,8 +22,8 @@ static int bmc150_magn_spi_probe(struct spi_device *spi)
|
||||
|
||||
regmap = devm_regmap_init_spi(spi, &bmc150_magn_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&spi->dev, "Failed to register spi regmap %d\n",
|
||||
(int)PTR_ERR(regmap));
|
||||
dev_err(&spi->dev, "Failed to register spi regmap: %pe\n",
|
||||
regmap);
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
return bmc150_magn_probe(&spi->dev, regmap, spi->irq, id->name);
|
||||
|
@ -239,7 +239,7 @@ static int mmc35240_init(struct mmc35240_data *data)
|
||||
return ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, MMC35240_OTP_START_ADDR,
|
||||
(u8 *)otp_data, sizeof(otp_data));
|
||||
otp_data, sizeof(otp_data));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -295,7 +295,7 @@ static int mmc35240_read_measurement(struct mmc35240_data *data, __le16 buf[3])
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return regmap_bulk_read(data->regmap, MMC35240_REG_XOUT_L, (u8 *)buf,
|
||||
return regmap_bulk_read(data->regmap, MMC35240_REG_XOUT_L, buf,
|
||||
3 * sizeof(__le16));
|
||||
}
|
||||
|
||||
|
@ -506,8 +506,7 @@ int st_magn_common_probe(struct iio_dev *indio_dev)
|
||||
indio_dev->channels = mdata->sensor_settings->ch;
|
||||
indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
|
||||
|
||||
mdata->current_fullscale = (struct st_sensor_fullscale_avl *)
|
||||
&mdata->sensor_settings->fs.fs_avl[0];
|
||||
mdata->current_fullscale = &mdata->sensor_settings->fs.fs_avl[0];
|
||||
mdata->odr = mdata->sensor_settings->odr.odr_avl[0].hz;
|
||||
|
||||
err = st_sensors_init_sensor(indio_dev, NULL);
|
||||
|
@ -337,8 +337,7 @@ static int bmp280_read_temp(struct bmp280_data *data,
|
||||
__be32 tmp = 0;
|
||||
s32 adc_temp, comp_temp;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB,
|
||||
(u8 *) &tmp, 3);
|
||||
ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB, &tmp, 3);
|
||||
if (ret < 0) {
|
||||
dev_err(data->dev, "failed to read temperature\n");
|
||||
return ret;
|
||||
@ -377,8 +376,7 @@ static int bmp280_read_press(struct bmp280_data *data,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BMP280_REG_PRESS_MSB,
|
||||
(u8 *) &tmp, 3);
|
||||
ret = regmap_bulk_read(data->regmap, BMP280_REG_PRESS_MSB, &tmp, 3);
|
||||
if (ret < 0) {
|
||||
dev_err(data->dev, "failed to read pressure\n");
|
||||
return ret;
|
||||
@ -400,8 +398,8 @@ static int bmp280_read_press(struct bmp280_data *data,
|
||||
|
||||
static int bmp280_read_humid(struct bmp280_data *data, int *val, int *val2)
|
||||
{
|
||||
__be16 tmp;
|
||||
int ret;
|
||||
__be16 tmp = 0;
|
||||
s32 adc_humidity;
|
||||
u32 comp_humidity;
|
||||
|
||||
@ -410,8 +408,7 @@ static int bmp280_read_humid(struct bmp280_data *data, int *val, int *val2)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BMP280_REG_HUMIDITY_MSB,
|
||||
(u8 *) &tmp, 2);
|
||||
ret = regmap_bulk_read(data->regmap, BMP280_REG_HUMIDITY_MSB, &tmp, 2);
|
||||
if (ret < 0) {
|
||||
dev_err(data->dev, "failed to read humidity\n");
|
||||
return ret;
|
||||
@ -575,57 +572,38 @@ static int bmp280_write_raw(struct iio_dev *indio_dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t bmp280_show_avail(char *buf, const int *vals, const int n)
|
||||
static int bmp280_read_avail(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
const int **vals, int *type, int *length,
|
||||
long mask)
|
||||
{
|
||||
size_t len = 0;
|
||||
int i;
|
||||
struct bmp280_data *data = iio_priv(indio_dev);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", vals[i]);
|
||||
|
||||
buf[len - 1] = '\n';
|
||||
|
||||
return len;
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
|
||||
switch (chan->type) {
|
||||
case IIO_PRESSURE:
|
||||
*vals = data->chip_info->oversampling_press_avail;
|
||||
*length = data->chip_info->num_oversampling_press_avail;
|
||||
break;
|
||||
case IIO_TEMP:
|
||||
*vals = data->chip_info->oversampling_temp_avail;
|
||||
*length = data->chip_info->num_oversampling_temp_avail;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
*type = IIO_VAL_INT;
|
||||
return IIO_AVAIL_LIST;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t bmp280_show_temp_oversampling_avail(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct bmp280_data *data = iio_priv(dev_to_iio_dev(dev));
|
||||
|
||||
return bmp280_show_avail(buf, data->chip_info->oversampling_temp_avail,
|
||||
data->chip_info->num_oversampling_temp_avail);
|
||||
}
|
||||
|
||||
static ssize_t bmp280_show_press_oversampling_avail(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct bmp280_data *data = iio_priv(dev_to_iio_dev(dev));
|
||||
|
||||
return bmp280_show_avail(buf, data->chip_info->oversampling_press_avail,
|
||||
data->chip_info->num_oversampling_press_avail);
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(in_temp_oversampling_ratio_available,
|
||||
S_IRUGO, bmp280_show_temp_oversampling_avail, NULL, 0);
|
||||
|
||||
static IIO_DEVICE_ATTR(in_pressure_oversampling_ratio_available,
|
||||
S_IRUGO, bmp280_show_press_oversampling_avail, NULL, 0);
|
||||
|
||||
static struct attribute *bmp280_attributes[] = {
|
||||
&iio_dev_attr_in_temp_oversampling_ratio_available.dev_attr.attr,
|
||||
&iio_dev_attr_in_pressure_oversampling_ratio_available.dev_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group bmp280_attrs_group = {
|
||||
.attrs = bmp280_attributes,
|
||||
};
|
||||
|
||||
static const struct iio_info bmp280_info = {
|
||||
.read_raw = &bmp280_read_raw,
|
||||
.read_avail = &bmp280_read_avail,
|
||||
.write_raw = &bmp280_write_raw,
|
||||
.attrs = &bmp280_attrs_group,
|
||||
};
|
||||
|
||||
static int bmp280_chip_config(struct bmp280_data *data)
|
||||
@ -713,7 +691,7 @@ static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
|
||||
unsigned int ctrl;
|
||||
|
||||
if (data->use_eoc)
|
||||
init_completion(&data->done);
|
||||
reinit_completion(&data->done);
|
||||
|
||||
ret = regmap_write(data->regmap, BMP280_REG_CTRL_MEAS, ctrl_meas);
|
||||
if (ret)
|
||||
@ -752,14 +730,14 @@ static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
|
||||
|
||||
static int bmp180_read_adc_temp(struct bmp280_data *data, int *val)
|
||||
{
|
||||
__be16 tmp;
|
||||
int ret;
|
||||
__be16 tmp = 0;
|
||||
|
||||
ret = bmp180_measure(data, BMP180_MEAS_TEMP);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB, (u8 *)&tmp, 2);
|
||||
ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB, &tmp, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -856,7 +834,7 @@ static int bmp180_read_adc_press(struct bmp280_data *data, int *val)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB, (u8 *)&tmp, 3);
|
||||
ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB, &tmp, 3);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -965,10 +943,12 @@ static int bmp085_fetch_eoc_irq(struct device *dev,
|
||||
|
||||
irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
|
||||
if (irq_trig != IRQF_TRIGGER_RISING) {
|
||||
dev_err(dev, "non-rising trigger given for EOC interrupt, "
|
||||
"trying to enforce it\n");
|
||||
dev_err(dev, "non-rising trigger given for EOC interrupt, trying to enforce it\n");
|
||||
irq_trig = IRQF_TRIGGER_RISING;
|
||||
}
|
||||
|
||||
init_completion(&data->done);
|
||||
|
||||
ret = devm_request_threaded_irq(dev,
|
||||
irq,
|
||||
bmp085_eoc_irq,
|
||||
@ -1082,9 +1062,9 @@ int bmp280_common_probe(struct device *dev,
|
||||
usleep_range(data->start_up_time, data->start_up_time + 100);
|
||||
|
||||
/* Bring chip out of reset if there is an assigned GPIO line */
|
||||
gpiod = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
|
||||
gpiod = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
|
||||
/* Deassert the signal */
|
||||
if (!IS_ERR(gpiod)) {
|
||||
if (gpiod) {
|
||||
dev_info(dev, "release reset\n");
|
||||
gpiod_set_value(gpiod, 0);
|
||||
}
|
||||
|
@ -683,8 +683,7 @@ EXPORT_SYMBOL(st_press_get_settings);
|
||||
int st_press_common_probe(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct st_sensor_data *press_data = iio_priv(indio_dev);
|
||||
struct st_sensors_platform_data *pdata =
|
||||
(struct st_sensors_platform_data *)press_data->dev->platform_data;
|
||||
struct st_sensors_platform_data *pdata = dev_get_platdata(press_data->dev);
|
||||
int err;
|
||||
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
@ -708,9 +707,7 @@ int st_press_common_probe(struct iio_dev *indio_dev)
|
||||
indio_dev->channels = press_data->sensor_settings->ch;
|
||||
indio_dev->num_channels = press_data->sensor_settings->num_ch;
|
||||
|
||||
press_data->current_fullscale =
|
||||
(struct st_sensor_fullscale_avl *)
|
||||
&press_data->sensor_settings->fs.fs_avl[0];
|
||||
press_data->current_fullscale = &press_data->sensor_settings->fs.fs_avl[0];
|
||||
|
||||
press_data->odr = press_data->sensor_settings->odr.odr_avl[0].hz;
|
||||
|
||||
|
@ -101,6 +101,19 @@ config SRF04
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called srf04.
|
||||
|
||||
config SX9310
|
||||
tristate "SX9310/SX9311 Semtech proximity sensor"
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
select REGMAP_I2C
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here to build a driver for Semtech's SX9310/SX9311 capacitive
|
||||
proximity/button sensor.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called sx9310.
|
||||
|
||||
config SX9500
|
||||
tristate "SX9500 Semtech proximity sensor"
|
||||
select IIO_BUFFER
|
||||
|
@ -12,6 +12,7 @@ obj-$(CONFIG_PING) += ping.o
|
||||
obj-$(CONFIG_RFD77402) += rfd77402.o
|
||||
obj-$(CONFIG_SRF04) += srf04.o
|
||||
obj-$(CONFIG_SRF08) += srf08.o
|
||||
obj-$(CONFIG_SX9310) += sx9310.o
|
||||
obj-$(CONFIG_SX9500) += sx9500.o
|
||||
obj-$(CONFIG_VL53L0X_I2C) += vl53l0x-i2c.o
|
||||
|
||||
|
1069
drivers/iio/proximity/sx9310.c
Normal file
1069
drivers/iio/proximity/sx9310.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -390,8 +390,8 @@ static struct ltc2983_custom_sensor *__ltc2983_custom_sensor_new(
|
||||
* For custom steinhart, the full u32 is taken. For all the others
|
||||
* the MSB is discarded.
|
||||
*/
|
||||
const u8 n_size = (is_steinhart == true) ? 4 : 3;
|
||||
const u8 e_size = (is_steinhart == true) ? sizeof(u32) : sizeof(u64);
|
||||
const u8 n_size = is_steinhart ? 4 : 3;
|
||||
const u8 e_size = is_steinhart ? sizeof(u32) : sizeof(u64);
|
||||
|
||||
n_entries = of_property_count_elems_of_size(np, propname, e_size);
|
||||
/* n_entries must be an even number */
|
||||
|
@ -4,7 +4,7 @@
|
||||
*
|
||||
* Copyright (C) Intuitive Aerial AB
|
||||
* Written by Marten Svanfeldt, marten@intuitiveaerial.com
|
||||
* Copyright (C) 2012, Analog Device Inc.
|
||||
* Copyright (C) 2012, Analog Devices Inc.
|
||||
* Author: Lars-Peter Clausen <lars@metafoo.de>
|
||||
* Copyright (C) 2015, Intel Corporation
|
||||
*/
|
||||
|
@ -34,7 +34,7 @@ turned on or off (if possible) via sysfs interfaces.
|
||||
fifo / ring buffers on the sensor chip. These greatly reduce the load
|
||||
on the host CPU by buffering relatively large numbers of data samples
|
||||
based on an internal sampling clock. Examples include VTI SCA3000
|
||||
series and Analog Device ADXL345 accelerometers. Each buffer supports
|
||||
series and Analog Devices ADXL345 accelerometers. Each buffer supports
|
||||
polling to establish when data is available.
|
||||
|
||||
* Trigger and software buffer support. In many data analysis
|
||||
|
@ -11,9 +11,13 @@
|
||||
#ifndef ADI_AXI_COMMON_H_
|
||||
#define ADI_AXI_COMMON_H_
|
||||
|
||||
#define ADI_AXI_REG_VERSION 0x0000
|
||||
#define ADI_AXI_REG_VERSION 0x0000
|
||||
|
||||
#define ADI_AXI_PCORE_VER(major, minor, patch) \
|
||||
(((major) << 16) | ((minor) << 8) | (patch))
|
||||
|
||||
#define ADI_AXI_PCORE_VER_MAJOR(version) (((version) >> 16) & 0xff)
|
||||
#define ADI_AXI_PCORE_VER_MINOR(version) (((version) >> 8) & 0xff)
|
||||
#define ADI_AXI_PCORE_VER_PATCH(version) ((version) & 0xff)
|
||||
|
||||
#endif /* ADI_AXI_COMMON_H_ */
|
||||
|
@ -133,62 +133,4 @@ void ad_sd_cleanup_buffer_and_trigger(struct iio_dev *indio_dev);
|
||||
|
||||
int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig);
|
||||
|
||||
#define __AD_SD_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
|
||||
_storagebits, _shift, _extend_name, _type, _mask_all) \
|
||||
{ \
|
||||
.type = (_type), \
|
||||
.differential = (_channel2 == -1 ? 0 : 1), \
|
||||
.indexed = 1, \
|
||||
.channel = (_channel1), \
|
||||
.channel2 = (_channel2), \
|
||||
.address = (_address), \
|
||||
.extend_name = (_extend_name), \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||
BIT(IIO_CHAN_INFO_OFFSET), \
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
||||
.info_mask_shared_by_all = _mask_all, \
|
||||
.scan_index = (_si), \
|
||||
.scan_type = { \
|
||||
.sign = 'u', \
|
||||
.realbits = (_bits), \
|
||||
.storagebits = (_storagebits), \
|
||||
.shift = (_shift), \
|
||||
.endianness = IIO_BE, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define AD_SD_DIFF_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
|
||||
_storagebits, _shift) \
|
||||
__AD_SD_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
|
||||
_storagebits, _shift, NULL, IIO_VOLTAGE, \
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ))
|
||||
|
||||
#define AD_SD_SHORTED_CHANNEL(_si, _channel, _address, _bits, \
|
||||
_storagebits, _shift) \
|
||||
__AD_SD_CHANNEL(_si, _channel, _channel, _address, _bits, \
|
||||
_storagebits, _shift, "shorted", IIO_VOLTAGE, \
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ))
|
||||
|
||||
#define AD_SD_CHANNEL(_si, _channel, _address, _bits, \
|
||||
_storagebits, _shift) \
|
||||
__AD_SD_CHANNEL(_si, _channel, -1, _address, _bits, \
|
||||
_storagebits, _shift, NULL, IIO_VOLTAGE, \
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ))
|
||||
|
||||
#define AD_SD_CHANNEL_NO_SAMP_FREQ(_si, _channel, _address, _bits, \
|
||||
_storagebits, _shift) \
|
||||
__AD_SD_CHANNEL(_si, _channel, -1, _address, _bits, \
|
||||
_storagebits, _shift, NULL, IIO_VOLTAGE, 0)
|
||||
|
||||
#define AD_SD_TEMP_CHANNEL(_si, _address, _bits, _storagebits, _shift) \
|
||||
__AD_SD_CHANNEL(_si, 0, -1, _address, _bits, \
|
||||
_storagebits, _shift, NULL, IIO_TEMP, \
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ))
|
||||
|
||||
#define AD_SD_SUPPLY_CHANNEL(_si, _channel, _address, _bits, _storagebits, \
|
||||
_shift) \
|
||||
__AD_SD_CHANNEL(_si, _channel, -1, _address, _bits, \
|
||||
_storagebits, _shift, "supply", IIO_VOLTAGE, \
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ))
|
||||
|
||||
#endif
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user