IIO: New device support, features and cleanup for 6.16 - take 2
Note - last minute rebase was to drop a typo patch that I'd accidentally picked up (in the microblaze arch Kconfig) Take 2 is due to that rebase messing up some fixes tags that were referring to patches after that point. There is a known merge conflict due to changes in neighbouring lines. Stephen's resolution in linux-next is: https://lore.kernel.org/linux-next/20250506155728.65605bae@canb.auug.org.au/ Added 3 named IIO reviewers to MAINTAINERS. This is a reflection of those who have been doing much of this work for some time. Lars-Peter is removed from the entry having moved on to other topics. Thanks Nuno, David and Andy for stepping up and Lars-Peter for all your hard work in the past! Includes the usual mix of new device support, features and general cleanup. This time we also have some tree wide changes. - Rip out the iio_device_claim_direct_scoped() as it proved hard to work with. This series includes quite a few related cleanups such as use of guard or factoring code out to allow direct returns. - Switch from iio_device_claim/release_direct_mode() to new iio_device_claim/release_direct() which is structured so that sparse can warn on failed releases. There were a few false positives but those were mostly in code that benefited from being cleaned up as part of this process. - Introduce iio_push_to_buffers_with_ts() to replace the _timestamp() version over time. This version takes the size of the supplied buffer which the core checks is at least as big as expected by calculation from channel descriptions of those channels enabled. Use this in an initial set of drivers. - Add macros for IIO_DECLARE_BUFFER_WITH_TS() and IIO_DECLARE_DMA_BUFFER_WITH_TS() to avoid lots of fiddly code to ensure correctly aligned buffers for timestamps being added onto the end of channel data. New device support ------------------ adi,ad3530r - New driver for AD3530, AD3530R, AD3531 and AD3531R DACs with programmable gain controls. R variants have internal references. adi,ad7476 - Add support (dt compatible only) for the Rohm BU79100G ADC which is fully compatible with the ti,ads7866. adi,ad7606 - Support ad7606c-16 and ad7606c-18 devices. Includes switch to dynamic channel information allocation. adi,ad7380 - Add support for the AD7389-4 dfrobot,sen0322 - New driver for this oxygen sensor. mediatek,mt2701-auxadc - Add binding for MT6893 which is fully compatible with already supported MT8173. meson-saradc - Support the GXLX SoCs. Mostly this is a workaround for some unrelated clock control bits found in the ADC register map. nuvoton,nct7201 - New driver for NCT7201 and NCT7202 I2C ADCs. rohm,bd79124 - New driver for this 12-bit, 8-channel SAR ADC. - Switch to new set_rv etc gpio callbacks that were added in 6.15. rohm,bd79703 - Add support for BD79700, BD79701 and BD79702 DACs that have subsets of functionality of the already supported bd79703. Included making this driver suitable for support device variants. st,stm32-lptimer - Add support for stm32pm25 to this trigger. Features -------- Beyond IIO - Property iterator for named children. core - Enable writes for 64 bit integers used for standard IIO ABI elements. Previously these could be read only. - Helper library that should avoid code duplication for simpler ADC bindings that have a child node per channel. - Enforce that IIO_DMA_MINALIGN is always at least 8 (almost always true and simplifies code on all significant architectures) core/backend - Add support to control source of data - useful when the HDL includes things like generated ramps for testing purposes. Enable this for adi-axi-dac adi,ad3552-hs - Add debugfs related callbacks to allow debug access to register contents. adi,ad4000 - Support SPI offload with appropriate FPGA firmware along with improving documentation. adi,ad7293 - Add support for external reference voltage. adi,ad7606 - Support SPI offload. adi,ad7768-1 - Support reset GPIO. adi,admv8818 - Support filter frequencies beyond 2^32. adi,adxl345 - Add single and double tap events. hid-sensor-prox - Support 16-bit report sizes as seen on some Intel platforms. invensense,icm42600 - Enable use of named interrupts to avoid problems with some wiring choices. Get the interrupt by name, but fallback to previous assumption on the first being INT1 if no names are supplied. microchip,mcp3911 - Add reset gpio support. rohm,bh7150 - Add reset gpio support. st,stm32 - Add support to control oversampling. ti,adc128s052 - Add support for ROHM BD79104 which is early compatible with the TI parts already supported by this driver. Includes some general driver cleanup and a separate dt binding. - Simplify reference voltage handling by assuming it is fixed after enabling the supply. winsen,mhz19b - New driver for this C02 sensor. Cleanup and minor fixes ----------------------- dt-bindings - Correct indentation and style for DTS examples. - Use unevalutateProperties for SPI devices instead of additionalProperties to allow generic SPI properties from spi-peripheral-props.yaml ABI Docs - Add missing docs for sampling_frequency when it applies only to events. Treewide - Various minor tweaks, comment fixes and similar. - Sort TI ADCs in Kconfig that had gotten out of order. - Switch various drives that provide GPIO chip functionality to the new callbacks with return values. - Standardize on { } formatting for all array sentinels. - Make use of aligned_s64 in a few places to replace either wrong types or manually defined equivalents. - Drop places where spi bits_per_word is set to 8 because that is the default anyway. adi,ad_sigma_delta library - Avoid a potential use of uninitialized data if reg_size has a value that is not supported (no drivers hit this but it is reasonable hardening) adi,ad4030 - Add error checking for scan types and no longer store it in state. - Rework code to reduce duplication. - Move setting the mode from buffer preenable() to update_scan_mode(), better matching expected semantics of the two different callbacks. - Improve data marshalling comments. adi,ad4695 - Use u16 for buffer elements as oversampling is not yet supported except with SPI offload (which doesn't use this path). adi,ad5592r - Clean up destruction of mutexes. - Use lock guards to simplify code (later patch fixes a missed unlock) adi,ad5933 - Correct some incorrect settling times. adi,ad7091 - Deduplicate handling of writable vs volatile registers as they are the inverse of each other for this device. adi,ad7124 - Fix 3db Filter frequency. - Remove ability to directly write the filter frequency (which was broken) - Register naming improvements. adi,ad7606 - Add a missing return value check. - Fill in max sampling rates for all chips. - Use devm_mutex_init() - Fix up some kernel-doc formatting issues. - Remove some camel case that snuck in. - Drop setting address field in channels as easily established from other fields. - Drop unnecessary parameter to ad76060_scale_setup_cb_t. adi,ad7768-1 - Convert to regmap. - Factor out buffer allocation. - Tidy up headers. adi,ad7944 - Stop setting bits_per_word in SPI xfers with no data. adi,ad9832 - Add of_device_id table rather than just relying on fallbacks. - Use FIELD_PREP() to set values of fields. adi,admv1013 - Cleanup a pointless ternary. adi,admv8818 - Fix up LPF Band 5 frequency which was slightly wrong. - Fix an integer overflow. - Fix range calculation adi,adt7316 - Replace irqd_get_trigger_type(irq_get_irq_data()) with simpler irq_get_trigger_type() adi,adxl345 - Use regmap cache instead of various state variables that were there to reduce bus accesses. - Make regmap return value checking consistent across all call sites. adi,axi-dac - Add a check on number of channels (0 to 15 valid) allwinner,sun20i - Use new adc-helpers to replace local parsing code for channel nodes. bosch,bmp290 - Move to local variables for sensor data marshalling removing the need for a messy definition that has to work for all supported parts. Follow up fix adds a missing initialization. dynaimage,al3010 and dynaimage,al3320a - Various minor cleanup to bring these drivers inline with reviewed feedback given on a new driver. - Fix an error path in which power down is not called when it should be. - Switch to regmap. google,cros_ec - Fix up a flexible array in middle of structure warning. - Flush fifo when changing the timeout to avoid potential long wait for samples. hid-sensor-rotation - Remove an __aligned(16) marking that doesn't seem to be justified. kionix,kxcjk-1013 - Deduplicate code for setting up interrupts. microchip,mcp3911 - Fix handling of conversion results register which differs across supported devices. idt,zopt2201 - Avoid duplicating register lists as all volatile registers are the inverse of writeable registers on this device. renesas,rzg2l - Use new adc-helpers to replace local parsing code for channel nodes. ti,ads1298 - Fix a missing Kconfig dependency. -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEEbilms4eEBlKRJoGxVIU0mcT0FogFAmgt1EgRHGppYzIzQGtl cm5lbC5vcmcACgkQVIU0mcT0Foii3g//bZJT2/rHGIkU/MKUsYQCZGh5ux7X59Kk DT8R7i8RYg2dshbtkkHUn/S6yC3OX84q3Legzy8TtHkPvGMK1NSwWCrn2cqkCZdG 4kksfq3P41FmRrpSfm4p+WSAD9nYzA/LToSLdwGIOa44lKxlCElBgsIDz/HxwXLB N08H5jniST+cmSWAkkxCj15jcKXGtuIUS3XSCffwlzQZNPHp7guk4u+5EiUaPwvy X75iZ6SthUo9GfE6QyhE4rdOceix6S5wsQrKVpGKB7ZuQbXYQxlvNVt/l5p6MGdY teoqB7CyUADD1yHZp9L85+JSqjbodxm5a/Y9b0wQKHV33dxphEVZeli9t+VZYg6K fSM5xq0Cmt0msXLGRgB1uvZcEfj+vlkn7SN9nyyfTN2nXoac1E/MYCEiCLMhOj6D jxwc1aQDwaT+f6U6mRyRab2+TPea7AOv81x0MyRclOArqY4NCOPIG+XvC2nouYXk 9MSyK4FIysbINjenFCZdpdibp3HKWGqc8rTv3NWrx7CejAYQoEkYW5WA9qyzy/I8 8gDbcQskcYcehrI8ztc1ratfKl5k0QJPCgcLvuTpxK3PkQCgX+dGnL1EXW7D4BRx 7Gl6O7gW7JR6kVx7LidJAxUSykoCdtPyiDxfEU8ypERiype2E6EJN/Bn11o1P8zr VZ/PdGti5gg= =vLKV -----END PGP SIGNATURE----- Merge tag 'iio-for-6.16a-take2' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/jic23/iio into char-misc-next Jonathan writes: IIO: New device support, features and cleanup for 6.16 - take 2 Note - last minute rebase was to drop a typo patch that I'd accidentally picked up (in the microblaze arch Kconfig) Take 2 is due to that rebase messing up some fixes tags that were referring to patches after that point. There is a known merge conflict due to changes in neighbouring lines. Stephen's resolution in linux-next is: https://lore.kernel.org/linux-next/20250506155728.65605bae@canb.auug.org.au/ Added 3 named IIO reviewers to MAINTAINERS. This is a reflection of those who have been doing much of this work for some time. Lars-Peter is removed from the entry having moved on to other topics. Thanks Nuno, David and Andy for stepping up and Lars-Peter for all your hard work in the past! Includes the usual mix of new device support, features and general cleanup. This time we also have some tree wide changes. - Rip out the iio_device_claim_direct_scoped() as it proved hard to work with. This series includes quite a few related cleanups such as use of guard or factoring code out to allow direct returns. - Switch from iio_device_claim/release_direct_mode() to new iio_device_claim/release_direct() which is structured so that sparse can warn on failed releases. There were a few false positives but those were mostly in code that benefited from being cleaned up as part of this process. - Introduce iio_push_to_buffers_with_ts() to replace the _timestamp() version over time. This version takes the size of the supplied buffer which the core checks is at least as big as expected by calculation from channel descriptions of those channels enabled. Use this in an initial set of drivers. - Add macros for IIO_DECLARE_BUFFER_WITH_TS() and IIO_DECLARE_DMA_BUFFER_WITH_TS() to avoid lots of fiddly code to ensure correctly aligned buffers for timestamps being added onto the end of channel data. New device support ------------------ adi,ad3530r - New driver for AD3530, AD3530R, AD3531 and AD3531R DACs with programmable gain controls. R variants have internal references. adi,ad7476 - Add support (dt compatible only) for the Rohm BU79100G ADC which is fully compatible with the ti,ads7866. adi,ad7606 - Support ad7606c-16 and ad7606c-18 devices. Includes switch to dynamic channel information allocation. adi,ad7380 - Add support for the AD7389-4 dfrobot,sen0322 - New driver for this oxygen sensor. mediatek,mt2701-auxadc - Add binding for MT6893 which is fully compatible with already supported MT8173. meson-saradc - Support the GXLX SoCs. Mostly this is a workaround for some unrelated clock control bits found in the ADC register map. nuvoton,nct7201 - New driver for NCT7201 and NCT7202 I2C ADCs. rohm,bd79124 - New driver for this 12-bit, 8-channel SAR ADC. - Switch to new set_rv etc gpio callbacks that were added in 6.15. rohm,bd79703 - Add support for BD79700, BD79701 and BD79702 DACs that have subsets of functionality of the already supported bd79703. Included making this driver suitable for support device variants. st,stm32-lptimer - Add support for stm32pm25 to this trigger. Features -------- Beyond IIO - Property iterator for named children. core - Enable writes for 64 bit integers used for standard IIO ABI elements. Previously these could be read only. - Helper library that should avoid code duplication for simpler ADC bindings that have a child node per channel. - Enforce that IIO_DMA_MINALIGN is always at least 8 (almost always true and simplifies code on all significant architectures) core/backend - Add support to control source of data - useful when the HDL includes things like generated ramps for testing purposes. Enable this for adi-axi-dac adi,ad3552-hs - Add debugfs related callbacks to allow debug access to register contents. adi,ad4000 - Support SPI offload with appropriate FPGA firmware along with improving documentation. adi,ad7293 - Add support for external reference voltage. adi,ad7606 - Support SPI offload. adi,ad7768-1 - Support reset GPIO. adi,admv8818 - Support filter frequencies beyond 2^32. adi,adxl345 - Add single and double tap events. hid-sensor-prox - Support 16-bit report sizes as seen on some Intel platforms. invensense,icm42600 - Enable use of named interrupts to avoid problems with some wiring choices. Get the interrupt by name, but fallback to previous assumption on the first being INT1 if no names are supplied. microchip,mcp3911 - Add reset gpio support. rohm,bh7150 - Add reset gpio support. st,stm32 - Add support to control oversampling. ti,adc128s052 - Add support for ROHM BD79104 which is early compatible with the TI parts already supported by this driver. Includes some general driver cleanup and a separate dt binding. - Simplify reference voltage handling by assuming it is fixed after enabling the supply. winsen,mhz19b - New driver for this C02 sensor. Cleanup and minor fixes ----------------------- dt-bindings - Correct indentation and style for DTS examples. - Use unevalutateProperties for SPI devices instead of additionalProperties to allow generic SPI properties from spi-peripheral-props.yaml ABI Docs - Add missing docs for sampling_frequency when it applies only to events. Treewide - Various minor tweaks, comment fixes and similar. - Sort TI ADCs in Kconfig that had gotten out of order. - Switch various drives that provide GPIO chip functionality to the new callbacks with return values. - Standardize on { } formatting for all array sentinels. - Make use of aligned_s64 in a few places to replace either wrong types or manually defined equivalents. - Drop places where spi bits_per_word is set to 8 because that is the default anyway. adi,ad_sigma_delta library - Avoid a potential use of uninitialized data if reg_size has a value that is not supported (no drivers hit this but it is reasonable hardening) adi,ad4030 - Add error checking for scan types and no longer store it in state. - Rework code to reduce duplication. - Move setting the mode from buffer preenable() to update_scan_mode(), better matching expected semantics of the two different callbacks. - Improve data marshalling comments. adi,ad4695 - Use u16 for buffer elements as oversampling is not yet supported except with SPI offload (which doesn't use this path). adi,ad5592r - Clean up destruction of mutexes. - Use lock guards to simplify code (later patch fixes a missed unlock) adi,ad5933 - Correct some incorrect settling times. adi,ad7091 - Deduplicate handling of writable vs volatile registers as they are the inverse of each other for this device. adi,ad7124 - Fix 3db Filter frequency. - Remove ability to directly write the filter frequency (which was broken) - Register naming improvements. adi,ad7606 - Add a missing return value check. - Fill in max sampling rates for all chips. - Use devm_mutex_init() - Fix up some kernel-doc formatting issues. - Remove some camel case that snuck in. - Drop setting address field in channels as easily established from other fields. - Drop unnecessary parameter to ad76060_scale_setup_cb_t. adi,ad7768-1 - Convert to regmap. - Factor out buffer allocation. - Tidy up headers. adi,ad7944 - Stop setting bits_per_word in SPI xfers with no data. adi,ad9832 - Add of_device_id table rather than just relying on fallbacks. - Use FIELD_PREP() to set values of fields. adi,admv1013 - Cleanup a pointless ternary. adi,admv8818 - Fix up LPF Band 5 frequency which was slightly wrong. - Fix an integer overflow. - Fix range calculation adi,adt7316 - Replace irqd_get_trigger_type(irq_get_irq_data()) with simpler irq_get_trigger_type() adi,adxl345 - Use regmap cache instead of various state variables that were there to reduce bus accesses. - Make regmap return value checking consistent across all call sites. adi,axi-dac - Add a check on number of channels (0 to 15 valid) allwinner,sun20i - Use new adc-helpers to replace local parsing code for channel nodes. bosch,bmp290 - Move to local variables for sensor data marshalling removing the need for a messy definition that has to work for all supported parts. Follow up fix adds a missing initialization. dynaimage,al3010 and dynaimage,al3320a - Various minor cleanup to bring these drivers inline with reviewed feedback given on a new driver. - Fix an error path in which power down is not called when it should be. - Switch to regmap. google,cros_ec - Fix up a flexible array in middle of structure warning. - Flush fifo when changing the timeout to avoid potential long wait for samples. hid-sensor-rotation - Remove an __aligned(16) marking that doesn't seem to be justified. kionix,kxcjk-1013 - Deduplicate code for setting up interrupts. microchip,mcp3911 - Fix handling of conversion results register which differs across supported devices. idt,zopt2201 - Avoid duplicating register lists as all volatile registers are the inverse of writeable registers on this device. renesas,rzg2l - Use new adc-helpers to replace local parsing code for channel nodes. ti,ads1298 - Fix a missing Kconfig dependency. * tag 'iio-for-6.16a-take2' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (260 commits) dt-bindings: iio: adc: Add ROHM BD79100G iio: adc: add support for Nuvoton NCT7201 dt-bindings: iio: adc: add NCT7201 ADCs iio: chemical: Add driver for SEN0322 dt-bindings: trivial-devices: Document SEN0322 iio: adc: ad7768-1: reorganize driver headers iio: bmp280: zero-init buffer iio: ssp_sensors: optimalize -> optimize HID: sensor-hub: Fix typo and improve documentation iio: admv1013: replace redundant ternary operator with just len iio: chemical: mhz19b: Fix error code in probe() iio: adc: at91-sama5d2: use IIO_DECLARE_BUFFER_WITH_TS iio: accel: sca3300: use IIO_DECLARE_BUFFER_WITH_TS iio: adc: ad7380: use IIO_DECLARE_DMA_BUFFER_WITH_TS iio: adc: ad4695: rename AD4695_MAX_VIN_CHANNELS iio: adc: ad4695: use IIO_DECLARE_DMA_BUFFER_WITH_TS iio: introduce IIO_DECLARE_BUFFER_WITH_TS macros iio: make IIO_DMA_MINALIGN minimum of 8 bytes iio: pressure: zpa2326_spi: remove bits_per_word = 8 iio: pressure: ms5611_spi: remove bits_per_word = 8 ...pull/1259/head
commit
0ca7cb7089
|
|
@ -94,6 +94,7 @@ Description:
|
|||
What: /sys/bus/iio/devices/iio:deviceX/sampling_frequency
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_sampling_frequency
|
||||
What: /sys/bus/iio/devices/iio:deviceX/buffer/sampling_frequency
|
||||
What: /sys/bus/iio/devices/iio:deviceX/events/sampling_frequency
|
||||
What: /sys/bus/iio/devices/triggerX/sampling_frequency
|
||||
KernelVersion: 2.6.35
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
|
|
@ -740,7 +741,9 @@ Description:
|
|||
1kohm_to_gnd: connected to ground via an 1kOhm resistor,
|
||||
2.5kohm_to_gnd: connected to ground via a 2.5kOhm resistor,
|
||||
6kohm_to_gnd: connected to ground via a 6kOhm resistor,
|
||||
7.7kohm_to_gnd: connected to ground via a 7.7kOhm resistor,
|
||||
20kohm_to_gnd: connected to ground via a 20kOhm resistor,
|
||||
32kohm_to_gnd: connected to ground via a 32kOhm resistor,
|
||||
42kohm_to_gnd: connected to ground via a 42kOhm resistor,
|
||||
90kohm_to_gnd: connected to ground via a 90kOhm resistor,
|
||||
100kohm_to_gnd: connected to ground via an 100kOhm resistor,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ description: |
|
|||
* https://www.analog.com/en/products/ad7386-4.html
|
||||
* https://www.analog.com/en/products/ad7387-4.html
|
||||
* https://www.analog.com/en/products/ad7388-4.html
|
||||
* https://www.analog.com/en/products/ad7389-4.html
|
||||
* https://www.analog.com/en/products/adaq4370-4.html
|
||||
* https://www.analog.com/en/products/adaq4380-4.html
|
||||
* https://www.analog.com/en/products/adaq4381-4.html
|
||||
|
|
@ -49,6 +50,7 @@ properties:
|
|||
- adi,ad7386-4
|
||||
- adi,ad7387-4
|
||||
- adi,ad7388-4
|
||||
- adi,ad7389-4
|
||||
- adi,adaq4370-4
|
||||
- adi,adaq4380-4
|
||||
- adi,adaq4381-4
|
||||
|
|
@ -213,6 +215,15 @@ allOf:
|
|||
properties:
|
||||
refin-supply: false
|
||||
|
||||
# adi,ad7389-4 is internal reference only
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
const: adi,ad7389-4
|
||||
then:
|
||||
properties:
|
||||
refio-supply: false
|
||||
|
||||
# adaq devices need more supplies and using channel to declare gain property
|
||||
# only applies to adaq devices
|
||||
- if:
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@ description: |
|
|||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- adi,ad7091
|
||||
- adi,ad7091r
|
||||
- adi,ad7273
|
||||
|
|
@ -46,6 +48,9 @@ properties:
|
|||
- ti,ads7867
|
||||
- ti,ads7868
|
||||
- lltc,ltc2314-14
|
||||
- items:
|
||||
- const: rohm,bu79100g
|
||||
- const: ti,ads7866
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
|
|||
|
|
@ -45,6 +45,14 @@ properties:
|
|||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
'#trigger-source-cells':
|
||||
description: |
|
||||
Cell indicates the output signal: 0 = BUSY, 1 = FIRSTDATA.
|
||||
|
||||
For convenience, macros for these values are available in
|
||||
dt-bindings/iio/adc/adi,ad7606.h.
|
||||
const: 1
|
||||
|
||||
# According to the datasheet, "Data is clocked in from SDI on the falling
|
||||
# edge of SCLK, while data is clocked out on DOUTA on the rising edge of
|
||||
# SCLK". Also, even if not stated textually in the datasheet, it is made
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ properties:
|
|||
- amlogic,meson8m2-saradc
|
||||
- amlogic,meson-gxbb-saradc
|
||||
- amlogic,meson-gxl-saradc
|
||||
- amlogic,meson-gxlx-saradc
|
||||
- amlogic,meson-gxm-saradc
|
||||
- amlogic,meson-axg-saradc
|
||||
- amlogic,meson-g12a-saradc
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ properties:
|
|||
- const: mediatek,mt2701-auxadc
|
||||
- items:
|
||||
- enum:
|
||||
- mediatek,mt6893-auxadc
|
||||
- mediatek,mt8183-auxadc
|
||||
- mediatek,mt8186-auxadc
|
||||
- mediatek,mt8188-auxadc
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@ properties:
|
|||
spi-max-frequency:
|
||||
maximum: 20000000
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
description: |
|
||||
Phandle and clock identifier for external sampling clock.
|
||||
|
|
@ -71,6 +74,7 @@ unevaluatedProperties: false
|
|||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
|
@ -80,6 +84,7 @@ examples:
|
|||
reg = <0>;
|
||||
interrupt-parent = <&gpio5>;
|
||||
interrupts = <15 2>;
|
||||
reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
|
||||
spi-max-frequency = <20000000>;
|
||||
microchip,device-addr = <0>;
|
||||
vref-supply = <&vref_reg>;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/nuvoton,nct7201.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Nuvoton nct7201 and similar ADCs
|
||||
|
||||
maintainers:
|
||||
- Eason Yang <j2anfernee@gmail.com>
|
||||
|
||||
description: |
|
||||
The NCT7201/NCT7202 is a Nuvoton Hardware Monitor IC, contains up to 12
|
||||
voltage monitoring channels, with SMBus interface, and up to 4 sets SMBus
|
||||
address selection by ADDR connection. It also provides ALERT# signal for
|
||||
event notification and reset input RSTIN# to recover it from a fault
|
||||
condition.
|
||||
|
||||
NCT7201 contains 8 voltage monitor inputs (VIN1~VIN8).
|
||||
NCT7202 contains 12 voltage monitor inputs (VIN1~VIN12).
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- nuvoton,nct7201
|
||||
- nuvoton,nct7202
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply:
|
||||
description:
|
||||
A 3.3V to supply that powers the chip.
|
||||
|
||||
vref-supply:
|
||||
description:
|
||||
The regulator supply for the ADC reference voltage.
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
adc@1d {
|
||||
compatible = "nuvoton,nct7202";
|
||||
reg = <0x1d>;
|
||||
vdd-supply = <&vdd>;
|
||||
vref-supply = <&vref>;
|
||||
interrupt-parent = <&gpio3>;
|
||||
interrupts = <30 IRQ_TYPE_LEVEL_LOW>;
|
||||
reset-gpios = <&gpio3 28 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/rohm,bd79104.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ROHM Semiconductor BD79104 ADC
|
||||
|
||||
maintainers:
|
||||
- Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
|
||||
description: |
|
||||
12 bit SPI ADC with 8 channels.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: rohm,bd79104
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
iovdd-supply: true
|
||||
|
||||
# The component data-sheet says the frequency is 20M. I, however, found
|
||||
# that the ROHM evaluation board BD79104FV-EVK-001 had problems with 20M.
|
||||
# I have successfully used it with 4M. My _assumption_ is that this is not
|
||||
# the limitation of the component itself, but a limitation of the EVK.
|
||||
spi-max-frequency:
|
||||
maximum: 20000000
|
||||
|
||||
"#io-channel-cells":
|
||||
const: 1
|
||||
|
||||
spi-cpha: true
|
||||
spi-cpol: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
- iovdd-supply
|
||||
- spi-cpha
|
||||
- spi-cpol
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
adc@0 {
|
||||
compatible = "rohm,bd79104";
|
||||
reg = <0>;
|
||||
vdd-supply = <&vdd_supply>;
|
||||
iovdd-supply = <&iovdd_supply>;
|
||||
spi-max-frequency = <4000000>;
|
||||
spi-cpha;
|
||||
spi-cpol;
|
||||
#io-channel-cells = <1>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/rohm,bd79124.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ROHM BD79124 ADC/GPO
|
||||
|
||||
maintainers:
|
||||
- Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
|
||||
description: |
|
||||
The ROHM BD79124 is a 12-bit, 8-channel, SAR ADC. The ADC supports
|
||||
an automatic measurement mode, with an alarm interrupt for out-of-window
|
||||
measurements. ADC input pins can be also configured as general purpose
|
||||
outputs.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: rohm,bd79124
|
||||
|
||||
reg:
|
||||
description:
|
||||
I2C slave address.
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
"#gpio-cells":
|
||||
const: 1
|
||||
description:
|
||||
The pin number.
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
iovdd-supply: true
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-7]+$":
|
||||
type: object
|
||||
$ref: /schemas/iio/adc/adc.yaml#
|
||||
description: Represents ADC channel.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
description: AIN pin number
|
||||
minimum: 0
|
||||
maximum: 7
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- iovdd-supply
|
||||
- vdd-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
adc: adc@10 {
|
||||
compatible = "rohm,bd79124";
|
||||
reg = <0x10>;
|
||||
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <29 8>;
|
||||
|
||||
vdd-supply = <&dummyreg>;
|
||||
iovdd-supply = <&dummyreg>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
channel@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
channel@1 {
|
||||
reg = <1>;
|
||||
};
|
||||
channel@2 {
|
||||
reg = <2>;
|
||||
};
|
||||
channel@3 {
|
||||
reg = <3>;
|
||||
};
|
||||
channel@4 {
|
||||
reg = <4>;
|
||||
};
|
||||
channel@5 {
|
||||
reg = <5>;
|
||||
};
|
||||
channel@6 {
|
||||
reg = <6>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/chemical/winsen,mhz19b.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MHZ19B CO2 sensor
|
||||
|
||||
maintainers:
|
||||
- Gyeyoung Baek <gye976@gmail.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: winsen,mhz19b
|
||||
|
||||
vin-supply:
|
||||
description: Regulator that provides power to the sensor
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- vin-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
serial {
|
||||
co2-sensor {
|
||||
compatible = "winsen,mhz19b";
|
||||
vin-supply = <&vdd>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/dac/adi,ad3530r.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices AD3530R and Similar DACs
|
||||
|
||||
maintainers:
|
||||
- Kim Seer Paller <kimseer.paller@analog.com>
|
||||
|
||||
description: |
|
||||
The AD3530/AD3530R (8-channel) and AD3531/AD3531R (4-channel) are low-power,
|
||||
16-bit, buffered voltage output digital-to-analog converters (DACs) with
|
||||
software-programmable gain controls, providing full-scale output spans of 2.5V
|
||||
or 5V for reference voltages of 2.5V. These devices operate from a single 2.7V
|
||||
to 5.5V supply and are guaranteed monotonic by design. The "R" variants
|
||||
include a 2.5V, 5ppm/°C internal reference, which is disabled by default.
|
||||
Datasheet can be found here:
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad3530_ad530r.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad3531-ad3531r.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,ad3530
|
||||
- adi,ad3530r
|
||||
- adi,ad3531
|
||||
- adi,ad3531r
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
spi-max-frequency:
|
||||
maximum: 50000000
|
||||
|
||||
vdd-supply:
|
||||
description: Power Supply Input.
|
||||
|
||||
iovdd-supply:
|
||||
description: Digital Power Supply Input.
|
||||
|
||||
io-channels:
|
||||
description:
|
||||
ADC channel used to monitor internal die temperature, output voltages, and
|
||||
current of a selected channel via the MUXOUT pin.
|
||||
maxItems: 1
|
||||
|
||||
ref-supply:
|
||||
description:
|
||||
Reference Input/Output. The voltage at the REF pin sets the full-scale
|
||||
range of all channels. If not provided the internal reference is used and
|
||||
also provided on the VREF pin.
|
||||
|
||||
reset-gpios:
|
||||
description:
|
||||
Active low signal that is falling edge sensitive. When it is deasserted,
|
||||
the digital core initialization is performed and all DAC registers except
|
||||
the Interface Configuration A register are reset to their default values.
|
||||
maxItems: 1
|
||||
|
||||
ldac-gpios:
|
||||
description:
|
||||
LDAC pin to be used as a hardware trigger to update the DAC channels. If
|
||||
not present, the DAC channels are updated by Software LDAC.
|
||||
maxItems: 1
|
||||
|
||||
adi,range-double:
|
||||
description:
|
||||
Configure the output range for all channels. If the property is present,
|
||||
the output will range from 0V to 2Vref. If the property is not present,
|
||||
the output will range from 0V to Vref.
|
||||
type: boolean
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
- iovdd-supply
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
dac@0 {
|
||||
compatible = "adi,ad3530r";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <1000000>;
|
||||
|
||||
vdd-supply = <&vdd>;
|
||||
iovdd-supply = <&iovdd>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -217,7 +217,7 @@ required:
|
|||
- reg
|
||||
- spi-max-frequency
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ properties:
|
|||
|
||||
vdrive-supply: true
|
||||
|
||||
vrefin-supply: true
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ required:
|
|||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ required:
|
|||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ required:
|
|||
- reg
|
||||
- vdd-supply
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
|||
|
|
@ -5,19 +5,26 @@
|
|||
$id: http://devicetree.org/schemas/iio/dac/rohm,bd79703.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ROHM BD79703 DAC device driver
|
||||
title: ROHM BD79700, BD79701, BD79702 and BD79703 DACs
|
||||
|
||||
maintainers:
|
||||
- Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
|
||||
description: |
|
||||
The ROHM BD79703 is a 6 channel, 8-bit DAC.
|
||||
Datasheet can be found here:
|
||||
The ROHM BD7970[0,1,2,3] are 8-bit DACs. The BD79700 has 2 channels,
|
||||
BD79701 3 channels, BD79702 4 channels and BD79703 has 6 channels.
|
||||
Datasheets for BD79702 and BD79703 can be found from
|
||||
https://fscdn.rohm.com/en/products/databook/datasheet/ic/data_converter/dac/bd79702fv-lb_bd79703fv-lb-e.pdf
|
||||
and for the BD79700 and the BD79701 from
|
||||
https://fscdn.rohm.com/en/products/databook/datasheet/ic/data_converter/dac/bd79700fvm-lb_bd79701fvm-lb-e.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: rohm,bd79703
|
||||
enum:
|
||||
- rohm,bd79700
|
||||
- rohm,bd79701
|
||||
- rohm,bd79702
|
||||
- rohm,bd79703
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
@ -27,23 +34,35 @@ properties:
|
|||
|
||||
vfs-supply:
|
||||
description:
|
||||
The regulator to use as a full scale voltage. The voltage should be between 2.7V .. VCC
|
||||
The regulator to use as a full scale voltage. The voltage should be
|
||||
between 2.7V .. VCC. Not present on BD79700 and BD79701.
|
||||
|
||||
vcc-supply:
|
||||
description:
|
||||
The regulator supplying the operating voltage. Should be between 2.7V ... 5.5V
|
||||
The regulator supplying the operating voltage. Should be between
|
||||
2.7V ... 5.5V. Is used also as a Vfs on BD79700 and BD79701.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- spi-max-frequency
|
||||
- vfs-supply
|
||||
- vcc-supply
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- rohm,bd79702
|
||||
- rohm,bd79703
|
||||
then:
|
||||
required:
|
||||
- vfs-supply
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
|||
|
|
@ -44,6 +44,24 @@ properties:
|
|||
'#clock-cells':
|
||||
const: 0
|
||||
|
||||
adi,lpf-margin-mhz:
|
||||
description:
|
||||
Sets the minimum distance between the fundamental frequency of `rf_in`
|
||||
and the corner frequency of the low-pass, output filter when operated in
|
||||
'auto' mode. The selected low-pass corner frequency will be greater than,
|
||||
or equal to, `rf_in` + `lpf-margin-hz`. If not setting is found that
|
||||
satisfies this relationship the filter will be put into 'bypass'.
|
||||
default: 0
|
||||
|
||||
adi,hpf-margin-mhz:
|
||||
description:
|
||||
Sets the minimum distance between the fundamental frequency of `rf_in`
|
||||
and the corner frequency of the high-pass, input filter when operated in
|
||||
'auto' mode. The selected high-pass corner frequency will be less than,
|
||||
or equal to, `rf_in` - `hpf-margin-hz`. If not setting is found that
|
||||
satisfies this relationship the filter will be put into 'bypass'.
|
||||
default: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
@ -61,6 +79,8 @@ examples:
|
|||
spi-max-frequency = <10000000>;
|
||||
clocks = <&admv8818_rfin>;
|
||||
clock-names = "rf_in";
|
||||
adi,lpf-margin-mhz = <300>;
|
||||
adi,hpf-margin-mhz = <300>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ required:
|
|||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
|||
|
|
@ -39,7 +39,16 @@ properties:
|
|||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
interrupt-names:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
items:
|
||||
enum:
|
||||
- INT1
|
||||
- INT2
|
||||
|
||||
drive-open-drain:
|
||||
type: boolean
|
||||
|
|
@ -76,6 +85,7 @@ examples:
|
|||
reg = <0x68>;
|
||||
interrupt-parent = <&gpio2>;
|
||||
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
|
||||
interrupt-names = "INT1";
|
||||
vdd-supply = <&vdd>;
|
||||
vddio-supply = <&vddio>;
|
||||
};
|
||||
|
|
@ -95,6 +105,7 @@ examples:
|
|||
spi-cpol;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
|
||||
interrupt-names = "INT1";
|
||||
vdd-supply = <&vdd>;
|
||||
vddio-supply = <&vddio>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -24,6 +24,10 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description: GPIO connected to the DVI reset pin (active low)
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
@ -32,6 +36,7 @@ additionalProperties: false
|
|||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
|
@ -39,6 +44,7 @@ examples:
|
|||
light-sensor@23 {
|
||||
compatible = "rohm,bh1750";
|
||||
reg = <0x23>;
|
||||
reset-gpios = <&gpio2 17 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ required:
|
|||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
dependentSchemas:
|
||||
honeywell,pmin-pascal:
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ allOf:
|
|||
honeywell,pmin-pascal: false
|
||||
honeywell,pmax-pascal: false
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
|||
|
|
@ -85,6 +85,8 @@ properties:
|
|||
- devantech,srf08
|
||||
# Devantech SRF10 ultrasonic ranger
|
||||
- devantech,srf10
|
||||
# DFRobot SEN0322 oxygen sensor
|
||||
- dfrobot,sen0322
|
||||
# DH electronics GmbH on-board CPLD trivial SPI device
|
||||
- dh,dhcom-board
|
||||
# DA9053: flexible system level PMIC with multicore support
|
||||
|
|
|
|||
|
|
@ -1689,6 +1689,8 @@ patternProperties:
|
|||
description: Wingtech Technology Co., Ltd.
|
||||
"^winlink,.*":
|
||||
description: WinLink Co., Ltd
|
||||
"^winsen,.*":
|
||||
description: Winsen Corp.
|
||||
"^winstar,.*":
|
||||
description: Winstar Display Corp.
|
||||
"^wirelesstag,.*":
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
==============
|
||||
AD3552R driver
|
||||
==============
|
||||
|
||||
Device driver for Analog Devices Inc. AD35XXR series of DACs. The module name
|
||||
is ``ad3552r``.
|
||||
With the same module name, two different driver variants are available, the
|
||||
``generic spi`` variant, to be used with any classic SPI controllers, and the
|
||||
``hs`` (high speed) variant, for an ADI ``axi-dac`` (IP core) based controller
|
||||
that allows to reach the maximum sample rate supported from the DACs, using the
|
||||
DMA transfer and all the SPI lines available (D/QDSPI)..
|
||||
The high speed driver variant is intended to be used with the ``adi-axi-dac``
|
||||
backend support enabled, that is enabled by default when the driver is selected.
|
||||
|
||||
Supported devices
|
||||
=================
|
||||
|
||||
* `AD3541R <https://www.analog.com/en/products/ad3541r.html>`_
|
||||
* `AD3542R <https://www.analog.com/en/products/ad3542r.html>`_
|
||||
* `AD3551R <https://www.analog.com/en/products/ad3551r.html>`_
|
||||
* `AD3552R <https://www.analog.com/en/products/ad3552r.html>`_
|
||||
|
||||
Wiring connections
|
||||
==================
|
||||
|
||||
Generic SPI
|
||||
-----------
|
||||
Use the classic SPI S_CLK/CS/SDO/SDI connection.
|
||||
|
||||
High speed (using axi-dac backend)
|
||||
----------------------------------
|
||||
|
||||
::
|
||||
|
||||
.-----------------. .-------.
|
||||
| |--- D/QSPI -----| |
|
||||
| DAC IP CORE |--- SPI S_CLK --| DAC |
|
||||
| |--- SPI CS -----| |
|
||||
| |--- LDAC -------| |
|
||||
| |--- RESET ------| |
|
||||
|_________________| |_______|
|
||||
|
||||
|
||||
High speed features
|
||||
===================
|
||||
|
||||
Device attributes
|
||||
-----------------
|
||||
|
||||
The following table shows the ad35xxr related device debug files, found in the
|
||||
specific debugfs path ``/sys/kernel/debug/iio/iio:deviceX``.
|
||||
|
||||
+-----------------------+------------------------------------------------------+
|
||||
| Debugfs device files | Description |
|
||||
+-----------------------+------------------------------------------------------+
|
||||
| data_source | The used data source, as |
|
||||
| | ``normal``, ``ramp-16bit``, etc. |
|
||||
+-----------------------+------------------------------------------------------+
|
||||
| data_source_available | The available data sources. |
|
||||
+-----------------------+------------------------------------------------------+
|
||||
|
||||
Usage examples
|
||||
--------------
|
||||
|
||||
. code-block:: bash
|
||||
root:/sys/bus/iio/devices/iio:device0# cat data_source
|
||||
normal
|
||||
root:/sys/bus/iio/devices/iio:device0# echo -n ramp-16bit > data_source
|
||||
root:/sys/bus/iio/devices/iio:device0# cat data_source
|
||||
ramp-16bit
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
AD4000 driver
|
||||
=============
|
||||
|
||||
Device driver for Analog Devices Inc. AD4000 series of ADCs.
|
||||
Device driver for Analog Devices Inc. AD4000 series of ADCs and similar devices.
|
||||
|
||||
Supported devices
|
||||
=================
|
||||
|
|
@ -25,6 +25,21 @@ Supported devices
|
|||
* `AD4022 <https://www.analog.com/AD4022>`_
|
||||
* `ADAQ4001 <https://www.analog.com/ADAQ4001>`_
|
||||
* `ADAQ4003 <https://www.analog.com/ADAQ4003>`_
|
||||
* `AD7685 <https://www.analog.com/AD7685>`_
|
||||
* `AD7686 <https://www.analog.com/AD7686>`_
|
||||
* `AD7687 <https://www.analog.com/AD7687>`_
|
||||
* `AD7688 <https://www.analog.com/AD7688>`_
|
||||
* `AD7690 <https://www.analog.com/AD7690>`_
|
||||
* `AD7691 <https://www.analog.com/AD7691>`_
|
||||
* `AD7693 <https://www.analog.com/AD7693>`_
|
||||
* `AD7942 <https://www.analog.com/AD7942>`_
|
||||
* `AD7946 <https://www.analog.com/AD7946>`_
|
||||
* `AD7980 <https://www.analog.com/AD7980>`_
|
||||
* `AD7982 <https://www.analog.com/AD7982>`_
|
||||
* `AD7983 <https://www.analog.com/AD7983>`_
|
||||
* `AD7984 <https://www.analog.com/AD7984>`_
|
||||
* `AD7988-1 <https://www.analog.com/AD7988-1>`_
|
||||
* `AD7988-5 <https://www.analog.com/AD7988-5>`_
|
||||
|
||||
Wiring connections
|
||||
------------------
|
||||
|
|
@ -129,3 +144,77 @@ Set ``adi,sdi-pin`` to ``"cs"`` to select this mode.
|
|||
^ | |
|
||||
+--------------------| SCLK |
|
||||
+-------------+
|
||||
|
||||
IIO Device characteristics
|
||||
==========================
|
||||
|
||||
The AD4000 series driver supports differential and pseudo-differential ADCs.
|
||||
|
||||
The span compression feature available in AD4000 series devices can be
|
||||
enabled/disabled by changing the ``_scale_available`` attribute of the voltage
|
||||
channel. Note that span compression configuration requires writing to AD4000
|
||||
configuration register, which is only possible when the ADC is wired in 3-wire
|
||||
turbo mode, and the SPI controller is ``SPI_MOSI_IDLE_HIGH`` capable. If those
|
||||
conditions are not met, no ``_scale_available`` attribute is provided.
|
||||
|
||||
Besides that, differential and pseudo-differential voltage channels present
|
||||
slightly different sysfs interfaces.
|
||||
|
||||
Pseudo-differential ADCs
|
||||
------------------------
|
||||
|
||||
Typical voltage channel attributes of a pseudo-differential AD4000 series device:
|
||||
|
||||
+-------------------------------------------+------------------------------------------+
|
||||
| Voltage Channel Attributes | Description |
|
||||
+===========================================+==========================================+
|
||||
| ``in_voltage0_raw`` | Raw ADC output code. |
|
||||
+-------------------------------------------+------------------------------------------+
|
||||
| ``in_voltage0_offset`` | Offset to convert raw value to mV. |
|
||||
+-------------------------------------------+------------------------------------------+
|
||||
| ``in_voltage0_scale`` | Scale factor to convert raw value to mV. |
|
||||
+-------------------------------------------+------------------------------------------+
|
||||
| ``in_voltage0_scale_available`` | Toggles input span compression |
|
||||
+-------------------------------------------+------------------------------------------+
|
||||
|
||||
Differential ADCs
|
||||
-----------------
|
||||
|
||||
Typical voltage channel attributes of a differential AD4000 series device:
|
||||
|
||||
+-------------------------------------------+------------------------------------------+
|
||||
| Voltage Channel Attributes | Description |
|
||||
+===========================================+==========================================+
|
||||
| ``in_voltage0-voltage1_raw`` | Raw ADC output code. |
|
||||
+-------------------------------------------+------------------------------------------+
|
||||
| ``in_voltage0-voltage1_scale`` | Scale factor to convert raw value to mV. |
|
||||
+-------------------------------------------+------------------------------------------+
|
||||
| ``in_voltage0-voltage1_scale_available`` | Toggles input span compression |
|
||||
+-------------------------------------------+------------------------------------------+
|
||||
|
||||
SPI offload support
|
||||
-------------------
|
||||
|
||||
To be able to achieve the maximum sample rate, the driver can be used with SPI
|
||||
offload engines such as the one usually present in `AXI SPI Engine`_, to provide
|
||||
SPI offload support.
|
||||
|
||||
.. _AXI SPI Engine: http://analogdevicesinc.github.io/hdl/projects/pulsar_adc/index.html
|
||||
|
||||
To keep up with SPI offloading transfer speeds, the ADC must be connected either
|
||||
in 3-wire turbo mode or in 3-wire without busy indicator mode and have SPI
|
||||
controller CS line connected to the CNV pin.
|
||||
|
||||
When set for SPI offload support, the IIO device will provide different
|
||||
interfaces.
|
||||
|
||||
* Either ``in_voltage0_sampling_frequency`` or
|
||||
``in_voltage0-voltage1_sampling_frequency`` file is provided to allow setting
|
||||
the sample rate.
|
||||
* IIO trigger device is not provided (no ``trigger`` directory).
|
||||
* ``timestamp`` channel is not provided.
|
||||
|
||||
Also, because the ADC output has a one sample latency (delay) when the device is
|
||||
wired in "3-wire" mode and only one transfer per sample is done when using SPI
|
||||
offloading, the first data sample in the buffer is not valid because it contains
|
||||
the output of an earlier conversion result.
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ The following chips are supported by this driver:
|
|||
* `AD7386-4 <https://www.analog.com/en/products/ad7386-4.html>`_
|
||||
* `AD7387-4 <https://www.analog.com/en/products/ad7387-4.html>`_
|
||||
* `AD7388-4 <https://www.analog.com/en/products/ad7388-4.html>`_
|
||||
* `AD7389-4 <https://www.analog.com/en/products/ad7389-4.html>`_
|
||||
* `ADAQ4370-4 <https://www.analog.com/en/products/adaq4370-4.html>`_
|
||||
* `ADAQ4380-4 <https://www.analog.com/en/products/adaq4380-4.html>`_
|
||||
* `ADAQ4381-4 <https://www.analog.com/en/products/adaq4381-4.html>`_
|
||||
|
|
@ -50,6 +51,12 @@ ad7380-4
|
|||
ad7380-4 supports only an external reference voltage (2.5V to 3.3V). It must be
|
||||
declared in the device tree as ``refin-supply``.
|
||||
|
||||
ad7389-4
|
||||
~~~~~~~~
|
||||
|
||||
ad7389-4 supports only an internal reference voltage. ``refin-supply`` and
|
||||
``refio-supply`` properties are both omitted in this case.
|
||||
|
||||
ADAQ devices
|
||||
~~~~~~~~~~~~
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,35 @@ SPI wiring modes
|
|||
These ADCs can output data on several SDO lines (1/2/4/8). The driver
|
||||
currently supports only 1 SDO line.
|
||||
|
||||
SPI offload wiring
|
||||
------------------
|
||||
When used with a SPI offload, the supported wiring configuration is:
|
||||
|
||||
.. code-block::
|
||||
|
||||
+-------------+ +-------------+
|
||||
| BUSY |-------->| TRIGGER |
|
||||
| CS |<--------| CS |
|
||||
| | | |
|
||||
| ADC | | SPI |
|
||||
| | | |
|
||||
| SDI |<--------| SDO |
|
||||
| DOUTA |-------->| SDI |
|
||||
| SCLK |<--------| SCLK |
|
||||
| | | |
|
||||
| | +-------------+
|
||||
| CONVST |<--------| PWM |
|
||||
+-------------+ +-------------+
|
||||
|
||||
In this case, the ``pwms`` property is required.
|
||||
The ``#trigger-source-cells = <1>`` property is also required to connect back
|
||||
to the SPI offload. The SPI offload will have ``trigger-sources`` property
|
||||
with a cell to indicate the busy signal:
|
||||
``<&ad7606 AD4695_TRIGGER_EVENT_BUSY>``.
|
||||
|
||||
.. seealso:: `SPI offload support`_
|
||||
|
||||
|
||||
Parallel wiring mode
|
||||
--------------------
|
||||
|
||||
|
|
@ -123,6 +152,22 @@ Unimplemented features
|
|||
- CRC indication
|
||||
- Calibration
|
||||
|
||||
SPI offload support
|
||||
===================
|
||||
|
||||
To be able to achieve the maximum sample rate, the driver can be used with the
|
||||
`AXI SPI Engine`_ to provide SPI offload support.
|
||||
|
||||
.. _AXI SPI Engine: https://analogdevicesinc.github.io/hdl/library/spi_engine/index.html
|
||||
|
||||
When SPI offload is being used, some attributes will be different.
|
||||
|
||||
* ``trigger`` directory is removed.
|
||||
* ``sampling_frequency`` attribute is added for setting the sample rate.
|
||||
* ``timestamp`` channel is removed.
|
||||
* Buffer data format may be different compared to when offload is not used,
|
||||
e.g. the ``in_voltage0_type`` attribute.
|
||||
|
||||
Device buffers
|
||||
==============
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ Industrial I/O Kernel Drivers
|
|||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
ad3552r
|
||||
ad4000
|
||||
ad4030
|
||||
ad4695
|
||||
|
|
|
|||
60
MAINTAINERS
60
MAINTAINERS
|
|
@ -1300,12 +1300,21 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
|
|||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
|
||||
F: drivers/net/amt.c
|
||||
|
||||
ANALOG DEVICES INC AD3530R DRIVER
|
||||
M: Kim Seer Paller <kimseer.paller@analog.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
F: Documentation/devicetree/bindings/iio/dac/adi,ad3530r.yaml
|
||||
F: drivers/iio/dac/ad3530r.c
|
||||
|
||||
ANALOG DEVICES INC AD3552R DRIVER
|
||||
M: Nuno Sá <nuno.sa@analog.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
F: Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
|
||||
F: Documentation/iio/ad3552r.rst
|
||||
F: drivers/iio/dac/ad3552r.c
|
||||
|
||||
ANALOG DEVICES INC AD4000 DRIVER
|
||||
|
|
@ -1349,6 +1358,16 @@ F: Documentation/iio/ad4695.rst
|
|||
F: drivers/iio/adc/ad4695.c
|
||||
F: include/dt-bindings/iio/adc/adi,ad4695.h
|
||||
|
||||
ANALOG DEVICES INC AD4851 DRIVER
|
||||
M: Sergiu Cuciurean <sergiu.cuciurean@analog.com>
|
||||
M: Dragos Bogdan <dragos.bogdan@analog.com>
|
||||
R: Antoniu Miclaus <antoniu.miclaus@analog.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
F: Documentation/devicetree/bindings/iio/adc/adi,ad4851.yaml
|
||||
F: drivers/iio/adc/ad4851.c
|
||||
|
||||
ANALOG DEVICES INC AD7091R DRIVER
|
||||
M: Marcelo Schmitt <marcelo.schmitt@analog.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
|
|
@ -6857,6 +6876,12 @@ L: linux-rtc@vger.kernel.org
|
|||
S: Maintained
|
||||
F: drivers/rtc/rtc-sd2405al.c
|
||||
|
||||
DFROBOT SEN0322 DRIVER
|
||||
M: Tóth János <gomba007@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/iio/chemical/sen0322.c
|
||||
|
||||
DH ELECTRONICS DHSOM SOM AND BOARD SUPPORT
|
||||
M: Christoph Niedermaier <cniedermaier@dh-electronics.com>
|
||||
M: Marek Vasut <marex@denx.de>
|
||||
|
|
@ -11488,6 +11513,13 @@ L: linux-media@vger.kernel.org
|
|||
S: Maintained
|
||||
F: drivers/media/rc/iguanair.c
|
||||
|
||||
IIO ADC HELPERS
|
||||
M: Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/iio/adc/industrialio-adc.c
|
||||
F: include/linux/iio/adc-helpers.h
|
||||
|
||||
IIO BACKEND FRAMEWORK
|
||||
M: Nuno Sa <nuno.sa@analog.com>
|
||||
R: Olivier Moysan <olivier.moysan@foss.st.com>
|
||||
|
|
@ -11536,7 +11568,9 @@ F: drivers/iio/common/scmi_sensors/scmi_iio.c
|
|||
|
||||
IIO SUBSYSTEM AND DRIVERS
|
||||
M: Jonathan Cameron <jic23@kernel.org>
|
||||
R: Lars-Peter Clausen <lars@metafoo.de>
|
||||
R: David Lechner <dlechner@baylibre.com>
|
||||
R: Nuno Sá <nuno.sa@analog.com>
|
||||
R: Andy Shevchenko <andy@kernel.org>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git
|
||||
|
|
@ -17436,6 +17470,13 @@ F: drivers/nubus/
|
|||
F: include/linux/nubus.h
|
||||
F: include/uapi/linux/nubus.h
|
||||
|
||||
NUVOTON NCT7201 IIO DRIVER
|
||||
M: Eason Yang <j2anfernee@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/adc/nuvoton,nct7201.yaml
|
||||
F: drivers/iio/adc/nct7201.c
|
||||
|
||||
NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER
|
||||
M: Antonino Daplas <adaplas@gmail.com>
|
||||
L: linux-fbdev@vger.kernel.org
|
||||
|
|
@ -21088,6 +21129,11 @@ S: Supported
|
|||
F: drivers/power/supply/bd99954-charger.c
|
||||
F: drivers/power/supply/bd99954-charger.h
|
||||
|
||||
ROHM BD79124 ADC / GPO IC
|
||||
M: Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
S: Supported
|
||||
F: drivers/iio/adc/rohm-bd79124.c
|
||||
|
||||
ROHM BH1745 COLOUR SENSOR
|
||||
M: Mudit Sharma <muditsharma.info@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
|
|
@ -24241,6 +24287,12 @@ M: Robert Richter <rric@kernel.org>
|
|||
S: Odd Fixes
|
||||
F: drivers/gpio/gpio-thunderx.c
|
||||
|
||||
TI ADC12xs and ROHM BD79104 ADC driver
|
||||
M: Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
S: Maintained
|
||||
F: drivers/iio/adc/ti-adc128s052.c
|
||||
L: linux-iio@vger.kernel.org
|
||||
|
||||
TI ADS1119 ADC DRIVER
|
||||
M: Francesco Dolcini <francesco@dolcini.it>
|
||||
M: João Paulo Gonçalves <jpaulo.silvagoncalves@gmail.com>
|
||||
|
|
@ -26151,6 +26203,12 @@ M: David Härdeman <david@hardeman.nu>
|
|||
S: Maintained
|
||||
F: drivers/media/rc/winbond-cir.c
|
||||
|
||||
WINSEN MHZ19B
|
||||
M: Gyeyoung Baek <gye976@gmail.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/chemical/winsen,mhz19b.yaml
|
||||
F: drivers/iio/chemical/mhz19b.c
|
||||
|
||||
WINSYSTEMS EBC-C384 WATCHDOG DRIVER
|
||||
L: linux-watchdog@vger.kernel.org
|
||||
S: Orphan
|
||||
|
|
|
|||
|
|
@ -945,6 +945,33 @@ unsigned int device_get_child_node_count(const struct device *dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(device_get_child_node_count);
|
||||
|
||||
/**
|
||||
* fwnode_get_named_child_node_count - number of child nodes with given name
|
||||
* @fwnode: Node which child nodes are counted.
|
||||
* @name: String to match child node name against.
|
||||
*
|
||||
* Scan child nodes and count all the nodes with a specific name. Potential
|
||||
* 'number' -ending after the 'at sign' for scanned names is ignored.
|
||||
* E.g.::
|
||||
* fwnode_get_named_child_node_count(fwnode, "channel");
|
||||
* would match all the nodes::
|
||||
* channel { }, channel@0 {}, channel@0xabba {}...
|
||||
*
|
||||
* Return: the number of child nodes with a matching name for a given device.
|
||||
*/
|
||||
unsigned int fwnode_get_named_child_node_count(const struct fwnode_handle *fwnode,
|
||||
const char *name)
|
||||
{
|
||||
struct fwnode_handle *child;
|
||||
unsigned int count = 0;
|
||||
|
||||
fwnode_for_each_named_child_node(fwnode, child, name)
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fwnode_get_named_child_node_count);
|
||||
|
||||
bool device_dma_supported(const struct device *dev)
|
||||
{
|
||||
return fwnode_call_bool_op(dev_fwnode(dev), device_dma_supported);
|
||||
|
|
|
|||
|
|
@ -111,6 +111,10 @@
|
|||
*/
|
||||
#define ADXL375_USCALE 480000
|
||||
|
||||
struct regmap;
|
||||
|
||||
bool adxl345_is_volatile_reg(struct device *dev, unsigned int reg);
|
||||
|
||||
struct adxl345_chip_info {
|
||||
const char *name;
|
||||
int uscale;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/property.h>
|
||||
|
|
@ -17,6 +18,7 @@
|
|||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/events.h>
|
||||
#include <linux/iio/kfifo_buf.h>
|
||||
|
||||
#include "adxl345.h"
|
||||
|
|
@ -31,18 +33,71 @@
|
|||
#define ADXL345_INT1 0
|
||||
#define ADXL345_INT2 1
|
||||
|
||||
#define ADXL345_REG_TAP_AXIS_MSK GENMASK(2, 0)
|
||||
#define ADXL345_REG_TAP_SUPPRESS_MSK BIT(3)
|
||||
#define ADXL345_REG_TAP_SUPPRESS BIT(3)
|
||||
|
||||
#define ADXL345_TAP_Z_EN BIT(0)
|
||||
#define ADXL345_TAP_Y_EN BIT(1)
|
||||
#define ADXL345_TAP_X_EN BIT(2)
|
||||
|
||||
/* single/double tap */
|
||||
enum adxl345_tap_type {
|
||||
ADXL345_SINGLE_TAP,
|
||||
ADXL345_DOUBLE_TAP,
|
||||
};
|
||||
|
||||
static const unsigned int adxl345_tap_int_reg[] = {
|
||||
[ADXL345_SINGLE_TAP] = ADXL345_INT_SINGLE_TAP,
|
||||
[ADXL345_DOUBLE_TAP] = ADXL345_INT_DOUBLE_TAP,
|
||||
};
|
||||
|
||||
enum adxl345_tap_time_type {
|
||||
ADXL345_TAP_TIME_LATENT,
|
||||
ADXL345_TAP_TIME_WINDOW,
|
||||
ADXL345_TAP_TIME_DUR,
|
||||
};
|
||||
|
||||
static const unsigned int adxl345_tap_time_reg[] = {
|
||||
[ADXL345_TAP_TIME_LATENT] = ADXL345_REG_LATENT,
|
||||
[ADXL345_TAP_TIME_WINDOW] = ADXL345_REG_WINDOW,
|
||||
[ADXL345_TAP_TIME_DUR] = ADXL345_REG_DUR,
|
||||
};
|
||||
|
||||
struct adxl345_state {
|
||||
const struct adxl345_chip_info *info;
|
||||
struct regmap *regmap;
|
||||
bool fifo_delay; /* delay: delay is needed for SPI */
|
||||
int irq;
|
||||
u8 intio;
|
||||
u8 int_map;
|
||||
u8 watermark;
|
||||
u8 fifo_mode;
|
||||
|
||||
u32 tap_duration_us;
|
||||
u32 tap_latent_us;
|
||||
u32 tap_window_us;
|
||||
|
||||
__le16 fifo_buf[ADXL345_DIRS * ADXL345_FIFO_SIZE + 1] __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
static struct iio_event_spec adxl345_events[] = {
|
||||
{
|
||||
/* single tap */
|
||||
.type = IIO_EV_TYPE_GESTURE,
|
||||
.dir = IIO_EV_DIR_SINGLETAP,
|
||||
.mask_separate = BIT(IIO_EV_INFO_ENABLE),
|
||||
.mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
|
||||
BIT(IIO_EV_INFO_TIMEOUT),
|
||||
},
|
||||
{
|
||||
/* double tap */
|
||||
.type = IIO_EV_TYPE_GESTURE,
|
||||
.dir = IIO_EV_DIR_DOUBLETAP,
|
||||
.mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) |
|
||||
BIT(IIO_EV_INFO_RESET_TIMEOUT) |
|
||||
BIT(IIO_EV_INFO_TAP2_MIN_DELAY),
|
||||
},
|
||||
};
|
||||
|
||||
#define ADXL345_CHANNEL(index, reg, axis) { \
|
||||
.type = IIO_ACCEL, \
|
||||
.modified = 1, \
|
||||
|
|
@ -59,6 +114,8 @@ struct adxl345_state {
|
|||
.storagebits = 16, \
|
||||
.endianness = IIO_LE, \
|
||||
}, \
|
||||
.event_spec = adxl345_events, \
|
||||
.num_event_specs = ARRAY_SIZE(adxl345_events), \
|
||||
}
|
||||
|
||||
enum adxl345_chans {
|
||||
|
|
@ -76,6 +133,25 @@ static const unsigned long adxl345_scan_masks[] = {
|
|||
0
|
||||
};
|
||||
|
||||
bool adxl345_is_volatile_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case ADXL345_REG_DATA_AXIS(0):
|
||||
case ADXL345_REG_DATA_AXIS(1):
|
||||
case ADXL345_REG_DATA_AXIS(2):
|
||||
case ADXL345_REG_DATA_AXIS(3):
|
||||
case ADXL345_REG_DATA_AXIS(4):
|
||||
case ADXL345_REG_DATA_AXIS(5):
|
||||
case ADXL345_REG_ACT_TAP_STATUS:
|
||||
case ADXL345_REG_FIFO_STATUS:
|
||||
case ADXL345_REG_INT_SOURCE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(adxl345_is_volatile_reg, "IIO_ADXL345");
|
||||
|
||||
/**
|
||||
* adxl345_set_measure_en() - Enable and disable measuring.
|
||||
*
|
||||
|
|
@ -96,24 +172,215 @@ static int adxl345_set_measure_en(struct adxl345_state *st, bool en)
|
|||
return regmap_write(st->regmap, ADXL345_REG_POWER_CTL, val);
|
||||
}
|
||||
|
||||
static int adxl345_set_interrupts(struct adxl345_state *st)
|
||||
/* tap */
|
||||
|
||||
static int _adxl345_set_tap_int(struct adxl345_state *st,
|
||||
enum adxl345_tap_type type, bool state)
|
||||
{
|
||||
unsigned int int_map = 0x00;
|
||||
unsigned int tap_threshold;
|
||||
bool axis_valid;
|
||||
bool singletap_args_valid = false;
|
||||
bool doubletap_args_valid = false;
|
||||
bool en = false;
|
||||
u32 axis_ctrl;
|
||||
int ret;
|
||||
unsigned int int_enable = st->int_map;
|
||||
unsigned int int_map;
|
||||
|
||||
/*
|
||||
* Any bits set to 0 in the INT map register send their respective
|
||||
* interrupts to the INT1 pin, whereas bits set to 1 send their respective
|
||||
* interrupts to the INT2 pin. The intio shall convert this accordingly.
|
||||
*/
|
||||
int_map = st->intio ? st->int_map : ~st->int_map;
|
||||
|
||||
ret = regmap_write(st->regmap, ADXL345_REG_INT_MAP, int_map);
|
||||
ret = regmap_read(st->regmap, ADXL345_REG_TAP_AXIS, &axis_ctrl);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return regmap_write(st->regmap, ADXL345_REG_INT_ENABLE, int_enable);
|
||||
axis_valid = FIELD_GET(ADXL345_REG_TAP_AXIS_MSK, axis_ctrl) > 0;
|
||||
|
||||
ret = regmap_read(st->regmap, ADXL345_REG_THRESH_TAP, &tap_threshold);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Note: A value of 0 for threshold and/or dur may result in undesirable
|
||||
* behavior if single tap/double tap interrupts are enabled.
|
||||
*/
|
||||
singletap_args_valid = tap_threshold > 0 && st->tap_duration_us > 0;
|
||||
|
||||
if (type == ADXL345_SINGLE_TAP) {
|
||||
en = axis_valid && singletap_args_valid;
|
||||
} else {
|
||||
/* doubletap: Window must be equal or greater than latent! */
|
||||
doubletap_args_valid = st->tap_latent_us > 0 &&
|
||||
st->tap_window_us > 0 &&
|
||||
st->tap_window_us >= st->tap_latent_us;
|
||||
|
||||
en = axis_valid && singletap_args_valid && doubletap_args_valid;
|
||||
}
|
||||
|
||||
if (state && en)
|
||||
int_map |= adxl345_tap_int_reg[type];
|
||||
|
||||
return regmap_update_bits(st->regmap, ADXL345_REG_INT_ENABLE,
|
||||
adxl345_tap_int_reg[type], int_map);
|
||||
}
|
||||
|
||||
static int adxl345_is_tap_en(struct adxl345_state *st,
|
||||
enum iio_modifier axis,
|
||||
enum adxl345_tap_type type, bool *en)
|
||||
{
|
||||
unsigned int regval;
|
||||
u32 axis_ctrl;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(st->regmap, ADXL345_REG_TAP_AXIS, &axis_ctrl);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Verify if axis is enabled for the tap detection. */
|
||||
switch (axis) {
|
||||
case IIO_MOD_X:
|
||||
*en = FIELD_GET(ADXL345_TAP_X_EN, axis_ctrl);
|
||||
break;
|
||||
case IIO_MOD_Y:
|
||||
*en = FIELD_GET(ADXL345_TAP_Y_EN, axis_ctrl);
|
||||
break;
|
||||
case IIO_MOD_Z:
|
||||
*en = FIELD_GET(ADXL345_TAP_Z_EN, axis_ctrl);
|
||||
break;
|
||||
default:
|
||||
*en = false;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (*en) {
|
||||
/*
|
||||
* If axis allow for tap detection, verify if the interrupt is
|
||||
* enabled for tap detection.
|
||||
*/
|
||||
ret = regmap_read(st->regmap, ADXL345_REG_INT_ENABLE, ®val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*en = adxl345_tap_int_reg[type] & regval;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adxl345_set_singletap_en(struct adxl345_state *st,
|
||||
enum iio_modifier axis, bool en)
|
||||
{
|
||||
int ret;
|
||||
u32 axis_ctrl;
|
||||
|
||||
switch (axis) {
|
||||
case IIO_MOD_X:
|
||||
axis_ctrl = ADXL345_TAP_X_EN;
|
||||
break;
|
||||
case IIO_MOD_Y:
|
||||
axis_ctrl = ADXL345_TAP_Y_EN;
|
||||
break;
|
||||
case IIO_MOD_Z:
|
||||
axis_ctrl = ADXL345_TAP_Z_EN;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (en)
|
||||
ret = regmap_set_bits(st->regmap, ADXL345_REG_TAP_AXIS,
|
||||
axis_ctrl);
|
||||
else
|
||||
ret = regmap_clear_bits(st->regmap, ADXL345_REG_TAP_AXIS,
|
||||
axis_ctrl);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return _adxl345_set_tap_int(st, ADXL345_SINGLE_TAP, en);
|
||||
}
|
||||
|
||||
static int adxl345_set_doubletap_en(struct adxl345_state *st, bool en)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Generally suppress detection of spikes during the latency period as
|
||||
* double taps here, this is fully optional for double tap detection
|
||||
*/
|
||||
ret = regmap_update_bits(st->regmap, ADXL345_REG_TAP_AXIS,
|
||||
ADXL345_REG_TAP_SUPPRESS_MSK,
|
||||
en ? ADXL345_REG_TAP_SUPPRESS : 0x00);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return _adxl345_set_tap_int(st, ADXL345_DOUBLE_TAP, en);
|
||||
}
|
||||
|
||||
static int _adxl345_set_tap_time(struct adxl345_state *st,
|
||||
enum adxl345_tap_time_type type, u32 val_us)
|
||||
{
|
||||
unsigned int regval;
|
||||
|
||||
switch (type) {
|
||||
case ADXL345_TAP_TIME_WINDOW:
|
||||
st->tap_window_us = val_us;
|
||||
break;
|
||||
case ADXL345_TAP_TIME_LATENT:
|
||||
st->tap_latent_us = val_us;
|
||||
break;
|
||||
case ADXL345_TAP_TIME_DUR:
|
||||
st->tap_duration_us = val_us;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* The scale factor is 1250us / LSB for tap_window_us and tap_latent_us.
|
||||
* For tap_duration_us the scale factor is 625us / LSB.
|
||||
*/
|
||||
if (type == ADXL345_TAP_TIME_DUR)
|
||||
regval = DIV_ROUND_CLOSEST(val_us, 625);
|
||||
else
|
||||
regval = DIV_ROUND_CLOSEST(val_us, 1250);
|
||||
|
||||
return regmap_write(st->regmap, adxl345_tap_time_reg[type], regval);
|
||||
}
|
||||
|
||||
static int adxl345_set_tap_duration(struct adxl345_state *st, u32 val_int,
|
||||
u32 val_fract_us)
|
||||
{
|
||||
/*
|
||||
* Max value is 255 * 625 us = 0.159375 seconds
|
||||
*
|
||||
* Note: the scaling is similar to the scaling in the ADXL380
|
||||
*/
|
||||
if (val_int || val_fract_us > 159375)
|
||||
return -EINVAL;
|
||||
|
||||
return _adxl345_set_tap_time(st, ADXL345_TAP_TIME_DUR, val_fract_us);
|
||||
}
|
||||
|
||||
static int adxl345_set_tap_window(struct adxl345_state *st, u32 val_int,
|
||||
u32 val_fract_us)
|
||||
{
|
||||
/*
|
||||
* Max value is 255 * 1250 us = 0.318750 seconds
|
||||
*
|
||||
* Note: the scaling is similar to the scaling in the ADXL380
|
||||
*/
|
||||
if (val_int || val_fract_us > 318750)
|
||||
return -EINVAL;
|
||||
|
||||
return _adxl345_set_tap_time(st, ADXL345_TAP_TIME_WINDOW, val_fract_us);
|
||||
}
|
||||
|
||||
static int adxl345_set_tap_latent(struct adxl345_state *st, u32 val_int,
|
||||
u32 val_fract_us)
|
||||
{
|
||||
/*
|
||||
* Max value is 255 * 1250 us = 0.318750 seconds
|
||||
*
|
||||
* Note: the scaling is similar to the scaling in the ADXL380
|
||||
*/
|
||||
if (val_int || val_fract_us > 318750)
|
||||
return -EINVAL;
|
||||
|
||||
return _adxl345_set_tap_time(st, ADXL345_TAP_TIME_LATENT, val_fract_us);
|
||||
}
|
||||
|
||||
static int adxl345_read_raw(struct iio_dev *indio_dev,
|
||||
|
|
@ -136,7 +403,7 @@ static int adxl345_read_raw(struct iio_dev *indio_dev,
|
|||
ret = regmap_bulk_read(st->regmap,
|
||||
ADXL345_REG_DATA_AXIS(chan->address),
|
||||
&accel, sizeof(accel));
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = sign_extend32(le16_to_cpu(accel), 12);
|
||||
|
|
@ -148,7 +415,7 @@ static int adxl345_read_raw(struct iio_dev *indio_dev,
|
|||
case IIO_CHAN_INFO_CALIBBIAS:
|
||||
ret = regmap_read(st->regmap,
|
||||
ADXL345_REG_OFS_AXIS(chan->address), ®val);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
/*
|
||||
* 8-bit resolution at +/- 2g, that is 4x accel data scale
|
||||
|
|
@ -159,7 +426,7 @@ static int adxl345_read_raw(struct iio_dev *indio_dev,
|
|||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
ret = regmap_read(st->regmap, ADXL345_REG_BW_RATE, ®val);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
samp_freq_nhz = ADXL345_BASE_RATE_NANO_HZ <<
|
||||
|
|
@ -201,6 +468,157 @@ static int adxl345_write_raw(struct iio_dev *indio_dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int adxl345_read_event_config(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir)
|
||||
{
|
||||
struct adxl345_state *st = iio_priv(indio_dev);
|
||||
bool int_en;
|
||||
int ret;
|
||||
|
||||
switch (type) {
|
||||
case IIO_EV_TYPE_GESTURE:
|
||||
switch (dir) {
|
||||
case IIO_EV_DIR_SINGLETAP:
|
||||
ret = adxl345_is_tap_en(st, chan->channel2,
|
||||
ADXL345_SINGLE_TAP, &int_en);
|
||||
if (ret)
|
||||
return ret;
|
||||
return int_en;
|
||||
case IIO_EV_DIR_DOUBLETAP:
|
||||
ret = adxl345_is_tap_en(st, chan->channel2,
|
||||
ADXL345_DOUBLE_TAP, &int_en);
|
||||
if (ret)
|
||||
return ret;
|
||||
return int_en;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int adxl345_write_event_config(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir,
|
||||
bool state)
|
||||
{
|
||||
struct adxl345_state *st = iio_priv(indio_dev);
|
||||
|
||||
switch (type) {
|
||||
case IIO_EV_TYPE_GESTURE:
|
||||
switch (dir) {
|
||||
case IIO_EV_DIR_SINGLETAP:
|
||||
return adxl345_set_singletap_en(st, chan->channel2, state);
|
||||
case IIO_EV_DIR_DOUBLETAP:
|
||||
return adxl345_set_doubletap_en(st, state);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int adxl345_read_event_value(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir,
|
||||
enum iio_event_info info,
|
||||
int *val, int *val2)
|
||||
{
|
||||
struct adxl345_state *st = iio_priv(indio_dev);
|
||||
unsigned int tap_threshold;
|
||||
int ret;
|
||||
|
||||
switch (type) {
|
||||
case IIO_EV_TYPE_GESTURE:
|
||||
switch (info) {
|
||||
case IIO_EV_INFO_VALUE:
|
||||
/*
|
||||
* The scale factor would be 62.5mg/LSB (i.e. 0xFF = 16g) but
|
||||
* not applied here. In context of this general purpose sensor,
|
||||
* what imports is rather signal intensity than the absolute
|
||||
* measured g value.
|
||||
*/
|
||||
ret = regmap_read(st->regmap, ADXL345_REG_THRESH_TAP,
|
||||
&tap_threshold);
|
||||
if (ret)
|
||||
return ret;
|
||||
*val = sign_extend32(tap_threshold, 7);
|
||||
return IIO_VAL_INT;
|
||||
case IIO_EV_INFO_TIMEOUT:
|
||||
*val = st->tap_duration_us;
|
||||
*val2 = 1000000;
|
||||
return IIO_VAL_FRACTIONAL;
|
||||
case IIO_EV_INFO_RESET_TIMEOUT:
|
||||
*val = st->tap_window_us;
|
||||
*val2 = 1000000;
|
||||
return IIO_VAL_FRACTIONAL;
|
||||
case IIO_EV_INFO_TAP2_MIN_DELAY:
|
||||
*val = st->tap_latent_us;
|
||||
*val2 = 1000000;
|
||||
return IIO_VAL_FRACTIONAL;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int adxl345_write_event_value(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir,
|
||||
enum iio_event_info info,
|
||||
int val, int val2)
|
||||
{
|
||||
struct adxl345_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
ret = adxl345_set_measure_en(st, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (type) {
|
||||
case IIO_EV_TYPE_GESTURE:
|
||||
switch (info) {
|
||||
case IIO_EV_INFO_VALUE:
|
||||
ret = regmap_write(st->regmap, ADXL345_REG_THRESH_TAP,
|
||||
min(val, 0xFF));
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case IIO_EV_INFO_TIMEOUT:
|
||||
ret = adxl345_set_tap_duration(st, val, val2);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case IIO_EV_INFO_RESET_TIMEOUT:
|
||||
ret = adxl345_set_tap_window(st, val, val2);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case IIO_EV_INFO_TAP2_MIN_DELAY:
|
||||
ret = adxl345_set_tap_latent(st, val, val2);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return adxl345_set_measure_en(st, true);
|
||||
}
|
||||
|
||||
static int adxl345_reg_access(struct iio_dev *indio_dev, unsigned int reg,
|
||||
unsigned int writeval, unsigned int *readval)
|
||||
{
|
||||
|
|
@ -214,7 +632,7 @@ static int adxl345_reg_access(struct iio_dev *indio_dev, unsigned int reg,
|
|||
static int adxl345_set_watermark(struct iio_dev *indio_dev, unsigned int value)
|
||||
{
|
||||
struct adxl345_state *st = iio_priv(indio_dev);
|
||||
unsigned int fifo_mask = 0x1F;
|
||||
const unsigned int fifo_mask = 0x1F, watermark_mask = 0x02;
|
||||
int ret;
|
||||
|
||||
value = min(value, ADXL345_FIFO_SIZE - 1);
|
||||
|
|
@ -224,9 +642,8 @@ static int adxl345_set_watermark(struct iio_dev *indio_dev, unsigned int value)
|
|||
return ret;
|
||||
|
||||
st->watermark = value;
|
||||
st->int_map |= ADXL345_INT_WATERMARK;
|
||||
|
||||
return 0;
|
||||
return regmap_update_bits(st->regmap, ADXL345_REG_INT_ENABLE,
|
||||
watermark_mask, ADXL345_INT_WATERMARK);
|
||||
}
|
||||
|
||||
static int adxl345_write_raw_get_fmt(struct iio_dev *indio_dev,
|
||||
|
|
@ -265,21 +682,25 @@ static const struct attribute_group adxl345_attrs_group = {
|
|||
|
||||
static int adxl345_set_fifo(struct adxl345_state *st)
|
||||
{
|
||||
unsigned int intio;
|
||||
int ret;
|
||||
|
||||
/* FIFO should only be configured while in standby mode */
|
||||
ret = adxl345_set_measure_en(st, false);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_read(st->regmap, ADXL345_REG_INT_MAP, &intio);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_write(st->regmap, ADXL345_REG_FIFO_CTL,
|
||||
FIELD_PREP(ADXL345_FIFO_CTL_SAMPLES_MSK,
|
||||
st->watermark) |
|
||||
FIELD_PREP(ADXL345_FIFO_CTL_TRIGGER_MSK,
|
||||
st->intio) |
|
||||
FIELD_PREP(ADXL345_FIFO_CTL_TRIGGER_MSK, intio) |
|
||||
FIELD_PREP(ADXL345_FIFO_CTL_MODE_MSK,
|
||||
st->fifo_mode));
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return adxl345_set_measure_en(st, true);
|
||||
|
|
@ -300,7 +721,7 @@ static int adxl345_get_samples(struct adxl345_state *st)
|
|||
int ret;
|
||||
|
||||
ret = regmap_read(st->regmap, ADXL345_REG_FIFO_STATUS, ®val);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return FIELD_GET(ADXL345_REG_FIFO_STATUS_MSK, regval);
|
||||
|
|
@ -328,7 +749,7 @@ static int adxl345_fifo_transfer(struct adxl345_state *st, int samples)
|
|||
/* read 3x 2 byte elements from base address into next fifo_buf position */
|
||||
ret = regmap_bulk_read(st->regmap, ADXL345_REG_XYZ_BASE,
|
||||
st->fifo_buf + (i * count / 2), count);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
|
|
@ -374,11 +795,6 @@ static void adxl345_fifo_reset(struct adxl345_state *st)
|
|||
static int adxl345_buffer_postenable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct adxl345_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
ret = adxl345_set_interrupts(st);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
st->fifo_mode = ADXL345_FIFO_STREAM;
|
||||
return adxl345_set_fifo(st);
|
||||
|
|
@ -391,11 +807,10 @@ static int adxl345_buffer_predisable(struct iio_dev *indio_dev)
|
|||
|
||||
st->fifo_mode = ADXL345_FIFO_BYPASS;
|
||||
ret = adxl345_set_fifo(st);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
st->int_map = 0x00;
|
||||
return adxl345_set_interrupts(st);
|
||||
return regmap_write(st->regmap, ADXL345_REG_INT_ENABLE, 0x00);
|
||||
}
|
||||
|
||||
static const struct iio_buffer_setup_ops adxl345_buffer_ops = {
|
||||
|
|
@ -422,6 +837,48 @@ static int adxl345_fifo_push(struct iio_dev *indio_dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat,
|
||||
enum iio_modifier tap_dir)
|
||||
{
|
||||
s64 ts = iio_get_time_ns(indio_dev);
|
||||
struct adxl345_state *st = iio_priv(indio_dev);
|
||||
int samples;
|
||||
int ret = -ENOENT;
|
||||
|
||||
if (FIELD_GET(ADXL345_INT_SINGLE_TAP, int_stat)) {
|
||||
ret = iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, tap_dir,
|
||||
IIO_EV_TYPE_GESTURE,
|
||||
IIO_EV_DIR_SINGLETAP),
|
||||
ts);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (FIELD_GET(ADXL345_INT_DOUBLE_TAP, int_stat)) {
|
||||
ret = iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, tap_dir,
|
||||
IIO_EV_TYPE_GESTURE,
|
||||
IIO_EV_DIR_DOUBLETAP),
|
||||
ts);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) {
|
||||
samples = adxl345_get_samples(st);
|
||||
if (samples < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (adxl345_fifo_push(indio_dev, samples) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* adxl345_irq_handler() - Handle irqs of the ADXL345.
|
||||
* @irq: The irq being handled.
|
||||
|
|
@ -433,21 +890,35 @@ static irqreturn_t adxl345_irq_handler(int irq, void *p)
|
|||
{
|
||||
struct iio_dev *indio_dev = p;
|
||||
struct adxl345_state *st = iio_priv(indio_dev);
|
||||
unsigned int regval;
|
||||
enum iio_modifier tap_dir = IIO_NO_MOD;
|
||||
u32 axis_ctrl;
|
||||
int int_stat;
|
||||
int samples;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(st->regmap, ADXL345_REG_TAP_AXIS, &axis_ctrl);
|
||||
if (ret)
|
||||
return IRQ_NONE;
|
||||
|
||||
if (FIELD_GET(ADXL345_REG_TAP_AXIS_MSK, axis_ctrl)) {
|
||||
ret = regmap_read(st->regmap, ADXL345_REG_ACT_TAP_STATUS, ®val);
|
||||
if (ret)
|
||||
return IRQ_NONE;
|
||||
|
||||
if (FIELD_GET(ADXL345_TAP_Z_EN, regval))
|
||||
tap_dir = IIO_MOD_Z;
|
||||
else if (FIELD_GET(ADXL345_TAP_Y_EN, regval))
|
||||
tap_dir = IIO_MOD_Y;
|
||||
else if (FIELD_GET(ADXL345_TAP_X_EN, regval))
|
||||
tap_dir = IIO_MOD_X;
|
||||
}
|
||||
|
||||
if (regmap_read(st->regmap, ADXL345_REG_INT_SOURCE, &int_stat))
|
||||
return IRQ_NONE;
|
||||
|
||||
if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) {
|
||||
samples = adxl345_get_samples(st);
|
||||
if (samples < 0)
|
||||
if (adxl345_push_event(indio_dev, int_stat, tap_dir))
|
||||
goto err;
|
||||
|
||||
if (adxl345_fifo_push(indio_dev, samples) < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (FIELD_GET(ADXL345_INT_OVERRUN, int_stat))
|
||||
goto err;
|
||||
|
||||
|
|
@ -464,6 +935,10 @@ static const struct iio_info adxl345_info = {
|
|||
.read_raw = adxl345_read_raw,
|
||||
.write_raw = adxl345_write_raw,
|
||||
.write_raw_get_fmt = adxl345_write_raw_get_fmt,
|
||||
.read_event_config = adxl345_read_event_config,
|
||||
.write_event_config = adxl345_write_event_config,
|
||||
.read_event_value = adxl345_read_event_value,
|
||||
.write_event_value = adxl345_write_event_value,
|
||||
.debugfs_reg_access = &adxl345_reg_access,
|
||||
.hwfifo_set_watermark = adxl345_set_watermark,
|
||||
};
|
||||
|
|
@ -492,10 +967,12 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap,
|
|||
struct adxl345_state *st;
|
||||
struct iio_dev *indio_dev;
|
||||
u32 regval;
|
||||
u8 intio = ADXL345_INT1;
|
||||
unsigned int data_format_mask = (ADXL345_DATA_FORMAT_RANGE |
|
||||
ADXL345_DATA_FORMAT_JUSTIFY |
|
||||
ADXL345_DATA_FORMAT_FULL_RES |
|
||||
ADXL345_DATA_FORMAT_SELF_TEST);
|
||||
unsigned int tap_threshold;
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
|
||||
|
|
@ -509,6 +986,12 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap,
|
|||
return -ENODEV;
|
||||
st->fifo_delay = fifo_delay_default;
|
||||
|
||||
/* Init with reasonable values */
|
||||
tap_threshold = 48; /* 48 [0x30] -> ~3g */
|
||||
st->tap_duration_us = 16; /* 16 [0x10] -> .010 */
|
||||
st->tap_window_us = 64; /* 64 [0x40] -> .080 */
|
||||
st->tap_latent_us = 16; /* 16 [0x10] -> .020 */
|
||||
|
||||
indio_dev->name = st->info->name;
|
||||
indio_dev->info = &adxl345_info;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
|
@ -516,6 +999,11 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap,
|
|||
indio_dev->num_channels = ARRAY_SIZE(adxl345_channels);
|
||||
indio_dev->available_scan_masks = adxl345_scan_masks;
|
||||
|
||||
/* Reset interrupts at start up */
|
||||
ret = regmap_write(st->regmap, ADXL345_REG_INT_ENABLE, 0x00);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (setup) {
|
||||
/* Perform optional initial bus specific configuration */
|
||||
ret = setup(dev, st->regmap);
|
||||
|
|
@ -540,7 +1028,7 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap,
|
|||
}
|
||||
|
||||
ret = regmap_read(st->regmap, ADXL345_REG_DEVID, ®val);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Error reading device ID\n");
|
||||
|
||||
if (regval != ADXL345_DEVID)
|
||||
|
|
@ -549,23 +1037,37 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap,
|
|||
|
||||
/* Enable measurement mode */
|
||||
ret = adxl345_set_measure_en(st, true);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to enable measurement mode\n");
|
||||
|
||||
ret = devm_add_action_or_reset(dev, adxl345_powerdown, st);
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
st->intio = ADXL345_INT1;
|
||||
st->irq = fwnode_irq_get_byname(dev_fwnode(dev), "INT1");
|
||||
if (st->irq < 0) {
|
||||
st->intio = ADXL345_INT2;
|
||||
intio = ADXL345_INT2;
|
||||
st->irq = fwnode_irq_get_byname(dev_fwnode(dev), "INT2");
|
||||
if (st->irq < 0)
|
||||
st->intio = ADXL345_INT_NONE;
|
||||
intio = ADXL345_INT_NONE;
|
||||
}
|
||||
|
||||
if (st->intio != ADXL345_INT_NONE) {
|
||||
if (intio != ADXL345_INT_NONE) {
|
||||
/*
|
||||
* Any bits set to 0 in the INT map register send their respective
|
||||
* interrupts to the INT1 pin, whereas bits set to 1 send their respective
|
||||
* interrupts to the INT2 pin. The intio shall convert this accordingly.
|
||||
*/
|
||||
regval = intio ? 0xff : 0;
|
||||
|
||||
ret = regmap_write(st->regmap, ADXL345_REG_INT_MAP, regval);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_write(st->regmap, ADXL345_REG_THRESH_TAP, tap_threshold);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* FIFO_STREAM mode is going to be activated later */
|
||||
ret = devm_iio_kfifo_buffer_setup(dev, indio_dev, &adxl345_buffer_ops);
|
||||
if (ret)
|
||||
|
|
@ -581,7 +1083,7 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap,
|
|||
ret = regmap_write(st->regmap, ADXL345_REG_FIFO_CTL,
|
||||
FIELD_PREP(ADXL345_FIFO_CTL_MODE_MSK,
|
||||
ADXL345_FIFO_BYPASS));
|
||||
if (ret < 0)
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
static const struct regmap_config adxl345_i2c_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.volatile_reg = adxl345_is_volatile_reg,
|
||||
.cache_type = REGCACHE_MAPLE,
|
||||
};
|
||||
|
||||
static int adxl345_i2c_probe(struct i2c_client *client)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ static const struct regmap_config adxl345_spi_regmap_config = {
|
|||
.val_bits = 8,
|
||||
/* Setting bits 7 and 6 enables multiple-byte read */
|
||||
.read_flag_mask = BIT(7) | BIT(6),
|
||||
.volatile_reg = adxl345_is_volatile_reg,
|
||||
.cache_type = REGCACHE_MAPLE,
|
||||
};
|
||||
|
||||
static int adxl345_spi_setup(struct device *dev, struct regmap *regmap)
|
||||
|
|
|
|||
|
|
@ -666,8 +666,8 @@ static irqreturn_t adxl355_trigger_handler(int irq, void *p)
|
|||
if (ret)
|
||||
goto out_unlock_notify;
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer,
|
||||
pf->timestamp);
|
||||
iio_push_to_buffers_with_ts(indio_dev, &data->buffer,
|
||||
sizeof(data->buffer), pf->timestamp);
|
||||
|
||||
out_unlock_notify:
|
||||
mutex_unlock(&data->lock);
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ MODULE_DEVICE_TABLE(i2c, adxl367_i2c_id);
|
|||
|
||||
static const struct of_device_id adxl367_of_match[] = {
|
||||
{ .compatible = "adi,adxl367" },
|
||||
{ },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, adxl367_of_match);
|
||||
|
||||
|
|
|
|||
|
|
@ -139,13 +139,13 @@ static int adxl367_spi_probe(struct spi_device *spi)
|
|||
|
||||
static const struct spi_device_id adxl367_spi_id[] = {
|
||||
{ "adxl367", 0 },
|
||||
{ },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, adxl367_spi_id);
|
||||
|
||||
static const struct of_device_id adxl367_of_match[] = {
|
||||
{ .compatible = "adi,adxl367" },
|
||||
{ },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, adxl367_of_match);
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ static int adxl372_i2c_probe(struct i2c_client *client)
|
|||
|
||||
static const struct i2c_device_id adxl372_i2c_id[] = {
|
||||
{ "adxl372" },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, adxl372_i2c_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ static int adxl372_spi_probe(struct spi_device *spi)
|
|||
|
||||
static const struct spi_device_id adxl372_spi_id[] = {
|
||||
{ "adxl372", 0 },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, adxl372_spi_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -887,7 +887,7 @@ static irqreturn_t bma180_trigger_handler(int irq, void *p)
|
|||
|
||||
mutex_unlock(&data->mutex);
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, time_ns);
|
||||
iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), time_ns);
|
||||
err:
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ static irqreturn_t bma220_trigger_handler(int irq, void *p)
|
|||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
|
||||
iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan),
|
||||
pf->timestamp);
|
||||
err:
|
||||
mutex_unlock(&data->lock);
|
||||
|
|
@ -307,12 +307,12 @@ static DEFINE_SIMPLE_DEV_PM_OPS(bma220_pm_ops, bma220_suspend, bma220_resume);
|
|||
|
||||
static const struct spi_device_id bma220_spi_id[] = {
|
||||
{"bma220", 0},
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct acpi_device_id bma220_acpi_id[] = {
|
||||
{"BMA0220", 0},
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, bma220_spi_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -1591,7 +1591,8 @@ static irqreturn_t bma400_trigger_handler(int irq, void *p)
|
|||
data->buffer.temperature = temp;
|
||||
}
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer,
|
||||
iio_push_to_buffers_with_ts(indio_dev, &data->buffer,
|
||||
sizeof(data->buffer),
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
mutex_unlock(&data->mutex);
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ static const struct acpi_device_id bmc150_accel_acpi_match[] = {
|
|||
{"BOSC0200"},
|
||||
{"BSBA0150"},
|
||||
{"DUAL250E"},
|
||||
{ },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match);
|
||||
|
||||
|
|
@ -255,7 +255,7 @@ static const struct i2c_device_id bmc150_accel_id[] = {
|
|||
{"bmc150_accel"},
|
||||
{"bmc156_accel", BOSCH_BMC156},
|
||||
{"bmi055_accel"},
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, bmc150_accel_id);
|
||||
|
|
@ -271,7 +271,7 @@ static const struct of_device_id bmc150_accel_of_match[] = {
|
|||
{ .compatible = "bosch,bmc150_accel" },
|
||||
{ .compatible = "bosch,bmc156_accel" },
|
||||
{ .compatible = "bosch,bmi055_accel" },
|
||||
{ },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bmc150_accel_of_match);
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ static const struct acpi_device_id bmc150_accel_acpi_match[] = {
|
|||
{"BMC150A"},
|
||||
{"BMI055A"},
|
||||
{"BSBA0150"},
|
||||
{ },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match);
|
||||
|
||||
|
|
@ -62,7 +62,7 @@ static const struct spi_device_id bmc150_accel_id[] = {
|
|||
{"bmc150_accel"},
|
||||
{"bmc156_accel", BOSCH_BMC156},
|
||||
{"bmi055_accel"},
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, bmc150_accel_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ static const struct of_device_id bmi088_of_match[] = {
|
|||
{ .compatible = "bosch,bmi085-accel" },
|
||||
{ .compatible = "bosch,bmi088-accel" },
|
||||
{ .compatible = "bosch,bmi090l-accel" },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bmi088_of_match);
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ static const struct i2c_device_id bmi088_accel_id[] = {
|
|||
{ "bmi085-accel", BOSCH_BMI085 },
|
||||
{ "bmi088-accel", BOSCH_BMI088 },
|
||||
{ "bmi090l-accel", BOSCH_BMI090L },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, bmi088_accel_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ static const struct of_device_id bmi088_of_match[] = {
|
|||
{ .compatible = "bosch,bmi085-accel" },
|
||||
{ .compatible = "bosch,bmi088-accel" },
|
||||
{ .compatible = "bosch,bmi090l-accel" },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bmi088_of_match);
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ static const struct spi_device_id bmi088_accel_id[] = {
|
|||
{"bmi085-accel", BOSCH_BMI085},
|
||||
{"bmi088-accel", BOSCH_BMI088},
|
||||
{"bmi090l-accel", BOSCH_BMI090L},
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, bmi088_accel_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ static const struct da280_match_data da280_match_data = { "da280", 3 };
|
|||
static const struct acpi_device_id da280_acpi_match[] = {
|
||||
{ "NSA2513", (kernel_ulong_t)&da217_match_data },
|
||||
{ "MIRAACC", (kernel_ulong_t)&da280_match_data },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, da280_acpi_match);
|
||||
|
||||
|
|
@ -165,7 +165,7 @@ static const struct i2c_device_id da280_i2c_id[] = {
|
|||
{ "da217", (kernel_ulong_t)&da217_match_data },
|
||||
{ "da226", (kernel_ulong_t)&da226_match_data },
|
||||
{ "da280", (kernel_ulong_t)&da280_match_data },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, da280_i2c_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(da311_pm_ops, da311_suspend, da311_resume);
|
|||
|
||||
static const struct i2c_device_id da311_i2c_id[] = {
|
||||
{ "da311" },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, da311_i2c_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(dmard10_pm_ops, dmard10_suspend,
|
|||
|
||||
static const struct i2c_device_id dmard10_i2c_id[] = {
|
||||
{ "dmard10" },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, dmard10_i2c_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -994,8 +994,8 @@ static int fxls8962af_fifo_flush(struct iio_dev *indio_dev)
|
|||
sizeof(data->scan.channels[0]));
|
||||
}
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
|
||||
tstamp);
|
||||
iio_push_to_buffers_with_ts(indio_dev, &data->scan,
|
||||
sizeof(data->scan), tstamp);
|
||||
|
||||
tstamp += sample_period;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,14 +32,14 @@ static const struct i2c_device_id fxls8962af_id[] = {
|
|||
{ "fxls8964af", fxls8964af },
|
||||
{ "fxls8967af", fxls8967af },
|
||||
{ "fxls8974cf", fxls8974cf },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, fxls8962af_id);
|
||||
|
||||
static const struct of_device_id fxls8962af_of_match[] = {
|
||||
{ .compatible = "nxp,fxls8962af" },
|
||||
{ .compatible = "nxp,fxls8964af" },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, fxls8962af_of_match);
|
||||
|
||||
|
|
|
|||
|
|
@ -30,14 +30,14 @@ static int fxls8962af_probe(struct spi_device *spi)
|
|||
static const struct of_device_id fxls8962af_spi_of_match[] = {
|
||||
{ .compatible = "nxp,fxls8962af" },
|
||||
{ .compatible = "nxp,fxls8964af" },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, fxls8962af_spi_of_match);
|
||||
|
||||
static const struct spi_device_id fxls8962af_spi_id_table[] = {
|
||||
{ "fxls8962af", fxls8962af },
|
||||
{ "fxls8964af", fxls8964af },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, fxls8962af_spi_id_table);
|
||||
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ static void hid_sensor_push_data(struct iio_dev *indio_dev, void *data,
|
|||
int len, int64_t timestamp)
|
||||
{
|
||||
dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, data, timestamp);
|
||||
iio_push_to_buffers_with_ts(indio_dev, data, len, timestamp);
|
||||
}
|
||||
|
||||
/* Callback handler to send event after all samples are received and captured */
|
||||
|
|
@ -440,7 +440,7 @@ static const struct platform_device_id hid_accel_3d_ids[] = {
|
|||
{ /* gravity sensor */
|
||||
.name = "HID-SENSOR-20007b",
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, hid_accel_3d_ids);
|
||||
|
||||
|
|
|
|||
|
|
@ -674,8 +674,8 @@ static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
|
||||
bool status)
|
||||
static int kxcjk1013_setup_interrupt(struct kxcjk1013_data *data,
|
||||
bool status, bool is_new_data)
|
||||
{
|
||||
const struct kx_chipset_regs *regs = data->info->regs;
|
||||
int ret;
|
||||
|
|
@ -690,9 +690,11 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (is_new_data == true) {
|
||||
ret = kxcjk1013_chip_update_thresholds(data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = i2c_smbus_read_byte_data(data->client, regs->int_ctrl1);
|
||||
if (ret < 0) {
|
||||
|
|
@ -717,69 +719,17 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (status)
|
||||
ret |= KXCJK1013_REG_CTRL1_BIT_WUFE;
|
||||
else
|
||||
ret &= ~KXCJK1013_REG_CTRL1_BIT_WUFE;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret);
|
||||
if (ret < 0) {
|
||||
dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (store_mode == OPERATION) {
|
||||
ret = kxcjk1013_set_mode(data, OPERATION);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data,
|
||||
bool status)
|
||||
{
|
||||
const struct kx_chipset_regs *regs = data->info->regs;
|
||||
int ret;
|
||||
enum kxcjk1013_mode store_mode;
|
||||
|
||||
ret = kxcjk1013_get_mode(data, &store_mode);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* This is requirement by spec to change state to STANDBY */
|
||||
ret = kxcjk1013_set_mode(data, STANDBY);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = i2c_smbus_read_byte_data(data->client, regs->int_ctrl1);
|
||||
if (ret < 0) {
|
||||
dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (status)
|
||||
ret |= KXCJK1013_REG_INT_CTRL1_BIT_IEN;
|
||||
else
|
||||
ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(data->client, regs->int_ctrl1, ret);
|
||||
if (ret < 0) {
|
||||
dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1);
|
||||
if (ret < 0) {
|
||||
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (is_new_data) {
|
||||
if (status)
|
||||
ret |= KXCJK1013_REG_CTRL1_BIT_DRDY;
|
||||
else
|
||||
ret &= ~KXCJK1013_REG_CTRL1_BIT_DRDY;
|
||||
} else {
|
||||
if (status)
|
||||
ret |= KXCJK1013_REG_CTRL1_BIT_WUFE;
|
||||
else
|
||||
ret &= ~KXCJK1013_REG_CTRL1_BIT_WUFE;
|
||||
}
|
||||
|
||||
ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret);
|
||||
if (ret < 0) {
|
||||
|
|
@ -1112,7 +1062,7 @@ static int kxcjk1013_write_event_config(struct iio_dev *indio_dev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = kxcjk1013_setup_any_motion_interrupt(data, state);
|
||||
ret = kxcjk1013_setup_interrupt(data, state, false);
|
||||
if (ret < 0) {
|
||||
kxcjk1013_set_power_state(data, false);
|
||||
data->ev_enable_state = 0;
|
||||
|
|
@ -1253,7 +1203,7 @@ static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p)
|
|||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
|
||||
iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan),
|
||||
data->timestamp);
|
||||
err:
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
|
@ -1293,10 +1243,7 @@ static int kxcjk1013_data_rdy_trigger_set_state(struct iio_trigger *trig,
|
|||
mutex_unlock(&data->mutex);
|
||||
return ret;
|
||||
}
|
||||
if (data->motion_trig == trig)
|
||||
ret = kxcjk1013_setup_any_motion_interrupt(data, state);
|
||||
else
|
||||
ret = kxcjk1013_setup_new_data_interrupt(data, state);
|
||||
ret = kxcjk1013_setup_interrupt(data, state, data->motion_trig != trig);
|
||||
if (ret < 0) {
|
||||
kxcjk1013_set_power_state(data, false);
|
||||
mutex_unlock(&data->mutex);
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ static void kxsd9_i2c_remove(struct i2c_client *client)
|
|||
|
||||
static const struct of_device_id kxsd9_of_match[] = {
|
||||
{ .compatible = "kionix,kxsd9", },
|
||||
{ },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, kxsd9_of_match);
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ static void kxsd9_spi_remove(struct spi_device *spi)
|
|||
|
||||
static const struct spi_device_id kxsd9_spi_id[] = {
|
||||
{"kxsd9", 0},
|
||||
{ },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, kxsd9_spi_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -229,8 +229,7 @@ static irqreturn_t kxsd9_trigger_handler(int irq, void *p)
|
|||
goto out;
|
||||
}
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev,
|
||||
&hw_values,
|
||||
iio_push_to_buffers_with_ts(indio_dev, &hw_values, sizeof(hw_values),
|
||||
iio_get_time_ns(indio_dev));
|
||||
out:
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
|
@ -273,7 +272,7 @@ kxsd9_get_mount_matrix(const struct iio_dev *indio_dev,
|
|||
|
||||
static const struct iio_chan_spec_ext_info kxsd9_ext_info[] = {
|
||||
IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE, kxsd9_get_mount_matrix),
|
||||
{ },
|
||||
{ }
|
||||
};
|
||||
|
||||
#define KXSD9_ACCEL_CHAN(axis, index) \
|
||||
|
|
|
|||
|
|
@ -103,7 +103,8 @@ static irqreturn_t mma7455_trigger_handler(int irq, void *p)
|
|||
if (ret)
|
||||
goto done;
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &mma7455->scan,
|
||||
iio_push_to_buffers_with_ts(indio_dev, &mma7455->scan,
|
||||
sizeof(mma7455->scan),
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
done:
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(mma7660_pm_ops, mma7660_suspend,
|
|||
|
||||
static const struct i2c_device_id mma7660_i2c_id[] = {
|
||||
{ "mma7660" },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, mma7660_i2c_id);
|
||||
|
||||
|
|
@ -274,7 +274,7 @@ MODULE_DEVICE_TABLE(of, mma7660_of_match);
|
|||
|
||||
static const struct acpi_device_id mma7660_acpi_id[] = {
|
||||
{"MMA7660", 0},
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(acpi, mma7660_acpi_id);
|
||||
|
|
|
|||
|
|
@ -1103,7 +1103,8 @@ static irqreturn_t mma8452_trigger_handler(int irq, void *p)
|
|||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer,
|
||||
iio_push_to_buffers_with_ts(indio_dev, &data->buffer,
|
||||
sizeof(data->buffer),
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
done:
|
||||
|
|
|
|||
|
|
@ -578,14 +578,14 @@ static const struct dev_pm_ops mma9551_pm_ops = {
|
|||
|
||||
static const struct acpi_device_id mma9551_acpi_match[] = {
|
||||
{"MMA9551", 0},
|
||||
{},
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(acpi, mma9551_acpi_match);
|
||||
|
||||
static const struct i2c_device_id mma9551_id[] = {
|
||||
{ "mma9551" },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, mma9551_id);
|
||||
|
|
|
|||
|
|
@ -919,7 +919,7 @@ static const struct iio_enum mma9553_calibgender_enum = {
|
|||
static const struct iio_chan_spec_ext_info mma9553_ext_info[] = {
|
||||
IIO_ENUM("calibgender", IIO_SHARED_BY_TYPE, &mma9553_calibgender_enum),
|
||||
IIO_ENUM_AVAILABLE("calibgender", IIO_SHARED_BY_TYPE, &mma9553_calibgender_enum),
|
||||
{},
|
||||
{ }
|
||||
};
|
||||
|
||||
#define MMA9553_PEDOMETER_CHANNEL(_type, _mask) { \
|
||||
|
|
@ -1216,14 +1216,14 @@ static const struct dev_pm_ops mma9553_pm_ops = {
|
|||
|
||||
static const struct acpi_device_id mma9553_acpi_match[] = {
|
||||
{"MMA9553", 0},
|
||||
{},
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(acpi, mma9553_acpi_match);
|
||||
|
||||
static const struct i2c_device_id mma9553_id[] = {
|
||||
{ "mma9553" },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, mma9553_id);
|
||||
|
|
|
|||
|
|
@ -919,7 +919,7 @@ static irqreturn_t msa311_buffer_thread(int irq, void *p)
|
|||
|
||||
mutex_unlock(&msa311->lock);
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &buf,
|
||||
iio_push_to_buffers_with_ts(indio_dev, &buf, sizeof(buf),
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
notify_done:
|
||||
|
|
|
|||
|
|
@ -335,7 +335,7 @@ static irqreturn_t mxc4005_trigger_handler(int irq, void *private)
|
|||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
|
||||
iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan),
|
||||
pf->timestamp);
|
||||
|
||||
err:
|
||||
|
|
@ -573,14 +573,14 @@ static const struct acpi_device_id mxc4005_acpi_match[] = {
|
|||
{"MXC4005", 0},
|
||||
{"MXC6655", 0},
|
||||
{"MDA6655", 0},
|
||||
{ },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, mxc4005_acpi_match);
|
||||
|
||||
static const struct of_device_id mxc4005_of_match[] = {
|
||||
{ .compatible = "memsic,mxc4005", },
|
||||
{ .compatible = "memsic,mxc6655", },
|
||||
{ },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mxc4005_of_match);
|
||||
|
||||
|
|
|
|||
|
|
@ -1541,7 +1541,7 @@ static const struct spi_device_id sca3000_id[] = {
|
|||
{"sca3000_e02", e02},
|
||||
{"sca3000_e04", e04},
|
||||
{"sca3000_e05", e05},
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, sca3000_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -58,15 +58,6 @@ enum sca3300_scan_indexes {
|
|||
SCA3300_SCAN_MAX
|
||||
};
|
||||
|
||||
/*
|
||||
* Buffer size max case:
|
||||
* Three accel channels, two bytes per channel.
|
||||
* Temperature channel, two bytes.
|
||||
* Three incli channels, two bytes per channel.
|
||||
* Timestamp channel, eight bytes.
|
||||
*/
|
||||
#define SCA3300_MAX_BUFFER_SIZE (ALIGN(sizeof(s16) * SCA3300_SCAN_MAX, sizeof(s64)) + sizeof(s64))
|
||||
|
||||
#define SCA3300_ACCEL_CHANNEL(index, reg, axis) { \
|
||||
.type = IIO_ACCEL, \
|
||||
.address = reg, \
|
||||
|
|
@ -193,9 +184,6 @@ struct sca3300_chip_info {
|
|||
* @spi: SPI device structure
|
||||
* @lock: Data buffer lock
|
||||
* @chip: Sensor chip specific information
|
||||
* @buffer: Triggered buffer:
|
||||
* -SCA3300: 4 channel 16-bit data + 64-bit timestamp
|
||||
* -SCL3300: 7 channel 16-bit data + 64-bit timestamp
|
||||
* @txbuf: Transmit buffer
|
||||
* @rxbuf: Receive buffer
|
||||
*/
|
||||
|
|
@ -203,7 +191,6 @@ struct sca3300_data {
|
|||
struct spi_device *spi;
|
||||
struct mutex lock;
|
||||
const struct sca3300_chip_info *chip;
|
||||
u8 buffer[SCA3300_MAX_BUFFER_SIZE] __aligned(sizeof(s64));
|
||||
u8 txbuf[4] __aligned(IIO_DMA_MINALIGN);
|
||||
u8 rxbuf[4];
|
||||
};
|
||||
|
|
@ -492,7 +479,7 @@ static irqreturn_t sca3300_trigger_handler(int irq, void *p)
|
|||
struct iio_dev *indio_dev = pf->indio_dev;
|
||||
struct sca3300_data *data = iio_priv(indio_dev);
|
||||
int bit, ret, val, i = 0;
|
||||
s16 *channels = (s16 *)data->buffer;
|
||||
IIO_DECLARE_BUFFER_WITH_TS(s16, channels, SCA3300_SCAN_MAX);
|
||||
|
||||
iio_for_each_active_channel(indio_dev, bit) {
|
||||
ret = sca3300_read_reg(data, indio_dev->channels[bit].address, &val);
|
||||
|
|
@ -505,7 +492,7 @@ static irqreturn_t sca3300_trigger_handler(int irq, void *p)
|
|||
channels[i++] = val;
|
||||
}
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
|
||||
iio_push_to_buffers_with_ts(indio_dev, channels, sizeof(channels),
|
||||
iio_get_time_ns(indio_dev));
|
||||
out:
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
|
@ -674,14 +661,14 @@ static int sca3300_probe(struct spi_device *spi)
|
|||
static const struct of_device_id sca3300_dt_ids[] = {
|
||||
{ .compatible = "murata,sca3300"},
|
||||
{ .compatible = "murata,scl3300"},
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sca3300_dt_ids);
|
||||
|
||||
static const struct spi_device_id sca3300_ids[] = {
|
||||
{ "sca3300" },
|
||||
{ "scl3300" },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, sca3300_ids);
|
||||
|
||||
|
|
|
|||
|
|
@ -126,14 +126,14 @@ static const struct of_device_id st_accel_of_match[] = {
|
|||
.compatible = "st,iis328dq",
|
||||
.data = IIS328DQ_ACCEL_DEV_NAME,
|
||||
},
|
||||
{},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, st_accel_of_match);
|
||||
|
||||
static const struct acpi_device_id st_accel_acpi_match[] = {
|
||||
{"SMO8840", (kernel_ulong_t)LIS2DH12_ACCEL_DEV_NAME},
|
||||
{"SMO8A90", (kernel_ulong_t)LNG2DM_ACCEL_DEV_NAME},
|
||||
{ },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, st_accel_acpi_match);
|
||||
|
||||
|
|
@ -164,7 +164,7 @@ static const struct i2c_device_id st_accel_id_table[] = {
|
|||
{ LSM303C_ACCEL_DEV_NAME },
|
||||
{ SC7A20_ACCEL_DEV_NAME },
|
||||
{ IIS328DQ_ACCEL_DEV_NAME },
|
||||
{},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
|
||||
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ static const struct of_device_id st_accel_of_match[] = {
|
|||
.compatible = "st,iis328dq",
|
||||
.data = IIS328DQ_ACCEL_DEV_NAME,
|
||||
},
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, st_accel_of_match);
|
||||
|
||||
|
|
@ -167,7 +167,7 @@ static const struct spi_device_id st_accel_id_table[] = {
|
|||
{ LIS302DL_ACCEL_DEV_NAME },
|
||||
{ LSM303C_ACCEL_DEV_NAME },
|
||||
{ IIS328DQ_ACCEL_DEV_NAME },
|
||||
{},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, st_accel_id_table);
|
||||
|
||||
|
|
|
|||
|
|
@ -460,7 +460,7 @@ static irqreturn_t stk8312_trigger_handler(int irq, void *p)
|
|||
}
|
||||
mutex_unlock(&data->lock);
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
|
||||
iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan),
|
||||
pf->timestamp);
|
||||
err:
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
|
@ -635,7 +635,7 @@ static const struct i2c_device_id stk8312_i2c_id[] = {
|
|||
/* Deprecated in favour of lowercase form */
|
||||
{ "STK8312" },
|
||||
{ "stk8312" },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, stk8312_i2c_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -340,7 +340,7 @@ static irqreturn_t stk8ba50_trigger_handler(int irq, void *p)
|
|||
data->scan.chans[i++] = ret;
|
||||
}
|
||||
}
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
|
||||
iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan),
|
||||
pf->timestamp);
|
||||
err:
|
||||
mutex_unlock(&data->lock);
|
||||
|
|
@ -526,13 +526,13 @@ static DEFINE_SIMPLE_DEV_PM_OPS(stk8ba50_pm_ops, stk8ba50_suspend,
|
|||
|
||||
static const struct i2c_device_id stk8ba50_i2c_id[] = {
|
||||
{ "stk8ba50" },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, stk8ba50_i2c_id);
|
||||
|
||||
static const struct acpi_device_id stk8ba50_acpi_id[] = {
|
||||
{"STK8BA50", 0},
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(acpi, stk8ba50_acpi_id);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
menu "Analog to digital converters"
|
||||
|
||||
config IIO_ADC_HELPER
|
||||
tristate
|
||||
|
||||
config AB8500_GPADC
|
||||
bool "ST-Ericsson AB8500 GPADC driver"
|
||||
depends on AB8500_CORE && REGULATOR_AB8500
|
||||
|
|
@ -25,10 +28,15 @@ config AD4000
|
|||
tristate "Analog Devices AD4000 ADC Driver"
|
||||
depends on SPI
|
||||
select IIO_BUFFER
|
||||
select IIO_BUFFER_DMAENGINE
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
select SPI_OFFLOAD
|
||||
help
|
||||
Say yes here to build support for Analog Devices AD4000 high speed
|
||||
SPI analog to digital converters (ADC).
|
||||
SPI analog to digital converters (ADC). If intended to use with
|
||||
SPI offloading support, it is recommended to enable
|
||||
CONFIG_SPI_AXI_SPI_ENGINE, CONFIG_PWM_AXI_PWMGEN, and
|
||||
CONFIG_SPI_OFFLOAD_TRIGGER_PWM.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
called ad4000.
|
||||
|
|
@ -282,6 +290,8 @@ config AD7606_IFACE_SPI
|
|||
tristate "Analog Devices AD7606 ADC driver with spi interface support"
|
||||
depends on SPI
|
||||
select AD7606
|
||||
select IIO_BUFFER_DMAENGINE
|
||||
select SPI_OFFLOAD
|
||||
help
|
||||
Say yes here to build spi interface support for Analog Devices:
|
||||
ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC).
|
||||
|
|
@ -320,6 +330,7 @@ config AD7766
|
|||
config AD7768_1
|
||||
tristate "Analog Devices AD7768-1 ADC driver"
|
||||
depends on SPI
|
||||
select REGMAP_SPI
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
|
|
@ -1093,6 +1104,17 @@ config NAU7802
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called nau7802.
|
||||
|
||||
config NCT7201
|
||||
tristate "Nuvoton Instruments NCT7201 and NCT7202 Power Monitor"
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
help
|
||||
If you say yes here you get support for the Nuvoton NCT7201 and
|
||||
NCT7202 Voltage Monitor.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called nct7201.
|
||||
|
||||
config NPCM_ADC
|
||||
tristate "Nuvoton NPCM ADC driver"
|
||||
depends on ARCH_NPCM || COMPILE_TEST
|
||||
|
|
@ -1233,6 +1255,18 @@ config RN5T618_ADC
|
|||
This driver can also be built as a module. If so, the module
|
||||
will be called rn5t618-adc.
|
||||
|
||||
config ROHM_BD79124
|
||||
tristate "Rohm BD79124 ADC driver"
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
select IIO_ADC_HELPER
|
||||
help
|
||||
Say yes here to build support for the ROHM BD79124 ADC. The
|
||||
ROHM BD79124 is a 12-bit, 8-channel, SAR ADC. The ADC supports
|
||||
also an automatic measurement mode, with an alarm interrupt for
|
||||
out-of-window measurements. The window is configurable for each
|
||||
channel.
|
||||
|
||||
config ROCKCHIP_SARADC
|
||||
tristate "Rockchip SARADC driver"
|
||||
depends on ARCH_ROCKCHIP || COMPILE_TEST
|
||||
|
|
@ -1264,6 +1298,7 @@ config RICHTEK_RTQ6056
|
|||
config RZG2L_ADC
|
||||
tristate "Renesas RZ/G2L ADC driver"
|
||||
depends on ARCH_RZG2L || COMPILE_TEST
|
||||
select IIO_ADC_HELPER
|
||||
help
|
||||
Say yes here to build support for the ADC found in Renesas
|
||||
RZ/G2L family.
|
||||
|
|
@ -1398,6 +1433,7 @@ config SUN4I_GPADC
|
|||
config SUN20I_GPADC
|
||||
tristate "Allwinner D1/T113s/T507/R329 and similar GPADCs driver"
|
||||
depends on ARCH_SUNXI || COMPILE_TEST
|
||||
select IIO_ADC_HELPER
|
||||
help
|
||||
Say yes here to build support for Allwinner (D1, T113, T507 and R329)
|
||||
SoCs GPADC. This ADC provides up to 16 channels.
|
||||
|
|
@ -1441,18 +1477,6 @@ config TI_ADC084S021
|
|||
This driver can also be built as a module. If so, the module will be
|
||||
called ti-adc084s021.
|
||||
|
||||
config TI_ADC12138
|
||||
tristate "Texas Instruments ADC12130/ADC12132/ADC12138"
|
||||
depends on SPI
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
help
|
||||
If you say yes here you get support for Texas Instruments ADC12130,
|
||||
ADC12132 and ADC12138 chips.
|
||||
|
||||
This driver can also be built as a module. If so, the module will be
|
||||
called ti-adc12138.
|
||||
|
||||
config TI_ADC108S102
|
||||
tristate "Texas Instruments ADC108S102 and ADC128S102 driver"
|
||||
depends on SPI
|
||||
|
|
@ -1465,12 +1489,24 @@ config TI_ADC108S102
|
|||
To compile this driver as a module, choose M here: the module will
|
||||
be called ti-adc108s102.
|
||||
|
||||
config TI_ADC12138
|
||||
tristate "Texas Instruments ADC12130/ADC12132/ADC12138"
|
||||
depends on SPI
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
help
|
||||
If you say yes here you get support for Texas Instruments ADC12130,
|
||||
ADC12132 and ADC12138 chips.
|
||||
|
||||
This driver can also be built as a module. If so, the module will be
|
||||
called ti-adc12138.
|
||||
|
||||
config TI_ADC128S052
|
||||
tristate "Texas Instruments ADC128S052/ADC122S021/ADC124S021"
|
||||
depends on SPI
|
||||
help
|
||||
If you say yes here you get support for Texas Instruments ADC128S052,
|
||||
ADC122S021 and ADC124S021 chips.
|
||||
ADC122S021, ADC124S021 and ROHM Semiconductor BD79104 chips.
|
||||
|
||||
This driver can also be built as a module. If so, the module will be
|
||||
called ti-adc128s052.
|
||||
|
|
@ -1500,6 +1536,16 @@ config TI_ADS1015
|
|||
This driver can also be built as a module. If so, the module will be
|
||||
called ti-ads1015.
|
||||
|
||||
config TI_ADS1100
|
||||
tristate "Texas Instruments ADS1100 and ADS1000 ADC"
|
||||
depends on I2C
|
||||
help
|
||||
If you say yes here you get support for Texas Instruments ADS1100 and
|
||||
ADS1000 ADC chips.
|
||||
|
||||
This driver can also be built as a module. If so, the module will be
|
||||
called ti-ads1100.
|
||||
|
||||
config TI_ADS1119
|
||||
tristate "Texas Instruments ADS1119 ADC"
|
||||
depends on I2C
|
||||
|
|
@ -1512,6 +1558,42 @@ config TI_ADS1119
|
|||
This driver can also be built as a module. If so, the module will be
|
||||
called ti-ads1119.
|
||||
|
||||
config TI_ADS124S08
|
||||
tristate "Texas Instruments ADS124S08"
|
||||
depends on SPI
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
help
|
||||
If you say yes here you get support for Texas Instruments ADS124S08
|
||||
and ADS124S06 ADC chips
|
||||
|
||||
This driver can also be built as a module. If so, the module will be
|
||||
called ti-ads124s08.
|
||||
|
||||
config TI_ADS1298
|
||||
tristate "Texas Instruments ADS1298"
|
||||
depends on SPI
|
||||
select IIO_BUFFER
|
||||
select IIO_KFIFO_BUF
|
||||
help
|
||||
If you say yes here you get support for Texas Instruments ADS1298
|
||||
medical ADC chips
|
||||
|
||||
This driver can also be built as a module. If so, the module will be
|
||||
called ti-ads1298.
|
||||
|
||||
config TI_ADS131E08
|
||||
tristate "Texas Instruments ADS131E08"
|
||||
depends on SPI
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
help
|
||||
Say yes here to get support for Texas Instruments ADS131E04, ADS131E06
|
||||
and ADS131E08 chips.
|
||||
|
||||
This driver can also be built as a module. If so, the module will be
|
||||
called ti-ads131e08.
|
||||
|
||||
config TI_ADS7138
|
||||
tristate "Texas Instruments ADS7128 and ADS7138 ADC driver"
|
||||
depends on I2C
|
||||
|
|
@ -1533,27 +1615,6 @@ config TI_ADS7924
|
|||
This driver can also be built as a module. If so, the module will be
|
||||
called ti-ads7924.
|
||||
|
||||
config TI_ADS1100
|
||||
tristate "Texas Instruments ADS1100 and ADS1000 ADC"
|
||||
depends on I2C
|
||||
help
|
||||
If you say yes here you get support for Texas Instruments ADS1100 and
|
||||
ADS1000 ADC chips.
|
||||
|
||||
This driver can also be built as a module. If so, the module will be
|
||||
called ti-ads1100.
|
||||
|
||||
config TI_ADS1298
|
||||
tristate "Texas Instruments ADS1298"
|
||||
depends on SPI
|
||||
select IIO_BUFFER
|
||||
help
|
||||
If you say yes here you get support for Texas Instruments ADS1298
|
||||
medical ADC chips
|
||||
|
||||
This driver can also be built as a module. If so, the module will be
|
||||
called ti-ads1298.
|
||||
|
||||
config TI_ADS7950
|
||||
tristate "Texas Instruments ADS7950 ADC driver"
|
||||
depends on SPI && GPIOLIB
|
||||
|
|
@ -1589,30 +1650,6 @@ config TI_ADS8688
|
|||
This driver can also be built as a module. If so, the module will be
|
||||
called ti-ads8688.
|
||||
|
||||
config TI_ADS124S08
|
||||
tristate "Texas Instruments ADS124S08"
|
||||
depends on SPI
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
help
|
||||
If you say yes here you get support for Texas Instruments ADS124S08
|
||||
and ADS124S06 ADC chips
|
||||
|
||||
This driver can also be built as a module. If so, the module will be
|
||||
called ti-ads124s08.
|
||||
|
||||
config TI_ADS131E08
|
||||
tristate "Texas Instruments ADS131E08"
|
||||
depends on SPI
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
help
|
||||
Say yes here to get support for Texas Instruments ADS131E04, ADS131E06
|
||||
and ADS131E08 chips.
|
||||
|
||||
This driver can also be built as a module. If so, the module will be
|
||||
called ti-ads131e08.
|
||||
|
||||
config TI_AM335X_ADC
|
||||
tristate "TI's AM335X ADC driver"
|
||||
depends on MFD_TI_AM335X_TSCADC && HAS_DMA
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
# Makefile for IIO ADC drivers
|
||||
#
|
||||
|
||||
obj-$(CONFIG_IIO_ADC_HELPER) += industrialio-adc.o
|
||||
|
||||
# When adding new entries keep the list in alphabetical order
|
||||
obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o
|
||||
obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
|
||||
|
|
@ -97,6 +99,7 @@ obj-$(CONFIG_MESON_SARADC) += meson_saradc.o
|
|||
obj-$(CONFIG_MP2629_ADC) += mp2629_adc.o
|
||||
obj-$(CONFIG_MXS_LRADC_ADC) += mxs-lradc-adc.o
|
||||
obj-$(CONFIG_NAU7802) += nau7802.o
|
||||
obj-$(CONFIG_NCT7201) += nct7201.o
|
||||
obj-$(CONFIG_NPCM_ADC) += npcm_adc.o
|
||||
obj-$(CONFIG_PAC1921) += pac1921.o
|
||||
obj-$(CONFIG_PAC1934) += pac1934.o
|
||||
|
|
@ -110,6 +113,7 @@ obj-$(CONFIG_QCOM_VADC_COMMON) += qcom-vadc-common.o
|
|||
obj-$(CONFIG_RCAR_GYRO_ADC) += rcar-gyroadc.o
|
||||
obj-$(CONFIG_RICHTEK_RTQ6056) += rtq6056.o
|
||||
obj-$(CONFIG_RN5T618_ADC) += rn5t618-adc.o
|
||||
obj-$(CONFIG_ROHM_BD79124) += rohm-bd79124.o
|
||||
obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
|
||||
obj-$(CONFIG_RZG2L_ADC) += rzg2l_adc.o
|
||||
obj-$(CONFIG_SC27XX_ADC) += sc27xx_adc.o
|
||||
|
|
|
|||
|
|
@ -15,12 +15,14 @@
|
|||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/spi/offload/consumer.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/units.h>
|
||||
#include <linux/util_macros.h>
|
||||
#include <linux/iio/iio.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/buffer-dmaengine.h>
|
||||
#include <linux/iio/triggered_buffer.h>
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
|
||||
|
|
@ -32,10 +34,11 @@
|
|||
/* AD4000 Configuration Register programmable bits */
|
||||
#define AD4000_CFG_SPAN_COMP BIT(3) /* Input span compression */
|
||||
#define AD4000_CFG_HIGHZ BIT(2) /* High impedance mode */
|
||||
#define AD4000_CFG_TURBO BIT(1) /* Turbo mode */
|
||||
|
||||
#define AD4000_SCALE_OPTIONS 2
|
||||
|
||||
#define __AD4000_DIFF_CHANNEL(_sign, _real_bits, _storage_bits, _reg_access) \
|
||||
#define __AD4000_DIFF_CHANNEL(_sign, _real_bits, _storage_bits, _reg_access, _offl)\
|
||||
{ \
|
||||
.type = IIO_VOLTAGE, \
|
||||
.indexed = 1, \
|
||||
|
|
@ -43,54 +46,65 @@
|
|||
.channel = 0, \
|
||||
.channel2 = 1, \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||
BIT(IIO_CHAN_INFO_SCALE), \
|
||||
BIT(IIO_CHAN_INFO_SCALE) | \
|
||||
(_offl ? BIT(IIO_CHAN_INFO_SAMP_FREQ) : 0), \
|
||||
.info_mask_separate_available = _reg_access ? BIT(IIO_CHAN_INFO_SCALE) : 0,\
|
||||
.scan_index = 0, \
|
||||
.scan_type = { \
|
||||
.sign = _sign, \
|
||||
.realbits = _real_bits, \
|
||||
.storagebits = _storage_bits, \
|
||||
.shift = _storage_bits - _real_bits, \
|
||||
.endianness = IIO_BE, \
|
||||
.shift = (_offl ? 0 : _storage_bits - _real_bits), \
|
||||
.endianness = _offl ? IIO_CPU : IIO_BE \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define AD4000_DIFF_CHANNEL(_sign, _real_bits, _reg_access) \
|
||||
#define AD4000_DIFF_CHANNEL(_sign, _real_bits, _reg_access, _offl) \
|
||||
__AD4000_DIFF_CHANNEL((_sign), (_real_bits), \
|
||||
((_real_bits) > 16 ? 32 : 16), (_reg_access))
|
||||
(((_offl) || ((_real_bits) > 16)) ? 32 : 16), \
|
||||
(_reg_access), (_offl))
|
||||
|
||||
/*
|
||||
* When SPI offload is configured, transfers are executed without CPU
|
||||
* intervention so no soft timestamp can be recorded when transfers run.
|
||||
* Because of that, the macros that set timestamp channel are only used when
|
||||
* transfers are not offloaded.
|
||||
*/
|
||||
#define AD4000_DIFF_CHANNELS(_sign, _real_bits, _reg_access) \
|
||||
{ \
|
||||
AD4000_DIFF_CHANNEL(_sign, _real_bits, _reg_access), \
|
||||
AD4000_DIFF_CHANNEL(_sign, _real_bits, _reg_access, 0), \
|
||||
IIO_CHAN_SOFT_TIMESTAMP(1), \
|
||||
}
|
||||
|
||||
#define __AD4000_PSEUDO_DIFF_CHANNEL(_sign, _real_bits, _storage_bits, _reg_access)\
|
||||
#define __AD4000_PSEUDO_DIFF_CHANNEL(_sign, _real_bits, _storage_bits, \
|
||||
_reg_access, _offl) \
|
||||
{ \
|
||||
.type = IIO_VOLTAGE, \
|
||||
.indexed = 1, \
|
||||
.channel = 0, \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||
BIT(IIO_CHAN_INFO_SCALE) | \
|
||||
BIT(IIO_CHAN_INFO_OFFSET), \
|
||||
BIT(IIO_CHAN_INFO_OFFSET) | \
|
||||
(_offl ? BIT(IIO_CHAN_INFO_SAMP_FREQ) : 0), \
|
||||
.info_mask_separate_available = _reg_access ? BIT(IIO_CHAN_INFO_SCALE) : 0,\
|
||||
.scan_index = 0, \
|
||||
.scan_type = { \
|
||||
.sign = _sign, \
|
||||
.realbits = _real_bits, \
|
||||
.storagebits = _storage_bits, \
|
||||
.shift = _storage_bits - _real_bits, \
|
||||
.endianness = IIO_BE, \
|
||||
.shift = (_offl ? 0 : _storage_bits - _real_bits), \
|
||||
.endianness = _offl ? IIO_CPU : IIO_BE \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define AD4000_PSEUDO_DIFF_CHANNEL(_sign, _real_bits, _reg_access) \
|
||||
#define AD4000_PSEUDO_DIFF_CHANNEL(_sign, _real_bits, _reg_access, _offl) \
|
||||
__AD4000_PSEUDO_DIFF_CHANNEL((_sign), (_real_bits), \
|
||||
((_real_bits) > 16 ? 32 : 16), (_reg_access))
|
||||
(((_offl) || ((_real_bits) > 16)) ? 32 : 16),\
|
||||
(_reg_access), (_offl))
|
||||
|
||||
#define AD4000_PSEUDO_DIFF_CHANNELS(_sign, _real_bits, _reg_access) \
|
||||
{ \
|
||||
AD4000_PSEUDO_DIFF_CHANNEL(_sign, _real_bits, _reg_access), \
|
||||
AD4000_PSEUDO_DIFF_CHANNEL(_sign, _real_bits, _reg_access, 0), \
|
||||
IIO_CHAN_SOFT_TIMESTAMP(1), \
|
||||
}
|
||||
|
||||
|
|
@ -184,212 +198,298 @@ struct ad4000_chip_info {
|
|||
const char *dev_name;
|
||||
struct iio_chan_spec chan_spec[2];
|
||||
struct iio_chan_spec reg_access_chan_spec[2];
|
||||
struct iio_chan_spec offload_chan_spec;
|
||||
struct iio_chan_spec reg_access_offload_chan_spec;
|
||||
const struct ad4000_time_spec *time_spec;
|
||||
bool has_hardware_gain;
|
||||
int max_rate_hz;
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4000_chip_info = {
|
||||
.dev_name = "ad4000",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
|
||||
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 1),
|
||||
.offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0, 1),
|
||||
.reg_access_offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 1, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
.max_rate_hz = 2 * MEGA,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4001_chip_info = {
|
||||
.dev_name = "ad4001",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 16, 1),
|
||||
.offload_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 0, 1),
|
||||
.reg_access_offload_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 1, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
.max_rate_hz = 2 * MEGA,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4002_chip_info = {
|
||||
.dev_name = "ad4002",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 1),
|
||||
.offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18, 0, 1),
|
||||
.reg_access_offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18, 1, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
.max_rate_hz = 2 * MEGA,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4003_chip_info = {
|
||||
.dev_name = "ad4003",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 18, 1),
|
||||
.offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 0, 1),
|
||||
.reg_access_offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 1, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
.max_rate_hz = 2 * MEGA,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4004_chip_info = {
|
||||
.dev_name = "ad4004",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
|
||||
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 1),
|
||||
.offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0, 1),
|
||||
.reg_access_offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 1, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
.max_rate_hz = 1 * MEGA,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4005_chip_info = {
|
||||
.dev_name = "ad4005",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 16, 1),
|
||||
.offload_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 0, 1),
|
||||
.reg_access_offload_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 1, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
.max_rate_hz = 1 * MEGA,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4006_chip_info = {
|
||||
.dev_name = "ad4006",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 1),
|
||||
.offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18, 0, 1),
|
||||
.reg_access_offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18, 1, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
.max_rate_hz = 1 * MEGA,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4007_chip_info = {
|
||||
.dev_name = "ad4007",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 18, 1),
|
||||
.offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 0, 1),
|
||||
.reg_access_offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 1, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
.max_rate_hz = 1 * MEGA,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4008_chip_info = {
|
||||
.dev_name = "ad4008",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
|
||||
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 1),
|
||||
.offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0, 1),
|
||||
.reg_access_offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 1, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
.max_rate_hz = 500 * KILO,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4010_chip_info = {
|
||||
.dev_name = "ad4010",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 1),
|
||||
.offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18, 0, 1),
|
||||
.reg_access_offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18, 1, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
.max_rate_hz = 500 * KILO,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4011_chip_info = {
|
||||
.dev_name = "ad4011",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 18, 1),
|
||||
.offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 0, 1),
|
||||
.reg_access_offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 1, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
.max_rate_hz = 500 * KILO,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4020_chip_info = {
|
||||
.dev_name = "ad4020",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 20, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 20, 1),
|
||||
.offload_chan_spec = AD4000_DIFF_CHANNEL('s', 20, 0, 1),
|
||||
.reg_access_offload_chan_spec = AD4000_DIFF_CHANNEL('s', 20, 1, 1),
|
||||
.time_spec = &ad4020_t_spec,
|
||||
.max_rate_hz = 1800 * KILO,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4021_chip_info = {
|
||||
.dev_name = "ad4021",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 20, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 20, 1),
|
||||
.offload_chan_spec = AD4000_DIFF_CHANNEL('s', 20, 0, 1),
|
||||
.reg_access_offload_chan_spec = AD4000_DIFF_CHANNEL('s', 20, 1, 1),
|
||||
.time_spec = &ad4020_t_spec,
|
||||
.max_rate_hz = 1 * MEGA,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad4022_chip_info = {
|
||||
.dev_name = "ad4022",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 20, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 20, 1),
|
||||
.offload_chan_spec = AD4000_DIFF_CHANNEL('s', 20, 0, 1),
|
||||
.reg_access_offload_chan_spec = AD4000_DIFF_CHANNEL('s', 20, 1, 1),
|
||||
.time_spec = &ad4020_t_spec,
|
||||
.max_rate_hz = 500 * KILO,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info adaq4001_chip_info = {
|
||||
.dev_name = "adaq4001",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 16, 1),
|
||||
.offload_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 0, 1),
|
||||
.reg_access_offload_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 1, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
.has_hardware_gain = true,
|
||||
.max_rate_hz = 2 * MEGA,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info adaq4003_chip_info = {
|
||||
.dev_name = "adaq4003",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0),
|
||||
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 18, 1),
|
||||
.offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 0, 1),
|
||||
.reg_access_offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 1, 1),
|
||||
.time_spec = &ad4000_t_spec,
|
||||
.has_hardware_gain = true,
|
||||
.max_rate_hz = 2 * MEGA,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7685_chip_info = {
|
||||
.dev_name = "ad7685",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
|
||||
.offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0, 1),
|
||||
.time_spec = &ad7687_t_spec,
|
||||
.max_rate_hz = 250 * KILO,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7686_chip_info = {
|
||||
.dev_name = "ad7686",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
|
||||
.offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0, 1),
|
||||
.time_spec = &ad7686_t_spec,
|
||||
.max_rate_hz = 500 * KILO,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7687_chip_info = {
|
||||
.dev_name = "ad7687",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0),
|
||||
.offload_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 0, 1),
|
||||
.time_spec = &ad7687_t_spec,
|
||||
.max_rate_hz = 250 * KILO,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7688_chip_info = {
|
||||
.dev_name = "ad7688",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0),
|
||||
.offload_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 0, 1),
|
||||
.time_spec = &ad7686_t_spec,
|
||||
.max_rate_hz = 500 * KILO,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7690_chip_info = {
|
||||
.dev_name = "ad7690",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0),
|
||||
.offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 0, 1),
|
||||
.time_spec = &ad7690_t_spec,
|
||||
.max_rate_hz = 400 * KILO,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7691_chip_info = {
|
||||
.dev_name = "ad7691",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0),
|
||||
.offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 0, 1),
|
||||
.time_spec = &ad7691_t_spec,
|
||||
.max_rate_hz = 250 * KILO,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7693_chip_info = {
|
||||
.dev_name = "ad7693",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0),
|
||||
.offload_chan_spec = AD4000_DIFF_CHANNEL('s', 16, 0, 1),
|
||||
.time_spec = &ad7686_t_spec,
|
||||
.max_rate_hz = 500 * KILO,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7942_chip_info = {
|
||||
.dev_name = "ad7942",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 14, 0),
|
||||
.offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 14, 0, 1),
|
||||
.time_spec = &ad7687_t_spec,
|
||||
.max_rate_hz = 250 * KILO,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7946_chip_info = {
|
||||
.dev_name = "ad7946",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 14, 0),
|
||||
.offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 14, 0, 1),
|
||||
.time_spec = &ad7686_t_spec,
|
||||
.max_rate_hz = 500 * KILO,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7980_chip_info = {
|
||||
.dev_name = "ad7980",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
|
||||
.offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0, 1),
|
||||
.time_spec = &ad7980_t_spec,
|
||||
.max_rate_hz = 1 * MEGA,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7982_chip_info = {
|
||||
.dev_name = "ad7982",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0),
|
||||
.offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 0, 1),
|
||||
.time_spec = &ad7980_t_spec,
|
||||
.max_rate_hz = 1 * MEGA,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7983_chip_info = {
|
||||
.dev_name = "ad7983",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
|
||||
.offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0, 1),
|
||||
.time_spec = &ad7983_t_spec,
|
||||
.max_rate_hz = 1 * MEGA + 333 * KILO + 333,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7984_chip_info = {
|
||||
.dev_name = "ad7984",
|
||||
.chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0),
|
||||
.offload_chan_spec = AD4000_DIFF_CHANNEL('s', 18, 0, 1),
|
||||
.time_spec = &ad7983_t_spec,
|
||||
.max_rate_hz = 1 * MEGA + 333 * KILO + 333,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7988_1_chip_info = {
|
||||
.dev_name = "ad7988-1",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
|
||||
.offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0, 1),
|
||||
.time_spec = &ad7988_1_t_spec,
|
||||
.max_rate_hz = 100 * KILO,
|
||||
};
|
||||
|
||||
static const struct ad4000_chip_info ad7988_5_chip_info = {
|
||||
.dev_name = "ad7988-5",
|
||||
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
|
||||
.offload_chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16, 0, 1),
|
||||
.time_spec = &ad7686_t_spec,
|
||||
.max_rate_hz = 500 * KILO,
|
||||
};
|
||||
|
||||
static const struct spi_offload_config ad4000_offload_config = {
|
||||
.capability_flags = SPI_OFFLOAD_CAP_TRIGGER |
|
||||
SPI_OFFLOAD_CAP_RX_STREAM_DMA,
|
||||
};
|
||||
|
||||
struct ad4000_state {
|
||||
|
|
@ -397,6 +497,13 @@ struct ad4000_state {
|
|||
struct gpio_desc *cnv_gpio;
|
||||
struct spi_transfer xfers[2];
|
||||
struct spi_message msg;
|
||||
struct spi_transfer offload_xfer;
|
||||
struct spi_message offload_msg;
|
||||
struct spi_offload *offload;
|
||||
struct spi_offload_trigger *offload_trigger;
|
||||
bool using_offload;
|
||||
unsigned long offload_trigger_hz;
|
||||
int max_rate_hz;
|
||||
struct mutex lock; /* Protect read modify write cycle */
|
||||
int vref_mv;
|
||||
enum ad4000_sdi sdi_pin;
|
||||
|
|
@ -411,8 +518,10 @@ struct ad4000_state {
|
|||
*/
|
||||
struct {
|
||||
union {
|
||||
__be16 sample_buf16;
|
||||
__be32 sample_buf32;
|
||||
__be16 sample_buf16_be;
|
||||
__be32 sample_buf32_be;
|
||||
u16 sample_buf16;
|
||||
u32 sample_buf32;
|
||||
} data;
|
||||
aligned_s64 timestamp;
|
||||
} scan __aligned(IIO_DMA_MINALIGN);
|
||||
|
|
@ -487,6 +596,25 @@ static int ad4000_read_reg(struct ad4000_state *st, unsigned int *val)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ad4000_set_sampling_freq(struct ad4000_state *st, int freq)
|
||||
{
|
||||
struct spi_offload_trigger_config config = {
|
||||
.type = SPI_OFFLOAD_TRIGGER_PERIODIC,
|
||||
.periodic = {
|
||||
.frequency_hz = freq,
|
||||
},
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = spi_offload_trigger_validate(st->offload_trigger, &config);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
st->offload_trigger_hz = config.periodic.frequency_hz;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ad4000_convert_and_acquire(struct ad4000_state *st)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -515,10 +643,17 @@ static int ad4000_single_conversion(struct iio_dev *indio_dev,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (chan->scan_type.storagebits > 16)
|
||||
sample = be32_to_cpu(st->scan.data.sample_buf32);
|
||||
if (chan->scan_type.endianness == IIO_BE) {
|
||||
if (chan->scan_type.realbits > 16)
|
||||
sample = be32_to_cpu(st->scan.data.sample_buf32_be);
|
||||
else
|
||||
sample = be16_to_cpu(st->scan.data.sample_buf16);
|
||||
sample = be16_to_cpu(st->scan.data.sample_buf16_be);
|
||||
} else {
|
||||
if (chan->scan_type.realbits > 16)
|
||||
sample = st->scan.data.sample_buf32;
|
||||
else
|
||||
sample = st->scan.data.sample_buf16;
|
||||
}
|
||||
|
||||
sample >>= chan->scan_type.shift;
|
||||
|
||||
|
|
@ -554,6 +689,9 @@ static int ad4000_read_raw(struct iio_dev *indio_dev,
|
|||
if (st->span_comp)
|
||||
*val = mult_frac(st->vref_mv, 1, 10);
|
||||
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
*val = st->offload_trigger_hz;
|
||||
return IIO_VAL_INT;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
|
@ -620,6 +758,7 @@ static int ad4000_write_raw(struct iio_dev *indio_dev,
|
|||
struct iio_chan_spec const *chan,
|
||||
int val, int val2, long mask)
|
||||
{
|
||||
struct ad4000_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
switch (mask) {
|
||||
|
|
@ -629,6 +768,15 @@ static int ad4000_write_raw(struct iio_dev *indio_dev,
|
|||
ret = __ad4000_write_raw(indio_dev, chan, val2);
|
||||
iio_device_release_direct(indio_dev);
|
||||
return ret;
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
if (val < 1 || val > st->max_rate_hz)
|
||||
return -EINVAL;
|
||||
|
||||
if (!iio_device_claim_direct(indio_dev))
|
||||
return -EBUSY;
|
||||
ret = ad4000_set_sampling_freq(st, val);
|
||||
iio_device_release_direct(indio_dev);
|
||||
return ret;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -645,7 +793,8 @@ static irqreturn_t ad4000_trigger_handler(int irq, void *p)
|
|||
if (ret < 0)
|
||||
goto err_out;
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &st->scan, pf->timestamp);
|
||||
iio_push_to_buffers_with_ts(indio_dev, &st->scan, sizeof(st->scan),
|
||||
pf->timestamp);
|
||||
|
||||
err_out:
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
|
@ -659,10 +808,114 @@ static const struct iio_info ad4000_reg_access_info = {
|
|||
.write_raw_get_fmt = &ad4000_write_raw_get_fmt,
|
||||
};
|
||||
|
||||
static const struct iio_info ad4000_offload_info = {
|
||||
.read_raw = &ad4000_read_raw,
|
||||
.write_raw = &ad4000_write_raw,
|
||||
.write_raw_get_fmt = &ad4000_write_raw_get_fmt,
|
||||
};
|
||||
|
||||
static const struct iio_info ad4000_info = {
|
||||
.read_raw = &ad4000_read_raw,
|
||||
};
|
||||
|
||||
static int ad4000_offload_buffer_postenable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct ad4000_state *st = iio_priv(indio_dev);
|
||||
struct spi_offload_trigger_config config = {
|
||||
.type = SPI_OFFLOAD_TRIGGER_PERIODIC,
|
||||
.periodic = {
|
||||
.frequency_hz = st->offload_trigger_hz,
|
||||
},
|
||||
};
|
||||
|
||||
return spi_offload_trigger_enable(st->offload, st->offload_trigger,
|
||||
&config);
|
||||
}
|
||||
|
||||
static int ad4000_offload_buffer_predisable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct ad4000_state *st = iio_priv(indio_dev);
|
||||
|
||||
spi_offload_trigger_disable(st->offload, st->offload_trigger);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct iio_buffer_setup_ops ad4000_offload_buffer_setup_ops = {
|
||||
.postenable = &ad4000_offload_buffer_postenable,
|
||||
.predisable = &ad4000_offload_buffer_predisable,
|
||||
};
|
||||
|
||||
static int ad4000_spi_offload_setup(struct iio_dev *indio_dev,
|
||||
struct ad4000_state *st)
|
||||
{
|
||||
struct spi_device *spi = st->spi;
|
||||
struct device *dev = &spi->dev;
|
||||
struct dma_chan *rx_dma;
|
||||
int ret;
|
||||
|
||||
st->offload_trigger = devm_spi_offload_trigger_get(dev, st->offload,
|
||||
SPI_OFFLOAD_TRIGGER_PERIODIC);
|
||||
if (IS_ERR(st->offload_trigger))
|
||||
return dev_err_probe(dev, PTR_ERR(st->offload_trigger),
|
||||
"Failed to get offload trigger\n");
|
||||
|
||||
ret = ad4000_set_sampling_freq(st, st->max_rate_hz);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"Failed to set sampling frequency\n");
|
||||
|
||||
rx_dma = devm_spi_offload_rx_stream_request_dma_chan(dev, st->offload);
|
||||
if (IS_ERR(rx_dma))
|
||||
return dev_err_probe(dev, PTR_ERR(rx_dma),
|
||||
"Failed to get offload RX DMA\n");
|
||||
|
||||
ret = devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, rx_dma,
|
||||
IIO_BUFFER_DIRECTION_IN);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to setup DMA buffer\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This executes a data sample transfer when using SPI offloading. The device
|
||||
* connections should be in "3-wire" mode, selected either when the adi,sdi-pin
|
||||
* device tree property is absent or set to "high". Also, the ADC CNV pin must
|
||||
* be connected to a SPI controller CS (it can't be connected to a GPIO).
|
||||
*
|
||||
* In order to achieve the maximum sample rate, we only do one transfer per
|
||||
* SPI offload trigger. Because the ADC output has a one sample latency (delay)
|
||||
* when the device is wired in "3-wire" mode and only one transfer per sample is
|
||||
* being made in turbo mode, the first data sample is not valid because it
|
||||
* contains the output of an earlier conversion result. We also set transfer
|
||||
* `bits_per_word` to achieve higher throughput by using the minimum number of
|
||||
* SCLK cycles. Also, a delay is added to make sure we meet the minimum quiet
|
||||
* time before releasing the CS line.
|
||||
*
|
||||
* Note that, with `bits_per_word` set to the number of ADC precision bits,
|
||||
* transfers use larger word sizes that get stored in 'in-memory wordsizes' that
|
||||
* are always in native CPU byte order. Because of that, IIO buffer elements
|
||||
* ought to be read in CPU endianness which requires setting IIO scan_type
|
||||
* endianness accordingly (i.e. IIO_CPU).
|
||||
*/
|
||||
static int ad4000_prepare_offload_message(struct ad4000_state *st,
|
||||
const struct iio_chan_spec *chan)
|
||||
{
|
||||
struct spi_transfer *xfer = &st->offload_xfer;
|
||||
|
||||
xfer->bits_per_word = chan->scan_type.realbits;
|
||||
xfer->len = chan->scan_type.realbits > 16 ? 4 : 2;
|
||||
xfer->delay.value = st->time_spec->t_quiet2_ns;
|
||||
xfer->delay.unit = SPI_DELAY_UNIT_NSECS;
|
||||
xfer->offload_flags = SPI_OFFLOAD_XFER_RX_STREAM;
|
||||
|
||||
spi_message_init_with_transfers(&st->offload_msg, xfer, 1);
|
||||
st->offload_msg.offload = st->offload;
|
||||
|
||||
return devm_spi_optimize_message(&st->spi->dev, st->spi, &st->offload_msg);
|
||||
}
|
||||
|
||||
/*
|
||||
* This executes a data sample transfer for when the device connections are
|
||||
* in "3-wire" mode, selected when the adi,sdi-pin device tree property is
|
||||
|
|
@ -689,7 +942,16 @@ static int ad4000_prepare_3wire_mode_message(struct ad4000_state *st,
|
|||
xfers[0].cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
|
||||
|
||||
xfers[1].rx_buf = &st->scan.data;
|
||||
xfers[1].len = BITS_TO_BYTES(chan->scan_type.storagebits);
|
||||
xfers[1].len = chan->scan_type.realbits > 16 ? 4 : 2;
|
||||
|
||||
/*
|
||||
* If the device is set up for SPI offloading, IIO channel scan_type is
|
||||
* set to IIO_CPU. When that is the case, use larger SPI word sizes for
|
||||
* single-shot reads too. Thus, sample data can be correctly handled in
|
||||
* ad4000_single_conversion() according to scan_type endianness.
|
||||
*/
|
||||
if (chan->scan_type.endianness != IIO_BE)
|
||||
xfers[1].bits_per_word = chan->scan_type.realbits;
|
||||
xfers[1].delay.value = st->time_spec->t_quiet2_ns;
|
||||
xfers[1].delay.unit = SPI_DELAY_UNIT_NSECS;
|
||||
|
||||
|
|
@ -733,6 +995,9 @@ static int ad4000_config(struct ad4000_state *st)
|
|||
if (device_property_present(&st->spi->dev, "adi,high-z-input"))
|
||||
reg_val |= FIELD_PREP(AD4000_CFG_HIGHZ, 1);
|
||||
|
||||
if (st->using_offload)
|
||||
reg_val |= FIELD_PREP(AD4000_CFG_TURBO, 1);
|
||||
|
||||
return ad4000_write_reg(st, reg_val);
|
||||
}
|
||||
|
||||
|
|
@ -755,6 +1020,7 @@ static int ad4000_probe(struct spi_device *spi)
|
|||
st = iio_priv(indio_dev);
|
||||
st->spi = spi;
|
||||
st->time_spec = chip->time_spec;
|
||||
st->max_rate_hz = chip->max_rate_hz;
|
||||
|
||||
ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(ad4000_power_supplies),
|
||||
ad4000_power_supplies);
|
||||
|
|
@ -772,6 +1038,26 @@ static int ad4000_probe(struct spi_device *spi)
|
|||
return dev_err_probe(dev, PTR_ERR(st->cnv_gpio),
|
||||
"Failed to get CNV GPIO");
|
||||
|
||||
st->offload = devm_spi_offload_get(dev, spi, &ad4000_offload_config);
|
||||
ret = PTR_ERR_OR_ZERO(st->offload);
|
||||
if (ret && ret != -ENODEV)
|
||||
return dev_err_probe(dev, ret, "Failed to get offload\n");
|
||||
|
||||
st->using_offload = !IS_ERR(st->offload);
|
||||
if (st->using_offload) {
|
||||
indio_dev->setup_ops = &ad4000_offload_buffer_setup_ops;
|
||||
ret = ad4000_spi_offload_setup(indio_dev, st);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
|
||||
&iio_pollfunc_store_time,
|
||||
&ad4000_trigger_handler,
|
||||
NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = device_property_match_property_string(dev, "adi,sdi-pin",
|
||||
ad4000_sdi_pin,
|
||||
ARRAY_SIZE(ad4000_sdi_pin));
|
||||
|
|
@ -784,7 +1070,6 @@ static int ad4000_probe(struct spi_device *spi)
|
|||
switch (st->sdi_pin) {
|
||||
case AD4000_SDI_MOSI:
|
||||
indio_dev->info = &ad4000_reg_access_info;
|
||||
indio_dev->channels = chip->reg_access_chan_spec;
|
||||
|
||||
/*
|
||||
* In "3-wire mode", the ADC SDI line must be kept high when
|
||||
|
|
@ -796,9 +1081,26 @@ static int ad4000_probe(struct spi_device *spi)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (st->using_offload) {
|
||||
indio_dev->channels = &chip->reg_access_offload_chan_spec;
|
||||
indio_dev->num_channels = 1;
|
||||
ret = ad4000_prepare_offload_message(st, indio_dev->channels);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"Failed to optimize SPI msg\n");
|
||||
} else {
|
||||
indio_dev->channels = chip->reg_access_chan_spec;
|
||||
indio_dev->num_channels = ARRAY_SIZE(chip->reg_access_chan_spec);
|
||||
}
|
||||
|
||||
/*
|
||||
* Call ad4000_prepare_3wire_mode_message() so single-shot read
|
||||
* SPI messages are always initialized.
|
||||
*/
|
||||
ret = ad4000_prepare_3wire_mode_message(st, &indio_dev->channels[0]);
|
||||
if (ret)
|
||||
return ret;
|
||||
return dev_err_probe(dev, ret,
|
||||
"Failed to optimize SPI msg\n");
|
||||
|
||||
ret = ad4000_config(st);
|
||||
if (ret < 0)
|
||||
|
|
@ -806,19 +1108,38 @@ static int ad4000_probe(struct spi_device *spi)
|
|||
|
||||
break;
|
||||
case AD4000_SDI_VIO:
|
||||
if (st->using_offload) {
|
||||
indio_dev->info = &ad4000_offload_info;
|
||||
indio_dev->channels = &chip->offload_chan_spec;
|
||||
indio_dev->num_channels = 1;
|
||||
|
||||
ret = ad4000_prepare_offload_message(st, indio_dev->channels);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"Failed to optimize SPI msg\n");
|
||||
} else {
|
||||
indio_dev->info = &ad4000_info;
|
||||
indio_dev->channels = chip->chan_spec;
|
||||
indio_dev->num_channels = ARRAY_SIZE(chip->chan_spec);
|
||||
}
|
||||
|
||||
ret = ad4000_prepare_3wire_mode_message(st, &indio_dev->channels[0]);
|
||||
if (ret)
|
||||
return ret;
|
||||
return dev_err_probe(dev, ret,
|
||||
"Failed to optimize SPI msg\n");
|
||||
|
||||
break;
|
||||
case AD4000_SDI_CS:
|
||||
if (st->using_offload)
|
||||
return dev_err_probe(dev, -EPROTONOSUPPORT,
|
||||
"Unsupported sdi-pin + offload config\n");
|
||||
indio_dev->info = &ad4000_info;
|
||||
indio_dev->channels = chip->chan_spec;
|
||||
indio_dev->num_channels = ARRAY_SIZE(chip->chan_spec);
|
||||
ret = ad4000_prepare_4wire_mode_message(st, &indio_dev->channels[0]);
|
||||
if (ret)
|
||||
return ret;
|
||||
return dev_err_probe(dev, ret,
|
||||
"Failed to optimize SPI msg\n");
|
||||
|
||||
break;
|
||||
case AD4000_SDI_GND:
|
||||
|
|
@ -830,7 +1151,6 @@ static int ad4000_probe(struct spi_device *spi)
|
|||
}
|
||||
|
||||
indio_dev->name = chip->dev_name;
|
||||
indio_dev->num_channels = 2;
|
||||
|
||||
ret = devm_mutex_init(dev, &st->lock);
|
||||
if (ret)
|
||||
|
|
@ -853,12 +1173,6 @@ static int ad4000_probe(struct spi_device *spi)
|
|||
|
||||
ad4000_fill_scale_tbl(st, &indio_dev->channels[0]);
|
||||
|
||||
ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
|
||||
&iio_pollfunc_store_time,
|
||||
&ad4000_trigger_handler, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return devm_iio_device_register(dev, indio_dev);
|
||||
}
|
||||
|
||||
|
|
@ -947,3 +1261,4 @@ module_spi_driver(ad4000_driver);
|
|||
MODULE_AUTHOR("Marcelo Schmitt <marcelo.schmitt@analog.com>");
|
||||
MODULE_DESCRIPTION("Analog Devices AD4000 ADC driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_IMPORT_NS("IIO_DMAENGINE_BUFFER");
|
||||
|
|
|
|||
|
|
@ -147,7 +147,6 @@ struct ad4030_state {
|
|||
struct spi_device *spi;
|
||||
struct regmap *regmap;
|
||||
const struct ad4030_chip_info *chip;
|
||||
const struct iio_scan_type *current_scan_type;
|
||||
struct gpio_desc *cnv_gpio;
|
||||
int vref_uv;
|
||||
int vio_uv;
|
||||
|
|
@ -245,7 +244,6 @@ static int ad4030_enter_config_mode(struct ad4030_state *st)
|
|||
|
||||
struct spi_transfer xfer = {
|
||||
.tx_buf = st->tx_data,
|
||||
.bits_per_word = 8,
|
||||
.len = 1,
|
||||
.speed_hz = AD4030_SPI_MAX_REG_XFER_SPEED,
|
||||
};
|
||||
|
|
@ -261,7 +259,6 @@ static int ad4030_exit_config_mode(struct ad4030_state *st)
|
|||
|
||||
struct spi_transfer xfer = {
|
||||
.tx_buf = st->tx_data,
|
||||
.bits_per_word = 8,
|
||||
.len = 3,
|
||||
.speed_hz = AD4030_SPI_MAX_REG_XFER_SPEED,
|
||||
};
|
||||
|
|
@ -277,7 +274,6 @@ static int ad4030_spi_read(void *context, const void *reg, size_t reg_size,
|
|||
struct spi_transfer xfer = {
|
||||
.tx_buf = st->tx_data,
|
||||
.rx_buf = st->rx_data.raw,
|
||||
.bits_per_word = 8,
|
||||
.len = reg_size + val_size,
|
||||
.speed_hz = AD4030_SPI_MAX_REG_XFER_SPEED,
|
||||
};
|
||||
|
|
@ -312,7 +308,6 @@ static int ad4030_spi_write(void *context, const void *data, size_t count)
|
|||
((u8 *)data)[2] == 0x81;
|
||||
struct spi_transfer xfer = {
|
||||
.tx_buf = st->tx_data,
|
||||
.bits_per_word = 8,
|
||||
.len = count,
|
||||
.speed_hz = AD4030_SPI_MAX_REG_XFER_SPEED,
|
||||
};
|
||||
|
|
@ -390,16 +385,17 @@ static int ad4030_get_chan_scale(struct iio_dev *indio_dev,
|
|||
struct ad4030_state *st = iio_priv(indio_dev);
|
||||
const struct iio_scan_type *scan_type;
|
||||
|
||||
if (chan->differential) {
|
||||
scan_type = iio_get_current_scan_type(indio_dev,
|
||||
st->chip->channels);
|
||||
*val = (st->vref_uv * 2) / MILLI;
|
||||
*val2 = scan_type->realbits;
|
||||
return IIO_VAL_FRACTIONAL_LOG2;
|
||||
}
|
||||
scan_type = iio_get_current_scan_type(indio_dev, st->chip->channels);
|
||||
if (IS_ERR(scan_type))
|
||||
return PTR_ERR(scan_type);
|
||||
|
||||
if (chan->differential)
|
||||
*val = (st->vref_uv * 2) / MILLI;
|
||||
else
|
||||
*val = st->vref_uv / MILLI;
|
||||
*val2 = chan->scan_type.realbits;
|
||||
|
||||
*val2 = scan_type->realbits;
|
||||
|
||||
return IIO_VAL_FRACTIONAL_LOG2;
|
||||
}
|
||||
|
||||
|
|
@ -561,11 +557,6 @@ static int ad4030_set_mode(struct iio_dev *indio_dev, unsigned long mask)
|
|||
st->mode = AD4030_OUT_DATA_MD_DIFF;
|
||||
}
|
||||
|
||||
st->current_scan_type = iio_get_current_scan_type(indio_dev,
|
||||
st->chip->channels);
|
||||
if (IS_ERR(st->current_scan_type))
|
||||
return PTR_ERR(st->current_scan_type);
|
||||
|
||||
return regmap_update_bits(st->regmap, AD4030_REG_MODES,
|
||||
AD4030_REG_MODES_MASK_OUT_DATA_MODE,
|
||||
st->mode);
|
||||
|
|
@ -613,15 +604,20 @@ static void ad4030_extract_interleaved(u8 *src, u32 *ch0, u32 *ch1)
|
|||
static int ad4030_conversion(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct ad4030_state *st = iio_priv(indio_dev);
|
||||
unsigned char diff_realbytes =
|
||||
BITS_TO_BYTES(st->current_scan_type->realbits);
|
||||
unsigned char diff_storagebytes =
|
||||
BITS_TO_BYTES(st->current_scan_type->storagebits);
|
||||
const struct iio_scan_type *scan_type;
|
||||
unsigned char diff_realbytes, diff_storagebytes;
|
||||
unsigned int bytes_to_read;
|
||||
unsigned long cnv_nb = BIT(st->avg_log2);
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
scan_type = iio_get_current_scan_type(indio_dev, st->chip->channels);
|
||||
if (IS_ERR(scan_type))
|
||||
return PTR_ERR(scan_type);
|
||||
|
||||
diff_realbytes = BITS_TO_BYTES(scan_type->realbits);
|
||||
diff_storagebytes = BITS_TO_BYTES(scan_type->storagebits);
|
||||
|
||||
/* Number of bytes for one differential channel */
|
||||
bytes_to_read = diff_realbytes;
|
||||
/* Add one byte if we are using a differential + common byte mode */
|
||||
|
|
@ -646,6 +642,12 @@ static int ad4030_conversion(struct iio_dev *indio_dev)
|
|||
&st->rx_data.dual.diff[0],
|
||||
&st->rx_data.dual.diff[1]);
|
||||
|
||||
/*
|
||||
* If no common mode voltage channel is enabled, we can use the raw
|
||||
* data as is. Otherwise, we need to rearrange the data a bit to match
|
||||
* the natural alignment of the IIO buffer.
|
||||
*/
|
||||
|
||||
if (st->mode != AD4030_OUT_DATA_MD_16_DIFF_8_COM &&
|
||||
st->mode != AD4030_OUT_DATA_MD_24_DIFF_8_COM)
|
||||
return 0;
|
||||
|
|
@ -672,11 +674,6 @@ static int ad4030_single_conversion(struct iio_dev *indio_dev,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
st->current_scan_type = iio_get_current_scan_type(indio_dev,
|
||||
st->chip->channels);
|
||||
if (IS_ERR(st->current_scan_type))
|
||||
return PTR_ERR(st->current_scan_type);
|
||||
|
||||
ret = ad4030_conversion(indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -706,7 +703,7 @@ static irqreturn_t ad4030_trigger_handler(int irq, void *p)
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, st->rx_data.raw,
|
||||
iio_push_to_buffers_with_ts(indio_dev, &st->rx_data, sizeof(st->rx_data),
|
||||
pf->timestamp);
|
||||
|
||||
out:
|
||||
|
|
@ -867,6 +864,12 @@ static int ad4030_get_current_scan_type(const struct iio_dev *indio_dev,
|
|||
return st->avg_log2 ? AD4030_SCAN_TYPE_AVG : AD4030_SCAN_TYPE_NORMAL;
|
||||
}
|
||||
|
||||
static int ad4030_update_scan_mode(struct iio_dev *indio_dev,
|
||||
const unsigned long *scan_mask)
|
||||
{
|
||||
return ad4030_set_mode(indio_dev, *scan_mask);
|
||||
}
|
||||
|
||||
static const struct iio_info ad4030_iio_info = {
|
||||
.read_avail = ad4030_read_avail,
|
||||
.read_raw = ad4030_read_raw,
|
||||
|
|
@ -874,13 +877,9 @@ static const struct iio_info ad4030_iio_info = {
|
|||
.debugfs_reg_access = ad4030_reg_access,
|
||||
.read_label = ad4030_read_label,
|
||||
.get_current_scan_type = ad4030_get_current_scan_type,
|
||||
.update_scan_mode = ad4030_update_scan_mode,
|
||||
};
|
||||
|
||||
static int ad4030_buffer_preenable(struct iio_dev *indio_dev)
|
||||
{
|
||||
return ad4030_set_mode(indio_dev, *indio_dev->active_scan_mask);
|
||||
}
|
||||
|
||||
static bool ad4030_validate_scan_mask(struct iio_dev *indio_dev,
|
||||
const unsigned long *scan_mask)
|
||||
{
|
||||
|
|
@ -894,7 +893,6 @@ static bool ad4030_validate_scan_mask(struct iio_dev *indio_dev,
|
|||
}
|
||||
|
||||
static const struct iio_buffer_setup_ops ad4030_buffer_setup_ops = {
|
||||
.preenable = ad4030_buffer_preenable,
|
||||
.validate_scan_mask = ad4030_validate_scan_mask,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -522,14 +522,14 @@ static int ad4130_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
|
|||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static void ad4130_gpio_set(struct gpio_chip *gc, unsigned int offset,
|
||||
static int ad4130_gpio_set(struct gpio_chip *gc, unsigned int offset,
|
||||
int value)
|
||||
{
|
||||
struct ad4130_state *st = gpiochip_get_data(gc);
|
||||
unsigned int mask = FIELD_PREP(AD4130_IO_CONTROL_GPIO_DATA_MASK,
|
||||
BIT(offset));
|
||||
|
||||
regmap_update_bits(st->regmap, AD4130_IO_CONTROL_REG, mask,
|
||||
return regmap_update_bits(st->regmap, AD4130_IO_CONTROL_REG, mask,
|
||||
value ? mask : 0);
|
||||
}
|
||||
|
||||
|
|
@ -2064,7 +2064,7 @@ static int ad4130_probe(struct spi_device *spi)
|
|||
st->gc.can_sleep = true;
|
||||
st->gc.init_valid_mask = ad4130_gpio_init_valid_mask;
|
||||
st->gc.get_direction = ad4130_gpio_get_direction;
|
||||
st->gc.set = ad4130_gpio_set;
|
||||
st->gc.set_rv = ad4130_gpio_set;
|
||||
|
||||
ret = devm_gpiochip_add_data(dev, &st->gc, st);
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -105,9 +105,7 @@
|
|||
#define AD4695_REG_ACCESS_SCLK_HZ (10 * MEGA)
|
||||
|
||||
/* Max number of voltage input channels. */
|
||||
#define AD4695_MAX_CHANNELS 16
|
||||
/* Max size of 1 raw sample in bytes. */
|
||||
#define AD4695_MAX_CHANNEL_SIZE 2
|
||||
#define AD4695_MAX_VIN_CHANNELS 16
|
||||
|
||||
enum ad4695_in_pair {
|
||||
AD4695_IN_PAIR_REFGND,
|
||||
|
|
@ -145,8 +143,8 @@ struct ad4695_state {
|
|||
/* offload also requires separate gpio to manually control CNV */
|
||||
struct gpio_desc *cnv_gpio;
|
||||
/* voltages channels plus temperature and timestamp */
|
||||
struct iio_chan_spec iio_chan[AD4695_MAX_CHANNELS + 2];
|
||||
struct ad4695_channel_config channels_cfg[AD4695_MAX_CHANNELS];
|
||||
struct iio_chan_spec iio_chan[AD4695_MAX_VIN_CHANNELS + 2];
|
||||
struct ad4695_channel_config channels_cfg[AD4695_MAX_VIN_CHANNELS];
|
||||
const struct ad4695_chip_info *chip_info;
|
||||
int sample_freq_range[3];
|
||||
/* Reference voltage. */
|
||||
|
|
@ -159,11 +157,10 @@ struct ad4695_state {
|
|||
* to control CS and add a delay between the last SCLK and next
|
||||
* CNV rising edges.
|
||||
*/
|
||||
struct spi_transfer buf_read_xfer[AD4695_MAX_CHANNELS * 2 + 3];
|
||||
struct spi_transfer buf_read_xfer[AD4695_MAX_VIN_CHANNELS * 2 + 3];
|
||||
struct spi_message buf_read_msg;
|
||||
/* Raw conversion data received. */
|
||||
u8 buf[ALIGN((AD4695_MAX_CHANNELS + 2) * AD4695_MAX_CHANNEL_SIZE,
|
||||
sizeof(s64)) + sizeof(s64)] __aligned(IIO_DMA_MINALIGN);
|
||||
IIO_DECLARE_DMA_BUFFER_WITH_TS(u16, buf, AD4695_MAX_VIN_CHANNELS + 1);
|
||||
u16 raw_data;
|
||||
/* Commands to send for single conversion. */
|
||||
u16 cnv_cmd;
|
||||
|
|
@ -660,9 +657,8 @@ static int ad4695_buffer_preenable(struct iio_dev *indio_dev)
|
|||
iio_for_each_active_channel(indio_dev, bit) {
|
||||
xfer = &st->buf_read_xfer[num_xfer];
|
||||
xfer->bits_per_word = 16;
|
||||
xfer->rx_buf = &st->buf[rx_buf_offset];
|
||||
xfer->rx_buf = &st->buf[rx_buf_offset++];
|
||||
xfer->len = 2;
|
||||
rx_buf_offset += xfer->len;
|
||||
|
||||
if (bit == temp_chan_bit) {
|
||||
temp_en = 1;
|
||||
|
|
@ -801,7 +797,8 @@ static irqreturn_t ad4695_trigger_handler(int irq, void *p)
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, st->buf, pf->timestamp);
|
||||
iio_push_to_buffers_with_ts(indio_dev, st->buf, sizeof(st->buf),
|
||||
pf->timestamp);
|
||||
|
||||
out:
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
|
|
|||
|
|
@ -387,13 +387,8 @@ EXPORT_SYMBOL_NS_GPL(ad7091r_writeable_reg, "IIO_AD7091R");
|
|||
|
||||
bool ad7091r_volatile_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case AD7091R_REG_RESULT:
|
||||
case AD7091R_REG_ALERT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
/* The volatile ad7091r registers are also the only RO ones. */
|
||||
return !ad7091r_writeable_reg(dev, reg);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(ad7091r_volatile_reg, "IIO_AD7091R");
|
||||
|
||||
|
|
|
|||
|
|
@ -41,68 +41,58 @@
|
|||
#define AD7124_GAIN(x) (0x31 + (x))
|
||||
|
||||
/* AD7124_STATUS */
|
||||
#define AD7124_STATUS_POR_FLAG_MSK BIT(4)
|
||||
#define AD7124_STATUS_POR_FLAG BIT(4)
|
||||
|
||||
/* AD7124_ADC_CONTROL */
|
||||
#define AD7124_ADC_STATUS_EN_MSK BIT(10)
|
||||
#define AD7124_ADC_STATUS_EN(x) FIELD_PREP(AD7124_ADC_STATUS_EN_MSK, x)
|
||||
#define AD7124_ADC_CTRL_REF_EN_MSK BIT(8)
|
||||
#define AD7124_ADC_CTRL_REF_EN(x) FIELD_PREP(AD7124_ADC_CTRL_REF_EN_MSK, x)
|
||||
#define AD7124_ADC_CTRL_PWR_MSK GENMASK(7, 6)
|
||||
#define AD7124_ADC_CTRL_PWR(x) FIELD_PREP(AD7124_ADC_CTRL_PWR_MSK, x)
|
||||
#define AD7124_ADC_CTRL_MODE_MSK GENMASK(5, 2)
|
||||
#define AD7124_ADC_CTRL_MODE(x) FIELD_PREP(AD7124_ADC_CTRL_MODE_MSK, x)
|
||||
#define AD7124_ADC_CONTROL_MODE GENMASK(5, 2)
|
||||
#define AD7124_ADC_CONTROL_MODE_CONTINUOUS 0
|
||||
#define AD7124_ADC_CONTROL_MODE_SINGLE 1
|
||||
#define AD7124_ADC_CONTROL_MODE_STANDBY 2
|
||||
#define AD7124_ADC_CONTROL_MODE_POWERDOWN 3
|
||||
#define AD7124_ADC_CONTROL_MODE_IDLE 4
|
||||
#define AD7124_ADC_CONTROL_MODE_INT_OFFSET_CALIB 5 /* Internal Zero-Scale Calibration */
|
||||
#define AD7124_ADC_CONTROL_MODE_INT_GAIN_CALIB 6 /* Internal Full-Scale Calibration */
|
||||
#define AD7124_ADC_CONTROL_MODE_SYS_OFFSET_CALIB 7 /* System Zero-Scale Calibration */
|
||||
#define AD7124_ADC_CONTROL_MODE_SYS_GAIN_CALIB 8 /* System Full-Scale Calibration */
|
||||
#define AD7124_ADC_CONTROL_POWER_MODE GENMASK(7, 6)
|
||||
#define AD7124_ADC_CONTROL_POWER_MODE_LOW 0
|
||||
#define AD7124_ADC_CONTROL_POWER_MODE_MID 1
|
||||
#define AD7124_ADC_CONTROL_POWER_MODE_FULL 2
|
||||
#define AD7124_ADC_CONTROL_REF_EN BIT(8)
|
||||
#define AD7124_ADC_CONTROL_DATA_STATUS BIT(10)
|
||||
|
||||
#define AD7124_MODE_CAL_INT_ZERO 0x5 /* Internal Zero-Scale Calibration */
|
||||
#define AD7124_MODE_CAL_INT_FULL 0x6 /* Internal Full-Scale Calibration */
|
||||
#define AD7124_MODE_CAL_SYS_ZERO 0x7 /* System Zero-Scale Calibration */
|
||||
#define AD7124_MODE_CAL_SYS_FULL 0x8 /* System Full-Scale Calibration */
|
||||
|
||||
/* AD7124 ID */
|
||||
#define AD7124_DEVICE_ID_MSK GENMASK(7, 4)
|
||||
#define AD7124_DEVICE_ID_GET(x) FIELD_GET(AD7124_DEVICE_ID_MSK, x)
|
||||
#define AD7124_SILICON_REV_MSK GENMASK(3, 0)
|
||||
#define AD7124_SILICON_REV_GET(x) FIELD_GET(AD7124_SILICON_REV_MSK, x)
|
||||
|
||||
#define CHIPID_AD7124_4 0x0
|
||||
#define CHIPID_AD7124_8 0x1
|
||||
/* AD7124_ID */
|
||||
#define AD7124_ID_SILICON_REVISION GENMASK(3, 0)
|
||||
#define AD7124_ID_DEVICE_ID GENMASK(7, 4)
|
||||
#define AD7124_ID_DEVICE_ID_AD7124_4 0x0
|
||||
#define AD7124_ID_DEVICE_ID_AD7124_8 0x1
|
||||
|
||||
/* AD7124_CHANNEL_X */
|
||||
#define AD7124_CHANNEL_EN_MSK BIT(15)
|
||||
#define AD7124_CHANNEL_EN(x) FIELD_PREP(AD7124_CHANNEL_EN_MSK, x)
|
||||
#define AD7124_CHANNEL_SETUP_MSK GENMASK(14, 12)
|
||||
#define AD7124_CHANNEL_SETUP(x) FIELD_PREP(AD7124_CHANNEL_SETUP_MSK, x)
|
||||
#define AD7124_CHANNEL_AINP_MSK GENMASK(9, 5)
|
||||
#define AD7124_CHANNEL_AINP(x) FIELD_PREP(AD7124_CHANNEL_AINP_MSK, x)
|
||||
#define AD7124_CHANNEL_AINM_MSK GENMASK(4, 0)
|
||||
#define AD7124_CHANNEL_AINM(x) FIELD_PREP(AD7124_CHANNEL_AINM_MSK, x)
|
||||
#define AD7124_CHANNEL_ENABLE BIT(15)
|
||||
#define AD7124_CHANNEL_SETUP GENMASK(14, 12)
|
||||
#define AD7124_CHANNEL_AINP GENMASK(9, 5)
|
||||
#define AD7124_CHANNEL_AINM GENMASK(4, 0)
|
||||
#define AD7124_CHANNEL_AINx_TEMPSENSOR 16
|
||||
#define AD7124_CHANNEL_AINx_AVSS 17
|
||||
|
||||
/* AD7124_CONFIG_X */
|
||||
#define AD7124_CONFIG_BIPOLAR_MSK BIT(11)
|
||||
#define AD7124_CONFIG_BIPOLAR(x) FIELD_PREP(AD7124_CONFIG_BIPOLAR_MSK, x)
|
||||
#define AD7124_CONFIG_REF_SEL_MSK GENMASK(4, 3)
|
||||
#define AD7124_CONFIG_REF_SEL(x) FIELD_PREP(AD7124_CONFIG_REF_SEL_MSK, x)
|
||||
#define AD7124_CONFIG_PGA_MSK GENMASK(2, 0)
|
||||
#define AD7124_CONFIG_PGA(x) FIELD_PREP(AD7124_CONFIG_PGA_MSK, x)
|
||||
#define AD7124_CONFIG_IN_BUFF_MSK GENMASK(6, 5)
|
||||
#define AD7124_CONFIG_IN_BUFF(x) FIELD_PREP(AD7124_CONFIG_IN_BUFF_MSK, x)
|
||||
#define AD7124_CONFIG_BIPOLAR BIT(11)
|
||||
#define AD7124_CONFIG_IN_BUFF GENMASK(6, 5)
|
||||
#define AD7124_CONFIG_AIN_BUFP BIT(6)
|
||||
#define AD7124_CONFIG_AIN_BUFM BIT(5)
|
||||
#define AD7124_CONFIG_REF_SEL GENMASK(4, 3)
|
||||
#define AD7124_CONFIG_PGA GENMASK(2, 0)
|
||||
|
||||
/* AD7124_FILTER_X */
|
||||
#define AD7124_FILTER_FS_MSK GENMASK(10, 0)
|
||||
#define AD7124_FILTER_FS(x) FIELD_PREP(AD7124_FILTER_FS_MSK, x)
|
||||
#define AD7124_FILTER_TYPE_MSK GENMASK(23, 21)
|
||||
#define AD7124_FILTER_TYPE_SEL(x) FIELD_PREP(AD7124_FILTER_TYPE_MSK, x)
|
||||
#define AD7124_FILTER_FS GENMASK(10, 0)
|
||||
#define AD7124_FILTER_FILTER GENMASK(23, 21)
|
||||
#define AD7124_FILTER_FILTER_SINC4 0
|
||||
#define AD7124_FILTER_FILTER_SINC3 2
|
||||
|
||||
#define AD7124_SINC3_FILTER 2
|
||||
#define AD7124_SINC4_FILTER 0
|
||||
|
||||
#define AD7124_CONF_ADDR_OFFSET 20
|
||||
#define AD7124_MAX_CONFIGS 8
|
||||
#define AD7124_MAX_CHANNELS 16
|
||||
|
||||
/* AD7124 input sources */
|
||||
#define AD7124_INPUT_TEMPSENSOR 16
|
||||
#define AD7124_INPUT_AVSS 17
|
||||
|
||||
enum ad7124_ids {
|
||||
ID_AD7124_4,
|
||||
|
|
@ -206,12 +196,12 @@ struct ad7124_state {
|
|||
static struct ad7124_chip_info ad7124_chip_info_tbl[] = {
|
||||
[ID_AD7124_4] = {
|
||||
.name = "ad7124-4",
|
||||
.chip_id = CHIPID_AD7124_4,
|
||||
.chip_id = AD7124_ID_DEVICE_ID_AD7124_4,
|
||||
.num_inputs = 8,
|
||||
},
|
||||
[ID_AD7124_8] = {
|
||||
.name = "ad7124-8",
|
||||
.chip_id = CHIPID_AD7124_8,
|
||||
.chip_id = AD7124_ID_DEVICE_ID_AD7124_8,
|
||||
.num_inputs = 16,
|
||||
},
|
||||
};
|
||||
|
|
@ -260,8 +250,8 @@ static int ad7124_set_mode(struct ad_sigma_delta *sd,
|
|||
{
|
||||
struct ad7124_state *st = container_of(sd, struct ad7124_state, sd);
|
||||
|
||||
st->adc_control &= ~AD7124_ADC_CTRL_MODE_MSK;
|
||||
st->adc_control |= AD7124_ADC_CTRL_MODE(mode);
|
||||
st->adc_control &= ~AD7124_ADC_CONTROL_MODE;
|
||||
st->adc_control |= FIELD_PREP(AD7124_ADC_CONTROL_MODE, mode);
|
||||
|
||||
return ad_sd_write_reg(&st->sd, AD7124_ADC_CONTROL, 2, st->adc_control);
|
||||
}
|
||||
|
|
@ -300,41 +290,15 @@ static int ad7124_get_3db_filter_freq(struct ad7124_state *st,
|
|||
fadc = st->channels[channel].cfg.odr;
|
||||
|
||||
switch (st->channels[channel].cfg.filter_type) {
|
||||
case AD7124_SINC3_FILTER:
|
||||
case AD7124_FILTER_FILTER_SINC3:
|
||||
return DIV_ROUND_CLOSEST(fadc * 272, 1000);
|
||||
case AD7124_FILTER_FILTER_SINC4:
|
||||
return DIV_ROUND_CLOSEST(fadc * 230, 1000);
|
||||
case AD7124_SINC4_FILTER:
|
||||
return DIV_ROUND_CLOSEST(fadc * 262, 1000);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static void ad7124_set_3db_filter_freq(struct ad7124_state *st, unsigned int channel,
|
||||
unsigned int freq)
|
||||
{
|
||||
unsigned int sinc4_3db_odr;
|
||||
unsigned int sinc3_3db_odr;
|
||||
unsigned int new_filter;
|
||||
unsigned int new_odr;
|
||||
|
||||
sinc4_3db_odr = DIV_ROUND_CLOSEST(freq * 1000, 230);
|
||||
sinc3_3db_odr = DIV_ROUND_CLOSEST(freq * 1000, 262);
|
||||
|
||||
if (sinc4_3db_odr > sinc3_3db_odr) {
|
||||
new_filter = AD7124_SINC3_FILTER;
|
||||
new_odr = sinc4_3db_odr;
|
||||
} else {
|
||||
new_filter = AD7124_SINC4_FILTER;
|
||||
new_odr = sinc3_3db_odr;
|
||||
}
|
||||
|
||||
if (new_odr != st->channels[channel].cfg.odr)
|
||||
st->channels[channel].cfg.live = false;
|
||||
|
||||
st->channels[channel].cfg.filter_type = new_filter;
|
||||
st->channels[channel].cfg.odr = new_odr;
|
||||
}
|
||||
|
||||
static struct ad7124_channel_config *ad7124_find_similar_live_cfg(struct ad7124_state *st,
|
||||
struct ad7124_channel_config *cfg)
|
||||
{
|
||||
|
|
@ -413,8 +377,7 @@ static int ad7124_init_config_vref(struct ad7124_state *st, struct ad7124_channe
|
|||
return 0;
|
||||
case AD7124_INT_REF:
|
||||
cfg->vref_mv = 2500;
|
||||
st->adc_control &= ~AD7124_ADC_CTRL_REF_EN_MSK;
|
||||
st->adc_control |= AD7124_ADC_CTRL_REF_EN(1);
|
||||
st->adc_control |= AD7124_ADC_CONTROL_REF_EN;
|
||||
return 0;
|
||||
default:
|
||||
return dev_err_probe(dev, -EINVAL, "Invalid reference %d\n", refsel);
|
||||
|
|
@ -438,18 +401,20 @@ static int ad7124_write_config(struct ad7124_state *st, struct ad7124_channel_co
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
tmp = (cfg->buf_positive << 1) + cfg->buf_negative;
|
||||
val = AD7124_CONFIG_BIPOLAR(cfg->bipolar) | AD7124_CONFIG_REF_SEL(cfg->refsel) |
|
||||
AD7124_CONFIG_IN_BUFF(tmp) | AD7124_CONFIG_PGA(cfg->pga_bits);
|
||||
val = FIELD_PREP(AD7124_CONFIG_BIPOLAR, cfg->bipolar) |
|
||||
FIELD_PREP(AD7124_CONFIG_REF_SEL, cfg->refsel) |
|
||||
(cfg->buf_positive ? AD7124_CONFIG_AIN_BUFP : 0) |
|
||||
(cfg->buf_negative ? AD7124_CONFIG_AIN_BUFM : 0) |
|
||||
FIELD_PREP(AD7124_CONFIG_PGA, cfg->pga_bits);
|
||||
|
||||
ret = ad_sd_write_reg(&st->sd, AD7124_CONFIG(cfg->cfg_slot), 2, val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
tmp = AD7124_FILTER_TYPE_SEL(cfg->filter_type) |
|
||||
AD7124_FILTER_FS(cfg->odr_sel_bits);
|
||||
tmp = FIELD_PREP(AD7124_FILTER_FILTER, cfg->filter_type) |
|
||||
FIELD_PREP(AD7124_FILTER_FS, cfg->odr_sel_bits);
|
||||
return ad7124_spi_write_mask(st, AD7124_FILTER(cfg->cfg_slot),
|
||||
AD7124_FILTER_TYPE_MSK | AD7124_FILTER_FS_MSK,
|
||||
AD7124_FILTER_FILTER | AD7124_FILTER_FS,
|
||||
tmp, 3);
|
||||
}
|
||||
|
||||
|
|
@ -514,7 +479,8 @@ static int ad7124_enable_channel(struct ad7124_state *st, struct ad7124_channel
|
|||
{
|
||||
ch->cfg.live = true;
|
||||
return ad_sd_write_reg(&st->sd, AD7124_CHANNEL(ch->nr), 2, ch->ain |
|
||||
AD7124_CHANNEL_SETUP(ch->cfg.cfg_slot) | AD7124_CHANNEL_EN(1));
|
||||
FIELD_PREP(AD7124_CHANNEL_SETUP, ch->cfg.cfg_slot) |
|
||||
AD7124_CHANNEL_ENABLE);
|
||||
}
|
||||
|
||||
static int ad7124_prepare_read(struct ad7124_state *st, int address)
|
||||
|
|
@ -564,8 +530,10 @@ static int ad7124_append_status(struct ad_sigma_delta *sd, bool append)
|
|||
unsigned int adc_control = st->adc_control;
|
||||
int ret;
|
||||
|
||||
adc_control &= ~AD7124_ADC_STATUS_EN_MSK;
|
||||
adc_control |= AD7124_ADC_STATUS_EN(append);
|
||||
if (append)
|
||||
adc_control |= AD7124_ADC_CONTROL_DATA_STATUS;
|
||||
else
|
||||
adc_control &= ~AD7124_ADC_CONTROL_DATA_STATUS;
|
||||
|
||||
ret = ad_sd_write_reg(&st->sd, AD7124_ADC_CONTROL, 2, adc_control);
|
||||
if (ret < 0)
|
||||
|
|
@ -580,7 +548,7 @@ static int ad7124_disable_one(struct ad_sigma_delta *sd, unsigned int chan)
|
|||
{
|
||||
struct ad7124_state *st = container_of(sd, struct ad7124_state, sd);
|
||||
|
||||
/* The relevant thing here is that AD7124_CHANNEL_EN_MSK is cleared. */
|
||||
/* The relevant thing here is that AD7124_CHANNEL_ENABLE is cleared. */
|
||||
return ad_sd_write_reg(&st->sd, AD7124_CHANNEL(chan), 2, 0);
|
||||
}
|
||||
|
||||
|
|
@ -739,14 +707,6 @@ static int ad7124_write_raw(struct iio_dev *indio_dev,
|
|||
|
||||
st->channels[chan->address].cfg.pga_bits = res;
|
||||
break;
|
||||
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
|
||||
if (val2 != 0) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
ad7124_set_3db_filter_freq(st, chan->address, val);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
|
@ -802,7 +762,7 @@ static int ad7124_update_scan_mode(struct iio_dev *indio_dev,
|
|||
if (bit_set)
|
||||
ret = __ad7124_set_channel(&st->sd, i);
|
||||
else
|
||||
ret = ad7124_spi_write_mask(st, AD7124_CHANNEL(i), AD7124_CHANNEL_EN_MSK,
|
||||
ret = ad7124_spi_write_mask(st, AD7124_CHANNEL(i), AD7124_CHANNEL_ENABLE,
|
||||
0, 2);
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&st->cfgs_lock);
|
||||
|
|
@ -843,14 +803,14 @@ static int ad7124_soft_reset(struct ad7124_state *st)
|
|||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "Error reading status register\n");
|
||||
|
||||
if (!(readval & AD7124_STATUS_POR_FLAG_MSK))
|
||||
if (!(readval & AD7124_STATUS_POR_FLAG))
|
||||
break;
|
||||
|
||||
/* The AD7124 requires typically 2ms to power up and settle */
|
||||
usleep_range(100, 2000);
|
||||
} while (--timeout);
|
||||
|
||||
if (readval & AD7124_STATUS_POR_FLAG_MSK)
|
||||
if (readval & AD7124_STATUS_POR_FLAG)
|
||||
return dev_err_probe(dev, -EIO, "Soft reset failed\n");
|
||||
|
||||
ret = ad_sd_read_reg(&st->sd, AD7124_GAIN(0), 3, &st->gain_default);
|
||||
|
|
@ -872,8 +832,8 @@ static int ad7124_check_chip_id(struct ad7124_state *st)
|
|||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "Failure to read ID register\n");
|
||||
|
||||
chip_id = AD7124_DEVICE_ID_GET(readval);
|
||||
silicon_rev = AD7124_SILICON_REV_GET(readval);
|
||||
chip_id = FIELD_GET(AD7124_ID_DEVICE_ID, readval);
|
||||
silicon_rev = FIELD_GET(AD7124_ID_SILICON_REVISION, readval);
|
||||
|
||||
if (chip_id != st->chip_info->chip_id)
|
||||
return dev_err_probe(dev, -ENODEV,
|
||||
|
|
@ -901,7 +861,7 @@ static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan
|
|||
if (ch->syscalib_mode == AD7124_SYSCALIB_ZERO_SCALE) {
|
||||
ch->cfg.calibration_offset = 0x800000;
|
||||
|
||||
ret = ad_sd_calibrate(&st->sd, AD7124_MODE_CAL_SYS_ZERO,
|
||||
ret = ad_sd_calibrate(&st->sd, AD7124_ADC_CONTROL_MODE_SYS_OFFSET_CALIB,
|
||||
chan->address);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
@ -916,7 +876,7 @@ static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan
|
|||
} else {
|
||||
ch->cfg.calibration_gain = st->gain_default;
|
||||
|
||||
ret = ad_sd_calibrate(&st->sd, AD7124_MODE_CAL_SYS_FULL,
|
||||
ret = ad_sd_calibrate(&st->sd, AD7124_ADC_CONTROL_MODE_SYS_GAIN_CALIB,
|
||||
chan->address);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
@ -1031,7 +991,7 @@ static bool ad7124_valid_input_select(unsigned int ain, const struct ad7124_chip
|
|||
if (ain >= info->num_inputs && ain < 16)
|
||||
return false;
|
||||
|
||||
return ain <= FIELD_MAX(AD7124_CHANNEL_AINM_MSK);
|
||||
return ain <= FIELD_MAX(AD7124_CHANNEL_AINM);
|
||||
}
|
||||
|
||||
static int ad7124_parse_channel_config(struct iio_dev *indio_dev,
|
||||
|
|
@ -1096,8 +1056,8 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev,
|
|||
"diff-channels property of %pfwP contains invalid data\n", child);
|
||||
|
||||
st->channels[channel].nr = channel;
|
||||
st->channels[channel].ain = AD7124_CHANNEL_AINP(ain[0]) |
|
||||
AD7124_CHANNEL_AINM(ain[1]);
|
||||
st->channels[channel].ain = FIELD_PREP(AD7124_CHANNEL_AINP, ain[0]) |
|
||||
FIELD_PREP(AD7124_CHANNEL_AINM, ain[1]);
|
||||
|
||||
cfg = &st->channels[channel].cfg;
|
||||
cfg->bipolar = fwnode_property_read_bool(child, "bipolar");
|
||||
|
|
@ -1123,8 +1083,8 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev,
|
|||
if (num_channels < AD7124_MAX_CHANNELS) {
|
||||
st->channels[num_channels] = (struct ad7124_channel) {
|
||||
.nr = num_channels,
|
||||
.ain = AD7124_CHANNEL_AINP(AD7124_INPUT_TEMPSENSOR) |
|
||||
AD7124_CHANNEL_AINM(AD7124_INPUT_AVSS),
|
||||
.ain = FIELD_PREP(AD7124_CHANNEL_AINP, AD7124_CHANNEL_AINx_TEMPSENSOR) |
|
||||
FIELD_PREP(AD7124_CHANNEL_AINM, AD7124_CHANNEL_AINx_AVSS),
|
||||
.cfg = {
|
||||
.bipolar = true,
|
||||
},
|
||||
|
|
@ -1175,11 +1135,11 @@ static int ad7124_setup(struct ad7124_state *st)
|
|||
}
|
||||
|
||||
/* Set the power mode */
|
||||
st->adc_control &= ~AD7124_ADC_CTRL_PWR_MSK;
|
||||
st->adc_control |= AD7124_ADC_CTRL_PWR(power_mode);
|
||||
st->adc_control &= ~AD7124_ADC_CONTROL_POWER_MODE;
|
||||
st->adc_control |= FIELD_PREP(AD7124_ADC_CONTROL_POWER_MODE, power_mode);
|
||||
|
||||
st->adc_control &= ~AD7124_ADC_CTRL_MODE_MSK;
|
||||
st->adc_control |= AD7124_ADC_CTRL_MODE(AD_SD_MODE_IDLE);
|
||||
st->adc_control &= ~AD7124_ADC_CONTROL_MODE;
|
||||
st->adc_control |= FIELD_PREP(AD7124_ADC_CONTROL_MODE, AD_SD_MODE_IDLE);
|
||||
|
||||
mutex_init(&st->cfgs_lock);
|
||||
INIT_KFIFO(st->live_cfgs_fifo);
|
||||
|
|
@ -1233,7 +1193,7 @@ static int __ad7124_calibrate_all(struct ad7124_state *st, struct iio_dev *indio
|
|||
* usual: first zero-scale then full-scale calibration.
|
||||
*/
|
||||
if (st->channels[i].cfg.pga_bits > 0) {
|
||||
ret = ad_sd_calibrate(&st->sd, AD7124_MODE_CAL_INT_FULL, i);
|
||||
ret = ad_sd_calibrate(&st->sd, AD7124_ADC_CONTROL_MODE_INT_GAIN_CALIB, i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
@ -1250,7 +1210,7 @@ static int __ad7124_calibrate_all(struct ad7124_state *st, struct iio_dev *indio
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = ad_sd_calibrate(&st->sd, AD7124_MODE_CAL_INT_ZERO, i);
|
||||
ret = ad_sd_calibrate(&st->sd, AD7124_ADC_CONTROL_MODE_INT_OFFSET_CALIB, i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
@ -1279,9 +1239,9 @@ static int ad7124_calibrate_all(struct ad7124_state *st, struct iio_dev *indio_d
|
|||
* The resulting calibration is then also valid for high-speed, so just
|
||||
* restore adc_control afterwards.
|
||||
*/
|
||||
if (FIELD_GET(AD7124_ADC_CTRL_PWR_MSK, adc_control) >= AD7124_FULL_POWER) {
|
||||
st->adc_control &= ~AD7124_ADC_CTRL_PWR_MSK;
|
||||
st->adc_control |= AD7124_ADC_CTRL_PWR(AD7124_MID_POWER);
|
||||
if (FIELD_GET(AD7124_ADC_CONTROL_POWER_MODE, adc_control) >= AD7124_FULL_POWER) {
|
||||
st->adc_control &= ~AD7124_ADC_CONTROL_POWER_MODE;
|
||||
st->adc_control |= FIELD_PREP(AD7124_ADC_CONTROL_POWER_MODE, AD7124_MID_POWER);
|
||||
}
|
||||
|
||||
ret = __ad7124_calibrate_all(st, indio_dev);
|
||||
|
|
|
|||
|
|
@ -86,10 +86,9 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p)
|
|||
int ret;
|
||||
|
||||
ret = spi_read(st->spi, st->data.sample, 4);
|
||||
if (ret == 0) {
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &st->data,
|
||||
if (ret == 0)
|
||||
iio_push_to_buffers_with_ts(indio_dev, &st->data, sizeof(st->data),
|
||||
pf->timestamp);
|
||||
}
|
||||
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
||||
|
|
|
|||
|
|
@ -572,7 +572,7 @@ static const struct iio_chan_spec_ext_info ad7280_cell_ext_info[] = {
|
|||
.write = ad7280_store_balance_timer,
|
||||
.shared = IIO_SEPARATE,
|
||||
},
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct iio_event_spec ad7280_events[] = {
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p)
|
|||
if (b_sent)
|
||||
goto done;
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf,
|
||||
iio_push_to_buffers_with_ts(indio_dev, st->rx_buf, sizeof(st->rx_buf),
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
done:
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
* ad7381-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7381-4.pdf
|
||||
* ad7383/4-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7383-4-ad7384-4.pdf
|
||||
* ad7386/7/8-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7386-4-7387-4-7388-4.pdf
|
||||
* ad7389-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7389-4.pdf
|
||||
* adaq4370-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4370-4.pdf
|
||||
* adaq4380-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4380-4.pdf
|
||||
* adaq4381-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4381-4.pdf
|
||||
|
|
@ -119,7 +120,8 @@ struct ad7380_chip_info {
|
|||
const char * const *supplies;
|
||||
unsigned int num_supplies;
|
||||
bool external_ref_only;
|
||||
bool adaq_internal_ref_only;
|
||||
bool internal_ref_only;
|
||||
unsigned int internal_ref_mv;
|
||||
const char * const *vcm_supplies;
|
||||
unsigned int num_vcm_supplies;
|
||||
const unsigned long *available_scan_masks;
|
||||
|
|
@ -609,6 +611,7 @@ static const struct ad7380_chip_info ad7380_chip_info = {
|
|||
.num_simult_channels = 2,
|
||||
.supplies = ad7380_supplies,
|
||||
.num_supplies = ARRAY_SIZE(ad7380_supplies),
|
||||
.internal_ref_mv = AD7380_INTERNAL_REF_MV,
|
||||
.available_scan_masks = ad7380_2_channel_scan_masks,
|
||||
.timing_specs = &ad7380_timing,
|
||||
.max_conversion_rate_hz = 4 * MEGA,
|
||||
|
|
@ -622,6 +625,7 @@ static const struct ad7380_chip_info ad7381_chip_info = {
|
|||
.num_simult_channels = 2,
|
||||
.supplies = ad7380_supplies,
|
||||
.num_supplies = ARRAY_SIZE(ad7380_supplies),
|
||||
.internal_ref_mv = AD7380_INTERNAL_REF_MV,
|
||||
.available_scan_masks = ad7380_2_channel_scan_masks,
|
||||
.timing_specs = &ad7380_timing,
|
||||
.max_conversion_rate_hz = 4 * MEGA,
|
||||
|
|
@ -637,6 +641,7 @@ static const struct ad7380_chip_info ad7383_chip_info = {
|
|||
.num_supplies = ARRAY_SIZE(ad7380_supplies),
|
||||
.vcm_supplies = ad7380_2_channel_vcm_supplies,
|
||||
.num_vcm_supplies = ARRAY_SIZE(ad7380_2_channel_vcm_supplies),
|
||||
.internal_ref_mv = AD7380_INTERNAL_REF_MV,
|
||||
.available_scan_masks = ad7380_2_channel_scan_masks,
|
||||
.timing_specs = &ad7380_timing,
|
||||
.max_conversion_rate_hz = 4 * MEGA,
|
||||
|
|
@ -652,6 +657,7 @@ static const struct ad7380_chip_info ad7384_chip_info = {
|
|||
.num_supplies = ARRAY_SIZE(ad7380_supplies),
|
||||
.vcm_supplies = ad7380_2_channel_vcm_supplies,
|
||||
.num_vcm_supplies = ARRAY_SIZE(ad7380_2_channel_vcm_supplies),
|
||||
.internal_ref_mv = AD7380_INTERNAL_REF_MV,
|
||||
.available_scan_masks = ad7380_2_channel_scan_masks,
|
||||
.timing_specs = &ad7380_timing,
|
||||
.max_conversion_rate_hz = 4 * MEGA,
|
||||
|
|
@ -665,6 +671,7 @@ static const struct ad7380_chip_info ad7386_chip_info = {
|
|||
.num_simult_channels = 2,
|
||||
.supplies = ad7380_supplies,
|
||||
.num_supplies = ARRAY_SIZE(ad7380_supplies),
|
||||
.internal_ref_mv = AD7380_INTERNAL_REF_MV,
|
||||
.has_mux = true,
|
||||
.available_scan_masks = ad7380_2x2_channel_scan_masks,
|
||||
.timing_specs = &ad7380_timing,
|
||||
|
|
@ -679,6 +686,7 @@ static const struct ad7380_chip_info ad7387_chip_info = {
|
|||
.num_simult_channels = 2,
|
||||
.supplies = ad7380_supplies,
|
||||
.num_supplies = ARRAY_SIZE(ad7380_supplies),
|
||||
.internal_ref_mv = AD7380_INTERNAL_REF_MV,
|
||||
.has_mux = true,
|
||||
.available_scan_masks = ad7380_2x2_channel_scan_masks,
|
||||
.timing_specs = &ad7380_timing,
|
||||
|
|
@ -693,6 +701,7 @@ static const struct ad7380_chip_info ad7388_chip_info = {
|
|||
.num_simult_channels = 2,
|
||||
.supplies = ad7380_supplies,
|
||||
.num_supplies = ARRAY_SIZE(ad7380_supplies),
|
||||
.internal_ref_mv = AD7380_INTERNAL_REF_MV,
|
||||
.has_mux = true,
|
||||
.available_scan_masks = ad7380_2x2_channel_scan_masks,
|
||||
.timing_specs = &ad7380_timing,
|
||||
|
|
@ -721,6 +730,7 @@ static const struct ad7380_chip_info ad7381_4_chip_info = {
|
|||
.num_simult_channels = 4,
|
||||
.supplies = ad7380_supplies,
|
||||
.num_supplies = ARRAY_SIZE(ad7380_supplies),
|
||||
.internal_ref_mv = AD7380_INTERNAL_REF_MV,
|
||||
.available_scan_masks = ad7380_4_channel_scan_masks,
|
||||
.timing_specs = &ad7380_4_timing,
|
||||
.max_conversion_rate_hz = 4 * MEGA,
|
||||
|
|
@ -734,6 +744,7 @@ static const struct ad7380_chip_info ad7383_4_chip_info = {
|
|||
.num_simult_channels = 4,
|
||||
.supplies = ad7380_supplies,
|
||||
.num_supplies = ARRAY_SIZE(ad7380_supplies),
|
||||
.internal_ref_mv = AD7380_INTERNAL_REF_MV,
|
||||
.vcm_supplies = ad7380_4_channel_vcm_supplies,
|
||||
.num_vcm_supplies = ARRAY_SIZE(ad7380_4_channel_vcm_supplies),
|
||||
.available_scan_masks = ad7380_4_channel_scan_masks,
|
||||
|
|
@ -749,6 +760,7 @@ static const struct ad7380_chip_info ad7384_4_chip_info = {
|
|||
.num_simult_channels = 4,
|
||||
.supplies = ad7380_supplies,
|
||||
.num_supplies = ARRAY_SIZE(ad7380_supplies),
|
||||
.internal_ref_mv = AD7380_INTERNAL_REF_MV,
|
||||
.vcm_supplies = ad7380_4_channel_vcm_supplies,
|
||||
.num_vcm_supplies = ARRAY_SIZE(ad7380_4_channel_vcm_supplies),
|
||||
.available_scan_masks = ad7380_4_channel_scan_masks,
|
||||
|
|
@ -764,6 +776,7 @@ static const struct ad7380_chip_info ad7386_4_chip_info = {
|
|||
.num_simult_channels = 4,
|
||||
.supplies = ad7380_supplies,
|
||||
.num_supplies = ARRAY_SIZE(ad7380_supplies),
|
||||
.internal_ref_mv = AD7380_INTERNAL_REF_MV,
|
||||
.has_mux = true,
|
||||
.available_scan_masks = ad7380_2x4_channel_scan_masks,
|
||||
.timing_specs = &ad7380_4_timing,
|
||||
|
|
@ -778,6 +791,7 @@ static const struct ad7380_chip_info ad7387_4_chip_info = {
|
|||
.num_simult_channels = 4,
|
||||
.supplies = ad7380_supplies,
|
||||
.num_supplies = ARRAY_SIZE(ad7380_supplies),
|
||||
.internal_ref_mv = AD7380_INTERNAL_REF_MV,
|
||||
.has_mux = true,
|
||||
.available_scan_masks = ad7380_2x4_channel_scan_masks,
|
||||
.timing_specs = &ad7380_4_timing,
|
||||
|
|
@ -792,12 +806,28 @@ static const struct ad7380_chip_info ad7388_4_chip_info = {
|
|||
.num_simult_channels = 4,
|
||||
.supplies = ad7380_supplies,
|
||||
.num_supplies = ARRAY_SIZE(ad7380_supplies),
|
||||
.internal_ref_mv = AD7380_INTERNAL_REF_MV,
|
||||
.has_mux = true,
|
||||
.available_scan_masks = ad7380_2x4_channel_scan_masks,
|
||||
.timing_specs = &ad7380_4_timing,
|
||||
.max_conversion_rate_hz = 4 * MEGA,
|
||||
};
|
||||
|
||||
static const struct ad7380_chip_info ad7389_4_chip_info = {
|
||||
.name = "ad7389-4",
|
||||
.channels = ad7380_4_channels,
|
||||
.offload_channels = ad7380_4_offload_channels,
|
||||
.num_channels = ARRAY_SIZE(ad7380_4_channels),
|
||||
.num_simult_channels = 4,
|
||||
.supplies = ad7380_supplies,
|
||||
.num_supplies = ARRAY_SIZE(ad7380_supplies),
|
||||
.internal_ref_only = true,
|
||||
.internal_ref_mv = AD7380_INTERNAL_REF_MV,
|
||||
.available_scan_masks = ad7380_4_channel_scan_masks,
|
||||
.timing_specs = &ad7380_4_timing,
|
||||
.max_conversion_rate_hz = 4 * MEGA,
|
||||
};
|
||||
|
||||
static const struct ad7380_chip_info adaq4370_4_chip_info = {
|
||||
.name = "adaq4370-4",
|
||||
.channels = adaq4380_4_channels,
|
||||
|
|
@ -806,7 +836,8 @@ static const struct ad7380_chip_info adaq4370_4_chip_info = {
|
|||
.num_simult_channels = 4,
|
||||
.supplies = adaq4380_supplies,
|
||||
.num_supplies = ARRAY_SIZE(adaq4380_supplies),
|
||||
.adaq_internal_ref_only = true,
|
||||
.internal_ref_only = true,
|
||||
.internal_ref_mv = ADAQ4380_INTERNAL_REF_MV,
|
||||
.has_hardware_gain = true,
|
||||
.available_scan_masks = ad7380_4_channel_scan_masks,
|
||||
.timing_specs = &ad7380_4_timing,
|
||||
|
|
@ -821,7 +852,8 @@ static const struct ad7380_chip_info adaq4380_4_chip_info = {
|
|||
.num_simult_channels = 4,
|
||||
.supplies = adaq4380_supplies,
|
||||
.num_supplies = ARRAY_SIZE(adaq4380_supplies),
|
||||
.adaq_internal_ref_only = true,
|
||||
.internal_ref_only = true,
|
||||
.internal_ref_mv = ADAQ4380_INTERNAL_REF_MV,
|
||||
.has_hardware_gain = true,
|
||||
.available_scan_masks = ad7380_4_channel_scan_masks,
|
||||
.timing_specs = &ad7380_4_timing,
|
||||
|
|
@ -836,7 +868,8 @@ static const struct ad7380_chip_info adaq4381_4_chip_info = {
|
|||
.num_simult_channels = 4,
|
||||
.supplies = adaq4380_supplies,
|
||||
.num_supplies = ARRAY_SIZE(adaq4380_supplies),
|
||||
.adaq_internal_ref_only = true,
|
||||
.internal_ref_only = true,
|
||||
.internal_ref_mv = ADAQ4380_INTERNAL_REF_MV,
|
||||
.has_hardware_gain = true,
|
||||
.available_scan_masks = ad7380_4_channel_scan_masks,
|
||||
.timing_specs = &ad7380_4_timing,
|
||||
|
|
@ -876,8 +909,7 @@ struct ad7380_state {
|
|||
* Make the buffer large enough for MAX_NUM_CHANNELS 32-bit samples and
|
||||
* one 64-bit aligned 64-bit timestamp.
|
||||
*/
|
||||
u8 scan_data[ALIGN(MAX_NUM_CHANNELS * sizeof(u32), sizeof(s64))
|
||||
+ sizeof(s64)] __aligned(IIO_DMA_MINALIGN);
|
||||
IIO_DECLARE_DMA_BUFFER_WITH_TS(u8, scan_data, MAX_NUM_CHANNELS * sizeof(u32));
|
||||
/* buffers for reading/writing registers */
|
||||
u16 tx;
|
||||
u16 rx;
|
||||
|
|
@ -1327,7 +1359,7 @@ static irqreturn_t ad7380_trigger_handler(int irq, void *p)
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &st->scan_data,
|
||||
iio_push_to_buffers_with_ts(indio_dev, &st->scan_data, sizeof(st->scan_data),
|
||||
pf->timestamp);
|
||||
|
||||
out:
|
||||
|
|
@ -1859,7 +1891,7 @@ static int ad7380_probe(struct spi_device *spi)
|
|||
"Failed to enable power supplies\n");
|
||||
fsleep(T_POWERUP_US);
|
||||
|
||||
if (st->chip_info->adaq_internal_ref_only) {
|
||||
if (st->chip_info->internal_ref_only) {
|
||||
/*
|
||||
* ADAQ chips use fixed internal reference but still
|
||||
* require a specific reference supply to power it.
|
||||
|
|
@ -1867,7 +1899,7 @@ static int ad7380_probe(struct spi_device *spi)
|
|||
* in bulk_get_enable().
|
||||
*/
|
||||
|
||||
st->vref_mv = ADAQ4380_INTERNAL_REF_MV;
|
||||
st->vref_mv = st->chip_info->internal_ref_mv;
|
||||
|
||||
/* these chips don't have a register bit for this */
|
||||
external_ref_en = false;
|
||||
|
|
@ -1892,7 +1924,8 @@ static int ad7380_probe(struct spi_device *spi)
|
|||
"Failed to get refio regulator\n");
|
||||
|
||||
external_ref_en = ret != -ENODEV;
|
||||
st->vref_mv = external_ref_en ? ret / 1000 : AD7380_INTERNAL_REF_MV;
|
||||
st->vref_mv = external_ref_en ? ret / 1000
|
||||
: st->chip_info->internal_ref_mv;
|
||||
}
|
||||
|
||||
if (st->chip_info->num_vcm_supplies > ARRAY_SIZE(st->vcm_mv))
|
||||
|
|
@ -2045,6 +2078,7 @@ static const struct of_device_id ad7380_of_match_table[] = {
|
|||
{ .compatible = "adi,ad7386-4", .data = &ad7386_4_chip_info },
|
||||
{ .compatible = "adi,ad7387-4", .data = &ad7387_4_chip_info },
|
||||
{ .compatible = "adi,ad7388-4", .data = &ad7388_4_chip_info },
|
||||
{ .compatible = "adi,ad7389-4", .data = &ad7389_4_chip_info },
|
||||
{ .compatible = "adi,adaq4370-4", .data = &adaq4370_4_chip_info },
|
||||
{ .compatible = "adi,adaq4380-4", .data = &adaq4380_4_chip_info },
|
||||
{ .compatible = "adi,adaq4381-4", .data = &adaq4381_4_chip_info },
|
||||
|
|
@ -2066,6 +2100,7 @@ static const struct spi_device_id ad7380_id_table[] = {
|
|||
{ "ad7386-4", (kernel_ulong_t)&ad7386_4_chip_info },
|
||||
{ "ad7387-4", (kernel_ulong_t)&ad7387_4_chip_info },
|
||||
{ "ad7388-4", (kernel_ulong_t)&ad7388_4_chip_info },
|
||||
{ "ad7389-4", (kernel_ulong_t)&ad7389_4_chip_info },
|
||||
{ "adaq4370-4", (kernel_ulong_t)&adaq4370_4_chip_info },
|
||||
{ "adaq4380-4", (kernel_ulong_t)&adaq4380_4_chip_info },
|
||||
{ "adaq4381-4", (kernel_ulong_t)&adaq4381_4_chip_info },
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ static irqreturn_t ad7476_trigger_handler(int irq, void *p)
|
|||
if (b_sent < 0)
|
||||
goto done;
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, st->data,
|
||||
iio_push_to_buffers_with_ts(indio_dev, st->data, sizeof(st->data),
|
||||
iio_get_time_ns(indio_dev));
|
||||
done:
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/pwm.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
|
@ -94,121 +95,35 @@ static const unsigned int ad7616_oversampling_avail[8] = {
|
|||
1, 2, 4, 8, 16, 32, 64, 128,
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec ad7605_channels[] = {
|
||||
IIO_CHAN_SOFT_TIMESTAMP(4),
|
||||
AD7605_CHANNEL(0),
|
||||
AD7605_CHANNEL(1),
|
||||
AD7605_CHANNEL(2),
|
||||
AD7605_CHANNEL(3),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec ad7606_channels_16bit[] = {
|
||||
IIO_CHAN_SOFT_TIMESTAMP(8),
|
||||
AD7606_CHANNEL(0, 16),
|
||||
AD7606_CHANNEL(1, 16),
|
||||
AD7606_CHANNEL(2, 16),
|
||||
AD7606_CHANNEL(3, 16),
|
||||
AD7606_CHANNEL(4, 16),
|
||||
AD7606_CHANNEL(5, 16),
|
||||
AD7606_CHANNEL(6, 16),
|
||||
AD7606_CHANNEL(7, 16),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec ad7606_channels_18bit[] = {
|
||||
IIO_CHAN_SOFT_TIMESTAMP(8),
|
||||
AD7606_CHANNEL(0, 18),
|
||||
AD7606_CHANNEL(1, 18),
|
||||
AD7606_CHANNEL(2, 18),
|
||||
AD7606_CHANNEL(3, 18),
|
||||
AD7606_CHANNEL(4, 18),
|
||||
AD7606_CHANNEL(5, 18),
|
||||
AD7606_CHANNEL(6, 18),
|
||||
AD7606_CHANNEL(7, 18),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec ad7607_channels[] = {
|
||||
IIO_CHAN_SOFT_TIMESTAMP(8),
|
||||
AD7606_CHANNEL(0, 14),
|
||||
AD7606_CHANNEL(1, 14),
|
||||
AD7606_CHANNEL(2, 14),
|
||||
AD7606_CHANNEL(3, 14),
|
||||
AD7606_CHANNEL(4, 14),
|
||||
AD7606_CHANNEL(5, 14),
|
||||
AD7606_CHANNEL(6, 14),
|
||||
AD7606_CHANNEL(7, 14),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec ad7608_channels[] = {
|
||||
IIO_CHAN_SOFT_TIMESTAMP(8),
|
||||
AD7606_CHANNEL(0, 18),
|
||||
AD7606_CHANNEL(1, 18),
|
||||
AD7606_CHANNEL(2, 18),
|
||||
AD7606_CHANNEL(3, 18),
|
||||
AD7606_CHANNEL(4, 18),
|
||||
AD7606_CHANNEL(5, 18),
|
||||
AD7606_CHANNEL(6, 18),
|
||||
AD7606_CHANNEL(7, 18),
|
||||
};
|
||||
|
||||
/*
|
||||
* The current assumption that this driver makes for AD7616, is that it's
|
||||
* working in Hardware Mode with Serial, Burst and Sequencer modes activated.
|
||||
* To activate them, following pins must be pulled high:
|
||||
* -SER/PAR
|
||||
* -SEQEN
|
||||
* And following pins must be pulled low:
|
||||
* -WR/BURST
|
||||
* -DB4/SER1W
|
||||
*/
|
||||
static const struct iio_chan_spec ad7616_channels[] = {
|
||||
IIO_CHAN_SOFT_TIMESTAMP(16),
|
||||
AD7606_CHANNEL(0, 16),
|
||||
AD7606_CHANNEL(1, 16),
|
||||
AD7606_CHANNEL(2, 16),
|
||||
AD7606_CHANNEL(3, 16),
|
||||
AD7606_CHANNEL(4, 16),
|
||||
AD7606_CHANNEL(5, 16),
|
||||
AD7606_CHANNEL(6, 16),
|
||||
AD7606_CHANNEL(7, 16),
|
||||
AD7606_CHANNEL(8, 16),
|
||||
AD7606_CHANNEL(9, 16),
|
||||
AD7606_CHANNEL(10, 16),
|
||||
AD7606_CHANNEL(11, 16),
|
||||
AD7606_CHANNEL(12, 16),
|
||||
AD7606_CHANNEL(13, 16),
|
||||
AD7606_CHANNEL(14, 16),
|
||||
AD7606_CHANNEL(15, 16),
|
||||
};
|
||||
|
||||
static int ad7606c_18bit_chan_scale_setup(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec *chan, int ch);
|
||||
struct iio_chan_spec *chan);
|
||||
static int ad7606c_16bit_chan_scale_setup(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec *chan, int ch);
|
||||
struct iio_chan_spec *chan);
|
||||
static int ad7606_16bit_chan_scale_setup(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec *chan, int ch);
|
||||
struct iio_chan_spec *chan);
|
||||
static int ad7607_chan_scale_setup(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec *chan, int ch);
|
||||
struct iio_chan_spec *chan);
|
||||
static int ad7608_chan_scale_setup(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec *chan, int ch);
|
||||
struct iio_chan_spec *chan);
|
||||
static int ad7609_chan_scale_setup(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec *chan, int ch);
|
||||
struct iio_chan_spec *chan);
|
||||
static int ad7616_sw_mode_setup(struct iio_dev *indio_dev);
|
||||
static int ad7606b_sw_mode_setup(struct iio_dev *indio_dev);
|
||||
|
||||
const struct ad7606_chip_info ad7605_4_info = {
|
||||
.channels = ad7605_channels,
|
||||
.max_samplerate = 300 * KILO,
|
||||
.name = "ad7605-4",
|
||||
.bits = 16,
|
||||
.num_adc_channels = 4,
|
||||
.num_channels = 5,
|
||||
.scale_setup_cb = ad7606_16bit_chan_scale_setup,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(ad7605_4_info, "IIO_AD7606");
|
||||
|
||||
const struct ad7606_chip_info ad7606_8_info = {
|
||||
.channels = ad7606_channels_16bit,
|
||||
.max_samplerate = 200 * KILO,
|
||||
.name = "ad7606-8",
|
||||
.bits = 16,
|
||||
.num_adc_channels = 8,
|
||||
.num_channels = 9,
|
||||
.oversampling_avail = ad7606_oversampling_avail,
|
||||
.oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
|
||||
.scale_setup_cb = ad7606_16bit_chan_scale_setup,
|
||||
|
|
@ -216,108 +131,116 @@ const struct ad7606_chip_info ad7606_8_info = {
|
|||
EXPORT_SYMBOL_NS_GPL(ad7606_8_info, "IIO_AD7606");
|
||||
|
||||
const struct ad7606_chip_info ad7606_6_info = {
|
||||
.channels = ad7606_channels_16bit,
|
||||
.max_samplerate = 200 * KILO,
|
||||
.name = "ad7606-6",
|
||||
.bits = 16,
|
||||
.num_adc_channels = 6,
|
||||
.num_channels = 7,
|
||||
.oversampling_avail = ad7606_oversampling_avail,
|
||||
.oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
|
||||
.scale_setup_cb = ad7606_16bit_chan_scale_setup,
|
||||
.offload_storagebits = 32,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(ad7606_6_info, "IIO_AD7606");
|
||||
|
||||
const struct ad7606_chip_info ad7606_4_info = {
|
||||
.channels = ad7606_channels_16bit,
|
||||
.max_samplerate = 200 * KILO,
|
||||
.name = "ad7606-4",
|
||||
.bits = 16,
|
||||
.num_adc_channels = 4,
|
||||
.num_channels = 5,
|
||||
.oversampling_avail = ad7606_oversampling_avail,
|
||||
.oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
|
||||
.scale_setup_cb = ad7606_16bit_chan_scale_setup,
|
||||
.offload_storagebits = 32,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(ad7606_4_info, "IIO_AD7606");
|
||||
|
||||
const struct ad7606_chip_info ad7606b_info = {
|
||||
.channels = ad7606_channels_16bit,
|
||||
.max_samplerate = 800 * KILO,
|
||||
.name = "ad7606b",
|
||||
.bits = 16,
|
||||
.num_adc_channels = 8,
|
||||
.num_channels = 9,
|
||||
.oversampling_avail = ad7606_oversampling_avail,
|
||||
.oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
|
||||
.scale_setup_cb = ad7606_16bit_chan_scale_setup,
|
||||
.sw_setup_cb = ad7606b_sw_mode_setup,
|
||||
.offload_storagebits = 32,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(ad7606b_info, "IIO_AD7606");
|
||||
|
||||
const struct ad7606_chip_info ad7606c_16_info = {
|
||||
.channels = ad7606_channels_16bit,
|
||||
.max_samplerate = 1 * MEGA,
|
||||
.name = "ad7606c16",
|
||||
.bits = 16,
|
||||
.num_adc_channels = 8,
|
||||
.num_channels = 9,
|
||||
.oversampling_avail = ad7606_oversampling_avail,
|
||||
.oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
|
||||
.scale_setup_cb = ad7606c_16bit_chan_scale_setup,
|
||||
.sw_setup_cb = ad7606b_sw_mode_setup,
|
||||
.offload_storagebits = 32,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(ad7606c_16_info, "IIO_AD7606");
|
||||
|
||||
const struct ad7606_chip_info ad7607_info = {
|
||||
.channels = ad7607_channels,
|
||||
.max_samplerate = 200 * KILO,
|
||||
.name = "ad7607",
|
||||
.bits = 14,
|
||||
.num_adc_channels = 8,
|
||||
.num_channels = 9,
|
||||
.oversampling_avail = ad7606_oversampling_avail,
|
||||
.oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
|
||||
.scale_setup_cb = ad7607_chan_scale_setup,
|
||||
.offload_storagebits = 32,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(ad7607_info, "IIO_AD7606");
|
||||
|
||||
const struct ad7606_chip_info ad7608_info = {
|
||||
.channels = ad7608_channels,
|
||||
.max_samplerate = 200 * KILO,
|
||||
.name = "ad7608",
|
||||
.bits = 18,
|
||||
.num_adc_channels = 8,
|
||||
.num_channels = 9,
|
||||
.oversampling_avail = ad7606_oversampling_avail,
|
||||
.oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
|
||||
.scale_setup_cb = ad7608_chan_scale_setup,
|
||||
.offload_storagebits = 32,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(ad7608_info, "IIO_AD7606");
|
||||
|
||||
const struct ad7606_chip_info ad7609_info = {
|
||||
.channels = ad7608_channels,
|
||||
.max_samplerate = 200 * KILO,
|
||||
.name = "ad7609",
|
||||
.bits = 18,
|
||||
.num_adc_channels = 8,
|
||||
.num_channels = 9,
|
||||
.oversampling_avail = ad7606_oversampling_avail,
|
||||
.oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
|
||||
.scale_setup_cb = ad7609_chan_scale_setup,
|
||||
.offload_storagebits = 32,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(ad7609_info, "IIO_AD7606");
|
||||
|
||||
const struct ad7606_chip_info ad7606c_18_info = {
|
||||
.channels = ad7606_channels_18bit,
|
||||
.max_samplerate = 1 * MEGA,
|
||||
.name = "ad7606c18",
|
||||
.bits = 18,
|
||||
.num_adc_channels = 8,
|
||||
.num_channels = 9,
|
||||
.oversampling_avail = ad7606_oversampling_avail,
|
||||
.oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
|
||||
.scale_setup_cb = ad7606c_18bit_chan_scale_setup,
|
||||
.sw_setup_cb = ad7606b_sw_mode_setup,
|
||||
.offload_storagebits = 32,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(ad7606c_18_info, "IIO_AD7606");
|
||||
|
||||
const struct ad7606_chip_info ad7616_info = {
|
||||
.channels = ad7616_channels,
|
||||
.max_samplerate = 1 * MEGA,
|
||||
.init_delay_ms = 15,
|
||||
.name = "ad7616",
|
||||
.bits = 16,
|
||||
.num_adc_channels = 16,
|
||||
.num_channels = 17,
|
||||
.oversampling_avail = ad7616_oversampling_avail,
|
||||
.oversampling_num = ARRAY_SIZE(ad7616_oversampling_avail),
|
||||
.os_req_reset = true,
|
||||
.scale_setup_cb = ad7606_16bit_chan_scale_setup,
|
||||
.sw_setup_cb = ad7616_sw_mode_setup,
|
||||
.offload_storagebits = 16,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(ad7616_info, "IIO_AD7606");
|
||||
|
||||
|
|
@ -335,10 +258,10 @@ int ad7606_reset(struct ad7606_state *st)
|
|||
EXPORT_SYMBOL_NS_GPL(ad7606_reset, "IIO_AD7606");
|
||||
|
||||
static int ad7606_16bit_chan_scale_setup(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec *chan, int ch)
|
||||
struct iio_chan_spec *chan)
|
||||
{
|
||||
struct ad7606_state *st = iio_priv(indio_dev);
|
||||
struct ad7606_chan_scale *cs = &st->chan_scales[ch];
|
||||
struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index];
|
||||
|
||||
if (!st->sw_mode_en) {
|
||||
/* tied to logic low, analog input range is +/- 5V */
|
||||
|
|
@ -362,7 +285,6 @@ static int ad7606_get_chan_config(struct iio_dev *indio_dev, int ch,
|
|||
{
|
||||
struct ad7606_state *st = iio_priv(indio_dev);
|
||||
unsigned int num_channels = st->chip_info->num_adc_channels;
|
||||
unsigned int offset = indio_dev->num_channels - st->chip_info->num_adc_channels;
|
||||
struct device *dev = st->dev;
|
||||
int ret;
|
||||
|
||||
|
|
@ -378,7 +300,7 @@ static int ad7606_get_chan_config(struct iio_dev *indio_dev, int ch,
|
|||
continue;
|
||||
|
||||
/* channel number (here) is from 1 to num_channels */
|
||||
if (reg < offset || reg > num_channels) {
|
||||
if (reg < 1 || reg > num_channels) {
|
||||
dev_warn(dev,
|
||||
"Invalid channel number (ignoring): %d\n", reg);
|
||||
continue;
|
||||
|
|
@ -414,10 +336,10 @@ static int ad7606_get_chan_config(struct iio_dev *indio_dev, int ch,
|
|||
}
|
||||
|
||||
static int ad7606c_18bit_chan_scale_setup(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec *chan, int ch)
|
||||
struct iio_chan_spec *chan)
|
||||
{
|
||||
struct ad7606_state *st = iio_priv(indio_dev);
|
||||
struct ad7606_chan_scale *cs = &st->chan_scales[ch];
|
||||
struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index];
|
||||
bool bipolar, differential;
|
||||
int ret;
|
||||
|
||||
|
|
@ -428,7 +350,8 @@ static int ad7606c_18bit_chan_scale_setup(struct iio_dev *indio_dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
ret = ad7606_get_chan_config(indio_dev, ch, &bipolar, &differential);
|
||||
ret = ad7606_get_chan_config(indio_dev, chan->scan_index, &bipolar,
|
||||
&differential);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -471,10 +394,10 @@ static int ad7606c_18bit_chan_scale_setup(struct iio_dev *indio_dev,
|
|||
}
|
||||
|
||||
static int ad7606c_16bit_chan_scale_setup(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec *chan, int ch)
|
||||
struct iio_chan_spec *chan)
|
||||
{
|
||||
struct ad7606_state *st = iio_priv(indio_dev);
|
||||
struct ad7606_chan_scale *cs = &st->chan_scales[ch];
|
||||
struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index];
|
||||
bool bipolar, differential;
|
||||
int ret;
|
||||
|
||||
|
|
@ -485,7 +408,8 @@ static int ad7606c_16bit_chan_scale_setup(struct iio_dev *indio_dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
ret = ad7606_get_chan_config(indio_dev, ch, &bipolar, &differential);
|
||||
ret = ad7606_get_chan_config(indio_dev, chan->scan_index, &bipolar,
|
||||
&differential);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -529,10 +453,10 @@ static int ad7606c_16bit_chan_scale_setup(struct iio_dev *indio_dev,
|
|||
}
|
||||
|
||||
static int ad7607_chan_scale_setup(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec *chan, int ch)
|
||||
struct iio_chan_spec *chan)
|
||||
{
|
||||
struct ad7606_state *st = iio_priv(indio_dev);
|
||||
struct ad7606_chan_scale *cs = &st->chan_scales[ch];
|
||||
struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index];
|
||||
|
||||
cs->range = 0;
|
||||
cs->scale_avail = ad7607_hw_scale_avail;
|
||||
|
|
@ -541,10 +465,10 @@ static int ad7607_chan_scale_setup(struct iio_dev *indio_dev,
|
|||
}
|
||||
|
||||
static int ad7608_chan_scale_setup(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec *chan, int ch)
|
||||
struct iio_chan_spec *chan)
|
||||
{
|
||||
struct ad7606_state *st = iio_priv(indio_dev);
|
||||
struct ad7606_chan_scale *cs = &st->chan_scales[ch];
|
||||
struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index];
|
||||
|
||||
cs->range = 0;
|
||||
cs->scale_avail = ad7606_18bit_hw_scale_avail;
|
||||
|
|
@ -553,10 +477,10 @@ static int ad7608_chan_scale_setup(struct iio_dev *indio_dev,
|
|||
}
|
||||
|
||||
static int ad7609_chan_scale_setup(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec *chan, int ch)
|
||||
struct iio_chan_spec *chan)
|
||||
{
|
||||
struct ad7606_state *st = iio_priv(indio_dev);
|
||||
struct ad7606_chan_scale *cs = &st->chan_scales[ch];
|
||||
struct ad7606_chan_scale *cs = &st->chan_scales[chan->scan_index];
|
||||
|
||||
cs->range = 0;
|
||||
cs->scale_avail = ad7609_hw_scale_avail;
|
||||
|
|
@ -599,7 +523,7 @@ static int ad7606_pwm_set_high(struct ad7606_state *st)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ad7606_pwm_set_low(struct ad7606_state *st)
|
||||
int ad7606_pwm_set_low(struct ad7606_state *st)
|
||||
{
|
||||
struct pwm_state cnvst_pwm_state;
|
||||
int ret;
|
||||
|
|
@ -612,8 +536,9 @@ static int ad7606_pwm_set_low(struct ad7606_state *st)
|
|||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(ad7606_pwm_set_low, "IIO_AD7606");
|
||||
|
||||
static int ad7606_pwm_set_swing(struct ad7606_state *st)
|
||||
int ad7606_pwm_set_swing(struct ad7606_state *st)
|
||||
{
|
||||
struct pwm_state cnvst_pwm_state;
|
||||
|
||||
|
|
@ -623,6 +548,7 @@ static int ad7606_pwm_set_swing(struct ad7606_state *st)
|
|||
|
||||
return pwm_apply_might_sleep(st->cnvst_pwm, &cnvst_pwm_state);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(ad7606_pwm_set_swing, "IIO_AD7606");
|
||||
|
||||
static bool ad7606_pwm_is_swinging(struct ad7606_state *st)
|
||||
{
|
||||
|
|
@ -679,7 +605,7 @@ static irqreturn_t ad7606_trigger_handler(int irq, void *p)
|
|||
if (ret)
|
||||
goto error_ret;
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &st->data,
|
||||
iio_push_to_buffers_with_ts(indio_dev, &st->data, sizeof(st->data),
|
||||
iio_get_time_ns(indio_dev));
|
||||
error_ret:
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
|
@ -693,8 +619,8 @@ static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch,
|
|||
int *val)
|
||||
{
|
||||
struct ad7606_state *st = iio_priv(indio_dev);
|
||||
unsigned int realbits = st->chip_info->channels[1].scan_type.realbits;
|
||||
const struct iio_chan_spec *chan;
|
||||
unsigned int realbits;
|
||||
int ret;
|
||||
|
||||
if (st->gpio_convst) {
|
||||
|
|
@ -711,7 +637,7 @@ static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch,
|
|||
* will not happen because IIO_CHAN_INFO_RAW is not supported for the backend.
|
||||
* TODO: Add support for reading a single value when the backend is used.
|
||||
*/
|
||||
if (!st->back) {
|
||||
if (st->trig) {
|
||||
ret = wait_for_completion_timeout(&st->completion,
|
||||
msecs_to_jiffies(1000));
|
||||
if (!ret) {
|
||||
|
|
@ -719,14 +645,20 @@ static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch,
|
|||
goto error_ret;
|
||||
}
|
||||
} else {
|
||||
fsleep(1);
|
||||
/*
|
||||
* If the BUSY interrupt is not available, wait enough time for
|
||||
* the longest possible conversion (max for the whole family is
|
||||
* around 350us).
|
||||
*/
|
||||
fsleep(400);
|
||||
}
|
||||
|
||||
ret = ad7606_read_samples(st);
|
||||
if (ret)
|
||||
goto error_ret;
|
||||
|
||||
chan = &indio_dev->channels[ch + 1];
|
||||
chan = &indio_dev->channels[ch];
|
||||
realbits = chan->scan_type.realbits;
|
||||
|
||||
if (realbits > 16)
|
||||
*val = st->data.buf32[ch];
|
||||
|
|
@ -764,14 +696,14 @@ static int ad7606_read_raw(struct iio_dev *indio_dev,
|
|||
case IIO_CHAN_INFO_RAW:
|
||||
if (!iio_device_claim_direct(indio_dev))
|
||||
return -EBUSY;
|
||||
ret = ad7606_scan_direct(indio_dev, chan->address, val);
|
||||
ret = ad7606_scan_direct(indio_dev, chan->scan_index, val);
|
||||
iio_device_release_direct(indio_dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
if (st->sw_mode_en)
|
||||
ch = chan->address;
|
||||
ch = chan->scan_index;
|
||||
cs = &st->chan_scales[ch];
|
||||
*val = cs->scale_avail[cs->range][0];
|
||||
*val2 = cs->scale_avail[cs->range][1];
|
||||
|
|
@ -780,10 +712,6 @@ static int ad7606_read_raw(struct iio_dev *indio_dev,
|
|||
*val = st->oversampling;
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
/*
|
||||
* TODO: return the real frequency intead of the requested one once
|
||||
* pwm_get_state_hw comes upstream.
|
||||
*/
|
||||
pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state);
|
||||
*val = DIV_ROUND_CLOSEST_ULL(NSEC_PER_SEC, cnvst_pwm_state.period);
|
||||
return IIO_VAL_INT;
|
||||
|
|
@ -853,7 +781,7 @@ static int ad7606_write_raw(struct iio_dev *indio_dev,
|
|||
switch (mask) {
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
if (st->sw_mode_en)
|
||||
ch = chan->address;
|
||||
ch = chan->scan_index;
|
||||
cs = &st->chan_scales[ch];
|
||||
for (i = 0; i < cs->num_scales; i++) {
|
||||
scale_avail_uv[i] = cs->scale_avail[i][0] * MICRO +
|
||||
|
|
@ -1060,7 +988,7 @@ static int ad7606_read_avail(struct iio_dev *indio_dev,
|
|||
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
if (st->sw_mode_en)
|
||||
ch = chan->address;
|
||||
ch = chan->scan_index;
|
||||
|
||||
cs = &st->chan_scales[ch];
|
||||
*vals = (int *)cs->scale_avail;
|
||||
|
|
@ -1275,29 +1203,91 @@ static int ad7606b_sw_mode_setup(struct iio_dev *indio_dev)
|
|||
return st->bops->sw_mode_config(indio_dev);
|
||||
}
|
||||
|
||||
static int ad7606_chan_scales_setup(struct iio_dev *indio_dev)
|
||||
static int ad7606_probe_channels(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct ad7606_state *st = iio_priv(indio_dev);
|
||||
unsigned int offset = indio_dev->num_channels - st->chip_info->num_adc_channels;
|
||||
struct iio_chan_spec *chans;
|
||||
size_t size;
|
||||
int ch, ret;
|
||||
struct device *dev = indio_dev->dev.parent;
|
||||
struct iio_chan_spec *channels;
|
||||
bool slow_bus;
|
||||
int ret, i;
|
||||
|
||||
/* Clone IIO channels, since some may be differential */
|
||||
size = indio_dev->num_channels * sizeof(*indio_dev->channels);
|
||||
chans = devm_kzalloc(st->dev, size, GFP_KERNEL);
|
||||
if (!chans)
|
||||
slow_bus = !(st->bops->iio_backend_config || st->offload_en);
|
||||
indio_dev->num_channels = st->chip_info->num_adc_channels;
|
||||
|
||||
/* Slow buses also get 1 more channel for soft timestamp */
|
||||
if (slow_bus)
|
||||
indio_dev->num_channels++;
|
||||
|
||||
channels = devm_kcalloc(dev, indio_dev->num_channels, sizeof(*channels),
|
||||
GFP_KERNEL);
|
||||
if (!channels)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(chans, indio_dev->channels, size);
|
||||
indio_dev->channels = chans;
|
||||
for (i = 0; i < st->chip_info->num_adc_channels; i++) {
|
||||
struct iio_chan_spec *chan = &channels[i];
|
||||
|
||||
for (ch = 0; ch < st->chip_info->num_adc_channels; ch++) {
|
||||
ret = st->chip_info->scale_setup_cb(indio_dev, &chans[ch + offset], ch);
|
||||
chan->type = IIO_VOLTAGE;
|
||||
chan->indexed = 1;
|
||||
chan->channel = i;
|
||||
chan->scan_index = i;
|
||||
chan->scan_type.sign = 's';
|
||||
chan->scan_type.realbits = st->chip_info->bits;
|
||||
/*
|
||||
* If in SPI offload mode, storagebits are set based
|
||||
* on the spi-engine hw implementation.
|
||||
*/
|
||||
chan->scan_type.storagebits = st->offload_en ?
|
||||
st->chip_info->offload_storagebits :
|
||||
(st->chip_info->bits > 16 ? 32 : 16);
|
||||
|
||||
chan->scan_type.endianness = IIO_CPU;
|
||||
|
||||
if (indio_dev->modes & INDIO_DIRECT_MODE)
|
||||
chan->info_mask_separate |= BIT(IIO_CHAN_INFO_RAW);
|
||||
|
||||
if (st->sw_mode_en) {
|
||||
chan->info_mask_separate |= BIT(IIO_CHAN_INFO_SCALE);
|
||||
chan->info_mask_separate_available |=
|
||||
BIT(IIO_CHAN_INFO_SCALE);
|
||||
|
||||
/*
|
||||
* All chips with software mode support oversampling,
|
||||
* so we skip the oversampling_available check. And the
|
||||
* shared_by_type instead of shared_by_all on slow
|
||||
* buses is for backward compatibility.
|
||||
*/
|
||||
if (slow_bus)
|
||||
chan->info_mask_shared_by_type |=
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO);
|
||||
else
|
||||
chan->info_mask_shared_by_all |=
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO);
|
||||
|
||||
chan->info_mask_shared_by_all_available |=
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO);
|
||||
} else {
|
||||
chan->info_mask_shared_by_type |=
|
||||
BIT(IIO_CHAN_INFO_SCALE);
|
||||
|
||||
if (st->chip_info->oversampling_avail)
|
||||
chan->info_mask_shared_by_all |=
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO);
|
||||
}
|
||||
|
||||
if (!slow_bus)
|
||||
chan->info_mask_shared_by_all |=
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ);
|
||||
|
||||
ret = st->chip_info->scale_setup_cb(indio_dev, chan);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (slow_bus)
|
||||
channels[i] = (struct iio_chan_spec)IIO_CHAN_SOFT_TIMESTAMP(i);
|
||||
|
||||
indio_dev->channels = channels;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1321,11 +1311,19 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
|
|||
st = iio_priv(indio_dev);
|
||||
dev_set_drvdata(dev, indio_dev);
|
||||
|
||||
ret = devm_mutex_init(dev, &st->lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
st->dev = dev;
|
||||
mutex_init(&st->lock);
|
||||
st->bops = bops;
|
||||
st->base_address = base_address;
|
||||
st->oversampling = 1;
|
||||
st->sw_mode_en = device_property_read_bool(dev, "adi,sw-mode");
|
||||
|
||||
if (st->sw_mode_en && !chip_info->sw_setup_cb)
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"Software mode is not supported for this chip\n");
|
||||
|
||||
ret = devm_regulator_get_enable(dev, "avcc");
|
||||
if (ret)
|
||||
|
|
@ -1354,10 +1352,21 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
|
|||
else
|
||||
indio_dev->info = &ad7606_info_no_os_or_range;
|
||||
}
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
/* AXI ADC backend doesn't support single read. */
|
||||
indio_dev->modes = st->bops->iio_backend_config ? 0 : INDIO_DIRECT_MODE;
|
||||
indio_dev->name = chip_info->name;
|
||||
indio_dev->channels = st->chip_info->channels;
|
||||
indio_dev->num_channels = st->chip_info->num_channels;
|
||||
|
||||
/* Using spi-engine with offload support ? */
|
||||
if (st->bops->offload_config) {
|
||||
ret = st->bops->offload_config(dev, indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ad7606_probe_channels(indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ad7606_reset(st);
|
||||
if (ret)
|
||||
|
|
@ -1370,7 +1379,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
|
|||
}
|
||||
|
||||
/* If convst pin is not defined, setup PWM. */
|
||||
if (!st->gpio_convst) {
|
||||
if (!st->gpio_convst || st->offload_en) {
|
||||
st->cnvst_pwm = devm_pwm_get(dev, NULL);
|
||||
if (IS_ERR(st->cnvst_pwm))
|
||||
return PTR_ERR(st->cnvst_pwm);
|
||||
|
|
@ -1400,8 +1409,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
|
|||
* If there is a backend, the PWM should not overpass the maximum sampling
|
||||
* frequency the chip supports.
|
||||
*/
|
||||
ret = ad7606_set_sampling_freq(st,
|
||||
chip_info->max_samplerate ? : 2 * KILO);
|
||||
ret = ad7606_set_sampling_freq(st, chip_info->max_samplerate);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -1410,8 +1418,7 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
|
|||
return ret;
|
||||
|
||||
indio_dev->setup_ops = &ad7606_backend_buffer_ops;
|
||||
} else {
|
||||
|
||||
} else if (!st->offload_en) {
|
||||
/* Reserve the PWM use only for backend (force gpio_convst definition) */
|
||||
if (!st->gpio_convst)
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
|
|
@ -1449,17 +1456,12 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
|
|||
st->write_scale = ad7606_write_scale_hw;
|
||||
st->write_os = ad7606_write_os_hw;
|
||||
|
||||
st->sw_mode_en = st->chip_info->sw_setup_cb &&
|
||||
device_property_present(st->dev, "adi,sw-mode");
|
||||
if (st->sw_mode_en) {
|
||||
/* Offload needs 1 DOUT line, applying this setting in sw_setup_cb. */
|
||||
if (st->sw_mode_en || st->offload_en) {
|
||||
indio_dev->info = &ad7606_info_sw_mode;
|
||||
st->chip_info->sw_setup_cb(indio_dev);
|
||||
}
|
||||
|
||||
ret = ad7606_chan_scales_setup(indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return devm_iio_device_register(dev, indio_dev);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(ad7606_probe, "IIO_AD7606");
|
||||
|
|
|
|||
|
|
@ -40,119 +40,48 @@
|
|||
#define AD7606_RANGE_CH_ADDR(ch) (0x03 + ((ch) >> 1))
|
||||
#define AD7606_OS_MODE 0x08
|
||||
|
||||
#define AD760X_CHANNEL(num, mask_sep, mask_type, mask_all, \
|
||||
mask_sep_avail, mask_all_avail, bits) { \
|
||||
.type = IIO_VOLTAGE, \
|
||||
.indexed = 1, \
|
||||
.channel = num, \
|
||||
.address = num, \
|
||||
.info_mask_separate = mask_sep, \
|
||||
.info_mask_separate_available = \
|
||||
mask_sep_avail, \
|
||||
.info_mask_shared_by_type = mask_type, \
|
||||
.info_mask_shared_by_all = mask_all, \
|
||||
.info_mask_shared_by_all_available = \
|
||||
mask_all_avail, \
|
||||
.scan_index = num, \
|
||||
.scan_type = { \
|
||||
.sign = 's', \
|
||||
.realbits = (bits), \
|
||||
.storagebits = (bits) > 16 ? 32 : 16, \
|
||||
.endianness = IIO_CPU, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define AD7606_SW_CHANNEL(num, bits) \
|
||||
AD760X_CHANNEL(num, \
|
||||
/* mask separate */ \
|
||||
BIT(IIO_CHAN_INFO_RAW) | \
|
||||
BIT(IIO_CHAN_INFO_SCALE), \
|
||||
/* mask type */ \
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
|
||||
/* mask all */ \
|
||||
0, \
|
||||
/* mask separate available */ \
|
||||
BIT(IIO_CHAN_INFO_SCALE), \
|
||||
/* mask all available */ \
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
|
||||
bits)
|
||||
|
||||
#define AD7605_CHANNEL(num) \
|
||||
AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \
|
||||
BIT(IIO_CHAN_INFO_SCALE), 0, 0, 0, 16)
|
||||
|
||||
#define AD7606_CHANNEL(num, bits) \
|
||||
AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \
|
||||
BIT(IIO_CHAN_INFO_SCALE), \
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
|
||||
0, 0, bits)
|
||||
|
||||
#define AD7616_CHANNEL(num) AD7606_SW_CHANNEL(num, 16)
|
||||
|
||||
#define AD7606_BI_CHANNEL(num) \
|
||||
AD760X_CHANNEL(num, 0, \
|
||||
BIT(IIO_CHAN_INFO_SCALE), \
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
|
||||
0, 0, 16)
|
||||
|
||||
#define AD7606_BI_SW_CHANNEL(num) \
|
||||
AD760X_CHANNEL(num, \
|
||||
/* mask separate */ \
|
||||
BIT(IIO_CHAN_INFO_SCALE), \
|
||||
/* mask type */ \
|
||||
0, \
|
||||
/* mask all */ \
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
|
||||
/* mask separate available */ \
|
||||
BIT(IIO_CHAN_INFO_SCALE), \
|
||||
/* mask all available */ \
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
|
||||
16)
|
||||
|
||||
struct ad7606_state;
|
||||
|
||||
typedef int (*ad7606_scale_setup_cb_t)(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec *chan, int ch);
|
||||
struct iio_chan_spec *chan);
|
||||
typedef int (*ad7606_sw_setup_cb_t)(struct iio_dev *indio_dev);
|
||||
|
||||
/**
|
||||
* struct ad7606_chip_info - chip specific information
|
||||
* @channels: channel specification
|
||||
* @max_samplerate: maximum supported samplerate
|
||||
* @name device name
|
||||
* @num_channels: number of channels
|
||||
* @num_adc_channels the number of channels the ADC actually inputs.
|
||||
* @max_samplerate: maximum supported sample rate
|
||||
* @name: device name
|
||||
* @bits: data width in bits
|
||||
* @num_adc_channels: the number of physical voltage inputs
|
||||
* @scale_setup_cb: callback to setup the scales for each channel
|
||||
* @sw_setup_cb: callback to setup the software mode if available.
|
||||
* @oversampling_avail pointer to the array which stores the available
|
||||
* @oversampling_avail: pointer to the array which stores the available
|
||||
* oversampling ratios.
|
||||
* @oversampling_num number of elements stored in oversampling_avail array
|
||||
* @os_req_reset some devices require a reset to update oversampling
|
||||
* @init_delay_ms required delay in milliseconds for initialization
|
||||
* @oversampling_num: number of elements stored in oversampling_avail array
|
||||
* @os_req_reset: some devices require a reset to update oversampling
|
||||
* @init_delay_ms: required delay in milliseconds for initialization
|
||||
* after a restart
|
||||
* @offload_storagebits: storage bits used by the offload hw implementation
|
||||
*/
|
||||
struct ad7606_chip_info {
|
||||
const struct iio_chan_spec *channels;
|
||||
unsigned int max_samplerate;
|
||||
const char *name;
|
||||
unsigned int bits;
|
||||
unsigned int num_adc_channels;
|
||||
unsigned int num_channels;
|
||||
ad7606_scale_setup_cb_t scale_setup_cb;
|
||||
ad7606_sw_setup_cb_t sw_setup_cb;
|
||||
const unsigned int *oversampling_avail;
|
||||
unsigned int oversampling_num;
|
||||
bool os_req_reset;
|
||||
unsigned long init_delay_ms;
|
||||
u8 offload_storagebits;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ad7606_chan_scale - channel scale configuration
|
||||
* @scale_avail pointer to the array which stores the available scales
|
||||
* @num_scales number of elements stored in the scale_avail array
|
||||
* @range voltage range selection, selects which scale to apply
|
||||
* @reg_offset offset for the register value, to be applied when
|
||||
* @scale_avail: pointer to the array which stores the available scales
|
||||
* @num_scales: number of elements stored in the scale_avail array
|
||||
* @range: voltage range selection, selects which scale to apply
|
||||
* @reg_offset: offset for the register value, to be applied when
|
||||
* writing the value of 'range' to the register value
|
||||
*/
|
||||
struct ad7606_chan_scale {
|
||||
|
|
@ -165,32 +94,35 @@ struct ad7606_chan_scale {
|
|||
|
||||
/**
|
||||
* struct ad7606_state - driver instance specific data
|
||||
* @dev pointer to kernel device
|
||||
* @chip_info entry in the table of chips that describes this device
|
||||
* @bops bus operations (SPI or parallel)
|
||||
* @chan_scales scale configuration for channels
|
||||
* @oversampling oversampling selection
|
||||
* @cnvst_pwm pointer to the PWM device connected to the cnvst pin
|
||||
* @base_address address from where to read data in parallel operation
|
||||
* @sw_mode_en software mode enabled
|
||||
* @oversampling_avail pointer to the array which stores the available
|
||||
* @dev: pointer to kernel device
|
||||
* @chip_info: entry in the table of chips that describes this device
|
||||
* @bops: bus operations (SPI or parallel)
|
||||
* @chan_scales: scale configuration for channels
|
||||
* @oversampling: oversampling selection
|
||||
* @cnvst_pwm: pointer to the PWM device connected to the cnvst pin
|
||||
* @base_address: address from where to read data in parallel operation
|
||||
* @sw_mode_en: software mode enabled
|
||||
* @oversampling_avail: pointer to the array which stores the available
|
||||
* oversampling ratios.
|
||||
* @num_os_ratios number of elements stored in oversampling_avail array
|
||||
* @write_scale pointer to the function which writes the scale
|
||||
* @write_os pointer to the function which writes the os
|
||||
* @lock protect sensor state from concurrent accesses to GPIOs
|
||||
* @gpio_convst GPIO descriptor for conversion start signal (CONVST)
|
||||
* @gpio_reset GPIO descriptor for device hard-reset
|
||||
* @gpio_range GPIO descriptor for range selection
|
||||
* @gpio_standby GPIO descriptor for stand-by signal (STBY),
|
||||
* @num_os_ratios: number of elements stored in oversampling_avail array
|
||||
* @back: pointer to the iio_backend structure, if used
|
||||
* @write_scale: pointer to the function which writes the scale
|
||||
* @write_os: pointer to the function which writes the os
|
||||
* @lock: protect sensor state from concurrent accesses to GPIOs
|
||||
* @gpio_convst: GPIO descriptor for conversion start signal (CONVST)
|
||||
* @gpio_reset: GPIO descriptor for device hard-reset
|
||||
* @gpio_range: GPIO descriptor for range selection
|
||||
* @gpio_standby: GPIO descriptor for stand-by signal (STBY),
|
||||
* controls power-down mode of device
|
||||
* @gpio_frstdata GPIO descriptor for reading from device when data
|
||||
* @gpio_frstdata: GPIO descriptor for reading from device when data
|
||||
* is being read on the first channel
|
||||
* @gpio_os GPIO descriptors to control oversampling on the device
|
||||
* @complete completion to indicate end of conversion
|
||||
* @trig The IIO trigger associated with the device.
|
||||
* @data buffer for reading data from the device
|
||||
* @d16 be16 buffer for reading data from the device
|
||||
* @gpio_os: GPIO descriptors to control oversampling on the device
|
||||
* @trig: The IIO trigger associated with the device.
|
||||
* @completion: completion to indicate end of conversion
|
||||
* @data: buffer for reading data from the device
|
||||
* @offload_en: SPI offload enabled
|
||||
* @bus_data: bus-specific variables
|
||||
* @d16: be16 buffer for reading data from the device
|
||||
*/
|
||||
struct ad7606_state {
|
||||
struct device *dev;
|
||||
|
|
@ -217,36 +149,44 @@ struct ad7606_state {
|
|||
struct iio_trigger *trig;
|
||||
struct completion completion;
|
||||
|
||||
bool offload_en;
|
||||
void *bus_data;
|
||||
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) may require the
|
||||
* transfer buffers to live in their own cache lines.
|
||||
* 16 * 16-bit samples + 64-bit timestamp - for AD7616
|
||||
* 8 * 32-bit samples + 64-bit timestamp - for AD7616C-18 (and similar)
|
||||
* 16 * 16-bit samples for AD7616
|
||||
* 8 * 32-bit samples for AD7616C-18 (and similar)
|
||||
*/
|
||||
struct {
|
||||
union {
|
||||
u16 buf16[20];
|
||||
u32 buf32[10];
|
||||
u16 buf16[16];
|
||||
u32 buf32[8];
|
||||
};
|
||||
aligned_s64 timestamp;
|
||||
} data __aligned(IIO_DMA_MINALIGN);
|
||||
__be16 d16[2];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ad7606_bus_ops - driver bus operations
|
||||
* @iio_backend_config function pointer for configuring the iio_backend for
|
||||
* @iio_backend_config: function pointer for configuring the iio_backend for
|
||||
* the compatibles that use it
|
||||
* @read_block function pointer for reading blocks of data
|
||||
* @read_block: function pointer for reading blocks of data
|
||||
* @sw_mode_config: pointer to a function which configured the device
|
||||
* for software mode
|
||||
* @reg_read function pointer for reading spi register
|
||||
* @reg_write function pointer for writing spi register
|
||||
* @write_mask function pointer for write spi register with mask
|
||||
* @update_scan_mode function pointer for handling the calls to iio_info's update_scan
|
||||
* mode when enabling/disabling channels.
|
||||
* @rd_wr_cmd pointer to the function which calculates the spi address
|
||||
* @offload_config: function pointer for configuring offload support,
|
||||
* where any
|
||||
* @reg_read: function pointer for reading spi register
|
||||
* @reg_write: function pointer for writing spi register
|
||||
* @update_scan_mode: function pointer for handling the calls to iio_info's
|
||||
* update_scan mode when enabling/disabling channels.
|
||||
* @rd_wr_cmd: pointer to the function which calculates the spi address
|
||||
*/
|
||||
struct ad7606_bus_ops {
|
||||
/* more methods added in future? */
|
||||
int (*iio_backend_config)(struct device *dev, struct iio_dev *indio_dev);
|
||||
int (*offload_config)(struct device *dev, struct iio_dev *indio_dev);
|
||||
int (*read_block)(struct device *dev, int num, void *data);
|
||||
int (*sw_mode_config)(struct iio_dev *indio_dev);
|
||||
int (*reg_read)(struct ad7606_state *st, unsigned int addr);
|
||||
|
|
@ -254,13 +194,13 @@ struct ad7606_bus_ops {
|
|||
unsigned int addr,
|
||||
unsigned int val);
|
||||
int (*update_scan_mode)(struct iio_dev *indio_dev, const unsigned long *scan_mask);
|
||||
u16 (*rd_wr_cmd)(int addr, char isWriteOp);
|
||||
u16 (*rd_wr_cmd)(int addr, char is_write_op);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ad7606_bus_info - agregate ad7606_chip_info and ad7606_bus_ops
|
||||
* @chip_info entry in the table of chips that describes this device
|
||||
* @bops bus operations (SPI or parallel)
|
||||
* struct ad7606_bus_info - aggregate ad7606_chip_info and ad7606_bus_ops
|
||||
* @chip_info: entry in the table of chips that describes this device
|
||||
* @bops: bus operations (SPI or parallel)
|
||||
*/
|
||||
struct ad7606_bus_info {
|
||||
const struct ad7606_chip_info *chip_info;
|
||||
|
|
@ -272,6 +212,8 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
|
|||
const struct ad7606_bus_ops *bops);
|
||||
|
||||
int ad7606_reset(struct ad7606_state *st);
|
||||
int ad7606_pwm_set_swing(struct ad7606_state *st);
|
||||
int ad7606_pwm_set_low(struct ad7606_state *st);
|
||||
|
||||
extern const struct ad7606_chip_info ad7605_4_info;
|
||||
extern const struct ad7606_chip_info ad7606_8_info;
|
||||
|
|
|
|||
|
|
@ -21,28 +21,6 @@
|
|||
#include "ad7606.h"
|
||||
#include "ad7606_bus_iface.h"
|
||||
|
||||
static const struct iio_chan_spec ad7606b_bi_channels[] = {
|
||||
AD7606_BI_CHANNEL(0),
|
||||
AD7606_BI_CHANNEL(1),
|
||||
AD7606_BI_CHANNEL(2),
|
||||
AD7606_BI_CHANNEL(3),
|
||||
AD7606_BI_CHANNEL(4),
|
||||
AD7606_BI_CHANNEL(5),
|
||||
AD7606_BI_CHANNEL(6),
|
||||
AD7606_BI_CHANNEL(7),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec ad7606b_bi_sw_channels[] = {
|
||||
AD7606_BI_SW_CHANNEL(0),
|
||||
AD7606_BI_SW_CHANNEL(1),
|
||||
AD7606_BI_SW_CHANNEL(2),
|
||||
AD7606_BI_SW_CHANNEL(3),
|
||||
AD7606_BI_SW_CHANNEL(4),
|
||||
AD7606_BI_SW_CHANNEL(5),
|
||||
AD7606_BI_SW_CHANNEL(6),
|
||||
AD7606_BI_SW_CHANNEL(7),
|
||||
};
|
||||
|
||||
static int ad7606_par_bus_update_scan_mode(struct iio_dev *indio_dev,
|
||||
const unsigned long *scan_mask)
|
||||
{
|
||||
|
|
@ -94,9 +72,6 @@ static int ad7606_par_bus_setup_iio_backend(struct device *dev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
indio_dev->channels = ad7606b_bi_channels;
|
||||
indio_dev->num_channels = 8;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -120,19 +95,11 @@ static int ad7606_par_bus_reg_write(struct ad7606_state *st, unsigned int addr,
|
|||
return pdata->bus_reg_write(st->back, addr, val);
|
||||
}
|
||||
|
||||
static int ad7606_par_bus_sw_mode_config(struct iio_dev *indio_dev)
|
||||
{
|
||||
indio_dev->channels = ad7606b_bi_sw_channels;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ad7606_bus_ops ad7606_bi_bops = {
|
||||
.iio_backend_config = ad7606_par_bus_setup_iio_backend,
|
||||
.update_scan_mode = ad7606_par_bus_update_scan_mode,
|
||||
.reg_read = ad7606_par_bus_reg_read,
|
||||
.reg_write = ad7606_par_bus_reg_write,
|
||||
.sw_mode_config = ad7606_par_bus_sw_mode_config,
|
||||
};
|
||||
|
||||
static int ad7606_par16_read_block(struct device *dev,
|
||||
|
|
@ -255,6 +222,8 @@ static const struct platform_device_id ad7606_driver_ids[] = {
|
|||
{ .name = "ad7606-6", .driver_data = (kernel_ulong_t)&ad7606_6_info, },
|
||||
{ .name = "ad7606-8", .driver_data = (kernel_ulong_t)&ad7606_8_info, },
|
||||
{ .name = "ad7606b", .driver_data = (kernel_ulong_t)&ad7606b_info, },
|
||||
{ .name = "ad7606c-16", .driver_data = (kernel_ulong_t)&ad7606c_16_info },
|
||||
{ .name = "ad7606c-18", .driver_data = (kernel_ulong_t)&ad7606c_18_info },
|
||||
{ .name = "ad7607", .driver_data = (kernel_ulong_t)&ad7607_info, },
|
||||
{ .name = "ad7608", .driver_data = (kernel_ulong_t)&ad7608_info, },
|
||||
{ .name = "ad7609", .driver_data = (kernel_ulong_t)&ad7609_info, },
|
||||
|
|
@ -268,6 +237,8 @@ static const struct of_device_id ad7606_of_match[] = {
|
|||
{ .compatible = "adi,ad7606-6", .data = &ad7606_6_info },
|
||||
{ .compatible = "adi,ad7606-8", .data = &ad7606_8_info },
|
||||
{ .compatible = "adi,ad7606b", .data = &ad7606b_info },
|
||||
{ .compatible = "adi,ad7606c-16", .data = &ad7606c_16_info },
|
||||
{ .compatible = "adi,ad7606c-18", .data = &ad7606c_18_info },
|
||||
{ .compatible = "adi,ad7607", .data = &ad7607_info },
|
||||
{ .compatible = "adi,ad7608", .data = &ad7608_info },
|
||||
{ .compatible = "adi,ad7609", .data = &ad7609_info },
|
||||
|
|
|
|||
|
|
@ -5,70 +5,43 @@
|
|||
* Copyright 2011 Analog Devices Inc.
|
||||
*/
|
||||
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pwm.h>
|
||||
#include <linux/spi/offload/consumer.h>
|
||||
#include <linux/spi/offload/provider.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#include <linux/iio/buffer-dmaengine.h>
|
||||
#include <linux/iio/iio.h>
|
||||
|
||||
#include <dt-bindings/iio/adc/adi,ad7606.h>
|
||||
|
||||
#include "ad7606.h"
|
||||
|
||||
#define MAX_SPI_FREQ_HZ 23500000 /* VDRIVE above 4.75 V */
|
||||
|
||||
static const struct iio_chan_spec ad7616_sw_channels[] = {
|
||||
IIO_CHAN_SOFT_TIMESTAMP(16),
|
||||
AD7616_CHANNEL(0),
|
||||
AD7616_CHANNEL(1),
|
||||
AD7616_CHANNEL(2),
|
||||
AD7616_CHANNEL(3),
|
||||
AD7616_CHANNEL(4),
|
||||
AD7616_CHANNEL(5),
|
||||
AD7616_CHANNEL(6),
|
||||
AD7616_CHANNEL(7),
|
||||
AD7616_CHANNEL(8),
|
||||
AD7616_CHANNEL(9),
|
||||
AD7616_CHANNEL(10),
|
||||
AD7616_CHANNEL(11),
|
||||
AD7616_CHANNEL(12),
|
||||
AD7616_CHANNEL(13),
|
||||
AD7616_CHANNEL(14),
|
||||
AD7616_CHANNEL(15),
|
||||
struct spi_bus_data {
|
||||
struct spi_offload *offload;
|
||||
struct spi_offload_trigger *offload_trigger;
|
||||
struct spi_transfer offload_xfer;
|
||||
struct spi_message offload_msg;
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec ad7606b_sw_channels[] = {
|
||||
IIO_CHAN_SOFT_TIMESTAMP(8),
|
||||
AD7606_SW_CHANNEL(0, 16),
|
||||
AD7606_SW_CHANNEL(1, 16),
|
||||
AD7606_SW_CHANNEL(2, 16),
|
||||
AD7606_SW_CHANNEL(3, 16),
|
||||
AD7606_SW_CHANNEL(4, 16),
|
||||
AD7606_SW_CHANNEL(5, 16),
|
||||
AD7606_SW_CHANNEL(6, 16),
|
||||
AD7606_SW_CHANNEL(7, 16),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec ad7606c_18_sw_channels[] = {
|
||||
IIO_CHAN_SOFT_TIMESTAMP(8),
|
||||
AD7606_SW_CHANNEL(0, 18),
|
||||
AD7606_SW_CHANNEL(1, 18),
|
||||
AD7606_SW_CHANNEL(2, 18),
|
||||
AD7606_SW_CHANNEL(3, 18),
|
||||
AD7606_SW_CHANNEL(4, 18),
|
||||
AD7606_SW_CHANNEL(5, 18),
|
||||
AD7606_SW_CHANNEL(6, 18),
|
||||
AD7606_SW_CHANNEL(7, 18),
|
||||
};
|
||||
|
||||
static u16 ad7616_spi_rd_wr_cmd(int addr, char isWriteOp)
|
||||
static u16 ad7616_spi_rd_wr_cmd(int addr, char is_write_op)
|
||||
{
|
||||
/*
|
||||
* The address of register consist of one w/r bit
|
||||
* 6 bits of address followed by one reserved bit.
|
||||
*/
|
||||
return ((addr & 0x7F) << 1) | ((isWriteOp & 0x1) << 7);
|
||||
return ((addr & 0x7F) << 1) | ((is_write_op & 0x1) << 7);
|
||||
}
|
||||
|
||||
static u16 ad7606B_spi_rd_wr_cmd(int addr, char is_write_op)
|
||||
static u16 ad7606b_spi_rd_wr_cmd(int addr, char is_write_op)
|
||||
{
|
||||
/*
|
||||
* The address of register consists of one bit which
|
||||
|
|
@ -160,82 +133,270 @@ static int ad7606_spi_reg_write(struct ad7606_state *st,
|
|||
return spi_write(spi, &st->d16[0], sizeof(st->d16[0]));
|
||||
}
|
||||
|
||||
static int ad7616_sw_mode_config(struct iio_dev *indio_dev)
|
||||
{
|
||||
/*
|
||||
* Scale can be configured individually for each channel
|
||||
* in software mode.
|
||||
*/
|
||||
indio_dev->channels = ad7616_sw_channels;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ad7606B_sw_mode_config(struct iio_dev *indio_dev)
|
||||
static int ad7606b_sw_mode_config(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct ad7606_state *st = iio_priv(indio_dev);
|
||||
|
||||
/* Configure device spi to output on a single channel */
|
||||
st->bops->reg_write(st,
|
||||
AD7606_CONFIGURATION_REGISTER,
|
||||
return st->bops->reg_write(st, AD7606_CONFIGURATION_REGISTER,
|
||||
AD7606_SINGLE_DOUT);
|
||||
}
|
||||
|
||||
static const struct spi_offload_config ad7606_spi_offload_config = {
|
||||
.capability_flags = SPI_OFFLOAD_CAP_TRIGGER |
|
||||
SPI_OFFLOAD_CAP_RX_STREAM_DMA,
|
||||
};
|
||||
|
||||
static int ad7606_spi_offload_buffer_postenable(struct iio_dev *indio_dev)
|
||||
{
|
||||
const struct iio_scan_type *scan_type;
|
||||
struct ad7606_state *st = iio_priv(indio_dev);
|
||||
struct spi_bus_data *bus_data = st->bus_data;
|
||||
struct spi_transfer *xfer = &bus_data->offload_xfer;
|
||||
struct spi_device *spi = to_spi_device(st->dev);
|
||||
struct spi_offload_trigger_config config = {
|
||||
.type = SPI_OFFLOAD_TRIGGER_DATA_READY,
|
||||
};
|
||||
int ret;
|
||||
|
||||
scan_type = &indio_dev->channels[0].scan_type;
|
||||
|
||||
xfer->bits_per_word = scan_type->realbits;
|
||||
xfer->offload_flags = SPI_OFFLOAD_XFER_RX_STREAM;
|
||||
/*
|
||||
* Scale can be configured individually for each channel
|
||||
* in software mode.
|
||||
* Using SPI offload, storagebits are related to the spi-engine
|
||||
* hw implementation, can be 16 or 32, so can't be used to compute
|
||||
* struct spi_transfer.len. Using realbits instead.
|
||||
*/
|
||||
indio_dev->channels = ad7606b_sw_channels;
|
||||
xfer->len = (scan_type->realbits > 16 ? 4 : 2) *
|
||||
st->chip_info->num_adc_channels;
|
||||
|
||||
spi_message_init_with_transfers(&bus_data->offload_msg, xfer, 1);
|
||||
bus_data->offload_msg.offload = bus_data->offload;
|
||||
|
||||
ret = spi_optimize_message(spi, &bus_data->offload_msg);
|
||||
if (ret) {
|
||||
dev_err(st->dev, "failed to prepare offload, err: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = spi_offload_trigger_enable(bus_data->offload,
|
||||
bus_data->offload_trigger,
|
||||
&config);
|
||||
if (ret)
|
||||
goto err_unoptimize_message;
|
||||
|
||||
ret = ad7606_pwm_set_swing(st);
|
||||
if (ret)
|
||||
goto err_offload_exit_conversion_mode;
|
||||
|
||||
return 0;
|
||||
|
||||
err_offload_exit_conversion_mode:
|
||||
spi_offload_trigger_disable(bus_data->offload,
|
||||
bus_data->offload_trigger);
|
||||
|
||||
err_unoptimize_message:
|
||||
spi_unoptimize_message(&bus_data->offload_msg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ad7606_spi_offload_buffer_predisable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct ad7606_state *st = iio_priv(indio_dev);
|
||||
struct spi_bus_data *bus_data = st->bus_data;
|
||||
int ret;
|
||||
|
||||
ret = ad7606_pwm_set_low(st);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
spi_offload_trigger_disable(bus_data->offload,
|
||||
bus_data->offload_trigger);
|
||||
spi_unoptimize_message(&bus_data->offload_msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ad7606c_18_sw_mode_config(struct iio_dev *indio_dev)
|
||||
static const struct iio_buffer_setup_ops ad7606_offload_buffer_setup_ops = {
|
||||
.postenable = ad7606_spi_offload_buffer_postenable,
|
||||
.predisable = ad7606_spi_offload_buffer_predisable,
|
||||
};
|
||||
|
||||
static bool ad7606_spi_offload_trigger_match(
|
||||
struct spi_offload_trigger *trigger,
|
||||
enum spi_offload_trigger_type type,
|
||||
u64 *args, u32 nargs)
|
||||
{
|
||||
if (type != SPI_OFFLOAD_TRIGGER_DATA_READY)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Requires 1 arg:
|
||||
* args[0] is the trigger event.
|
||||
*/
|
||||
if (nargs != 1 || args[0] != AD7606_TRIGGER_EVENT_BUSY)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int ad7606_spi_offload_trigger_request(
|
||||
struct spi_offload_trigger *trigger,
|
||||
enum spi_offload_trigger_type type,
|
||||
u64 *args, u32 nargs)
|
||||
{
|
||||
/* Should already be validated by match, but just in case. */
|
||||
if (nargs != 1)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ad7606_spi_offload_trigger_validate(
|
||||
struct spi_offload_trigger *trigger,
|
||||
struct spi_offload_trigger_config *config)
|
||||
{
|
||||
if (config->type != SPI_OFFLOAD_TRIGGER_DATA_READY)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct spi_offload_trigger_ops ad7606_offload_trigger_ops = {
|
||||
.match = ad7606_spi_offload_trigger_match,
|
||||
.request = ad7606_spi_offload_trigger_request,
|
||||
.validate = ad7606_spi_offload_trigger_validate,
|
||||
};
|
||||
|
||||
static int ad7606_spi_offload_probe(struct device *dev,
|
||||
struct iio_dev *indio_dev)
|
||||
{
|
||||
struct ad7606_state *st = iio_priv(indio_dev);
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
struct spi_bus_data *bus_data;
|
||||
struct dma_chan *rx_dma;
|
||||
struct spi_offload_trigger_info trigger_info = {
|
||||
.fwnode = dev_fwnode(dev),
|
||||
.ops = &ad7606_offload_trigger_ops,
|
||||
.priv = st,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = ad7606B_sw_mode_config(indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
bus_data = devm_kzalloc(dev, sizeof(*bus_data), GFP_KERNEL);
|
||||
if (!bus_data)
|
||||
return -ENOMEM;
|
||||
st->bus_data = bus_data;
|
||||
|
||||
indio_dev->channels = ad7606c_18_sw_channels;
|
||||
bus_data->offload = devm_spi_offload_get(dev, spi,
|
||||
&ad7606_spi_offload_config);
|
||||
ret = PTR_ERR_OR_ZERO(bus_data->offload);
|
||||
if (ret && ret != -ENODEV)
|
||||
return dev_err_probe(dev, ret, "failed to get SPI offload\n");
|
||||
/* Allow main ad7606_probe function to continue. */
|
||||
if (ret == -ENODEV)
|
||||
return 0;
|
||||
|
||||
ret = devm_spi_offload_trigger_register(dev, &trigger_info);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"failed to register offload trigger\n");
|
||||
|
||||
bus_data->offload_trigger = devm_spi_offload_trigger_get(dev,
|
||||
bus_data->offload, SPI_OFFLOAD_TRIGGER_DATA_READY);
|
||||
if (IS_ERR(bus_data->offload_trigger))
|
||||
return dev_err_probe(dev, PTR_ERR(bus_data->offload_trigger),
|
||||
"failed to get offload trigger\n");
|
||||
|
||||
/* TODO: PWM setup should be ok, done for the backend. PWM mutex ? */
|
||||
rx_dma = devm_spi_offload_rx_stream_request_dma_chan(dev,
|
||||
bus_data->offload);
|
||||
if (IS_ERR(rx_dma))
|
||||
return dev_err_probe(dev, PTR_ERR(rx_dma),
|
||||
"failed to get offload RX DMA\n");
|
||||
|
||||
ret = devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev,
|
||||
rx_dma, IIO_BUFFER_DIRECTION_IN);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"failed to setup offload RX DMA\n");
|
||||
|
||||
/* Use offload ops. */
|
||||
indio_dev->setup_ops = &ad7606_offload_buffer_setup_ops;
|
||||
|
||||
st->offload_en = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ad7606_spi_update_scan_mode(struct iio_dev *indio_dev,
|
||||
const unsigned long *scan_mask)
|
||||
{
|
||||
struct ad7606_state *st = iio_priv(indio_dev);
|
||||
|
||||
if (st->offload_en) {
|
||||
unsigned int num_adc_ch = st->chip_info->num_adc_channels;
|
||||
|
||||
/*
|
||||
* SPI offload requires that all channels are enabled since
|
||||
* there isn't a way to selectively disable channels that get
|
||||
* read (this is simultaneous sampling ADC) and the DMA buffer
|
||||
* has no way of demuxing the data to filter out unwanted
|
||||
* channels.
|
||||
*/
|
||||
if (bitmap_weight(scan_mask, num_adc_ch) != num_adc_ch)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ad7606_bus_ops ad7606_spi_bops = {
|
||||
.offload_config = ad7606_spi_offload_probe,
|
||||
.read_block = ad7606_spi_read_block,
|
||||
.update_scan_mode = ad7606_spi_update_scan_mode,
|
||||
};
|
||||
|
||||
static const struct ad7606_bus_ops ad7607_spi_bops = {
|
||||
.offload_config = ad7606_spi_offload_probe,
|
||||
.read_block = ad7606_spi_read_block14to16,
|
||||
.update_scan_mode = ad7606_spi_update_scan_mode,
|
||||
};
|
||||
|
||||
static const struct ad7606_bus_ops ad7608_spi_bops = {
|
||||
.offload_config = ad7606_spi_offload_probe,
|
||||
.read_block = ad7606_spi_read_block18to32,
|
||||
.update_scan_mode = ad7606_spi_update_scan_mode,
|
||||
};
|
||||
|
||||
static const struct ad7606_bus_ops ad7616_spi_bops = {
|
||||
.offload_config = ad7606_spi_offload_probe,
|
||||
.read_block = ad7606_spi_read_block,
|
||||
.reg_read = ad7606_spi_reg_read,
|
||||
.reg_write = ad7606_spi_reg_write,
|
||||
.rd_wr_cmd = ad7616_spi_rd_wr_cmd,
|
||||
.sw_mode_config = ad7616_sw_mode_config,
|
||||
.update_scan_mode = ad7606_spi_update_scan_mode,
|
||||
};
|
||||
|
||||
static const struct ad7606_bus_ops ad7606b_spi_bops = {
|
||||
.offload_config = ad7606_spi_offload_probe,
|
||||
.read_block = ad7606_spi_read_block,
|
||||
.reg_read = ad7606_spi_reg_read,
|
||||
.reg_write = ad7606_spi_reg_write,
|
||||
.rd_wr_cmd = ad7606B_spi_rd_wr_cmd,
|
||||
.sw_mode_config = ad7606B_sw_mode_config,
|
||||
.rd_wr_cmd = ad7606b_spi_rd_wr_cmd,
|
||||
.sw_mode_config = ad7606b_sw_mode_config,
|
||||
.update_scan_mode = ad7606_spi_update_scan_mode,
|
||||
};
|
||||
|
||||
static const struct ad7606_bus_ops ad7606c_18_spi_bops = {
|
||||
.offload_config = ad7606_spi_offload_probe,
|
||||
.read_block = ad7606_spi_read_block18to32,
|
||||
.reg_read = ad7606_spi_reg_read,
|
||||
.reg_write = ad7606_spi_reg_write,
|
||||
.rd_wr_cmd = ad7606B_spi_rd_wr_cmd,
|
||||
.sw_mode_config = ad7606c_18_sw_mode_config,
|
||||
.rd_wr_cmd = ad7606b_spi_rd_wr_cmd,
|
||||
.sw_mode_config = ad7606b_sw_mode_config,
|
||||
.update_scan_mode = ad7606_spi_update_scan_mode,
|
||||
};
|
||||
|
||||
static const struct ad7606_bus_info ad7605_4_bus_info = {
|
||||
|
|
@ -348,3 +509,4 @@ MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
|
|||
MODULE_DESCRIPTION("Analog Devices AD7606 ADC");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_IMPORT_NS("IIO_AD7606");
|
||||
MODULE_IMPORT_NS("IIO_DMAENGINE_BUFFER");
|
||||
|
|
|
|||
|
|
@ -4,14 +4,17 @@
|
|||
*
|
||||
* Copyright 2017 Analog Devices Inc.
|
||||
*/
|
||||
#include <linux/array_size.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
|
@ -53,12 +56,15 @@
|
|||
#define AD7768_REG_SPI_DIAG_ENABLE 0x28
|
||||
#define AD7768_REG_ADC_DIAG_ENABLE 0x29
|
||||
#define AD7768_REG_DIG_DIAG_ENABLE 0x2A
|
||||
#define AD7768_REG_ADC_DATA 0x2C
|
||||
#define AD7768_REG24_ADC_DATA 0x2C
|
||||
#define AD7768_REG_MASTER_STATUS 0x2D
|
||||
#define AD7768_REG_SPI_DIAG_STATUS 0x2E
|
||||
#define AD7768_REG_ADC_DIAG_STATUS 0x2F
|
||||
#define AD7768_REG_DIG_DIAG_STATUS 0x30
|
||||
#define AD7768_REG_MCLK_COUNTER 0x31
|
||||
#define AD7768_REG_COEFF_CONTROL 0x32
|
||||
#define AD7768_REG24_COEFF_DATA 0x33
|
||||
#define AD7768_REG_ACCESS_KEY 0x34
|
||||
|
||||
/* AD7768_REG_POWER_CLOCK */
|
||||
#define AD7768_PWR_MCLK_DIV_MSK GENMASK(5, 4)
|
||||
|
|
@ -76,9 +82,6 @@
|
|||
#define AD7768_CONV_MODE_MSK GENMASK(2, 0)
|
||||
#define AD7768_CONV_MODE(x) FIELD_PREP(AD7768_CONV_MODE_MSK, x)
|
||||
|
||||
#define AD7768_RD_FLAG_MSK(x) (BIT(6) | ((x) & 0x3F))
|
||||
#define AD7768_WR_FLAG_MSK(x) ((x) & 0x3F)
|
||||
|
||||
enum ad7768_conv_mode {
|
||||
AD7768_CONTINUOUS,
|
||||
AD7768_ONE_SHOT,
|
||||
|
|
@ -153,6 +156,8 @@ static const struct iio_chan_spec ad7768_channels[] = {
|
|||
|
||||
struct ad7768_state {
|
||||
struct spi_device *spi;
|
||||
struct regmap *regmap;
|
||||
struct regmap *regmap24;
|
||||
struct regulator *vref;
|
||||
struct clk *mclk;
|
||||
unsigned int mclk_freq;
|
||||
|
|
@ -160,6 +165,7 @@ struct ad7768_state {
|
|||
struct completion completion;
|
||||
struct iio_trigger *trig;
|
||||
struct gpio_desc *gpio_sync_in;
|
||||
struct gpio_desc *gpio_reset;
|
||||
const char *labels[ARRAY_SIZE(ad7768_channels)];
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) may require the
|
||||
|
|
@ -175,46 +181,82 @@ struct ad7768_state {
|
|||
} data __aligned(IIO_DMA_MINALIGN);
|
||||
};
|
||||
|
||||
static int ad7768_spi_reg_read(struct ad7768_state *st, unsigned int addr,
|
||||
unsigned int len)
|
||||
{
|
||||
unsigned int shift;
|
||||
int ret;
|
||||
static const struct regmap_range ad7768_regmap_rd_ranges[] = {
|
||||
regmap_reg_range(AD7768_REG_CHIP_TYPE, AD7768_REG_CHIP_GRADE),
|
||||
regmap_reg_range(AD7768_REG_SCRATCH_PAD, AD7768_REG_SCRATCH_PAD),
|
||||
regmap_reg_range(AD7768_REG_VENDOR_L, AD7768_REG_VENDOR_H),
|
||||
regmap_reg_range(AD7768_REG_INTERFACE_FORMAT, AD7768_REG_GAIN_LO),
|
||||
regmap_reg_range(AD7768_REG_SPI_DIAG_ENABLE, AD7768_REG_DIG_DIAG_ENABLE),
|
||||
regmap_reg_range(AD7768_REG_MASTER_STATUS, AD7768_REG_COEFF_CONTROL),
|
||||
regmap_reg_range(AD7768_REG_ACCESS_KEY, AD7768_REG_ACCESS_KEY),
|
||||
};
|
||||
|
||||
shift = 32 - (8 * len);
|
||||
st->data.d8[0] = AD7768_RD_FLAG_MSK(addr);
|
||||
static const struct regmap_access_table ad7768_regmap_rd_table = {
|
||||
.yes_ranges = ad7768_regmap_rd_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(ad7768_regmap_rd_ranges),
|
||||
};
|
||||
|
||||
ret = spi_write_then_read(st->spi, st->data.d8, 1,
|
||||
&st->data.d32, len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
static const struct regmap_range ad7768_regmap_wr_ranges[] = {
|
||||
regmap_reg_range(AD7768_REG_SCRATCH_PAD, AD7768_REG_SCRATCH_PAD),
|
||||
regmap_reg_range(AD7768_REG_INTERFACE_FORMAT, AD7768_REG_GPIO_WRITE),
|
||||
regmap_reg_range(AD7768_REG_OFFSET_HI, AD7768_REG_GAIN_LO),
|
||||
regmap_reg_range(AD7768_REG_SPI_DIAG_ENABLE, AD7768_REG_DIG_DIAG_ENABLE),
|
||||
regmap_reg_range(AD7768_REG_SPI_DIAG_STATUS, AD7768_REG_SPI_DIAG_STATUS),
|
||||
regmap_reg_range(AD7768_REG_COEFF_CONTROL, AD7768_REG_COEFF_CONTROL),
|
||||
regmap_reg_range(AD7768_REG_ACCESS_KEY, AD7768_REG_ACCESS_KEY),
|
||||
};
|
||||
|
||||
return (be32_to_cpu(st->data.d32) >> shift);
|
||||
}
|
||||
static const struct regmap_access_table ad7768_regmap_wr_table = {
|
||||
.yes_ranges = ad7768_regmap_wr_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(ad7768_regmap_wr_ranges),
|
||||
};
|
||||
|
||||
static int ad7768_spi_reg_write(struct ad7768_state *st,
|
||||
unsigned int addr,
|
||||
unsigned int val)
|
||||
{
|
||||
st->data.d8[0] = AD7768_WR_FLAG_MSK(addr);
|
||||
st->data.d8[1] = val & 0xFF;
|
||||
static const struct regmap_config ad7768_regmap_config = {
|
||||
.name = "ad7768-1-8",
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.read_flag_mask = BIT(6),
|
||||
.rd_table = &ad7768_regmap_rd_table,
|
||||
.wr_table = &ad7768_regmap_wr_table,
|
||||
.max_register = AD7768_REG_ACCESS_KEY,
|
||||
.use_single_write = true,
|
||||
.use_single_read = true,
|
||||
};
|
||||
|
||||
return spi_write(st->spi, st->data.d8, 2);
|
||||
}
|
||||
static const struct regmap_range ad7768_regmap24_rd_ranges[] = {
|
||||
regmap_reg_range(AD7768_REG24_ADC_DATA, AD7768_REG24_ADC_DATA),
|
||||
regmap_reg_range(AD7768_REG24_COEFF_DATA, AD7768_REG24_COEFF_DATA),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table ad7768_regmap24_rd_table = {
|
||||
.yes_ranges = ad7768_regmap24_rd_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(ad7768_regmap24_rd_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_range ad7768_regmap24_wr_ranges[] = {
|
||||
regmap_reg_range(AD7768_REG24_COEFF_DATA, AD7768_REG24_COEFF_DATA),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table ad7768_regmap24_wr_table = {
|
||||
.yes_ranges = ad7768_regmap24_wr_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(ad7768_regmap24_wr_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_config ad7768_regmap24_config = {
|
||||
.name = "ad7768-1-24",
|
||||
.reg_bits = 8,
|
||||
.val_bits = 24,
|
||||
.read_flag_mask = BIT(6),
|
||||
.rd_table = &ad7768_regmap24_rd_table,
|
||||
.wr_table = &ad7768_regmap24_wr_table,
|
||||
.max_register = AD7768_REG24_COEFF_DATA,
|
||||
};
|
||||
|
||||
static int ad7768_set_mode(struct ad7768_state *st,
|
||||
enum ad7768_conv_mode mode)
|
||||
{
|
||||
int regval;
|
||||
|
||||
regval = ad7768_spi_reg_read(st, AD7768_REG_CONVERSION, 1);
|
||||
if (regval < 0)
|
||||
return regval;
|
||||
|
||||
regval &= ~AD7768_CONV_MODE_MSK;
|
||||
regval |= AD7768_CONV_MODE(mode);
|
||||
|
||||
return ad7768_spi_reg_write(st, AD7768_REG_CONVERSION, regval);
|
||||
return regmap_update_bits(st->regmap, AD7768_REG_CONVERSION,
|
||||
AD7768_CONV_MODE_MSK, AD7768_CONV_MODE(mode));
|
||||
}
|
||||
|
||||
static int ad7768_scan_direct(struct iio_dev *indio_dev)
|
||||
|
|
@ -233,9 +275,10 @@ static int ad7768_scan_direct(struct iio_dev *indio_dev)
|
|||
if (!ret)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
readval = ad7768_spi_reg_read(st, AD7768_REG_ADC_DATA, 3);
|
||||
if (readval < 0)
|
||||
return readval;
|
||||
ret = regmap_read(st->regmap24, AD7768_REG24_ADC_DATA, &readval);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Any SPI configuration of the AD7768-1 can only be
|
||||
* performed in continuous conversion mode.
|
||||
|
|
@ -258,16 +301,23 @@ static int ad7768_reg_access(struct iio_dev *indio_dev,
|
|||
if (!iio_device_claim_direct(indio_dev))
|
||||
return -EBUSY;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (readval) {
|
||||
ret = ad7768_spi_reg_read(st, reg, 1);
|
||||
if (ret < 0)
|
||||
goto err_release;
|
||||
*readval = ret;
|
||||
ret = 0;
|
||||
if (regmap_check_range_table(st->regmap, reg, &ad7768_regmap_rd_table))
|
||||
ret = regmap_read(st->regmap, reg, readval);
|
||||
|
||||
if (regmap_check_range_table(st->regmap24, reg, &ad7768_regmap24_rd_table))
|
||||
ret = regmap_read(st->regmap24, reg, readval);
|
||||
|
||||
} else {
|
||||
ret = ad7768_spi_reg_write(st, reg, writeval);
|
||||
if (regmap_check_range_table(st->regmap, reg, &ad7768_regmap_wr_table))
|
||||
ret = regmap_write(st->regmap, reg, writeval);
|
||||
|
||||
if (regmap_check_range_table(st->regmap24, reg, &ad7768_regmap24_wr_table))
|
||||
ret = regmap_write(st->regmap24, reg, writeval);
|
||||
|
||||
}
|
||||
err_release:
|
||||
|
||||
iio_device_release_direct(indio_dev);
|
||||
|
||||
return ret;
|
||||
|
|
@ -284,7 +334,7 @@ static int ad7768_set_dig_fil(struct ad7768_state *st,
|
|||
else
|
||||
mode = AD7768_DIG_FIL_DEC_RATE(dec_rate);
|
||||
|
||||
ret = ad7768_spi_reg_write(st, AD7768_REG_DIGITAL_FILTER, mode);
|
||||
ret = regmap_write(st->regmap, AD7768_REG_DIGITAL_FILTER, mode);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
@ -321,7 +371,7 @@ static int ad7768_set_freq(struct ad7768_state *st,
|
|||
*/
|
||||
pwr_mode = AD7768_PWR_MCLK_DIV(ad7768_clk_config[idx].mclk_div) |
|
||||
AD7768_PWR_PWRMODE(ad7768_clk_config[idx].pwrmode);
|
||||
ret = ad7768_spi_reg_write(st, AD7768_REG_POWER_CLOCK, pwr_mode);
|
||||
ret = regmap_write(st->regmap, AD7768_REG_POWER_CLOCK, pwr_mode);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
@ -440,19 +490,30 @@ static int ad7768_setup(struct ad7768_state *st)
|
|||
{
|
||||
int ret;
|
||||
|
||||
st->gpio_reset = devm_gpiod_get_optional(&st->spi->dev, "reset",
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(st->gpio_reset))
|
||||
return PTR_ERR(st->gpio_reset);
|
||||
|
||||
if (st->gpio_reset) {
|
||||
fsleep(10);
|
||||
gpiod_set_value_cansleep(st->gpio_reset, 0);
|
||||
fsleep(200);
|
||||
} else {
|
||||
/*
|
||||
* Two writes to the SPI_RESET[1:0] bits are required to initiate
|
||||
* a software reset. The bits must first be set to 11, and then
|
||||
* to 10. When the sequence is detected, the reset occurs.
|
||||
* See the datasheet, page 70.
|
||||
*/
|
||||
ret = ad7768_spi_reg_write(st, AD7768_REG_SYNC_RESET, 0x3);
|
||||
ret = regmap_write(st->regmap, AD7768_REG_SYNC_RESET, 0x3);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ad7768_spi_reg_write(st, AD7768_REG_SYNC_RESET, 0x2);
|
||||
ret = regmap_write(st->regmap, AD7768_REG_SYNC_RESET, 0x2);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
st->gpio_sync_in = devm_gpiod_get(&st->spi->dev, "adi,sync-in",
|
||||
GPIOD_OUT_LOW);
|
||||
|
|
@ -474,7 +535,8 @@ static irqreturn_t ad7768_trigger_handler(int irq, void *p)
|
|||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &st->data.scan,
|
||||
iio_push_to_buffers_with_ts(indio_dev, &st->data.scan,
|
||||
sizeof(st->data.scan),
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
out:
|
||||
|
|
@ -505,18 +567,19 @@ static int ad7768_buffer_postenable(struct iio_dev *indio_dev)
|
|||
* continuous read mode. Subsequent data reads do not require an
|
||||
* initial 8-bit write to query the ADC_DATA register.
|
||||
*/
|
||||
return ad7768_spi_reg_write(st, AD7768_REG_INTERFACE_FORMAT, 0x01);
|
||||
return regmap_write(st->regmap, AD7768_REG_INTERFACE_FORMAT, 0x01);
|
||||
}
|
||||
|
||||
static int ad7768_buffer_predisable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct ad7768_state *st = iio_priv(indio_dev);
|
||||
unsigned int unused;
|
||||
|
||||
/*
|
||||
* To exit continuous read mode, perform a single read of the ADC_DATA
|
||||
* reg (0x2C), which allows further configuration of the device.
|
||||
*/
|
||||
return ad7768_spi_reg_read(st, AD7768_REG_ADC_DATA, 3);
|
||||
return regmap_read(st->regmap24, AD7768_REG24_ADC_DATA, &unused);
|
||||
}
|
||||
|
||||
static const struct iio_buffer_setup_ops ad7768_buffer_ops = {
|
||||
|
|
@ -559,6 +622,31 @@ static int ad7768_set_channel_label(struct iio_dev *indio_dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ad7768_triggered_buffer_alloc(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct ad7768_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
st->trig = devm_iio_trigger_alloc(indio_dev->dev.parent, "%s-dev%d",
|
||||
indio_dev->name,
|
||||
iio_device_id(indio_dev));
|
||||
if (!st->trig)
|
||||
return -ENOMEM;
|
||||
|
||||
st->trig->ops = &ad7768_trigger_ops;
|
||||
iio_trigger_set_drvdata(st->trig, indio_dev);
|
||||
ret = devm_iio_trigger_register(indio_dev->dev.parent, st->trig);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
indio_dev->trig = iio_trigger_get(st->trig);
|
||||
|
||||
return devm_iio_triggered_buffer_setup(indio_dev->dev.parent, indio_dev,
|
||||
&iio_pollfunc_store_time,
|
||||
&ad7768_trigger_handler,
|
||||
&ad7768_buffer_ops);
|
||||
}
|
||||
|
||||
static int ad7768_probe(struct spi_device *spi)
|
||||
{
|
||||
struct ad7768_state *st;
|
||||
|
|
@ -587,6 +675,16 @@ static int ad7768_probe(struct spi_device *spi)
|
|||
|
||||
st->spi = spi;
|
||||
|
||||
st->regmap = devm_regmap_init_spi(spi, &ad7768_regmap_config);
|
||||
if (IS_ERR(st->regmap))
|
||||
return dev_err_probe(&spi->dev, PTR_ERR(st->regmap),
|
||||
"Failed to initialize regmap");
|
||||
|
||||
st->regmap24 = devm_regmap_init_spi(spi, &ad7768_regmap24_config);
|
||||
if (IS_ERR(st->regmap24))
|
||||
return dev_err_probe(&spi->dev, PTR_ERR(st->regmap24),
|
||||
"Failed to initialize regmap24");
|
||||
|
||||
st->vref = devm_regulator_get(&spi->dev, "vref");
|
||||
if (IS_ERR(st->vref))
|
||||
return PTR_ERR(st->vref);
|
||||
|
|
@ -619,20 +717,6 @@ static int ad7768_probe(struct spi_device *spi)
|
|||
return ret;
|
||||
}
|
||||
|
||||
st->trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d",
|
||||
indio_dev->name,
|
||||
iio_device_id(indio_dev));
|
||||
if (!st->trig)
|
||||
return -ENOMEM;
|
||||
|
||||
st->trig->ops = &ad7768_trigger_ops;
|
||||
iio_trigger_set_drvdata(st->trig, indio_dev);
|
||||
ret = devm_iio_trigger_register(&spi->dev, st->trig);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
indio_dev->trig = iio_trigger_get(st->trig);
|
||||
|
||||
init_completion(&st->completion);
|
||||
|
||||
ret = ad7768_set_channel_label(indio_dev, ARRAY_SIZE(ad7768_channels));
|
||||
|
|
@ -646,10 +730,7 @@ static int ad7768_probe(struct spi_device *spi)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
|
||||
&iio_pollfunc_store_time,
|
||||
&ad7768_trigger_handler,
|
||||
&ad7768_buffer_ops);
|
||||
ret = ad7768_triggered_buffer_alloc(indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -658,7 +739,7 @@ static int ad7768_probe(struct spi_device *spi)
|
|||
|
||||
static const struct spi_device_id ad7768_id_table[] = {
|
||||
{ "ad7768-1", 0 },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, ad7768_id_table);
|
||||
|
||||
|
|
|
|||
|
|
@ -595,7 +595,8 @@ static irqreturn_t ad7779_trigger_handler(int irq, void *p)
|
|||
goto exit_handler;
|
||||
}
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &st->data, pf->timestamp);
|
||||
iio_push_to_buffers_with_ts(indio_dev, &st->data, sizeof(st->data),
|
||||
pf->timestamp);
|
||||
|
||||
exit_handler:
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
|
|
|||
|
|
@ -464,7 +464,7 @@ static const struct spi_device_id ad7791_spi_ids[] = {
|
|||
{ "ad7789", AD7789 },
|
||||
{ "ad7790", AD7790 },
|
||||
{ "ad7791", AD7791 },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, ad7791_spi_ids);
|
||||
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ static irqreturn_t ad7923_trigger_handler(int irq, void *p)
|
|||
if (b_sent)
|
||||
goto done;
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf,
|
||||
iio_push_to_buffers_with_ts(indio_dev, st->rx_buf, sizeof(st->rx_buf),
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
done:
|
||||
|
|
|
|||
|
|
@ -189,11 +189,6 @@ static int ad7944_3wire_cs_mode_init_msg(struct device *dev, struct ad7944_adc *
|
|||
: adc->timing_spec->conv_ns;
|
||||
struct spi_transfer *xfers = adc->xfers;
|
||||
|
||||
/*
|
||||
* NB: can get better performance from some SPI controllers if we use
|
||||
* the same bits_per_word in every transfer.
|
||||
*/
|
||||
xfers[0].bits_per_word = chan->scan_type.realbits;
|
||||
/*
|
||||
* CS is tied to CNV and we need a low to high transition to start the
|
||||
* conversion, so place CNV low for t_QUIET to prepare for this.
|
||||
|
|
@ -208,7 +203,6 @@ static int ad7944_3wire_cs_mode_init_msg(struct device *dev, struct ad7944_adc *
|
|||
xfers[1].cs_off = 1;
|
||||
xfers[1].delay.value = t_conv_ns;
|
||||
xfers[1].delay.unit = SPI_DELAY_UNIT_NSECS;
|
||||
xfers[1].bits_per_word = chan->scan_type.realbits;
|
||||
|
||||
/* Then we can read the data during the acquisition phase */
|
||||
xfers[2].rx_buf = &adc->sample.raw;
|
||||
|
|
@ -227,11 +221,6 @@ static int ad7944_4wire_mode_init_msg(struct device *dev, struct ad7944_adc *adc
|
|||
: adc->timing_spec->conv_ns;
|
||||
struct spi_transfer *xfers = adc->xfers;
|
||||
|
||||
/*
|
||||
* NB: can get better performance from some SPI controllers if we use
|
||||
* the same bits_per_word in every transfer.
|
||||
*/
|
||||
xfers[0].bits_per_word = chan->scan_type.realbits;
|
||||
/*
|
||||
* CS has to be high for full conversion time to avoid triggering the
|
||||
* busy indication.
|
||||
|
|
|
|||
|
|
@ -958,7 +958,7 @@ static const struct i2c_device_id ad799x_id[] = {
|
|||
{ "ad7994", ad7994 },
|
||||
{ "ad7997", ad7997 },
|
||||
{ "ad7998", ad7998 },
|
||||
{}
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, ad799x_id);
|
||||
|
|
|
|||
|
|
@ -587,6 +587,10 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
|
|||
* byte set to zero. */
|
||||
ad_sd_read_reg_raw(sigma_delta, data_reg, transfer_size, &data[1]);
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err_ratelimited(&indio_dev->dev, "Unsupported reg_size: %u\n", reg_size);
|
||||
goto irq_handled;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -702,7 +702,7 @@ static const struct of_device_id adi_axi_adc_of_match[] = {
|
|||
{ .compatible = "adi,axi-adc-10.0.a", .data = &adc_generic },
|
||||
{ .compatible = "adi,axi-ad485x", .data = &adi_axi_ad485x },
|
||||
{ .compatible = "adi,axi-ad7606x", .data = &adc_ad7606 },
|
||||
{ /* end of list */ }
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, adi_axi_adc_of_match);
|
||||
|
||||
|
|
|
|||
|
|
@ -586,15 +586,6 @@ struct at91_adc_temp {
|
|||
u16 saved_oversampling;
|
||||
};
|
||||
|
||||
/*
|
||||
* Buffer size requirements:
|
||||
* No channels * bytes_per_channel(2) + timestamp bytes (8)
|
||||
* Divided by 2 because we need half words.
|
||||
* We assume 32 channels for now, has to be increased if needed.
|
||||
* Nobody minds a buffer being too big.
|
||||
*/
|
||||
#define AT91_BUFFER_MAX_HWORDS ((32 * 2 + 8) / 2)
|
||||
|
||||
struct at91_adc_state {
|
||||
void __iomem *base;
|
||||
int irq;
|
||||
|
|
@ -616,8 +607,8 @@ struct at91_adc_state {
|
|||
struct at91_adc_temp temp_st;
|
||||
struct iio_dev *indio_dev;
|
||||
struct device *dev;
|
||||
/* Ensure naturally aligned timestamp */
|
||||
u16 buffer[AT91_BUFFER_MAX_HWORDS] __aligned(8);
|
||||
/* We assume 32 channels for now, has to be increased if needed. */
|
||||
IIO_DECLARE_BUFFER_WITH_TS(u16, buffer, 32);
|
||||
/*
|
||||
* lock to prevent concurrent 'single conversion' requests through
|
||||
* sysfs.
|
||||
|
|
|
|||
|
|
@ -163,14 +163,14 @@ static const struct iio_map axp20x_maps[] = {
|
|||
IIO_MAP("batt_v", "axp20x-battery-power-supply", "batt_v"),
|
||||
IIO_MAP("batt_chrg_i", "axp20x-battery-power-supply", "batt_chrg_i"),
|
||||
IIO_MAP("batt_dischrg_i", "axp20x-battery-power-supply", "batt_dischrg_i"),
|
||||
{ /* sentinel */ }
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct iio_map axp22x_maps[] = {
|
||||
IIO_MAP("batt_v", "axp20x-battery-power-supply", "batt_v"),
|
||||
IIO_MAP("batt_chrg_i", "axp20x-battery-power-supply", "batt_chrg_i"),
|
||||
IIO_MAP("batt_dischrg_i", "axp20x-battery-power-supply", "batt_dischrg_i"),
|
||||
{ /* sentinel */ }
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct iio_map axp717_maps[] = {
|
||||
|
|
@ -1074,7 +1074,7 @@ static const struct of_device_id axp20x_adc_of_match[] = {
|
|||
{ .compatible = "x-powers,axp221-adc", .data = (void *)&axp22x_data, },
|
||||
{ .compatible = "x-powers,axp717-adc", .data = (void *)&axp717_data, },
|
||||
{ .compatible = "x-powers,axp813-adc", .data = (void *)&axp813_data, },
|
||||
{ /* sentinel */ }
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, axp20x_adc_of_match);
|
||||
|
||||
|
|
@ -1084,7 +1084,7 @@ static const struct platform_device_id axp20x_adc_id_match[] = {
|
|||
{ .name = "axp22x-adc", .driver_data = (kernel_ulong_t)&axp22x_data, },
|
||||
{ .name = "axp717-adc", .driver_data = (kernel_ulong_t)&axp717_data, },
|
||||
{ .name = "axp813-adc", .driver_data = (kernel_ulong_t)&axp813_data, },
|
||||
{ /* sentinel */ },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, axp20x_adc_id_match);
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue