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
Greg Kroah-Hartman 2025-05-22 15:54:52 +02:00
commit 0ca7cb7089
464 changed files with 8505 additions and 3214 deletions

View File

@ -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,

View File

@ -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:

View File

@ -17,35 +17,40 @@ description: |
properties:
compatible:
enum:
- adi,ad7091
- adi,ad7091r
- adi,ad7273
- adi,ad7274
- adi,ad7276
- adi,ad7277
- adi,ad7278
- adi,ad7466
- adi,ad7467
- adi,ad7468
- adi,ad7475
- adi,ad7476
- adi,ad7476a
- adi,ad7477
- adi,ad7477a
- adi,ad7478
- adi,ad7478a
- adi,ad7495
- adi,ad7910
- adi,ad7920
- adi,ad7940
- ti,adc081s
- ti,adc101s
- ti,adc121s
- ti,ads7866
- ti,ads7867
- ti,ads7868
- lltc,ltc2314-14
oneOf:
- items:
- enum:
- adi,ad7091
- adi,ad7091r
- adi,ad7273
- adi,ad7274
- adi,ad7276
- adi,ad7277
- adi,ad7278
- adi,ad7466
- adi,ad7467
- adi,ad7468
- adi,ad7475
- adi,ad7476
- adi,ad7476a
- adi,ad7477
- adi,ad7477a
- adi,ad7478
- adi,ad7478a
- adi,ad7495
- adi,ad7910
- adi,ad7920
- adi,ad7940
- ti,adc081s
- ti,adc101s
- ti,adc121s
- ti,ads7866
- ti,ads7867
- ti,ads7868
- lltc,ltc2314-14
- items:
- const: rohm,bu79100g
- const: ti,ads7866
reg:
maxItems: 1

View File

@ -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

View File

@ -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

View File

@ -34,6 +34,7 @@ properties:
- const: mediatek,mt2701-auxadc
- items:
- enum:
- mediatek,mt6893-auxadc
- mediatek,mt8183-auxadc
- mediatek,mt8186-auxadc
- mediatek,mt8188-auxadc

View File

@ -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>;

View File

@ -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>;
};
};
...

View File

@ -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>;
};
};
...

View File

@ -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>;
};
};
};

View File

@ -498,7 +498,7 @@ patternProperties:
examples:
- |
// Example 1: with stm32f429, ADC1, single-ended channel 8
adc123: adc@40012000 {
adc123: adc@40012000 {
compatible = "st,stm32f4-adc-core";
reg = <0x40012000 0x400>;
interrupts = <18>;
@ -512,28 +512,28 @@ examples:
#address-cells = <1>;
#size-cells = <0>;
adc@0 {
compatible = "st,stm32f4-adc";
#io-channel-cells = <1>;
reg = <0x0>;
clocks = <&rcc 0 168>;
interrupt-parent = <&adc123>;
interrupts = <0>;
st,adc-channels = <8>;
dmas = <&dma2 0 0 0x400 0x0>;
dma-names = "rx";
assigned-resolution-bits = <8>;
compatible = "st,stm32f4-adc";
#io-channel-cells = <1>;
reg = <0x0>;
clocks = <&rcc 0 168>;
interrupt-parent = <&adc123>;
interrupts = <0>;
st,adc-channels = <8>;
dmas = <&dma2 0 0 0x400 0x0>;
dma-names = "rx";
assigned-resolution-bits = <8>;
};
// ...
// other adc child nodes follow...
};
};
- |
// Example 2: with stm32mp157c to setup ADC1 with:
// - channels 0 & 1 as single-ended
// - channels 2 & 3 as differential (with resp. 6 & 7 negative inputs)
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
adc12: adc@48003000 {
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
adc12: adc@48003000 {
compatible = "st,stm32mp1-adc-core";
reg = <0x48003000 0x400>;
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
@ -550,27 +550,27 @@ examples:
#address-cells = <1>;
#size-cells = <0>;
adc@0 {
compatible = "st,stm32mp1-adc";
#io-channel-cells = <1>;
reg = <0x0>;
interrupt-parent = <&adc12>;
interrupts = <0>;
st,adc-channels = <0 1>;
st,adc-diff-channels = <2 6>, <3 7>;
st,min-sample-time-nsecs = <5000>;
dmas = <&dmamux1 9 0x400 0x05>;
dma-names = "rx";
compatible = "st,stm32mp1-adc";
#io-channel-cells = <1>;
reg = <0x0>;
interrupt-parent = <&adc12>;
interrupts = <0>;
st,adc-channels = <0 1>;
st,adc-diff-channels = <2 6>, <3 7>;
st,min-sample-time-nsecs = <5000>;
dmas = <&dmamux1 9 0x400 0x05>;
dma-names = "rx";
};
// ...
// other adc child node follow...
};
};
- |
// Example 3: with stm32mp157c to setup ADC2 with:
// - internal channels 13, 14, 15.
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
adc122: adc@48003000 {
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
adc122: adc@48003000 {
compatible = "st,stm32mp1-adc-core";
reg = <0x48003000 0x400>;
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
@ -587,28 +587,28 @@ examples:
#address-cells = <1>;
#size-cells = <0>;
adc@100 {
compatible = "st,stm32mp1-adc";
#io-channel-cells = <1>;
reg = <0x100>;
interrupts = <1>;
#address-cells = <1>;
#size-cells = <0>;
channel@13 {
reg = <13>;
label = "vrefint";
st,min-sample-time-ns = <9000>;
};
channel@14 {
reg = <14>;
label = "vddcore";
st,min-sample-time-ns = <9000>;
};
channel@15 {
reg = <15>;
label = "vbat";
st,min-sample-time-ns = <9000>;
};
compatible = "st,stm32mp1-adc";
#io-channel-cells = <1>;
reg = <0x100>;
interrupts = <1>;
#address-cells = <1>;
#size-cells = <0>;
channel@13 {
reg = <13>;
label = "vrefint";
st,min-sample-time-ns = <9000>;
};
channel@14 {
reg = <14>;
label = "vddcore";
st,min-sample-time-ns = <9000>;
};
channel@15 {
reg = <15>;
label = "vbat";
st,min-sample-time-ns = <9000>;
};
};
};
};
...

View File

@ -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>;
};
};
...

View File

@ -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>;
};
};
...

View File

@ -217,7 +217,7 @@ required:
- reg
- spi-max-frequency
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View File

@ -27,6 +27,8 @@ properties:
vdrive-supply: true
vrefin-supply: true
reset-gpios:
maxItems: 1

View File

@ -144,7 +144,7 @@ required:
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View File

@ -124,7 +124,7 @@ required:
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View File

@ -64,7 +64,7 @@ required:
- reg
- vdd-supply
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View File

@ -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:
- |

View File

@ -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>;
};
};
...

View File

@ -53,7 +53,7 @@ required:
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View File

@ -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>;
};

View File

@ -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>;
};
};

View File

@ -102,7 +102,7 @@ required:
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml
additionalProperties: false
unevaluatedProperties: false
dependentSchemas:
honeywell,pmin-pascal:

View File

@ -115,7 +115,7 @@ allOf:
honeywell,pmin-pascal: false
honeywell,pmax-pascal: false
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View File

@ -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

View File

@ -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,.*":

View File

@ -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

View File

@ -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.

View File

@ -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
~~~~~~~~~~~~

View File

@ -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
==============

View File

@ -19,6 +19,7 @@ Industrial I/O Kernel Drivers
.. toctree::
:maxdepth: 1
ad3552r
ad4000
ad4030
ad4695

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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, &regval);
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), &regval);
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, &regval);
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, &regval);
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,20 +890,34 @@ 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, &regval);
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)
goto err;
if (adxl345_fifo_push(indio_dev, samples) < 0)
goto err;
}
if (adxl345_push_event(indio_dev, int_stat, tap_dir))
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, &regval);
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;
}

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -103,8 +103,8 @@ 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,
pf->timestamp);
iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan),
pf->timestamp);
err:
mutex_unlock(&data->lock);
iio_trigger_notify_done(indio_dev->trig);
@ -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);

View File

@ -1591,8 +1591,9 @@ 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_get_time_ns(indio_dev));
iio_push_to_buffers_with_ts(indio_dev, &data->buffer,
sizeof(data->buffer),
iio_get_time_ns(indio_dev));
mutex_unlock(&data->mutex);
iio_trigger_notify_done(indio_dev->trig);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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,69 +690,12 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
if (ret < 0)
return ret;
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) {
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 (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 (is_new_data == true) {
ret = kxcjk1013_chip_update_thresholds(data);
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");
@ -776,10 +719,17 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data,
return ret;
}
if (status)
ret |= KXCJK1013_REG_CTRL1_BIT_DRDY;
else
ret &= ~KXCJK1013_REG_CTRL1_BIT_DRDY;
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,8 +1203,8 @@ 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,
data->timestamp);
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);

View File

@ -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);

View File

@ -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);

View File

@ -229,9 +229,8 @@ static irqreturn_t kxsd9_trigger_handler(int irq, void *p)
goto out;
}
iio_push_to_buffers_with_timestamp(indio_dev,
&hw_values,
iio_get_time_ns(indio_dev));
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) \

View File

@ -103,8 +103,9 @@ 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_get_time_ns(indio_dev));
iio_push_to_buffers_with_ts(indio_dev, &mma7455->scan,
sizeof(mma7455->scan),
iio_get_time_ns(indio_dev));
done:
iio_trigger_notify_done(indio_dev->trig);

View File

@ -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);

View File

@ -1103,8 +1103,9 @@ 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_get_time_ns(indio_dev));
iio_push_to_buffers_with_ts(indio_dev, &data->buffer,
sizeof(data->buffer),
iio_get_time_ns(indio_dev));
done:
iio_trigger_notify_done(indio_dev->trig);

View File

@ -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);

View File

@ -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);

View File

@ -919,8 +919,8 @@ static irqreturn_t msa311_buffer_thread(int irq, void *p)
mutex_unlock(&msa311->lock);
iio_push_to_buffers_with_timestamp(indio_dev, &buf,
iio_get_time_ns(indio_dev));
iio_push_to_buffers_with_ts(indio_dev, &buf, sizeof(buf),
iio_get_time_ns(indio_dev));
notify_done:
iio_trigger_notify_done(indio_dev->trig);

View File

@ -335,8 +335,8 @@ 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,
pf->timestamp);
iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan),
pf->timestamp);
err:
iio_trigger_notify_done(indio_dev->trig);
@ -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);

View File

@ -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);

View File

@ -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,8 +492,8 @@ static irqreturn_t sca3300_trigger_handler(int irq, void *p)
channels[i++] = val;
}
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
iio_get_time_ns(indio_dev));
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);

View File

@ -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);

View File

@ -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);

View File

@ -460,8 +460,8 @@ static irqreturn_t stk8312_trigger_handler(int irq, void *p)
}
mutex_unlock(&data->lock);
iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
pf->timestamp);
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);

View File

@ -340,8 +340,8 @@ 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,
pf->timestamp);
iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan),
pf->timestamp);
err:
mutex_unlock(&data->lock);
iio_trigger_notify_done(indio_dev->trig);
@ -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);

View File

@ -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

View File

@ -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

View File

@ -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);
else
sample = be16_to_cpu(st->scan.data.sample_buf16);
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_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:
indio_dev->info = &ad4000_info;
indio_dev->channels = chip->chan_spec;
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");

View File

@ -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 = scan_type->realbits;
*val = st->vref_uv / MILLI;
*val2 = chan->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,8 +703,8 @@ 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,
pf->timestamp);
iio_push_to_buffers_with_ts(indio_dev, &st->rx_data, sizeof(st->rx_data),
pf->timestamp);
out:
iio_trigger_notify_done(indio_dev->trig);
@ -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,
};

View File

@ -522,15 +522,15 @@ 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,
int value)
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,
value ? mask : 0);
return regmap_update_bits(st->regmap, AD4130_IO_CONTROL_REG, mask,
value ? mask : 0);
}
static int ad4130_set_mode(struct ad4130_state *st, enum ad4130_mode mode)
@ -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)

View File

@ -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);

View File

@ -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");

View File

@ -32,7 +32,7 @@
#define AD7124_IO_CONTROL_2 0x04
#define AD7124_ID 0x05
#define AD7124_ERROR 0x06
#define AD7124_ERROR_EN 0x07
#define AD7124_ERROR_EN 0x07
#define AD7124_MCLK_COUNT 0x08
#define AD7124_CHANNEL(x) (0x09 + (x))
#define AD7124_CONFIG(x) (0x19 + (x))
@ -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,16 +707,8 @@ 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;
ret = -EINVAL;
}
mutex_unlock(&st->cfgs_lock);
@ -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);

View File

@ -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,
pf->timestamp);
}
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);

View File

@ -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[] = {

View File

@ -155,8 +155,8 @@ 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_get_time_ns(indio_dev));
iio_push_to_buffers_with_ts(indio_dev, st->rx_buf, sizeof(st->rx_buf),
iio_get_time_ns(indio_dev));
done:
iio_trigger_notify_done(indio_dev->trig);

View File

@ -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,8 +1359,8 @@ 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,
pf->timestamp);
iio_push_to_buffers_with_ts(indio_dev, &st->scan_data, sizeof(st->scan_data),
pf->timestamp);
out:
iio_trigger_notify_done(indio_dev->trig);
@ -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 },

View File

@ -99,8 +99,8 @@ 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_get_time_ns(indio_dev));
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);

View File

@ -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,8 +605,8 @@ 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_get_time_ns(indio_dev));
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);
/* The rising edge of the CONVST signal starts a new conversion. */
@ -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");

View File

@ -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)
*/
union {
u16 buf16[20];
u32 buf32[10];
struct {
union {
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;

View File

@ -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 },

View File

@ -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,
AD7606_SINGLE_DOUT);
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");

View File

@ -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;
/*
* 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);
if (ret)
return 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);
ret = ad7768_spi_reg_write(st, AD7768_REG_SYNC_RESET, 0x2);
if (ret)
return ret;
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 = regmap_write(st->regmap, AD7768_REG_SYNC_RESET, 0x3);
if (ret)
return ret;
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,8 +535,9 @@ 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_get_time_ns(indio_dev));
iio_push_to_buffers_with_ts(indio_dev, &st->data.scan,
sizeof(st->data.scan),
iio_get_time_ns(indio_dev));
out:
iio_trigger_notify_done(indio_dev->trig);
@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -207,8 +207,8 @@ 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_get_time_ns(indio_dev));
iio_push_to_buffers_with_ts(indio_dev, st->rx_buf, sizeof(st->rx_buf),
iio_get_time_ns(indio_dev));
done:
iio_trigger_notify_done(indio_dev->trig);

View File

@ -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.

View File

@ -958,7 +958,7 @@ static const struct i2c_device_id ad799x_id[] = {
{ "ad7994", ad7994 },
{ "ad7997", ad7997 },
{ "ad7998", ad7998 },
{}
{ }
};
MODULE_DEVICE_TABLE(i2c, ad799x_id);

View File

@ -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;
}
/*

View File

@ -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);

View File

@ -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.

Some files were not shown because too many files have changed in this diff Show More