mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 01:32:21 +02:00
IIO: New device support, features and cleanup for the 7.2 cycle.
Like many areas of the kernel IIO has seen a lot of new contributors though in this case that is not all AI driven, but also reflects and annual surge of student contributions from usp.br. We also have several new regular reviewers who are helping with the surge (thanks to all our active reviewers!) Given there was a lot of cases of similar improvements applied to different drivers, I have grouped those into a special section (various drivers) to avoid mass duplication. New device support ------------------ adi,ad4130 - Add support for AD4129-4, AD4129-8, AD4130-4, AD4131-4 and AD4131-8 after reworking the driver to be suitable for multiple device support. adi,ad4080 - Support the AD4880 and AD4884 dual-channel parts. Interesting parts as have two separate data pipelines (including SPI buses interfaces), but the only current backend IP combines the two so they cannot be treated as independent devices. adi,ad5706r - New driver for this 4 channel current output DAC. adi,ad4691 - New driver supporting this family of ADCs. Support for AD4691, AD4692, AD4693 and AD4694 which support either 8 or 16 channels with different max sampling rates. Feature rich driver including SPI offload support. adi,ltc2983 - Add support for the ADT7604 in which the same sensor die as the LTC2984 is used for leak detection (liquid coverage of a sense area). allwinner,adc - Support for A523 SoCs. Similar to existing parts but with an additional clock. Includes adding support for non contiguous channel lookup for in kernel use (fwnode_xlate callback). broadcomm,apds9999 - New driver for the APDS9999 Ambient Light, RGB and proximity sensor. memsic,mmc5983 - New driver for this 3-axis magnetometer. taos,tsl2772 - Add support for the AVAGO APDS9900 and APDS9901 Ambient Light and Proximity sensors. which are very similar to existing part with slightly different integration time choices. Includes removal of driver for these parts from drivers/misc. vishay,veml3328 - New driver for this RGB+IR light sensor. Features -------- IIO Core - Support for IEEE 754 floating point values in buffer scan elements. - Support quaternion axis representation (missing the scaler part) microchip,mcp4821 - Add configurable gain control qcom,pm8xxx-xoadc - Add per channel labels. st,lsm6dsx - Support for rotation sensing on the LSM6DSV and LSM6DSV16X using both floating point and new quaterionaxis rotation modifier. MAINTAINERS update ------------------ IIO top level entry - Include Documentation/driver-api/iio/ adi,* - Top level ADI entry maintainer switch from Lars-Peter Clausen to Nuno Sá reflecting what has been the reality for some time. Thanks to Lars-Peter who was very active for many years, but has moved on to other things. Also add the linux@analog.com email list to ensure we don't get a gap in future. - Maintainer updates to reflect Cosmin Tanislav having moved on - thanks to Marcelo Schmitt for taking these over. sensiron,scd30 - Replace maintainer (Tomasz Duszynski) with Maxwell Doose. Cleanups, minor fixes and hardening. ------------------------------------ Documentation - Add missing powerdown modes to ABI docs. - Use modern helpers for buffer definition in the examples. core - Rework of the handling of timestamps so that the offset is cached at buffer resize time (during enabling) rather than based on assumption that relied in the timestamp being last and the largest element and so always 8 bytes before end of the scan. Underlying problem was triggered by scans with repeated type elements such as quaternions with each element more than 2 bytes - Giving a 16 byte+ aligned channel with result that a following timestamp may be 16 bytes from end of scan, rather than 8. Note that for the bosch,bno55 a compatibility hack means that it will duplicate the timestamp putting a second copy at previously incorrect location. - Tidy up use of kernel types in buffer code to not use int64_t given all calls use s64. various drivers - Drop unused driver_data in device id tables - includes cleanup of various drivers that had only one choice where it can be hard coded elsewhere. - Move to named initializers for many i2c_device_id and platform_device_id tables (I have no idea how we go into habit of using named initializers for only a subset of the table types - e.g. of_device_id). - Make IIO_CHAN_SOFT_TIMESTAMP() macro a compound literal allowing simple use in various drivers that do dynamic channel definitions. Use it in all such cases. - Use dev_err_probe() and local dev variables to tidy up older drivers. - Switch more drivers to devm_mutex_init() to provide minor debug benefits. - Reorder code to put MODULE_DEVICE_TABLE() next to the tables. - Lots of use of cleanup.h magic to improve code flow, often including related refactors such as introducing helpers. - Replacement of usleep_range() with fsleep() - Reduce logging noise where functions either provide their own extensive reports on error, or where a clear error code is returned to userspace. - Minor spelling and style fixes (improving bracket usage, not using __packed etc) hid-sensors-* - Drop helpers for setting channel bit masks in favor of a compound literal at the call site. Also general cleanup of surrounding code. hid-sensors-magn - Use u32 rather than bare unsigned for types. hid-sensors-rotation - Make sue of ext_scan_type handling for static case rather than duplicate chan_info structures. adi,ad3552r - Use field_get() to replace open coded equivalent. adi,ad4170 - Switch from switch to table lookup for GPIO modes. adi,ad5686 - Apply IWYU principal to included a consistent set of headers. - Deduplicate regmaps for AD5684 and AD5693 as identical. - Switch from an enum value in driver data and array look up to pointers to separate structures, improving readabilty and avoiding issues with 0 value when using helpers to deal with different firmware types. - Add of_match_id table to SPI driver rather than relying on fallback to spi_device_id table. - Introduce some helpers for powerdown mask control. - Add helpers for control sync simplifying a couple of corner cases. - Docs fixes. - Add an ops structure to simplify future addition of operations beyond read and write. adi,ad7191 - Switch to best practice of using device_property_present() to detect if an optional property is there rather than error values on querying the property. adi,ad7280a - Use local variables to improve readability of breaking up chan-address. adi,ad7825 - Cleanup a type mismatch in clamp() call. adi,ad799x - Include improvements - Local dev variable to shorten code lines. - Cache regulator voltage at probe (these never change in practice) - Convert to devm for all unwind handling. adi,ad9832 - Improve include relevance including replacing kernel.h with more specific headers. - Simplify some maths. adi,ad9834 - Improve include relevance including replacing kernel.h with more specific headers. adi,adt7316 - Add a comment to avoid future 'fixes' for error handling during the odd sequence used to flip from I2C mode to SPI mode. adi,adxl* - Documentation consistency improvements. asahi-kasei,ak8975 - Fix missing runtime pm calls for buffered capture. - Fix missing pm_runtime_put_autosuspend() in an error path that would leave the device stuck on. - Close a potential uninitialized kernel stack leak. - Extensive driver modernization including: header relevance, fsleep() various minor bugs, dropping duplicate error messages and avoiding magic lengths for buffers. - Replace opencoded polling with iopoll(). - Add error checking to gpio reads. avia,hx711 - Move scale computation from global data to per device avoiding problems if multiple devices present. - General binding text cleanup. bosch,bmg160 - Add missing mount-matrix entry to binding. bosch,bno55 - Terminate error strings with newlines. devantech,srf08 - Replace sprintf() with sysfs_emit() and sysfs_emit_at() to make intent clearer. freescale,mma8452 - Add missing return value check. - Fix potential probe ordering issue by switching to non devm irq request. linear,ltc2309 - Add chip specific read delays. - Improve chip_info structure, adding __counted_by_ptr marking and reorganizing to improve packing. linear,ltc2983 - Fix a firmware combination where default n_wires of 2 bypasses exclusion of adi,current-rotate whereas explicitly setting it to 2 does not. - Fix potential race with completion reinit. - Improve error message wording consistency. - Use fwnode_property_present() to detect optional properties rather than fragile return value checking. microchip,mcp3422 - Use of GENMASK(), FIELD_GET(), FIELD_PREP() to improve readability and generally modernize driver. microchip,mcp47feb02 - Fix binding example to use a possible I2C address. - Fix binding bounds on channel number. - Standardize binding example indentation nxp,saradc - Increase chances of recovering from a failure in the interrupt handler by notifying the trigger that it can reenable even when the read failed. - Use field_get() to replace opencoded equivalent. qualcomm,* - Standardize on Qualcomm company naming in Kconfig. richtek,rtq6056 - Add i2c_device_id table for legacy instantiation. samsung,ssp - Replace custom timestamp channel macro with main one. sciosense,ens210 - Now scoped_guard() has been reworked, no need for a return that can never be reached. sensiron,scd30 - Constify command lookup table. - Sanity check for NULL buffer of non zero size being provided to sc30_i2c_command() sensortek,stk3310 - Include more appropriate headers. - Ensure interrupt in appropriate mode after resume. - Structure definition improvements. - Use size_of() to replace opencoded sizes. siliconimage,si1133 - Resolve counter related issues on timeout error paths. - Unused macro removal, improved macro definitions,. - Include relevance improvements. st,lsm6dsx - Fix an issue with applying invalid data check to wrong type of sample. taos,tcs3472 - Try to powerdown chip on probe failure. - Devm usage and dropping of remove() callback. - Various other minor cleanup. taos,tsl2591 - Dead code removal. - Simplify tsl2591_persist functions using a look up table. ti,ads1298 - Fix wrong comment on timeout (and minor code improvement) - Drop unnecessary CONFIG2 write during init. ti,ads7950 - Check ret rather that ret < 0 for spi_setup() call. - Use fully devm managed resources including moving to devm_regulator_get_enable_read_voltage() at probe time rather than querying evey time. - Using spi_optimize_message() to reduce CPU usage. ti,ads8688 - User read_avail() callback rather than open coding handling of available attributes. ti,opt3001 - Header relevance improvements - Use GENMASK for field definitions to improve readability. vishay,vcnl4000 - Switch from enum in device_data to individual names structures impmroving code readabililty. - Move to devm handling for remainder of probe. vishay,veml6030 - Drop pointless read of current Iteration Time index as it is not used. xilinx,ams - Fix potential out of bound channel lookup. - Replace some large switch statements with table lookups. yamaha,yas530 - Put label in chip info structure to avoid look up in i2c_device_id table. Drop ---- iio-trig-interrupt. - Not used for some time and no support for modern firmware bindings or in kernel users. So drop it. -----BEGIN PGP SIGNATURE----- iQJFBAABCgAvFiEEbilms4eEBlKRJoGxVIU0mcT0FogFAmolp9kRHGppYzIzQGtl cm5lbC5vcmcACgkQVIU0mcT0FoieAxAArpdsc3rjgjeFxymnbXPWqjohz/XCg3Ps XXxbyaLCvphsJ7P7vsp7acX0vIdi+mqPLU+6Vl67OolFVKM3+84PMoHY3s0wbbMj xDgcI6zR4kwGUpGry9FKr3/UQaSNLo7ahYq7UZKJA8vCoHd11AUzh8TCz/myrdnK Ju6I+FScj6L8lkftaGgYqzHEOoKXQtXaUrYbUFQR/vm9/FlgEkF5qP4pcVxBfAox OtO9jjQOpOAZnTEEbjy6mmEVyuIzOAjLQFxPBzaUuWtZv51P5OZGOS0WNYvt4zvK ziaRPgTIShjUVGkQmhmZ3AjmrYmRjWMhyR58BAyYgqbN/OAwtaJEou8UCDeVQxst B3Tj10VrxuHCEmXvy7ex5SqsKBQ1BHuz3bS8u2znEFp7RcxIorXllRLckpdIFyIa LDyO6krus1mBhLVQ1LVhQNlpi6KKvVD3fcV/14fUoG/ZAP6ta3cdA7jybp1k4aNs PYdlTuJn9jLhRrjHEFaM9hT3St/MRSJ3/rFj4rEHufs3w7iATKWwR9YqcNG8VNFN rGz0aB72J1FxevP3/n5MfXkYUZTmw776Oy/IfB2swXMpH23L2+3b8+ZJUy2HJbBJ 69sjgvEiFkhsJBI8eLe6pEWoD6wkq6KDamcYcgnUNPu8AaC45DLPuGHEPyjzk/AX vuc+ysTUb70= =AW+z -----END PGP SIGNATURE----- Merge tag 'iio-for-7.2a' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/jic23/iio into work-testing IIO: New device support, features and cleanup for the 7.2 cycle. Like many areas of the kernel IIO has seen a lot of new contributors though in this case that is not all AI driven, but also reflects and annual surge of student contributions from usp.br. We also have several new regular reviewers who are helping with the surge (thanks to all our active reviewers!) Given there was a lot of cases of similar improvements applied to different drivers, I have grouped those into a special section (various drivers) to avoid mass duplication. New device support ------------------ adi,ad4130 - Add support for AD4129-4, AD4129-8, AD4130-4, AD4131-4 and AD4131-8 after reworking the driver to be suitable for multiple device support. adi,ad4080 - Support the AD4880 and AD4884 dual-channel parts. Interesting parts as have two separate data pipelines (including SPI buses interfaces), but the only current backend IP combines the two so they cannot be treated as independent devices. adi,ad5706r - New driver for this 4 channel current output DAC. adi,ad4691 - New driver supporting this family of ADCs. Support for AD4691, AD4692, AD4693 and AD4694 which support either 8 or 16 channels with different max sampling rates. Feature rich driver including SPI offload support. adi,ltc2983 - Add support for the ADT7604 in which the same sensor die as the LTC2984 is used for leak detection (liquid coverage of a sense area). allwinner,adc - Support for A523 SoCs. Similar to existing parts but with an additional clock. Includes adding support for non contiguous channel lookup for in kernel use (fwnode_xlate callback). broadcomm,apds9999 - New driver for the APDS9999 Ambient Light, RGB and proximity sensor. memsic,mmc5983 - New driver for this 3-axis magnetometer. taos,tsl2772 - Add support for the AVAGO APDS9900 and APDS9901 Ambient Light and Proximity sensors. which are very similar to existing part with slightly different integration time choices. Includes removal of driver for these parts from drivers/misc. vishay,veml3328 - New driver for this RGB+IR light sensor. Features -------- IIO Core - Support for IEEE 754 floating point values in buffer scan elements. - Support quaternion axis representation (missing the scaler part) microchip,mcp4821 - Add configurable gain control qcom,pm8xxx-xoadc - Add per channel labels. st,lsm6dsx - Support for rotation sensing on the LSM6DSV and LSM6DSV16X using both floating point and new quaterionaxis rotation modifier. MAINTAINERS update ------------------ IIO top level entry - Include Documentation/driver-api/iio/ adi,* - Top level ADI entry maintainer switch from Lars-Peter Clausen to Nuno Sá reflecting what has been the reality for some time. Thanks to Lars-Peter who was very active for many years, but has moved on to other things. Also add the linux@analog.com email list to ensure we don't get a gap in future. - Maintainer updates to reflect Cosmin Tanislav having moved on - thanks to Marcelo Schmitt for taking these over. sensiron,scd30 - Replace maintainer (Tomasz Duszynski) with Maxwell Doose. Cleanups, minor fixes and hardening. ------------------------------------ Documentation - Add missing powerdown modes to ABI docs. - Use modern helpers for buffer definition in the examples. core - Rework of the handling of timestamps so that the offset is cached at buffer resize time (during enabling) rather than based on assumption that relied in the timestamp being last and the largest element and so always 8 bytes before end of the scan. Underlying problem was triggered by scans with repeated type elements such as quaternions with each element more than 2 bytes - Giving a 16 byte+ aligned channel with result that a following timestamp may be 16 bytes from end of scan, rather than 8. Note that for the bosch,bno55 a compatibility hack means that it will duplicate the timestamp putting a second copy at previously incorrect location. - Tidy up use of kernel types in buffer code to not use int64_t given all calls use s64. various drivers - Drop unused driver_data in device id tables - includes cleanup of various drivers that had only one choice where it can be hard coded elsewhere. - Move to named initializers for many i2c_device_id and platform_device_id tables (I have no idea how we go into habit of using named initializers for only a subset of the table types - e.g. of_device_id). - Make IIO_CHAN_SOFT_TIMESTAMP() macro a compound literal allowing simple use in various drivers that do dynamic channel definitions. Use it in all such cases. - Use dev_err_probe() and local dev variables to tidy up older drivers. - Switch more drivers to devm_mutex_init() to provide minor debug benefits. - Reorder code to put MODULE_DEVICE_TABLE() next to the tables. - Lots of use of cleanup.h magic to improve code flow, often including related refactors such as introducing helpers. - Replacement of usleep_range() with fsleep() - Reduce logging noise where functions either provide their own extensive reports on error, or where a clear error code is returned to userspace. - Minor spelling and style fixes (improving bracket usage, not using __packed etc) hid-sensors-* - Drop helpers for setting channel bit masks in favor of a compound literal at the call site. Also general cleanup of surrounding code. hid-sensors-magn - Use u32 rather than bare unsigned for types. hid-sensors-rotation - Make sue of ext_scan_type handling for static case rather than duplicate chan_info structures. adi,ad3552r - Use field_get() to replace open coded equivalent. adi,ad4170 - Switch from switch to table lookup for GPIO modes. adi,ad5686 - Apply IWYU principal to included a consistent set of headers. - Deduplicate regmaps for AD5684 and AD5693 as identical. - Switch from an enum value in driver data and array look up to pointers to separate structures, improving readabilty and avoiding issues with 0 value when using helpers to deal with different firmware types. - Add of_match_id table to SPI driver rather than relying on fallback to spi_device_id table. - Introduce some helpers for powerdown mask control. - Add helpers for control sync simplifying a couple of corner cases. - Docs fixes. - Add an ops structure to simplify future addition of operations beyond read and write. adi,ad7191 - Switch to best practice of using device_property_present() to detect if an optional property is there rather than error values on querying the property. adi,ad7280a - Use local variables to improve readability of breaking up chan-address. adi,ad7825 - Cleanup a type mismatch in clamp() call. adi,ad799x - Include improvements - Local dev variable to shorten code lines. - Cache regulator voltage at probe (these never change in practice) - Convert to devm for all unwind handling. adi,ad9832 - Improve include relevance including replacing kernel.h with more specific headers. - Simplify some maths. adi,ad9834 - Improve include relevance including replacing kernel.h with more specific headers. adi,adt7316 - Add a comment to avoid future 'fixes' for error handling during the odd sequence used to flip from I2C mode to SPI mode. adi,adxl* - Documentation consistency improvements. asahi-kasei,ak8975 - Fix missing runtime pm calls for buffered capture. - Fix missing pm_runtime_put_autosuspend() in an error path that would leave the device stuck on. - Close a potential uninitialized kernel stack leak. - Extensive driver modernization including: header relevance, fsleep() various minor bugs, dropping duplicate error messages and avoiding magic lengths for buffers. - Replace opencoded polling with iopoll(). - Add error checking to gpio reads. avia,hx711 - Move scale computation from global data to per device avoiding problems if multiple devices present. - General binding text cleanup. bosch,bmg160 - Add missing mount-matrix entry to binding. bosch,bno55 - Terminate error strings with newlines. devantech,srf08 - Replace sprintf() with sysfs_emit() and sysfs_emit_at() to make intent clearer. freescale,mma8452 - Add missing return value check. - Fix potential probe ordering issue by switching to non devm irq request. linear,ltc2309 - Add chip specific read delays. - Improve chip_info structure, adding __counted_by_ptr marking and reorganizing to improve packing. linear,ltc2983 - Fix a firmware combination where default n_wires of 2 bypasses exclusion of adi,current-rotate whereas explicitly setting it to 2 does not. - Fix potential race with completion reinit. - Improve error message wording consistency. - Use fwnode_property_present() to detect optional properties rather than fragile return value checking. microchip,mcp3422 - Use of GENMASK(), FIELD_GET(), FIELD_PREP() to improve readability and generally modernize driver. microchip,mcp47feb02 - Fix binding example to use a possible I2C address. - Fix binding bounds on channel number. - Standardize binding example indentation nxp,saradc - Increase chances of recovering from a failure in the interrupt handler by notifying the trigger that it can reenable even when the read failed. - Use field_get() to replace opencoded equivalent. qualcomm,* - Standardize on Qualcomm company naming in Kconfig. richtek,rtq6056 - Add i2c_device_id table for legacy instantiation. samsung,ssp - Replace custom timestamp channel macro with main one. sciosense,ens210 - Now scoped_guard() has been reworked, no need for a return that can never be reached. sensiron,scd30 - Constify command lookup table. - Sanity check for NULL buffer of non zero size being provided to sc30_i2c_command() sensortek,stk3310 - Include more appropriate headers. - Ensure interrupt in appropriate mode after resume. - Structure definition improvements. - Use size_of() to replace opencoded sizes. siliconimage,si1133 - Resolve counter related issues on timeout error paths. - Unused macro removal, improved macro definitions,. - Include relevance improvements. st,lsm6dsx - Fix an issue with applying invalid data check to wrong type of sample. taos,tcs3472 - Try to powerdown chip on probe failure. - Devm usage and dropping of remove() callback. - Various other minor cleanup. taos,tsl2591 - Dead code removal. - Simplify tsl2591_persist functions using a look up table. ti,ads1298 - Fix wrong comment on timeout (and minor code improvement) - Drop unnecessary CONFIG2 write during init. ti,ads7950 - Check ret rather that ret < 0 for spi_setup() call. - Use fully devm managed resources including moving to devm_regulator_get_enable_read_voltage() at probe time rather than querying evey time. - Using spi_optimize_message() to reduce CPU usage. ti,ads8688 - User read_avail() callback rather than open coding handling of available attributes. ti,opt3001 - Header relevance improvements - Use GENMASK for field definitions to improve readability. vishay,vcnl4000 - Switch from enum in device_data to individual names structures impmroving code readabililty. - Move to devm handling for remainder of probe. vishay,veml6030 - Drop pointless read of current Iteration Time index as it is not used. xilinx,ams - Fix potential out of bound channel lookup. - Replace some large switch statements with table lookups. yamaha,yas530 - Put label in chip info structure to avoid look up in i2c_device_id table. Drop ---- iio-trig-interrupt. - Not used for some time and no support for modern firmware bindings or in kernel users. So drop it. * tag 'iio-for-7.2a' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (266 commits) iio: adc: nxp-sar-adc: harden buffer ISR against per-channel read failure iio: chemical: scd30: Replace manual locking with RAII locking iio: light: tsl2591: remove unneeded tsl2591_compatible_als_persist_cycle() iio: dac: ad5686: create bus ops struct iio: dac: ad5686: cleanup doc header of local structs iio: dac: ad5686: add control_sync() for single-channel devices iio: dac: ad5686: add helpers to handle powerdown masks iio: dac: ad5686: add of_match table to the spi driver iio: dac: ad5686: drop enum id iio: dac: ad5686: remove redundant register definition iio: dac: ad5686: refactor include headers iio: adc: ad4080: fix AD4880 chip ID iio: light: veml3328: add support for new device dt-bindings: iio: light: veml6030: add veml3328 docs: iio: adc: ad4691: add driver documentation iio: adc: ad4691: add oversampling support iio: adc: ad4691: add SPI offload support iio: adc: ad4691: add triggered buffer support iio: adc: ad4691: add initial driver for AD4691 family dt-bindings: iio: adc: add AD4691 family ...
This commit is contained in:
commit
47b56cc367
|
|
@ -764,10 +764,13 @@ Contact: linux-iio@vger.kernel.org
|
|||
Description:
|
||||
Specifies the output powerdown mode.
|
||||
DAC output stage is disconnected from the amplifier and
|
||||
500ohm_to_gnd: connected to ground via a 500Ohm resistor,
|
||||
1kohm_to_gnd: connected to ground via an 1kOhm resistor,
|
||||
2.5kohm_to_gnd: connected to ground via a 2.5kOhm resistor,
|
||||
3.85kohm_to_gnd: connected to ground via a 3.85kOhm resistor,
|
||||
6kohm_to_gnd: connected to ground via a 6kOhm resistor,
|
||||
7.7kohm_to_gnd: connected to ground via a 7.7kOhm resistor,
|
||||
16kohm_to_gnd: connected to ground via a 16kOhm 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,
|
||||
|
|
@ -1510,21 +1513,24 @@ Contact: linux-iio@vger.kernel.org
|
|||
Description:
|
||||
Description of the scan element data storage within the buffer
|
||||
and hence the form in which it is read from user-space.
|
||||
Form is [be|le]:[s|u]bits/storagebits[>>shift].
|
||||
be or le specifies big or little endian. s or u specifies if
|
||||
signed (2's complement) or unsigned. bits is the number of bits
|
||||
of data and storagebits is the space (after padding) that it
|
||||
occupies in the buffer. shift if specified, is the shift that
|
||||
needs to be applied prior to masking out unused bits. Some
|
||||
devices put their data in the middle of the transferred elements
|
||||
with additional information on both sides. Note that some
|
||||
devices will have additional information in the unused bits
|
||||
so to get a clean value, the bits value must be used to mask
|
||||
the buffer output value appropriately. The storagebits value
|
||||
also specifies the data alignment. So s48/64>>2 will be a
|
||||
signed 48 bit integer stored in a 64 bit location aligned to
|
||||
a 64 bit boundary. To obtain the clean value, shift right 2
|
||||
and apply a mask to zero the top 16 bits of the result.
|
||||
Form is [be|le]:[f|s|u]bits/storagebits[>>shift].
|
||||
be or le specifies big or little endian. f means floating-point
|
||||
(IEEE 754 binary format), s means signed (2's complement), u means
|
||||
unsigned. bits is the number of bits of data and storagebits is the
|
||||
space (after padding) that it occupies in the buffer; when using a
|
||||
floating-point format, bits must be one of the width values defined
|
||||
in the IEEE 754 standard for binary interchange formats (e.g. 16
|
||||
indicates the binary16 format for half-precision numbers). shift,
|
||||
if specified, is the shift that needs to be applied prior to
|
||||
masking out unused bits. Some devices put their data in the middle
|
||||
of the transferred elements with additional information on both
|
||||
sides. Note that some devices will have additional information in
|
||||
the unused bits, so to get a clean value the bits value must be
|
||||
used to mask the buffer output value appropriately. The storagebits
|
||||
value also specifies the data alignment. So s48/64>>2 will be a
|
||||
signed 48 bit integer stored in a 64 bit location aligned to a 64
|
||||
bit boundary. To obtain the clean value, shift right 2 and apply a
|
||||
mask to zero the top 16 bits of the result.
|
||||
For other storage combinations this attribute will be extended
|
||||
appropriately.
|
||||
|
||||
|
|
@ -1752,6 +1758,21 @@ Description:
|
|||
measurement from channel Y. Units after application of scale and
|
||||
offset are milliamps.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_rot_quaternionaxis_raw
|
||||
KernelVersion: 7.1
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Raw value of {x, y, z} components of the quaternion vector. These
|
||||
components represent the axis about which a rotation occurs, and are
|
||||
subject to the following constraints:
|
||||
|
||||
- the quaternion vector is normalized, i.e. w^2 + x^2 + y^2 + z^2 = 1
|
||||
- the rotation angle is within the [-pi, pi] range, i.e. the w
|
||||
component (which represents the amount of rotation) is non-negative
|
||||
|
||||
These constraints allow the w value to be calculated from the other
|
||||
components: w = sqrt(1 - (x^2 + y^2 + z^2)).
|
||||
|
||||
What: /sys/.../iio:deviceX/in_energy_en
|
||||
What: /sys/.../iio:deviceX/in_distance_en
|
||||
What: /sys/.../iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_en
|
||||
|
|
@ -1959,6 +1980,23 @@ Description:
|
|||
Raw (unscaled no offset etc.) resistance reading.
|
||||
Units after application of scale and offset are ohms.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_coverageY_raw
|
||||
KernelVersion: 7.2
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Raw (unscaled no offset etc.) coverage reading. Used for sensors
|
||||
that report fractional coverage as a percentage, such as leak
|
||||
detectors where the value represents what portion of the sensing
|
||||
element is wetted. Units after application of scale and offset are
|
||||
percent.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_coverageY_scale
|
||||
KernelVersion: 7.2
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Scale to be applied to in_coverageY_raw to obtain coverage
|
||||
in percent.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/heater_enable
|
||||
KernelVersion: 4.1.0
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
|
|
|
|||
|
|
@ -18,7 +18,11 @@ description: |
|
|||
service a wide variety of precision, wide bandwidth data acquisition
|
||||
applications.
|
||||
|
||||
The AD4880 is a dual-channel variant with two independent ADC channels,
|
||||
each with its own SPI configuration interface.
|
||||
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad4080.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad4880.pdf
|
||||
|
||||
$ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
|
|
@ -34,9 +38,16 @@ properties:
|
|||
- adi,ad4086
|
||||
- adi,ad4087
|
||||
- adi,ad4088
|
||||
- adi,ad4880
|
||||
- adi,ad4884
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
description:
|
||||
SPI chip select(s). For single-channel devices, one chip select.
|
||||
For multi-channel devices like AD4880, two chip selects are required
|
||||
as each channel has its own SPI configuration interface.
|
||||
|
||||
spi-max-frequency:
|
||||
description: Configuration of the SPI bus.
|
||||
|
|
@ -60,7 +71,10 @@ properties:
|
|||
vrefin-supply: true
|
||||
|
||||
io-backends:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
items:
|
||||
- description: Backend for channel A (primary)
|
||||
- description: Backend for channel B (secondary)
|
||||
|
||||
adi,lvds-cnv-enable:
|
||||
description: Enable the LVDS signal type on the CNV pin. Default is CMOS.
|
||||
|
|
@ -81,6 +95,27 @@ required:
|
|||
- vdd33-supply
|
||||
- vrefin-supply
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- adi,ad4880
|
||||
- adi,ad4884
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
minItems: 2
|
||||
io-backends:
|
||||
minItems: 2
|
||||
else:
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
io-backends:
|
||||
maxItems: 1
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
|
@ -101,4 +136,21 @@ examples:
|
|||
io-backends = <&iio_backend>;
|
||||
};
|
||||
};
|
||||
- |
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
adc@0 {
|
||||
compatible = "adi,ad4880";
|
||||
reg = <0>, <1>;
|
||||
spi-max-frequency = <10000000>;
|
||||
vdd33-supply = <&vdd33>;
|
||||
vddldo-supply = <&vddldo>;
|
||||
vrefin-supply = <&vrefin>;
|
||||
clocks = <&cnv>;
|
||||
clock-names = "cnv";
|
||||
io-backends = <&iio_backend_cha>, <&iio_backend_chb>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
|
|||
|
|
@ -5,19 +5,30 @@
|
|||
$id: http://devicetree.org/schemas/iio/adc/adi,ad4130.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices AD4130 ADC device driver
|
||||
title: Analog Devices AD4130 family ADCs
|
||||
|
||||
maintainers:
|
||||
- Cosmin Tanislav <cosmin.tanislav@analog.com>
|
||||
|
||||
description: |
|
||||
Bindings for the Analog Devices AD4130 ADC. Datasheet can be found here:
|
||||
Bindings for the Analog Devices AD4130 family ADCs.
|
||||
Datasheets can be found here:
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/AD4129-4.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/AD4129-8.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/AD4130-4.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/AD4130-8.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/AD4131-4.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/AD4131-8.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,ad4129-4
|
||||
- adi,ad4129-8
|
||||
- adi,ad4130-4
|
||||
- adi,ad4130
|
||||
- adi,ad4131-4
|
||||
- adi,ad4131-8
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
@ -32,6 +43,10 @@ properties:
|
|||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
description: |
|
||||
Data Ready / FIFO interrupt. For devices with FIFO support, the
|
||||
interrupt polarity specified here is inverted when the device enters
|
||||
FIFO mode, and normal for data ready.
|
||||
|
||||
interrupt-names:
|
||||
description: |
|
||||
|
|
|
|||
180
Documentation/devicetree/bindings/iio/adc/adi,ad4691.yaml
Normal file
180
Documentation/devicetree/bindings/iio/adc/adi,ad4691.yaml
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/adi,ad4691.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices AD4691 Family Multichannel SAR ADCs
|
||||
|
||||
maintainers:
|
||||
- Radu Sabau <radu.sabau@analog.com>
|
||||
|
||||
description: |
|
||||
The AD4691 family are high-speed, low-power, multichannel successive
|
||||
approximation register (SAR) analog-to-digital converters (ADCs) with
|
||||
an SPI-compatible serial interface. The ADC supports CNV Burst Mode,
|
||||
where an external PWM drives the CNV pin, and Manual Mode, where CNV
|
||||
is directly tied to the SPI chip-select.
|
||||
|
||||
Datasheets:
|
||||
* https://www.analog.com/en/products/ad4691.html
|
||||
* https://www.analog.com/en/products/ad4692.html
|
||||
* https://www.analog.com/en/products/ad4693.html
|
||||
* https://www.analog.com/en/products/ad4694.html
|
||||
|
||||
$ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,ad4691
|
||||
- adi,ad4692
|
||||
- adi,ad4693
|
||||
- adi,ad4694
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
spi-max-frequency:
|
||||
maximum: 40000000
|
||||
|
||||
spi-cpol: true
|
||||
spi-cpha: true
|
||||
|
||||
avdd-supply:
|
||||
description: Analog power supply (4.5V to 5.5V).
|
||||
|
||||
vdd-supply:
|
||||
description:
|
||||
External 1.8V digital core supply. When present, the internal LDO is
|
||||
disabled (LDO_EN = 0). Mutually exclusive with ldo-in-supply.
|
||||
|
||||
ldo-in-supply:
|
||||
description:
|
||||
LDO input supply (2.4V to 5.5V). When present and vdd-supply is absent,
|
||||
the internal LDO generates 1.8V VDD from this input (LDO_EN = 1).
|
||||
Mutually exclusive with vdd-supply.
|
||||
|
||||
vio-supply:
|
||||
description: I/O voltage supply (1.71V to 1.89V or VDD).
|
||||
|
||||
ref-supply:
|
||||
description: External reference voltage supply (2.4V to 5.25V).
|
||||
|
||||
refin-supply:
|
||||
description: Internal reference buffer input supply.
|
||||
|
||||
reset-gpios:
|
||||
description:
|
||||
GPIO line controlling the hardware reset pin (active-low).
|
||||
maxItems: 1
|
||||
|
||||
pwms:
|
||||
description:
|
||||
PWM connected to the CNV pin. When present, selects CNV Burst Mode where
|
||||
the PWM drives the conversion rate. When absent, Manual Mode is used
|
||||
(CNV tied to SPI CS).
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
description:
|
||||
Interrupt lines connected to the ADC GP pins. Each GP pin can be
|
||||
physically wired to an interrupt-capable input on the SoC.
|
||||
maxItems: 4
|
||||
|
||||
interrupt-names:
|
||||
description: Names of the interrupt lines, matching the GP pin names.
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
items:
|
||||
enum:
|
||||
- gp0
|
||||
- gp1
|
||||
- gp2
|
||||
- gp3
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
'#gpio-cells':
|
||||
const: 2
|
||||
|
||||
'#trigger-source-cells':
|
||||
description:
|
||||
This node can act as a trigger source. The single cell in a consumer
|
||||
reference specifies the GP pin number (0-3) used as the trigger output.
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- avdd-supply
|
||||
- vio-supply
|
||||
|
||||
allOf:
|
||||
# vdd-supply and ldo-in-supply are mutually exclusive, one is required:
|
||||
# either an external 1.8V VDD is provided or the internal LDO is fed from
|
||||
# ldo-in-supply to generate VDD.
|
||||
- oneOf:
|
||||
- required:
|
||||
- vdd-supply
|
||||
- required:
|
||||
- ldo-in-supply
|
||||
# ref-supply and refin-supply are mutually exclusive, one is required
|
||||
- oneOf:
|
||||
- required:
|
||||
- ref-supply
|
||||
- required:
|
||||
- refin-supply
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
/* AD4692 in CNV Burst Mode with SPI offload */
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
adc@0 {
|
||||
compatible = "adi,ad4692";
|
||||
reg = <0>;
|
||||
spi-cpol;
|
||||
spi-cpha;
|
||||
spi-max-frequency = <40000000>;
|
||||
|
||||
avdd-supply = <&avdd_supply>;
|
||||
ldo-in-supply = <&avdd_supply>;
|
||||
vio-supply = <&vio_supply>;
|
||||
ref-supply = <&ref_5v>;
|
||||
|
||||
reset-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
|
||||
|
||||
pwms = <&pwm_gen 0 0>;
|
||||
|
||||
#trigger-source-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
/* AD4692 in Manual Mode (CNV tied to SPI CS) */
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
adc@0 {
|
||||
compatible = "adi,ad4692";
|
||||
reg = <0>;
|
||||
spi-cpol;
|
||||
spi-cpha;
|
||||
spi-max-frequency = <31250000>;
|
||||
|
||||
avdd-supply = <&avdd_supply>;
|
||||
ldo-in-supply = <&avdd_supply>;
|
||||
vio-supply = <&vio_supply>;
|
||||
refin-supply = <&refin_supply>;
|
||||
|
||||
reset-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
|
@ -14,6 +14,7 @@ properties:
|
|||
oneOf:
|
||||
- enum:
|
||||
- allwinner,sun20i-d1-gpadc
|
||||
- allwinner,sun55i-a523-gpadc
|
||||
- items:
|
||||
- enum:
|
||||
- allwinner,sun50i-h616-gpadc
|
||||
|
|
@ -29,7 +30,12 @@ properties:
|
|||
const: 0
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
|
@ -40,6 +46,30 @@ properties:
|
|||
resets:
|
||||
maxItems: 1
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- allwinner,sun55i-a523-gpadc
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: Bus clock
|
||||
- description: Module clock
|
||||
clock-names:
|
||||
items:
|
||||
- const: bus
|
||||
- const: mod
|
||||
required:
|
||||
- clock-names
|
||||
else:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 1
|
||||
clock-names: false
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-9a-f]+$":
|
||||
$ref: adc.yaml
|
||||
|
|
|
|||
|
|
@ -10,14 +10,9 @@ maintainers:
|
|||
- Andreas Klinger <ak@it-klinger.de>
|
||||
|
||||
description: |
|
||||
Bit-banging driver using two GPIOs:
|
||||
- sck-gpio gives a clock to the sensor with 24 cycles for data retrieval
|
||||
and up to 3 cycles for selection of the input channel and gain for the
|
||||
next measurement
|
||||
- dout-gpio is the sensor data the sensor responds to the clock
|
||||
|
||||
Specifications about the driver can be found at:
|
||||
http://www.aviaic.com/ENProducts.aspx
|
||||
The HX711 is a 24-bit ADC with selectable gain (32/64/128) and two
|
||||
differential input channels. Channel A supports gain 64 and 128;
|
||||
channel B supports gain 32.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -26,23 +21,23 @@ properties:
|
|||
|
||||
sck-gpios:
|
||||
description:
|
||||
Definition of the GPIO for the clock (output). In the datasheet it is
|
||||
named PD_SCK
|
||||
GPIO for the clock output (PD_SCK in the datasheet).
|
||||
maxItems: 1
|
||||
|
||||
dout-gpios:
|
||||
description:
|
||||
Definition of the GPIO for the data-out sent by the sensor in
|
||||
response to the clock (input).
|
||||
See Documentation/devicetree/bindings/gpio/gpio.txt for information
|
||||
on how to specify a consumer gpio.
|
||||
GPIO for the data output from the sensor (DOUT in the datasheet).
|
||||
maxItems: 1
|
||||
|
||||
avdd-supply:
|
||||
description:
|
||||
Definition of the regulator used as analog supply
|
||||
Analog supply voltage (AVDD).
|
||||
|
||||
clock-frequency:
|
||||
description:
|
||||
Controls the SCK bit-bang timing. The value is used to derive the
|
||||
delay between SCK edges; keep the SCK high time below 60 us to
|
||||
avoid triggering chip power-down mode.
|
||||
minimum: 20000
|
||||
maximum: 2500000
|
||||
default: 400000
|
||||
|
|
|
|||
|
|
@ -78,6 +78,10 @@ patternProperties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
label:
|
||||
description: |
|
||||
Unique name to identify which channel this is.
|
||||
|
||||
qcom,decimation:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |
|
||||
|
|
@ -130,36 +134,47 @@ examples:
|
|||
|
||||
vcoin: adc-channel@0 {
|
||||
reg = <0x00 0x00>;
|
||||
label = "vcoin";
|
||||
};
|
||||
vbat: adc-channel@1 {
|
||||
reg = <0x00 0x01>;
|
||||
label = "vbat";
|
||||
};
|
||||
dcin: adc-channel@2 {
|
||||
reg = <0x00 0x02>;
|
||||
label = "dcin";
|
||||
};
|
||||
ichg: adc-channel@3 {
|
||||
reg = <0x00 0x03>;
|
||||
label = "ichg";
|
||||
};
|
||||
vph_pwr: adc-channel@4 {
|
||||
reg = <0x00 0x04>;
|
||||
label = "vph_pwr";
|
||||
};
|
||||
usb_vbus: adc-channel@a {
|
||||
reg = <0x00 0x0a>;
|
||||
label = "usb_vbus";
|
||||
};
|
||||
die_temp: adc-channel@b {
|
||||
reg = <0x00 0x0b>;
|
||||
label = "die_temp";
|
||||
};
|
||||
ref_625mv: adc-channel@c {
|
||||
reg = <0x00 0x0c>;
|
||||
label = "ref_625mv";
|
||||
};
|
||||
ref_1250mv: adc-channel@d {
|
||||
reg = <0x00 0x0d>;
|
||||
label = "ref_1250mv";
|
||||
};
|
||||
ref_325mv: adc-channel@e {
|
||||
reg = <0x00 0x0e>;
|
||||
label = "ref_325mv";
|
||||
};
|
||||
ref_muxoff: adc-channel@f {
|
||||
reg = <0x00 0x0f>;
|
||||
label = "ref_muxoff";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
|
|||
title: Sensirion SCD30 carbon dioxide sensor
|
||||
|
||||
maintainers:
|
||||
- Tomasz Duszynski <tomasz.duszynski@octakon.com>
|
||||
- Maxwell Doose <m32285159@gmail.com>
|
||||
|
||||
description: |
|
||||
Air quality sensor capable of measuring co2 concentration, temperature
|
||||
|
|
|
|||
105
Documentation/devicetree/bindings/iio/dac/adi,ad5706r.yaml
Normal file
105
Documentation/devicetree/bindings/iio/dac/adi,ad5706r.yaml
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/dac/adi,ad5706r.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices AD5706R 4-Channel Current Output DAC
|
||||
|
||||
maintainers:
|
||||
- Alexis Czezar Torreno <alexisczezar.torreno@analog.com>
|
||||
|
||||
description: |
|
||||
The AD5706R is a 4-channel, 16-bit resolution, current output
|
||||
digital-to-analog converter (DAC) with programmable output current
|
||||
ranges (50mA, 150mA, 200mA, 300mA), an integrated 2.5V voltage
|
||||
reference, and load DAC, A/B toggle, and dither functions.
|
||||
|
||||
Datasheet:
|
||||
https://www.analog.com/en/products/ad5706r.html
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,ad5706r
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
avdd-supply:
|
||||
description: Analog power supply (2.9V to 3.6V).
|
||||
|
||||
iovdd-supply:
|
||||
description: Logic power supply (1.14V to 1.89V).
|
||||
|
||||
pvdd0-supply:
|
||||
description: Power supply for IDAC0 channel (1.65V to AVDD).
|
||||
|
||||
pvdd1-supply:
|
||||
description: Power supply for IDAC1 channel (1.65V to AVDD).
|
||||
|
||||
pvdd2-supply:
|
||||
description: Power supply for IDAC2 channel (1.65V to AVDD).
|
||||
|
||||
pvdd3-supply:
|
||||
description: Power supply for IDAC3 channel (1.65V to AVDD).
|
||||
|
||||
vref-supply:
|
||||
description:
|
||||
Optional external 2.5V voltage reference. If not provided, the
|
||||
internal 2.5V reference is used.
|
||||
|
||||
pwms:
|
||||
maxItems: 1
|
||||
description:
|
||||
Optional PWM connected to the LDAC/TGP/DCK pin for hardware
|
||||
triggered DAC updates, toggle, or dither clock generation.
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
description:
|
||||
GPIO connected to the active low RESET pin. If not provided,
|
||||
software reset is used.
|
||||
|
||||
enable-gpios:
|
||||
maxItems: 1
|
||||
description:
|
||||
GPIO connected to the active low OUT_EN pin. Controls whether
|
||||
the current outputs are enabled or in high-Z/ground state.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- avdd-supply
|
||||
- iovdd-supply
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
dac@0 {
|
||||
compatible = "adi,ad5706r";
|
||||
reg = <0>;
|
||||
avdd-supply = <&avdd>;
|
||||
iovdd-supply = <&iovdd>;
|
||||
pvdd0-supply = <&pvdd>;
|
||||
pvdd1-supply = <&pvdd>;
|
||||
pvdd2-supply = <&pvdd>;
|
||||
pvdd3-supply = <&pvdd>;
|
||||
vref-supply = <&vref>;
|
||||
spi-max-frequency = <50000000>;
|
||||
pwms = <&pwm0 0 1000000 0>;
|
||||
reset-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
|
||||
enable-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -161,8 +161,8 @@ patternProperties:
|
|||
properties:
|
||||
reg:
|
||||
description: The channel number.
|
||||
minItems: 1
|
||||
maxItems: 8
|
||||
minimum: 0
|
||||
maximum: 7
|
||||
|
||||
label:
|
||||
description: Unique name to identify which channel this is.
|
||||
|
|
@ -280,23 +280,23 @@ examples:
|
|||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
dac@0 {
|
||||
compatible = "microchip,mcp47feb02";
|
||||
reg = <0>;
|
||||
vdd-supply = <&vdac_vdd>;
|
||||
vref-supply = <&vref_reg>;
|
||||
dac@60 {
|
||||
compatible = "microchip,mcp47feb02";
|
||||
reg = <0x60>;
|
||||
vdd-supply = <&vdac_vdd>;
|
||||
vref-supply = <&vref_reg>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
channel@0 {
|
||||
reg = <0>;
|
||||
label = "Adjustable_voltage_ch0";
|
||||
};
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
channel@0 {
|
||||
reg = <0>;
|
||||
label = "Adjustable_voltage_ch0";
|
||||
};
|
||||
|
||||
channel@1 {
|
||||
reg = <0x1>;
|
||||
label = "Adjustable_voltage_ch1";
|
||||
};
|
||||
};
|
||||
channel@1 {
|
||||
reg = <0x1>;
|
||||
label = "Adjustable_voltage_ch1";
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@ properties:
|
|||
vdd-supply: true
|
||||
vddio-supply: true
|
||||
|
||||
mount-matrix:
|
||||
description: an optional 3x3 mounting rotation matrix.
|
||||
|
||||
spi-max-frequency:
|
||||
maximum: 10000000
|
||||
|
||||
|
|
@ -56,6 +59,9 @@ examples:
|
|||
reg = <0x69>;
|
||||
interrupt-parent = <&gpio6>;
|
||||
interrupts = <18 IRQ_TYPE_EDGE_RISING>;
|
||||
mount-matrix = "0", "1", "0",
|
||||
"1", "0", "0",
|
||||
"0", "0", "1";
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/light/brcm,apds9999.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
title: Broadcom APDS-9999 Digital Proximity and RGB Sensor
|
||||
|
||||
maintainers:
|
||||
- Jose A. Perez de Azpillaga <azpijr@gmail.com>
|
||||
|
||||
description: |
|
||||
Broadcom APDS-9999 is a digital proximity and RGB sensor with
|
||||
ambient light sensing (ALS) capability. The device uses individual
|
||||
R, G, B, and IR channels plus a Vertical Cavity Surface Emitting
|
||||
Laser (VCSEL) for proximity detection.
|
||||
|
||||
Datasheet: https://docs.broadcom.com/docs/APDS-9999-DS
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- brcm,apds9999
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
vcsel-supply:
|
||||
description: VCSEL power supply (VVCSEL pin)
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
light-sensor@52 {
|
||||
compatible = "brcm,apds9999";
|
||||
reg = <0x52>;
|
||||
vdd-supply = <&vdd_reg>;
|
||||
vcsel-supply = <&vcsel_reg>;
|
||||
};
|
||||
};
|
||||
|
|
@ -26,6 +26,8 @@ properties:
|
|||
- amstaos,tmd2672
|
||||
- amstaos,tsl2772
|
||||
- amstaos,tmd2772
|
||||
- avago,apds9900
|
||||
- avago,apds9901
|
||||
- avago,apds9930
|
||||
|
||||
reg:
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
$id: http://devicetree.org/schemas/iio/light/vishay,veml6030.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: VEML3235, VEML6030, VEML6035 and VEML7700 Ambient Light Sensors (ALS)
|
||||
title: VEML3235, VEML3328, VEML6030, VEML6035 and VEML7700 Ambient Light Sensors (ALS)
|
||||
|
||||
maintainers:
|
||||
- Rishi Gupta <gupt21@gmail.com>
|
||||
|
|
@ -21,6 +21,7 @@ description: |
|
|||
|
||||
Specifications about the sensors can be found at:
|
||||
https://www.vishay.com/docs/80131/veml3235.pdf
|
||||
https://www.vishay.com/docs/84968/veml3328.pdf
|
||||
https://www.vishay.com/docs/84366/veml6030.pdf
|
||||
https://www.vishay.com/docs/84889/veml6035.pdf
|
||||
https://www.vishay.com/docs/84286/veml7700.pdf
|
||||
|
|
@ -29,6 +30,7 @@ properties:
|
|||
compatible:
|
||||
enum:
|
||||
- vishay,veml3235
|
||||
- vishay,veml3328
|
||||
- vishay,veml6030
|
||||
- vishay,veml6035
|
||||
- vishay,veml7700
|
||||
|
|
@ -79,6 +81,7 @@ allOf:
|
|||
compatible:
|
||||
enum:
|
||||
- vishay,veml3235
|
||||
- vishay,veml3328
|
||||
- vishay,veml7700
|
||||
then:
|
||||
properties:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/magnetometer/memsic,mmc5983.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MEMSIC MMC5983MA 3-axis magnetic sensor
|
||||
|
||||
maintainers:
|
||||
- Vladislav Kulikov <vlad.kulikov.c@gmail.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: memsic,mmc5983
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply:
|
||||
description: Regulator that provides power to the sensor
|
||||
|
||||
vddio-supply:
|
||||
description: Regulator that provides power to the digital interface and INT pin
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
magnetometer@30 {
|
||||
compatible = "memsic,mmc5983";
|
||||
reg = <0x30>;
|
||||
vdd-supply = <&vdd_3v3_reg>;
|
||||
vddio-supply = <&vdd_3v3_reg>;
|
||||
};
|
||||
};
|
||||
- |
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
magnetometer@0 {
|
||||
compatible = "memsic,mmc5983";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <10000000>;
|
||||
vdd-supply = <&vdd_3v3_reg>;
|
||||
vddio-supply = <&vdd_3v3_reg>;
|
||||
};
|
||||
};
|
||||
|
|
@ -4,14 +4,18 @@
|
|||
$id: http://devicetree.org/schemas/iio/temperature/adi,ltc2983.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices LTC2983, LTC2986, LTM2985 Multi-sensor Temperature system
|
||||
title: Analog Devices LTC2983 and similar Multi-sensor Temperature systems
|
||||
|
||||
maintainers:
|
||||
- Nuno Sá <nuno.sa@analog.com>
|
||||
|
||||
description: |
|
||||
Analog Devices LTC2983, LTC2984, LTC2986, LTM2985 Multi-Sensor Digital
|
||||
Temperature Measurement Systems
|
||||
Analog Devices Multi-Sensor Digital Temperature Measurement Systems:
|
||||
- ADT7604
|
||||
- LTC2983
|
||||
- LTC2984
|
||||
- LTC2986
|
||||
- LTM2985
|
||||
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/2983fc.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/2984fb.pdf
|
||||
|
|
@ -43,6 +47,7 @@ properties:
|
|||
compatible:
|
||||
oneOf:
|
||||
- enum:
|
||||
- adi,adt7604
|
||||
- adi,ltc2983
|
||||
- adi,ltc2986
|
||||
- adi,ltm2985
|
||||
|
|
@ -436,6 +441,121 @@ patternProperties:
|
|||
required:
|
||||
- adi,custom-temp
|
||||
|
||||
'^copper-trace@':
|
||||
$ref: '#/$defs/sensor-node'
|
||||
unevaluatedProperties: false
|
||||
description: |
|
||||
Copper trace resistance sensor (some parts only). Two variants exist:
|
||||
sub-ohm (< 1 ohm, no custom table allowed) and standard (> 1 ohm,
|
||||
required custom table).
|
||||
|
||||
properties:
|
||||
reg:
|
||||
minimum: 2
|
||||
maximum: 20
|
||||
|
||||
adi,sensor-type:
|
||||
description: Sensor type for copper trace sensors.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
const: 32
|
||||
|
||||
adi,rsense-handle:
|
||||
description: Associated sense resistor sensor.
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
|
||||
adi,copper-trace-sub-ohm:
|
||||
description:
|
||||
Select the sub-ohm (< 1 ohm) copper trace variant. Custom table
|
||||
and excitation current are not allowed in this mode.
|
||||
type: boolean
|
||||
|
||||
adi,excitation-current-microamp:
|
||||
description:
|
||||
Excitation current applied to the copper trace. Not used in
|
||||
sub-ohm mode. The datasheet recommends 1mA for copper trace
|
||||
sensors due to their typically small resistance.
|
||||
enum: [5, 10, 25, 50, 100, 250, 500, 1000]
|
||||
default: 1000
|
||||
|
||||
adi,custom-copper-trace:
|
||||
description:
|
||||
Resistance-to-temperature table for copper trace sensors with
|
||||
resistance > 1 ohm. Required when adi,copper-trace-sub-ohm is not
|
||||
set. See Page 36 of the datasheet.
|
||||
$ref: /schemas/types.yaml#/definitions/uint64-matrix
|
||||
minItems: 3
|
||||
maxItems: 64
|
||||
items:
|
||||
items:
|
||||
- description: Resistance point in uOhms.
|
||||
- description: Temperature point in uK.
|
||||
|
||||
required:
|
||||
- adi,rsense-handle
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
required:
|
||||
- adi,copper-trace-sub-ohm
|
||||
then:
|
||||
properties:
|
||||
adi,custom-copper-trace: false
|
||||
adi,excitation-current-microamp: false
|
||||
- if:
|
||||
not:
|
||||
required:
|
||||
- adi,copper-trace-sub-ohm
|
||||
then:
|
||||
required:
|
||||
- adi,custom-copper-trace
|
||||
|
||||
'^leak-detector@':
|
||||
$ref: '#/$defs/sensor-node'
|
||||
unevaluatedProperties: false
|
||||
description: |
|
||||
Leak detector sensor (some parts only). Outputs resistance in ohms and
|
||||
a coverage percentage via IIO_COVERAGE (raw/1024 = coverage %).
|
||||
|
||||
properties:
|
||||
reg:
|
||||
minimum: 2
|
||||
maximum: 20
|
||||
|
||||
adi,sensor-type:
|
||||
description: Sensor type for leak detector sensors.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
const: 33
|
||||
|
||||
adi,rsense-handle:
|
||||
description: Associated sense resistor sensor.
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
|
||||
adi,excitation-current-nanoamp:
|
||||
description:
|
||||
Excitation current applied to the leak detector. The correct value
|
||||
depends on the electrical characteristics of the liquid being sensed.
|
||||
For example, 10000 (10µA) is recommended for PG25 (see datasheet
|
||||
Table 39).
|
||||
enum: [250, 500, 1000, 5000, 10000, 25000, 50000, 100000, 250000,
|
||||
500000, 1000000]
|
||||
|
||||
adi,custom-leak-detector:
|
||||
description: |
|
||||
Lookup table mapping resistance to coverage percentage. Entries must
|
||||
be in ascending resistance order.
|
||||
$ref: /schemas/types.yaml#/definitions/uint64-matrix
|
||||
minItems: 3
|
||||
maxItems: 64
|
||||
items:
|
||||
items:
|
||||
- description: Resistance point in uOhms.
|
||||
- description: Coverage data percentage (0 to 100).
|
||||
|
||||
required:
|
||||
- adi,rsense-handle
|
||||
- adi,excitation-current-nanoamp
|
||||
- adi,custom-leak-detector
|
||||
|
||||
'^rsense@':
|
||||
$ref: '#/$defs/sensor-node'
|
||||
unevaluatedProperties: false
|
||||
|
|
@ -477,6 +597,32 @@ allOf:
|
|||
patternProperties:
|
||||
'^temp@': false
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: adi,adt7604
|
||||
then:
|
||||
patternProperties:
|
||||
'^thermocouple@': false
|
||||
'^diode@': false
|
||||
'^adc@': false
|
||||
'^temp@': false
|
||||
'^rtd@':
|
||||
properties:
|
||||
adi,sensor-type:
|
||||
not:
|
||||
const: 18
|
||||
'^thermistor@':
|
||||
properties:
|
||||
adi,sensor-type:
|
||||
not:
|
||||
const: 27
|
||||
else:
|
||||
patternProperties:
|
||||
'^copper-trace@': false
|
||||
'^leak-detector@': false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
|
@ -556,4 +702,69 @@ examples:
|
|||
};
|
||||
};
|
||||
};
|
||||
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
temperature-sensor@0 {
|
||||
compatible = "adi,adt7604";
|
||||
reg = <0>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <25 IRQ_TYPE_EDGE_RISING>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
vdd-supply = <&supply>;
|
||||
|
||||
trace_rsense: rsense@2 {
|
||||
reg = <2>;
|
||||
adi,sensor-type = <29>;
|
||||
adi,rsense-val-milli-ohms = <100000>; // 100 ohm
|
||||
};
|
||||
|
||||
copper-trace@4 {
|
||||
reg = <4>;
|
||||
adi,sensor-type = <32>;
|
||||
adi,rsense-handle = <&trace_rsense>;
|
||||
adi,copper-trace-sub-ohm;
|
||||
};
|
||||
|
||||
r_sense: rsense@12 {
|
||||
reg = <12>;
|
||||
adi,sensor-type = <29>;
|
||||
adi,rsense-val-milli-ohms = <1000000>; // 1 kohm
|
||||
};
|
||||
|
||||
leak-detector@14 {
|
||||
reg = <14>;
|
||||
adi,sensor-type = <33>;
|
||||
adi,rsense-handle = <&r_sense>;
|
||||
adi,excitation-current-nanoamp = <10000>;
|
||||
adi,custom-leak-detector =
|
||||
/bits/ 64 < 0 100>,
|
||||
/bits/ 64 < 202020000 99>,
|
||||
/bits/ 64 < 285710000 70>,
|
||||
/bits/ 64 < 333330000 60>,
|
||||
/bits/ 64 < 400000000 50>,
|
||||
/bits/ 64 < 500000000 40>,
|
||||
/bits/ 64 < 666670000 30>,
|
||||
/bits/ 64 < 1000000000 20>,
|
||||
/bits/ 64 < 2000000000 10>,
|
||||
/bits/ 64 <1000000000000 0>;
|
||||
};
|
||||
|
||||
rtd@18 {
|
||||
reg = <18>;
|
||||
adi,sensor-type = <12>; // PT100
|
||||
adi,rsense-handle = <&r_sense>;
|
||||
adi,number-of-wires = <2>;
|
||||
adi,rsense-share;
|
||||
adi,excitation-current-microamp = <500>;
|
||||
adi,rtd-curve = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
|
|||
|
|
@ -37,9 +37,10 @@ directory contains attributes of the following form:
|
|||
* :file:`index`, the scan_index of the channel.
|
||||
* :file:`type`, description of the scan element data storage within the buffer
|
||||
and hence the form in which it is read from user space.
|
||||
Format is [be|le]:[s|u]bits/storagebits[Xrepeat][>>shift] .
|
||||
Format is [be|le]:[f|s|u]bits/storagebits[Xrepeat][>>shift] .
|
||||
|
||||
* *be* or *le*, specifies big or little endian.
|
||||
* *f*, specifies if floating-point.
|
||||
* *s* or *u*, specifies if signed (2's complement) or unsigned.
|
||||
* *bits*, is the number of valid data bits.
|
||||
* *storagebits*, is the number of bits (after padding) that it occupies in the
|
||||
|
|
@ -78,7 +79,7 @@ fields in iio_chan_spec definition::
|
|||
/* other members */
|
||||
int scan_index
|
||||
struct {
|
||||
char sign;
|
||||
char format;
|
||||
u8 realbits;
|
||||
u8 storagebits;
|
||||
u8 shift;
|
||||
|
|
@ -98,7 +99,7 @@ following channel definition::
|
|||
/* other stuff here */
|
||||
.scan_index = 0,
|
||||
.scan_type = {
|
||||
.sign = 's',
|
||||
.format = IIO_SCAN_FORMAT_SIGNED_INT,
|
||||
.realbits = 12,
|
||||
.storagebits = 16,
|
||||
.shift = 4,
|
||||
|
|
|
|||
|
|
@ -29,21 +29,21 @@ A typical triggered buffer setup looks like this::
|
|||
|
||||
irqreturn_t sensor_trigger_handler(int irq, void *p)
|
||||
{
|
||||
u16 buf[8];
|
||||
IIO_DECLARE_BUFFER_WITH_TS(u16, buf, 3) = { };
|
||||
int i = 0;
|
||||
|
||||
/* read data for each active channel */
|
||||
for_each_set_bit(bit, active_scan_mask, masklength)
|
||||
buf[i++] = sensor_get_data(bit)
|
||||
iio_for_each_active_channel(indio_dev, bit)
|
||||
buf[i++] = sensor_get_data(bit);
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, buf, timestamp);
|
||||
iio_push_to_buffers_with_ts(indio_dev, buf, sizeof(buf), timestamp);
|
||||
|
||||
iio_trigger_notify_done(trigger);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/* setup triggered buffer, usually in probe function */
|
||||
iio_triggered_buffer_setup(indio_dev, sensor_iio_polfunc,
|
||||
iio_triggered_buffer_setup(indio_dev, sensor_iio_pollfunc,
|
||||
sensor_trigger_handler,
|
||||
sensor_buffer_setup_ops);
|
||||
|
||||
|
|
|
|||
227
Documentation/iio/ad4691.rst
Normal file
227
Documentation/iio/ad4691.rst
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
=============
|
||||
AD4691 driver
|
||||
=============
|
||||
|
||||
ADC driver for Analog Devices Inc. AD4691 family of multichannel SAR ADCs.
|
||||
The module name is ``ad4691``.
|
||||
|
||||
|
||||
Supported devices
|
||||
=================
|
||||
|
||||
The following chips are supported by this driver:
|
||||
|
||||
* `AD4691 <https://www.analog.com/en/products/ad4691.html>`_ — 16-channel, 500 kSPS
|
||||
* `AD4692 <https://www.analog.com/en/products/ad4692.html>`_ — 16-channel, 1 MSPS
|
||||
* `AD4693 <https://www.analog.com/en/products/ad4693.html>`_ — 8-channel, 500 kSPS
|
||||
* `AD4694 <https://www.analog.com/en/products/ad4694.html>`_ — 8-channel, 1 MSPS
|
||||
|
||||
|
||||
IIO channels
|
||||
============
|
||||
|
||||
Each physical ADC input maps to one IIO voltage channel. The AD4691 and AD4692
|
||||
expose 16 channels (``voltage0`` through ``voltage15``); the AD4693 and AD4694
|
||||
expose 8 channels (``voltage0`` through ``voltage7``).
|
||||
|
||||
All channels share a common scale (``in_voltage_scale``), derived from the
|
||||
reference voltage. Each channel exposes:
|
||||
|
||||
* ``in_voltageN_raw`` — single-shot ADC result
|
||||
|
||||
The following attributes are shared across all channels:
|
||||
|
||||
* ``in_voltage_sampling_frequency`` — effective output rate, defined as the
|
||||
internal oscillator frequency divided by the oversampling ratio. Writing this
|
||||
attribute selects the nearest achievable rate for the current OSR; the value
|
||||
read back reflects the actual rate after snapping to the closest valid
|
||||
oscillator entry.
|
||||
* ``in_voltage_sampling_frequency_available`` — list of achievable effective
|
||||
rates for the current oversampling ratio. The list updates dynamically when
|
||||
the oversampling ratio changes.
|
||||
|
||||
The following attributes are shared across all channels and only available in
|
||||
CNV Burst Mode:
|
||||
|
||||
* ``in_voltage_oversampling_ratio`` — hardware oversampling depth applied to
|
||||
all channels; see `Oversampling`_ below.
|
||||
* ``in_voltage_oversampling_ratio_available`` — valid ratios: 1, 2, 4, 8, 16,
|
||||
32.
|
||||
|
||||
|
||||
Operating modes
|
||||
===============
|
||||
|
||||
The driver supports two operating modes, selected automatically from the
|
||||
device tree at probe time.
|
||||
|
||||
Manual Mode
|
||||
-----------
|
||||
|
||||
Selected when no ``pwms`` property is present in the device tree. The CNV pin
|
||||
is tied to the SPI chip-select: every CS assertion triggers a conversion and
|
||||
returns the previous result. A user-defined IIO trigger (e.g. hrtimer trigger)
|
||||
drives the buffer.
|
||||
|
||||
Oversampling is not supported in Manual Mode.
|
||||
|
||||
CNV Burst Mode
|
||||
--------------
|
||||
|
||||
Selected when a ``pwms`` property is present in the device tree. A PWM drives
|
||||
the CNV pin at the configured conversion rate. A GP pin wired to the SoC and
|
||||
declared in the device tree signals DATA_READY at the end of each burst,
|
||||
triggering a readout of all active channel results into the IIO buffer.
|
||||
|
||||
The buffer output rate is controlled by the ``sampling_frequency`` attribute
|
||||
on the IIO buffer. In practice the PWM rate should be set low enough to allow
|
||||
the SPI readout to complete before the next conversion burst begins.
|
||||
|
||||
Autonomous Mode (idle / single-shot)
|
||||
-------------------------------------
|
||||
|
||||
When the IIO buffer is disabled, ``in_voltageN_raw`` reads perform a single
|
||||
conversion on the requested channel using the internal oscillator. The
|
||||
oscillator is started and stopped around each read to save power.
|
||||
|
||||
|
||||
Oversampling
|
||||
============
|
||||
|
||||
In CNV Burst Mode a shared hardware accumulator averages a configurable number
|
||||
of successive conversions across all active channels. The result is always a
|
||||
16-bit mean, so the buffer data type (shown in ``buffer0/in_voltageN_type``)
|
||||
is unaffected by the oversampling ratio. Valid ratios are 1, 2, 4, 8, 16 and
|
||||
32; the default is 1 (no averaging). Oversampling is not supported in Manual
|
||||
Mode.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# Set oversampling ratio to 16 (shared across all channels)
|
||||
echo 16 > /sys/bus/iio/devices/iio:device0/in_voltage_oversampling_ratio
|
||||
|
||||
# Read the resulting effective sampling frequency
|
||||
cat /sys/bus/iio/devices/iio:device0/in_voltage_sampling_frequency
|
||||
|
||||
Writing ``in_voltage_oversampling_ratio`` stores the new shared depth and snaps
|
||||
the internal oscillator to the largest valid table entry that is both less than
|
||||
or equal to ``old_effective_rate × new_osr`` and evenly divisible by
|
||||
``new_osr``. This preserves an integer read-back of
|
||||
``in_voltage_sampling_frequency`` after the change and keeps the oscillator as
|
||||
close as possible to the previous effective rate.
|
||||
|
||||
|
||||
Reference voltage
|
||||
=================
|
||||
|
||||
The driver supports two reference configurations, mutually exclusive:
|
||||
|
||||
* **External reference** (``ref-supply``): a voltage between 2.4 V and 5.25 V
|
||||
supplied externally.
|
||||
* **Buffered internal reference** (``refin-supply``): an internal reference
|
||||
buffer is enabled by the driver.
|
||||
|
||||
Exactly one of ``ref-supply`` or ``refin-supply`` must be present in the
|
||||
device tree. The reference voltage determines the full-scale range reported
|
||||
via ``in_voltage_scale``.
|
||||
|
||||
|
||||
LDO supply
|
||||
==========
|
||||
|
||||
The chip contains an internal LDO that powers part of the analog front-end.
|
||||
The supply configuration is mutually exclusive:
|
||||
|
||||
* **External VDD** (``vdd-supply``): an external 1.8 V supply is used directly;
|
||||
the internal LDO is disabled.
|
||||
* **Internal LDO** (``ldo-in-supply``): the internal LDO is enabled and fed
|
||||
from the ``ldo-in`` regulator. Use this when no external 1.8 V VDD is present.
|
||||
|
||||
Exactly one of ``vdd-supply`` or ``ldo-in-supply`` must be provided.
|
||||
|
||||
|
||||
Reset
|
||||
=====
|
||||
|
||||
The driver supports two reset mechanisms:
|
||||
|
||||
* **Hardware reset** (``reset-gpios`` in device tree): the GPIO line is
|
||||
asserted then deasserted at probe; the driver waits 300 µs for the chip
|
||||
to complete its internal reset sequence before accepting SPI commands.
|
||||
* **Software reset** (fallback when ``reset-gpios`` is absent): written
|
||||
automatically at probe.
|
||||
|
||||
|
||||
GP pins and interrupts
|
||||
======================
|
||||
|
||||
The chip exposes up to four general-purpose (GP) pins. In CNV Burst Mode
|
||||
(non-offload), one GP pin must be wired to an interrupt-capable SoC input and
|
||||
declared in the device tree using the ``interrupts`` and ``interrupt-names``
|
||||
properties. The ``interrupt-names`` value identifies which GP pin is used
|
||||
(``"gp0"`` through ``"gp3"``).
|
||||
|
||||
Example device tree fragment::
|
||||
|
||||
adc@0 {
|
||||
compatible = "adi,ad4692";
|
||||
...
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "gp0";
|
||||
};
|
||||
|
||||
|
||||
SPI offload support
|
||||
===================
|
||||
|
||||
When a SPI offload engine (e.g. the AXI SPI Engine) is present, the driver
|
||||
uses DMA-backed transfers for CPU-independent, high-throughput data capture.
|
||||
SPI offload is detected automatically at probe; if no offload hardware is
|
||||
available the driver falls back to the software triggered-buffer path.
|
||||
|
||||
Two SPI offload sub-modes exist:
|
||||
|
||||
CNV Burst offload
|
||||
-----------------
|
||||
|
||||
Used when a ``pwms`` property is present and SPI offload is available. The PWM
|
||||
drives CNV at the configured rate; on DATA_READY the offload engine reads all
|
||||
active channel results and streams them directly to the IIO DMA buffer with no
|
||||
CPU involvement. The GP pin used as DATA_READY trigger is supplied by the
|
||||
trigger-source consumer at buffer enable time; no ``interrupt-names`` entry is
|
||||
required.
|
||||
|
||||
Manual offload
|
||||
--------------
|
||||
|
||||
Used when no ``pwms`` property is present and SPI offload is available. A
|
||||
periodic SPI offload trigger controls the conversion rate and the offload engine
|
||||
streams results directly to the IIO DMA buffer.
|
||||
|
||||
The ``sampling_frequency`` attribute on the IIO buffer controls the trigger
|
||||
rate (in Hz). The initial rate is 100 kHz.
|
||||
|
||||
Oversampling is not supported in Manual Mode.
|
||||
|
||||
|
||||
Buffer data format
|
||||
==================
|
||||
|
||||
The sample format in the IIO buffer depends on whether SPI offload is in use.
|
||||
|
||||
Software triggered-buffer path (no SPI offload)
|
||||
------------------------------------------------
|
||||
|
||||
Each active channel occupies one 16-bit big-endian slot (``storagebits=16``,
|
||||
``endianness=be``). Active channels are packed densely in scan-index order,
|
||||
followed by a 64-bit software timestamp appended by the IIO core.
|
||||
|
||||
SPI offload path
|
||||
----------------
|
||||
|
||||
Each active channel occupies one 16-bit CPU-native slot (``storagebits=16``,
|
||||
``endianness=cpu``). The SPI offload engine streams 16-bit words directly from
|
||||
the SPI Engine into the DMA buffer; no software timestamp is appended.
|
||||
|
|
@ -11,7 +11,7 @@ This driver supports Analog Device's ADXL313 on SPI/I2C bus.
|
|||
|
||||
* `ADXL313 <https://www.analog.com/ADXL313>`_
|
||||
|
||||
The ADXL313is a low noise density, low power, 3-axis accelerometer with
|
||||
The ADXL313 is a low noise density, low power, 3-axis accelerometer with
|
||||
selectable measurement ranges. The ADXL313 supports the ±0.5 g, ±1 g, ±2 g and
|
||||
±4 g ranges.
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ specific device folder path ``/sys/bus/iio/devices/iio:deviceX``.
|
|||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
| in_accel_x_raw | Raw X-axis accelerometer channel value. |
|
||||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
| in_accel_y_calibbias | y-axis acceleration offset correction |
|
||||
| in_accel_y_calibbias | Calibration offset for the Y-axis accelerometer channel. |
|
||||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
| in_accel_y_raw | Raw Y-axis accelerometer channel value. |
|
||||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
|
|
@ -112,9 +112,9 @@ apply the following formula:
|
|||
Where _offset and _scale are device attributes. If no _offset attribute is
|
||||
present, simply assume its value is 0.
|
||||
|
||||
The ADXL313 driver offers data for a single types of channels, the table below
|
||||
shows the measurement units for the processed value, which are defined by the
|
||||
IIO framework:
|
||||
The ADXL313 driver offers data for multiple channels of a single type.
|
||||
The table below shows the measurement units for the processed value,
|
||||
which are defined by the IIO framework:
|
||||
|
||||
+-------------------------------------+---------------------------+
|
||||
| Channel type | Measurement unit |
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ specific device folder path ``/sys/bus/iio/devices/iio:deviceX``.
|
|||
+-------------------------------------------+----------------------------------------------------------+
|
||||
| in_accel_x_raw | Raw X-axis accelerometer channel value. |
|
||||
+-------------------------------------------+----------------------------------------------------------+
|
||||
| in_accel_y_calibbias | Y-axis acceleration offset correction |
|
||||
| in_accel_y_calibbias | Calibration offset for the Y-axis accelerometer channel. |
|
||||
+-------------------------------------------+----------------------------------------------------------+
|
||||
| in_accel_y_raw | Raw Y-axis accelerometer channel value. |
|
||||
+-------------------------------------------+----------------------------------------------------------+
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ specific device folder path ``/sys/bus/iio/devices/iio:deviceX``.
|
|||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
| in_accel_x_raw | Raw X-axis accelerometer channel value. |
|
||||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
| in_accel_y_calibbias | y-axis acceleration offset correction |
|
||||
| in_accel_y_calibbias | Calibration offset for the Y-axis accelerometer channel. |
|
||||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
| in_accel_y_raw | Raw Y-axis accelerometer channel value. |
|
||||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
|
|
|
|||
|
|
@ -83,9 +83,10 @@ and the relevant _type attributes to establish the data storage format.
|
|||
|
||||
Read-only attribute containing the description of the scan element data storage
|
||||
within the buffer and hence the form in which it is read from userspace. Format
|
||||
is [be|le]:[s|u]bits/storagebits[Xrepeat][>>shift], where:
|
||||
is [be|le]:[f|s|u]bits/storagebits[Xrepeat][>>shift], where:
|
||||
|
||||
- **be** or **le** specifies big or little-endian.
|
||||
- **f** specifies if floating-point.
|
||||
- **s** or **u** specifies if signed (2's complement) or unsigned.
|
||||
- **bits** is the number of valid data bits.
|
||||
- **storagebits** is the number of bits (after padding) that it occupies in the
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ Industrial I/O Kernel Drivers
|
|||
ad4000
|
||||
ad4030
|
||||
ad4062
|
||||
ad4691
|
||||
ad4695
|
||||
ad7191
|
||||
ad7380
|
||||
|
|
|
|||
|
|
@ -1,128 +0,0 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
======================
|
||||
Kernel driver apds990x
|
||||
======================
|
||||
|
||||
Supported chips:
|
||||
Avago APDS990X
|
||||
|
||||
Data sheet:
|
||||
Not freely available
|
||||
|
||||
Author:
|
||||
Samu Onkalo <samu.p.onkalo@nokia.com>
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
APDS990x is a combined ambient light and proximity sensor. ALS and proximity
|
||||
functionality are highly connected. ALS measurement path must be running
|
||||
while the proximity functionality is enabled.
|
||||
|
||||
ALS produces raw measurement values for two channels: Clear channel
|
||||
(infrared + visible light) and IR only. However, threshold comparisons happen
|
||||
using clear channel only. Lux value and the threshold level on the HW
|
||||
might vary quite much depending the spectrum of the light source.
|
||||
|
||||
Driver makes necessary conversions to both directions so that user handles
|
||||
only lux values. Lux value is calculated using information from the both
|
||||
channels. HW threshold level is calculated from the given lux value to match
|
||||
with current type of the lightning. Sometimes inaccuracy of the estimations
|
||||
lead to false interrupt, but that doesn't harm.
|
||||
|
||||
ALS contains 4 different gain steps. Driver automatically
|
||||
selects suitable gain step. After each measurement, reliability of the results
|
||||
is estimated and new measurement is triggered if necessary.
|
||||
|
||||
Platform data can provide tuned values to the conversion formulas if
|
||||
values are known. Otherwise plain sensor default values are used.
|
||||
|
||||
Proximity side is little bit simpler. There is no need for complex conversions.
|
||||
It produces directly usable values.
|
||||
|
||||
Driver controls chip operational state using pm_runtime framework.
|
||||
Voltage regulators are controlled based on chip operational state.
|
||||
|
||||
SYSFS
|
||||
-----
|
||||
|
||||
|
||||
chip_id
|
||||
RO - shows detected chip type and version
|
||||
|
||||
power_state
|
||||
RW - enable / disable chip. Uses counting logic
|
||||
|
||||
1 enables the chip
|
||||
0 disables the chip
|
||||
lux0_input
|
||||
RO - measured lux value
|
||||
|
||||
sysfs_notify called when threshold interrupt occurs
|
||||
|
||||
lux0_sensor_range
|
||||
RO - lux0_input max value.
|
||||
|
||||
Actually never reaches since sensor tends
|
||||
to saturate much before that. Real max value varies depending
|
||||
on the light spectrum etc.
|
||||
|
||||
lux0_rate
|
||||
RW - measurement rate in Hz
|
||||
|
||||
lux0_rate_avail
|
||||
RO - supported measurement rates
|
||||
|
||||
lux0_calibscale
|
||||
RW - calibration value.
|
||||
|
||||
Set to neutral value by default.
|
||||
Output results are multiplied with calibscale / calibscale_default
|
||||
value.
|
||||
|
||||
lux0_calibscale_default
|
||||
RO - neutral calibration value
|
||||
|
||||
lux0_thresh_above_value
|
||||
RW - HI level threshold value.
|
||||
|
||||
All results above the value
|
||||
trigs an interrupt. 65535 (i.e. sensor_range) disables the above
|
||||
interrupt.
|
||||
|
||||
lux0_thresh_below_value
|
||||
RW - LO level threshold value.
|
||||
|
||||
All results below the value
|
||||
trigs an interrupt. 0 disables the below interrupt.
|
||||
|
||||
prox0_raw
|
||||
RO - measured proximity value
|
||||
|
||||
sysfs_notify called when threshold interrupt occurs
|
||||
|
||||
prox0_sensor_range
|
||||
RO - prox0_raw max value (1023)
|
||||
|
||||
prox0_raw_en
|
||||
RW - enable / disable proximity - uses counting logic
|
||||
|
||||
- 1 enables the proximity
|
||||
- 0 disables the proximity
|
||||
|
||||
prox0_reporting_mode
|
||||
RW - trigger / periodic.
|
||||
|
||||
In "trigger" mode the driver tells two possible
|
||||
values: 0 or prox0_sensor_range value. 0 means no proximity,
|
||||
1023 means proximity. This causes minimal number of interrupts.
|
||||
In "periodic" mode the driver reports all values above
|
||||
prox0_thresh_above. This causes more interrupts, but it can give
|
||||
_rough_ estimate about the distance.
|
||||
|
||||
prox0_reporting_mode_avail
|
||||
RO - accepted values to prox0_reporting_mode (trigger, periodic)
|
||||
|
||||
prox0_thresh_above_value
|
||||
RW - threshold level which trigs proximity events.
|
||||
|
|
@ -13,7 +13,6 @@ fit into other categories.
|
|||
|
||||
ad525x_dpot
|
||||
amd-sbi
|
||||
apds990x
|
||||
bh1770glc
|
||||
c2port
|
||||
dw-xdata-pcie
|
||||
|
|
|
|||
52
MAINTAINERS
52
MAINTAINERS
|
|
@ -639,7 +639,7 @@ F: drivers/iio/accel/adxl355_i2c.c
|
|||
F: drivers/iio/accel/adxl355_spi.c
|
||||
|
||||
ADXL367 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
|
||||
M: Cosmin Tanislav <cosmin.tanislav@analog.com>
|
||||
M: Marcelo Schmitt <marcelo.schmitt@analog.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
|
|
@ -1459,7 +1459,7 @@ F: Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml
|
|||
F: drivers/iio/adc/ad4080.c
|
||||
|
||||
ANALOG DEVICES INC AD4130 DRIVER
|
||||
M: Cosmin Tanislav <cosmin.tanislav@analog.com>
|
||||
M: Marcelo Schmitt <marcelo.schmitt@analog.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
|
|
@ -1483,6 +1483,15 @@ W: https://ez.analog.com/linux-software-drivers
|
|||
F: Documentation/devicetree/bindings/iio/adc/adi,ad4170-4.yaml
|
||||
F: drivers/iio/adc/ad4170-4.c
|
||||
|
||||
ANALOG DEVICES INC AD4691 DRIVER
|
||||
M: Radu Sabau <radu.sabau@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,ad4691.yaml
|
||||
F: Documentation/iio/ad4691.rst
|
||||
F: drivers/iio/adc/ad4691.c
|
||||
|
||||
ANALOG DEVICES INC AD4695 DRIVER
|
||||
M: Michael Hennerich <michael.hennerich@analog.com>
|
||||
M: Nuno Sá <nuno.sa@analog.com>
|
||||
|
|
@ -1505,6 +1514,14 @@ 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 AD5706R DRIVER
|
||||
M: Alexis Czezar Torreno <alexisczezar.torreno@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,ad5706r.yaml
|
||||
F: drivers/iio/dac/ad5706r.c
|
||||
|
||||
ANALOG DEVICES INC AD7091R DRIVER
|
||||
M: Marcelo Schmitt <marcelo.schmitt@analog.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
|
|
@ -1547,7 +1564,7 @@ F: Documentation/devicetree/bindings/iio/dac/adi,ad7293.yaml
|
|||
F: drivers/iio/dac/ad7293.c
|
||||
|
||||
ANALOG DEVICES INC AD74115 DRIVER
|
||||
M: Cosmin Tanislav <cosmin.tanislav@analog.com>
|
||||
M: Marcelo Schmitt <marcelo.schmitt@analog.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
|
|
@ -1555,7 +1572,7 @@ F: Documentation/devicetree/bindings/iio/addac/adi,ad74115.yaml
|
|||
F: drivers/iio/addac/ad74115.c
|
||||
|
||||
ANALOG DEVICES INC AD74413R DRIVER
|
||||
M: Cosmin Tanislav <cosmin.tanislav@analog.com>
|
||||
M: Marcelo Schmitt <marcelo.schmitt@analog.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
|
|
@ -1851,8 +1868,9 @@ W: https://ez.analog.com/linux-software-drivers
|
|||
F: drivers/dma/dma-axi-dmac.c
|
||||
|
||||
ANALOG DEVICES INC IIO DRIVERS
|
||||
M: Lars-Peter Clausen <lars@metafoo.de>
|
||||
M: Nuno Sá <nuno.sa@analog.com>
|
||||
M: Michael Hennerich <Michael.Hennerich@analog.com>
|
||||
L: linux@analog.com
|
||||
S: Supported
|
||||
W: http://wiki.analog.com/
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
|
|
@ -4991,6 +5009,13 @@ S: Maintained
|
|||
F: Documentation/devicetree/bindings/iio/light/brcm,apds9160.yaml
|
||||
F: drivers/iio/light/apds9160.c
|
||||
|
||||
BROADCOM APDS9999 AMBIENT LIGHT SENSOR DRIVER
|
||||
M: Jose A. Perez de Azpillaga <azpijr@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/light/brcm,apds9999.yaml
|
||||
F: drivers/iio/light/apds9999.c
|
||||
|
||||
BROADCOM ASP 2.0 ETHERNET DRIVER
|
||||
M: Justin Chen <justin.chen@broadcom.com>
|
||||
M: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
|
|
@ -12500,6 +12525,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git
|
|||
F: Documentation/ABI/testing/configfs-iio*
|
||||
F: Documentation/ABI/testing/sysfs-bus-iio*
|
||||
F: Documentation/devicetree/bindings/iio/
|
||||
F: Documentation/driver-api/iio/
|
||||
F: Documentation/iio/
|
||||
F: drivers/iio/
|
||||
F: drivers/staging/iio/
|
||||
|
|
@ -17179,6 +17205,13 @@ F: drivers/mtd/
|
|||
F: include/linux/mtd/
|
||||
F: include/uapi/mtd/
|
||||
|
||||
MEMSIC MMC5983 MAGNETOMETER DRIVER
|
||||
M: Vladislav Kulikov <vlad.kulikov.c@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/magnetometer/memsic,mmc5983.yaml
|
||||
F: drivers/iio/magnetometer/mmc5983.c
|
||||
|
||||
MEN A21 WATCHDOG DRIVER
|
||||
M: Johannes Thumshirn <morbidrsa@gmail.com>
|
||||
L: linux-watchdog@vger.kernel.org
|
||||
|
|
@ -22637,7 +22670,7 @@ F: Documentation/devicetree/bindings/mtd/renesas-nandc.yaml
|
|||
F: drivers/mtd/nand/raw/renesas-nand-controller.c
|
||||
|
||||
RENESAS R-CAR GYROADC DRIVER
|
||||
M: Marek Vasut <marek.vasut@gmail.com>
|
||||
M: Marek Vasut <marek.vasut+renesas@mailbox.org>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/iio/adc/renesas,rcar-gyroadc.yaml
|
||||
|
|
@ -24228,7 +24261,7 @@ F: Documentation/devicetree/bindings/iio/chemical/senseair,sunrise.yaml
|
|||
F: drivers/iio/chemical/sunrise_co2.c
|
||||
|
||||
SENSIRION SCD30 CARBON DIOXIDE SENSOR DRIVER
|
||||
M: Tomasz Duszynski <tomasz.duszynski@octakon.com>
|
||||
M: Maxwell Doose <m32285159@gmail.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/chemical/sensirion,scd30.yaml
|
||||
F: drivers/iio/chemical/scd30.h
|
||||
|
|
@ -28407,6 +28440,11 @@ S: Maintained
|
|||
F: Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml
|
||||
F: drivers/iio/light/veml3235.c
|
||||
|
||||
VISHAY VEML3328 RGB IR LIGHT SENSOR DRIVER
|
||||
M: Joshua Crofts <joshua.crofts1@gmail.com>
|
||||
S: Maintained
|
||||
F: drivers/iio/light/veml3328.c
|
||||
|
||||
VISHAY VEML6030 AMBIENT LIGHT SENSOR DRIVER
|
||||
M: Javier Carrasco <javier.carrasco.cruz@gmail.com>
|
||||
S: Maintained
|
||||
|
|
|
|||
|
|
@ -1240,7 +1240,9 @@ int adxl313_core_probe(struct device *dev,
|
|||
data->regmap = regmap;
|
||||
data->chip_info = chip_info;
|
||||
|
||||
mutex_init(&data->lock);
|
||||
ret = devm_mutex_init(dev, &data->lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
indio_dev->name = chip_info->name;
|
||||
indio_dev->info = &adxl313_info;
|
||||
|
|
@ -1250,10 +1252,8 @@ int adxl313_core_probe(struct device *dev,
|
|||
indio_dev->available_scan_masks = adxl313_scan_masks;
|
||||
|
||||
ret = adxl313_setup(dev, data, setup);
|
||||
if (ret) {
|
||||
dev_err(dev, "ADXL313 setup failed\n");
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "ADXL313 setup failed\n");
|
||||
|
||||
int_line = adxl313_get_int_type(dev, &irq);
|
||||
if (int_line == ADXL313_INT_NONE) {
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ MODULE_DEVICE_TABLE(of, adxl313_of_match);
|
|||
static int adxl313_i2c_probe(struct i2c_client *client)
|
||||
{
|
||||
const struct adxl313_chip_info *chip_data;
|
||||
struct device *dev = &client->dev;
|
||||
struct regmap *regmap;
|
||||
|
||||
/*
|
||||
|
|
@ -75,13 +76,10 @@ static int adxl313_i2c_probe(struct i2c_client *client)
|
|||
|
||||
regmap = devm_regmap_init_i2c(client,
|
||||
&adxl31x_i2c_regmap_config[chip_data->type]);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&client->dev, "Error initializing i2c regmap: %ld\n",
|
||||
PTR_ERR(regmap));
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
if (IS_ERR(regmap))
|
||||
return dev_err_probe(dev, PTR_ERR(regmap), "Error initializing i2c regmap\n");
|
||||
|
||||
return adxl313_core_probe(&client->dev, regmap, chip_data, NULL);
|
||||
return adxl313_core_probe(dev, regmap, chip_data, NULL);
|
||||
}
|
||||
|
||||
static struct i2c_driver adxl313_i2c_driver = {
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ static int adxl313_spi_setup(struct device *dev, struct regmap *regmap)
|
|||
static int adxl313_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
const struct adxl313_chip_info *chip_data;
|
||||
struct device *dev = &spi->dev;
|
||||
struct regmap *regmap;
|
||||
int ret;
|
||||
|
||||
|
|
@ -83,14 +84,10 @@ static int adxl313_spi_probe(struct spi_device *spi)
|
|||
regmap = devm_regmap_init_spi(spi,
|
||||
&adxl31x_spi_regmap_config[chip_data->type]);
|
||||
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&spi->dev, "Error initializing spi regmap: %ld\n",
|
||||
PTR_ERR(regmap));
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
if (IS_ERR(regmap))
|
||||
return dev_err_probe(dev, PTR_ERR(regmap), "Error initializing spi regmap\n");
|
||||
|
||||
return adxl313_core_probe(&spi->dev, regmap,
|
||||
chip_data, &adxl313_spi_setup);
|
||||
return adxl313_core_probe(dev, regmap, chip_data, &adxl313_spi_setup);
|
||||
}
|
||||
|
||||
static const struct spi_device_id adxl313_spi_id[] = {
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ static const struct adxl345_chip_info adxl375_i2c_info = {
|
|||
};
|
||||
|
||||
static const struct i2c_device_id adxl345_i2c_id[] = {
|
||||
{ "adxl345", (kernel_ulong_t)&adxl345_i2c_info },
|
||||
{ "adxl375", (kernel_ulong_t)&adxl375_i2c_info },
|
||||
{ .name = "adxl345", .driver_data = (kernel_ulong_t)&adxl345_i2c_info },
|
||||
{ .name = "adxl375", .driver_data = (kernel_ulong_t)&adxl375_i2c_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, adxl345_i2c_id);
|
||||
|
|
|
|||
|
|
@ -336,10 +336,8 @@ static int adxl355_setup(struct adxl355_data *data)
|
|||
return ret;
|
||||
|
||||
do {
|
||||
if (--retries == 0) {
|
||||
dev_err(data->dev, "Shadow registers mismatch\n");
|
||||
return -EIO;
|
||||
}
|
||||
if (--retries == 0)
|
||||
return dev_err_probe(data->dev, -EIO, "Shadow registers mismatch\n");
|
||||
|
||||
/*
|
||||
* Perform a software reset to make sure the device is in a consistent
|
||||
|
|
@ -351,7 +349,7 @@ static int adxl355_setup(struct adxl355_data *data)
|
|||
return ret;
|
||||
|
||||
/* Wait at least 5ms after software reset */
|
||||
usleep_range(5000, 10000);
|
||||
fsleep(5 * USEC_PER_MSEC);
|
||||
|
||||
/* Read shadow registers for comparison */
|
||||
ret = regmap_bulk_read(data->regmap,
|
||||
|
|
@ -775,10 +773,8 @@ static int adxl355_probe_trigger(struct iio_dev *indio_dev, int irq)
|
|||
irq);
|
||||
|
||||
ret = devm_iio_trigger_register(data->dev, data->dready_trig);
|
||||
if (ret) {
|
||||
dev_err(data->dev, "iio trigger register failed\n");
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(data->dev, ret, "iio trigger register failed\n");
|
||||
|
||||
indio_dev->trig = iio_trigger_get(data->dready_trig);
|
||||
|
||||
|
|
@ -802,7 +798,9 @@ int adxl355_core_probe(struct device *dev, struct regmap *regmap,
|
|||
data->dev = dev;
|
||||
data->op_mode = ADXL355_STANDBY;
|
||||
data->chip_info = chip_info;
|
||||
mutex_init(&data->lock);
|
||||
ret = devm_mutex_init(dev, &data->lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
indio_dev->name = chip_info->name;
|
||||
indio_dev->info = &adxl355_info;
|
||||
|
|
@ -812,18 +810,14 @@ int adxl355_core_probe(struct device *dev, struct regmap *regmap,
|
|||
indio_dev->available_scan_masks = adxl355_avail_scan_masks;
|
||||
|
||||
ret = adxl355_setup(data);
|
||||
if (ret) {
|
||||
dev_err(dev, "ADXL355 setup failed\n");
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "ADXL355 setup failed\n");
|
||||
|
||||
ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
|
||||
&iio_pollfunc_store_time,
|
||||
&adxl355_trigger_handler, NULL);
|
||||
if (ret) {
|
||||
dev_err(dev, "iio triggered buffer setup failed\n");
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "iio triggered buffer setup failed\n");
|
||||
|
||||
irq = fwnode_irq_get_byname(dev_fwnode(dev), "DRDY");
|
||||
if (irq > 0) {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ static const struct regmap_config adxl355_i2c_regmap_config = {
|
|||
static int adxl355_i2c_probe(struct i2c_client *client)
|
||||
{
|
||||
struct regmap *regmap;
|
||||
struct device *dev = &client->dev;
|
||||
const struct adxl355_chip_info *chip_data;
|
||||
|
||||
chip_data = i2c_get_match_data(client);
|
||||
|
|
@ -30,19 +31,15 @@ static int adxl355_i2c_probe(struct i2c_client *client)
|
|||
return -ENODEV;
|
||||
|
||||
regmap = devm_regmap_init_i2c(client, &adxl355_i2c_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&client->dev, "Error initializing i2c regmap: %ld\n",
|
||||
PTR_ERR(regmap));
|
||||
if (IS_ERR(regmap))
|
||||
return dev_err_probe(dev, PTR_ERR(regmap), "Error initializing i2c regmap\n");
|
||||
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
return adxl355_core_probe(&client->dev, regmap, chip_data);
|
||||
return adxl355_core_probe(dev, regmap, chip_data);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id adxl355_i2c_id[] = {
|
||||
{ "adxl355", (kernel_ulong_t)&adxl35x_chip_info[ADXL355] },
|
||||
{ "adxl359", (kernel_ulong_t)&adxl35x_chip_info[ADXL359] },
|
||||
{ .name = "adxl355", .driver_data = (kernel_ulong_t)&adxl35x_chip_info[ADXL355] },
|
||||
{ .name = "adxl359", .driver_data = (kernel_ulong_t)&adxl35x_chip_info[ADXL359] },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, adxl355_i2c_id);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ static const struct regmap_config adxl355_spi_regmap_config = {
|
|||
static int adxl355_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
const struct adxl355_chip_info *chip_data;
|
||||
struct device *dev = &spi->dev;
|
||||
struct regmap *regmap;
|
||||
|
||||
chip_data = spi_get_device_match_data(spi);
|
||||
|
|
@ -33,14 +34,10 @@ static int adxl355_spi_probe(struct spi_device *spi)
|
|||
return -EINVAL;
|
||||
|
||||
regmap = devm_regmap_init_spi(spi, &adxl355_spi_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
dev_err(&spi->dev, "Error initializing spi regmap: %ld\n",
|
||||
PTR_ERR(regmap));
|
||||
if (IS_ERR(regmap))
|
||||
return dev_err_probe(dev, PTR_ERR(regmap), "Error initializing spi regmap\n");
|
||||
|
||||
return PTR_ERR(regmap);
|
||||
}
|
||||
|
||||
return adxl355_core_probe(&spi->dev, regmap, chip_data);
|
||||
return adxl355_core_probe(dev, regmap, chip_data);
|
||||
}
|
||||
|
||||
static const struct spi_device_id adxl355_spi_id[] = {
|
||||
|
|
|
|||
|
|
@ -1445,7 +1445,9 @@ int adxl367_probe(struct device *dev, const struct adxl367_ops *ops,
|
|||
st->context = context;
|
||||
st->ops = ops;
|
||||
|
||||
mutex_init(&st->lock);
|
||||
ret = devm_mutex_init(dev, &st->lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
indio_dev->channels = adxl367_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(adxl367_channels);
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ static int adxl367_i2c_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id adxl367_i2c_id[] = {
|
||||
{ "adxl367" },
|
||||
{ .name = "adxl367" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, adxl367_i2c_id);
|
||||
|
|
|
|||
|
|
@ -1299,7 +1299,9 @@ int adxl372_probe(struct device *dev, struct regmap *regmap,
|
|||
st->irq = irq;
|
||||
st->chip_info = chip_info;
|
||||
|
||||
mutex_init(&st->threshold_m);
|
||||
ret = devm_mutex_init(dev, &st->threshold_m);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
indio_dev->channels = adxl372_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(adxl372_channels);
|
||||
|
|
@ -1314,10 +1316,8 @@ int adxl372_probe(struct device *dev, struct regmap *regmap,
|
|||
}
|
||||
|
||||
ret = adxl372_setup(st);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "ADXL372 setup failed\n");
|
||||
return ret;
|
||||
}
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "ADXL372 setup failed\n");
|
||||
|
||||
if (chip_info->fifo_supported) {
|
||||
ret = adxl372_buffer_setup(indio_dev);
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ static int adxl372_i2c_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id adxl372_i2c_id[] = {
|
||||
{ "adxl371", (kernel_ulong_t)&adxl371_chip_info },
|
||||
{ "adxl372", (kernel_ulong_t)&adxl372_chip_info },
|
||||
{ .name = "adxl371", .driver_data = (kernel_ulong_t)&adxl371_chip_info },
|
||||
{ .name = "adxl372", .driver_data = (kernel_ulong_t)&adxl372_chip_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, adxl372_i2c_id);
|
||||
|
|
|
|||
|
|
@ -1967,7 +1967,9 @@ int adxl380_probe(struct device *dev, struct regmap *regmap,
|
|||
st->chip_info = chip_info;
|
||||
st->odr = ADXL380_ODR_DSM;
|
||||
|
||||
mutex_init(&st->lock);
|
||||
ret = devm_mutex_init(dev, &st->lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
indio_dev->channels = adxl380_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(adxl380_channels);
|
||||
|
|
|
|||
|
|
@ -33,10 +33,10 @@ static int adxl380_i2c_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id adxl380_i2c_id[] = {
|
||||
{ "adxl318", (kernel_ulong_t)&adxl318_chip_info },
|
||||
{ "adxl319", (kernel_ulong_t)&adxl319_chip_info },
|
||||
{ "adxl380", (kernel_ulong_t)&adxl380_chip_info },
|
||||
{ "adxl382", (kernel_ulong_t)&adxl382_chip_info },
|
||||
{ .name = "adxl318", .driver_data = (kernel_ulong_t)&adxl318_chip_info },
|
||||
{ .name = "adxl319", .driver_data = (kernel_ulong_t)&adxl319_chip_info },
|
||||
{ .name = "adxl380", .driver_data = (kernel_ulong_t)&adxl380_chip_info },
|
||||
{ .name = "adxl382", .driver_data = (kernel_ulong_t)&adxl382_chip_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, adxl380_i2c_id);
|
||||
|
|
|
|||
|
|
@ -1083,11 +1083,11 @@ static int bma180_resume(struct device *dev)
|
|||
static DEFINE_SIMPLE_DEV_PM_OPS(bma180_pm_ops, bma180_suspend, bma180_resume);
|
||||
|
||||
static const struct i2c_device_id bma180_ids[] = {
|
||||
{ "bma023", (kernel_ulong_t)&bma180_part_info[BMA023] },
|
||||
{ "bma150", (kernel_ulong_t)&bma180_part_info[BMA150] },
|
||||
{ "bma180", (kernel_ulong_t)&bma180_part_info[BMA180] },
|
||||
{ "bma250", (kernel_ulong_t)&bma180_part_info[BMA250] },
|
||||
{ "smb380", (kernel_ulong_t)&bma180_part_info[BMA150] },
|
||||
{ .name = "bma023", .driver_data = (kernel_ulong_t)&bma180_part_info[BMA023] },
|
||||
{ .name = "bma150", .driver_data = (kernel_ulong_t)&bma180_part_info[BMA150] },
|
||||
{ .name = "bma180", .driver_data = (kernel_ulong_t)&bma180_part_info[BMA180] },
|
||||
{ .name = "bma250", .driver_data = (kernel_ulong_t)&bma180_part_info[BMA250] },
|
||||
{ .name = "smb380", .driver_data = (kernel_ulong_t)&bma180_part_info[BMA150] },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ static const struct of_device_id bma220_i2c_match[] = {
|
|||
MODULE_DEVICE_TABLE(of, bma220_i2c_match);
|
||||
|
||||
static const struct i2c_device_id bma220_i2c_id[] = {
|
||||
{ "bma220" },
|
||||
{ .name = "bma220" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, bma220_i2c_id);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ static int bma400_i2c_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id bma400_i2c_ids[] = {
|
||||
{ "bma400" },
|
||||
{ .name = "bma400" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, bma400_i2c_ids);
|
||||
|
|
|
|||
|
|
@ -245,16 +245,16 @@ static const struct acpi_device_id bmc150_accel_acpi_match[] = {
|
|||
MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match);
|
||||
|
||||
static const struct i2c_device_id bmc150_accel_id[] = {
|
||||
{"bma222"},
|
||||
{"bma222e"},
|
||||
{"bma250e"},
|
||||
{"bma253"},
|
||||
{"bma254"},
|
||||
{"bma255"},
|
||||
{"bma280"},
|
||||
{"bmc150_accel"},
|
||||
{"bmc156_accel", BOSCH_BMC156},
|
||||
{"bmi055_accel"},
|
||||
{ .name = "bma222", .driver_data = BOSCH_UNKNOWN },
|
||||
{ .name = "bma222e", .driver_data = BOSCH_UNKNOWN },
|
||||
{ .name = "bma250e", .driver_data = BOSCH_UNKNOWN },
|
||||
{ .name = "bma253", .driver_data = BOSCH_UNKNOWN },
|
||||
{ .name = "bma254", .driver_data = BOSCH_UNKNOWN },
|
||||
{ .name = "bma255", .driver_data = BOSCH_UNKNOWN },
|
||||
{ .name = "bma280", .driver_data = BOSCH_UNKNOWN },
|
||||
{ .name = "bmc150_accel", .driver_data = BOSCH_UNKNOWN },
|
||||
{ .name = "bmc156_accel", .driver_data = BOSCH_BMC156 },
|
||||
{ .name = "bmi055_accel", .driver_data = BOSCH_UNKNOWN },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -45,9 +45,9 @@ static const struct of_device_id bmi088_of_match[] = {
|
|||
MODULE_DEVICE_TABLE(of, bmi088_of_match);
|
||||
|
||||
static const struct i2c_device_id bmi088_accel_id[] = {
|
||||
{ "bmi085-accel", BOSCH_BMI085 },
|
||||
{ "bmi088-accel", BOSCH_BMI088 },
|
||||
{ "bmi090l-accel", BOSCH_BMI090L },
|
||||
{ .name = "bmi085-accel", .driver_data = BOSCH_BMI085 },
|
||||
{ .name = "bmi088-accel", .driver_data = BOSCH_BMI088 },
|
||||
{ .name = "bmi090l-accel", .driver_data = BOSCH_BMI090L },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, bmi088_accel_id);
|
||||
|
|
|
|||
|
|
@ -162,9 +162,9 @@ static const struct acpi_device_id da280_acpi_match[] = {
|
|||
MODULE_DEVICE_TABLE(acpi, da280_acpi_match);
|
||||
|
||||
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 },
|
||||
{ .name = "da217", .driver_data = (kernel_ulong_t)&da217_match_data },
|
||||
{ .name = "da226", .driver_data = (kernel_ulong_t)&da226_match_data },
|
||||
{ .name = "da280", .driver_data = (kernel_ulong_t)&da280_match_data },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, da280_i2c_id);
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ static int da311_resume(struct device *dev)
|
|||
static DEFINE_SIMPLE_DEV_PM_OPS(da311_pm_ops, da311_suspend, da311_resume);
|
||||
|
||||
static const struct i2c_device_id da311_i2c_id[] = {
|
||||
{ "da311" },
|
||||
{ .name = "da311" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, da311_i2c_id);
|
||||
|
|
|
|||
|
|
@ -199,9 +199,9 @@ static DEFINE_SIMPLE_DEV_PM_OPS(dmard06_pm_ops, dmard06_suspend,
|
|||
dmard06_resume);
|
||||
|
||||
static const struct i2c_device_id dmard06_id[] = {
|
||||
{ "dmard05" },
|
||||
{ "dmard06" },
|
||||
{ "dmard07" },
|
||||
{ .name = "dmard05" },
|
||||
{ .name = "dmard06" },
|
||||
{ .name = "dmard07" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, dmard06_id);
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ static int dmard09_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id dmard09_id[] = {
|
||||
{ "dmard09" },
|
||||
{ .name = "dmard09" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(dmard10_pm_ops, dmard10_suspend,
|
|||
dmard10_resume);
|
||||
|
||||
static const struct i2c_device_id dmard10_i2c_id[] = {
|
||||
{ "dmard10" },
|
||||
{ .name = "dmard10" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, dmard10_i2c_id);
|
||||
|
|
|
|||
|
|
@ -28,10 +28,10 @@ static int fxls8962af_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id fxls8962af_id[] = {
|
||||
{ "fxls8962af", fxls8962af },
|
||||
{ "fxls8964af", fxls8964af },
|
||||
{ "fxls8967af", fxls8967af },
|
||||
{ "fxls8974cf", fxls8974cf },
|
||||
{ .name = "fxls8962af", .driver_data = fxls8962af },
|
||||
{ .name = "fxls8964af", .driver_data = fxls8964af },
|
||||
{ .name = "fxls8967af", .driver_data = fxls8967af },
|
||||
{ .name = "fxls8974cf", .driver_data = fxls8974cf },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, fxls8962af_id);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
* HID Sensors Driver
|
||||
* Copyright (c) 2012, Intel Corporation.
|
||||
*/
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
|
|
@ -119,17 +120,6 @@ static const struct iio_chan_spec gravity_channels[] = {
|
|||
IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP),
|
||||
};
|
||||
|
||||
/* Adjust channel real bits based on report descriptor */
|
||||
static void accel_3d_adjust_channel_bit_mask(struct iio_chan_spec *channels,
|
||||
int channel, int size)
|
||||
{
|
||||
channels[channel].scan_type.sign = 's';
|
||||
/* Real storage bits will change based on the report desc. */
|
||||
channels[channel].scan_type.realbits = size * 8;
|
||||
/* Maximum size of a sample to capture is u32 */
|
||||
channels[channel].scan_type.storagebits = sizeof(u32) * 8;
|
||||
}
|
||||
|
||||
/* Channel read_raw handler */
|
||||
static int accel_3d_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
|
|
@ -297,19 +287,20 @@ static int accel_3d_parse_report(struct platform_device *pdev,
|
|||
struct accel_3d_state *st)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= CHANNEL_SCAN_INDEX_Z; ++i) {
|
||||
for (unsigned int ch = CHANNEL_SCAN_INDEX_X; ch <= CHANNEL_SCAN_INDEX_Z; ch++) {
|
||||
ret = sensor_hub_input_get_attribute_info(hsdev,
|
||||
HID_INPUT_REPORT,
|
||||
usage_id,
|
||||
HID_USAGE_SENSOR_ACCEL_X_AXIS + i,
|
||||
&st->accel[CHANNEL_SCAN_INDEX_X + i]);
|
||||
HID_USAGE_SENSOR_ACCEL_X_AXIS + ch,
|
||||
&st->accel[ch]);
|
||||
if (ret < 0)
|
||||
break;
|
||||
accel_3d_adjust_channel_bit_mask(channels,
|
||||
CHANNEL_SCAN_INDEX_X + i,
|
||||
st->accel[CHANNEL_SCAN_INDEX_X + i].size);
|
||||
channels[ch].scan_type = (struct iio_scan_type) {
|
||||
.format = 's',
|
||||
.realbits = BYTES_TO_BITS(st->accel[ch].size),
|
||||
.storagebits = BITS_PER_TYPE(u32),
|
||||
};
|
||||
}
|
||||
dev_dbg(&pdev->dev, "accel_3d %x:%x, %x:%x, %x:%x\n",
|
||||
st->accel[0].index,
|
||||
|
|
|
|||
|
|
@ -1630,11 +1630,11 @@ static const struct dev_pm_ops kxcjk1013_pm_ops = {
|
|||
};
|
||||
|
||||
static const struct i2c_device_id kxcjk1013_id[] = {
|
||||
{ "kxcjk1013", (kernel_ulong_t)&kxcjk1013_info },
|
||||
{ "kxcj91008", (kernel_ulong_t)&kxcj91008_info },
|
||||
{ "kxtj21009", (kernel_ulong_t)&kxtj21009_info },
|
||||
{ "kxtf9", (kernel_ulong_t)&kxtf9_info },
|
||||
{ "kx023-1025", (kernel_ulong_t)&kx0231025_info },
|
||||
{ .name = "kxcjk1013", .driver_data = (kernel_ulong_t)&kxcjk1013_info },
|
||||
{ .name = "kxcj91008", .driver_data = (kernel_ulong_t)&kxcj91008_info },
|
||||
{ .name = "kxtj21009", .driver_data = (kernel_ulong_t)&kxtj21009_info },
|
||||
{ .name = "kxtf9", .driver_data = (kernel_ulong_t)&kxtf9_info },
|
||||
{ .name = "kx023-1025", .driver_data = (kernel_ulong_t)&kx0231025_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, kxcjk1013_id);
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ static const struct of_device_id kxsd9_of_match[] = {
|
|||
MODULE_DEVICE_TABLE(of, kxsd9_of_match);
|
||||
|
||||
static const struct i2c_device_id kxsd9_i2c_id[] = {
|
||||
{ "kxsd9" },
|
||||
{ .name = "kxsd9" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, kxsd9_i2c_id);
|
||||
|
|
|
|||
|
|
@ -230,8 +230,8 @@ static int mc3230_resume(struct device *dev)
|
|||
static DEFINE_SIMPLE_DEV_PM_OPS(mc3230_pm_ops, mc3230_suspend, mc3230_resume);
|
||||
|
||||
static const struct i2c_device_id mc3230_i2c_id[] = {
|
||||
{ "mc3230", (kernel_ulong_t)&mc3230_chip_info },
|
||||
{ "mc3510c", (kernel_ulong_t)&mc3510c_chip_info },
|
||||
{ .name = "mc3230", .driver_data = (kernel_ulong_t)&mc3230_chip_info },
|
||||
{ .name = "mc3510c", .driver_data = (kernel_ulong_t)&mc3510c_chip_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, mc3230_i2c_id);
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ static void mma7455_i2c_remove(struct i2c_client *i2c)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id mma7455_i2c_ids[] = {
|
||||
{ "mma7455" },
|
||||
{ "mma7456" },
|
||||
{ .name = "mma7455" },
|
||||
{ .name = "mma7456" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, mma7455_i2c_ids);
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(mma7660_pm_ops, mma7660_suspend,
|
|||
mma7660_resume);
|
||||
|
||||
static const struct i2c_device_id mma7660_i2c_id[] = {
|
||||
{ "mma7660" },
|
||||
{ .name = "mma7660" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, mma7660_i2c_id);
|
||||
|
|
|
|||
|
|
@ -18,21 +18,22 @@
|
|||
* TODO: orientation events
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/events.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/trigger.h>
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/iio/triggered_buffer.h>
|
||||
#include <linux/iio/events.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define MMA8452_STATUS 0x00
|
||||
#define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
|
||||
|
|
@ -252,6 +253,8 @@ static int mma8452_read(struct mma8452_data *data, __be16 buf[3])
|
|||
|
||||
ret = i2c_smbus_read_i2c_block_data(data->client, MMA8452_OUT_X,
|
||||
3 * sizeof(__be16), (u8 *)buf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = mma8452_set_runtime_pm_state(data->client, false);
|
||||
|
||||
|
|
@ -704,8 +707,8 @@ static int mma8452_set_hp_filter_frequency(struct mma8452_data *data,
|
|||
}
|
||||
|
||||
static int __mma8452_write_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int val, int val2, long mask)
|
||||
struct iio_chan_spec const *chan,
|
||||
int val, int val2, long mask)
|
||||
{
|
||||
struct mma8452_data *data = iio_priv(indio_dev);
|
||||
int i, j, ret;
|
||||
|
|
@ -786,8 +789,9 @@ static int mma8452_write_raw(struct iio_dev *indio_dev,
|
|||
}
|
||||
|
||||
static int mma8452_get_event_regs(struct mma8452_data *data,
|
||||
const struct iio_chan_spec *chan, enum iio_event_direction dir,
|
||||
const struct mma8452_event_regs **ev_reg)
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_direction dir,
|
||||
const struct mma8452_event_regs **ev_reg)
|
||||
{
|
||||
if (!chan)
|
||||
return -EINVAL;
|
||||
|
|
@ -816,11 +820,11 @@ static int mma8452_get_event_regs(struct mma8452_data *data,
|
|||
}
|
||||
|
||||
static int mma8452_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)
|
||||
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 mma8452_data *data = iio_priv(indio_dev);
|
||||
int ret, us, power_mode;
|
||||
|
|
@ -879,11 +883,11 @@ static int mma8452_read_event_value(struct iio_dev *indio_dev,
|
|||
}
|
||||
|
||||
static int mma8452_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)
|
||||
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 mma8452_data *data = iio_priv(indio_dev);
|
||||
int ret, reg, steps;
|
||||
|
|
@ -953,8 +957,7 @@ static int mma8452_read_event_config(struct iio_dev *indio_dev,
|
|||
case IIO_EV_DIR_FALLING:
|
||||
return mma8452_freefall_mode_enabled(data);
|
||||
case IIO_EV_DIR_RISING:
|
||||
ret = i2c_smbus_read_byte_data(data->client,
|
||||
ev_regs->ev_cfg);
|
||||
ret = i2c_smbus_read_byte_data(data->client, ev_regs->ev_cfg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
@ -1191,7 +1194,7 @@ static const struct attribute_group mma8452_event_attribute_group = {
|
|||
|
||||
static const struct iio_mount_matrix *
|
||||
mma8452_get_mount_matrix(const struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan)
|
||||
const struct iio_chan_spec *chan)
|
||||
{
|
||||
struct mma8452_data *data = iio_priv(indio_dev);
|
||||
|
||||
|
|
@ -1514,8 +1517,9 @@ static int mma8452_reset(struct i2c_client *client)
|
|||
* The following code will read the reset register, and check whether
|
||||
* this reset works.
|
||||
*/
|
||||
i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG2,
|
||||
MMA8452_CTRL_REG2_RST);
|
||||
i2c_smbus_write_byte_data(client,
|
||||
MMA8452_CTRL_REG2,
|
||||
MMA8452_CTRL_REG2_RST);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
usleep_range(100, 200);
|
||||
|
|
@ -1544,6 +1548,7 @@ MODULE_DEVICE_TABLE(of, mma8452_dt_ids);
|
|||
|
||||
static int mma8452_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct mma8452_data *data;
|
||||
struct iio_dev *indio_dev;
|
||||
int ret;
|
||||
|
|
@ -1576,14 +1581,12 @@ static int mma8452_probe(struct i2c_client *client)
|
|||
"failed to get VDDIO regulator!\n");
|
||||
|
||||
ret = regulator_enable(data->vdd_reg);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "failed to enable VDD regulator!\n");
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to enable VDD regulator!\n");
|
||||
|
||||
ret = regulator_enable(data->vddio_reg);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "failed to enable VDDIO regulator!\n");
|
||||
dev_err_probe(dev, ret, "failed to enable VDDIO regulator!\n");
|
||||
goto disable_regulator_vdd;
|
||||
}
|
||||
|
||||
|
|
@ -1645,8 +1648,8 @@ static int mma8452_probe(struct i2c_client *client)
|
|||
dev_dbg(&client->dev, "using interrupt line INT2\n");
|
||||
} else {
|
||||
ret = i2c_smbus_write_byte_data(client,
|
||||
MMA8452_CTRL_REG5,
|
||||
data->chip_info->all_events);
|
||||
MMA8452_CTRL_REG5,
|
||||
data->chip_info->all_events);
|
||||
if (ret < 0)
|
||||
goto disable_regulators;
|
||||
|
||||
|
|
@ -1654,8 +1657,8 @@ static int mma8452_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
ret = i2c_smbus_write_byte_data(client,
|
||||
MMA8452_CTRL_REG4,
|
||||
data->chip_info->enabled_events);
|
||||
MMA8452_CTRL_REG4,
|
||||
data->chip_info->enabled_events);
|
||||
if (ret < 0)
|
||||
goto disable_regulators;
|
||||
|
||||
|
|
@ -1680,18 +1683,16 @@ static int mma8452_probe(struct i2c_client *client)
|
|||
goto trigger_cleanup;
|
||||
|
||||
if (client->irq) {
|
||||
ret = devm_request_threaded_irq(&client->dev,
|
||||
client->irq,
|
||||
NULL, mma8452_interrupt,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
client->name, indio_dev);
|
||||
ret = request_threaded_irq(client->irq, NULL, mma8452_interrupt,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
client->name, indio_dev);
|
||||
if (ret)
|
||||
goto buffer_cleanup;
|
||||
}
|
||||
|
||||
ret = pm_runtime_set_active(&client->dev);
|
||||
if (ret < 0)
|
||||
goto buffer_cleanup;
|
||||
goto free_irq;
|
||||
|
||||
pm_runtime_enable(&client->dev);
|
||||
pm_runtime_set_autosuspend_delay(&client->dev,
|
||||
|
|
@ -1700,7 +1701,7 @@ static int mma8452_probe(struct i2c_client *client)
|
|||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret < 0)
|
||||
goto buffer_cleanup;
|
||||
goto free_irq;
|
||||
|
||||
ret = mma8452_set_freefall_mode(data, false);
|
||||
if (ret < 0)
|
||||
|
|
@ -1711,6 +1712,10 @@ static int mma8452_probe(struct i2c_client *client)
|
|||
unregister_device:
|
||||
iio_device_unregister(indio_dev);
|
||||
|
||||
free_irq:
|
||||
if (client->irq)
|
||||
free_irq(client->irq, indio_dev);
|
||||
|
||||
buffer_cleanup:
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
|
||||
|
|
@ -1736,6 +1741,9 @@ static void mma8452_remove(struct i2c_client *client)
|
|||
pm_runtime_disable(&client->dev);
|
||||
pm_runtime_set_suspended(&client->dev);
|
||||
|
||||
if (client->irq)
|
||||
free_irq(client->irq, indio_dev);
|
||||
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
mma8452_trigger_cleanup(indio_dev);
|
||||
mma8452_standby(iio_priv(indio_dev));
|
||||
|
|
@ -1821,12 +1829,12 @@ static const struct dev_pm_ops mma8452_pm_ops = {
|
|||
};
|
||||
|
||||
static const struct i2c_device_id mma8452_id[] = {
|
||||
{ "fxls8471", (kernel_ulong_t)&mma_chip_info_table[fxls8471] },
|
||||
{ "mma8451", (kernel_ulong_t)&mma_chip_info_table[mma8451] },
|
||||
{ "mma8452", (kernel_ulong_t)&mma_chip_info_table[mma8452] },
|
||||
{ "mma8453", (kernel_ulong_t)&mma_chip_info_table[mma8453] },
|
||||
{ "mma8652", (kernel_ulong_t)&mma_chip_info_table[mma8652] },
|
||||
{ "mma8653", (kernel_ulong_t)&mma_chip_info_table[mma8653] },
|
||||
{ .name = "fxls8471", .driver_data = (kernel_ulong_t)&mma_chip_info_table[fxls8471] },
|
||||
{ .name = "mma8451", .driver_data = (kernel_ulong_t)&mma_chip_info_table[mma8451] },
|
||||
{ .name = "mma8452", .driver_data = (kernel_ulong_t)&mma_chip_info_table[mma8452] },
|
||||
{ .name = "mma8453", .driver_data = (kernel_ulong_t)&mma_chip_info_table[mma8453] },
|
||||
{ .name = "mma8652", .driver_data = (kernel_ulong_t)&mma_chip_info_table[mma8652] },
|
||||
{ .name = "mma8653", .driver_data = (kernel_ulong_t)&mma_chip_info_table[mma8653] },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, mma8452_id);
|
||||
|
|
|
|||
|
|
@ -582,7 +582,7 @@ static const struct acpi_device_id mma9551_acpi_match[] = {
|
|||
MODULE_DEVICE_TABLE(acpi, mma9551_acpi_match);
|
||||
|
||||
static const struct i2c_device_id mma9551_id[] = {
|
||||
{ "mma9551" },
|
||||
{ .name = "mma9551" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1219,7 +1219,7 @@ static const struct acpi_device_id mma9553_acpi_match[] = {
|
|||
MODULE_DEVICE_TABLE(acpi, mma9553_acpi_match);
|
||||
|
||||
static const struct i2c_device_id mma9553_id[] = {
|
||||
{ "mma9553" },
|
||||
{ .name = "mma9553" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -580,8 +580,8 @@ static const struct of_device_id mxc4005_of_match[] = {
|
|||
MODULE_DEVICE_TABLE(of, mxc4005_of_match);
|
||||
|
||||
static const struct i2c_device_id mxc4005_id[] = {
|
||||
{ "mxc4005" },
|
||||
{ "mxc6655" },
|
||||
{ .name = "mxc4005" },
|
||||
{ .name = "mxc6655" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, mxc4005_id);
|
||||
|
|
|
|||
|
|
@ -171,8 +171,8 @@ static const struct acpi_device_id mxc6255_acpi_match[] = {
|
|||
MODULE_DEVICE_TABLE(acpi, mxc6255_acpi_match);
|
||||
|
||||
static const struct i2c_device_id mxc6255_id[] = {
|
||||
{ "mxc6225" },
|
||||
{ "mxc6255" },
|
||||
{ .name = "mxc6225" },
|
||||
{ .name = "mxc6255" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, mxc6255_id);
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ static const struct iio_chan_spec ssp_acc_channels[] = {
|
|||
SSP_CHANNEL_AG(IIO_ACCEL, IIO_MOD_X, SSP_CHANNEL_SCAN_INDEX_X),
|
||||
SSP_CHANNEL_AG(IIO_ACCEL, IIO_MOD_Y, SSP_CHANNEL_SCAN_INDEX_Y),
|
||||
SSP_CHANNEL_AG(IIO_ACCEL, IIO_MOD_Z, SSP_CHANNEL_SCAN_INDEX_Z),
|
||||
SSP_CHAN_TIMESTAMP(SSP_CHANNEL_SCAN_INDEX_TIME),
|
||||
IIO_CHAN_SOFT_TIMESTAMP(SSP_CHANNEL_SCAN_INDEX_TIME),
|
||||
};
|
||||
|
||||
static int ssp_process_accel_data(struct iio_dev *indio_dev, void *buf,
|
||||
|
|
|
|||
|
|
@ -138,32 +138,32 @@ static const struct acpi_device_id st_accel_acpi_match[] = {
|
|||
MODULE_DEVICE_TABLE(acpi, st_accel_acpi_match);
|
||||
|
||||
static const struct i2c_device_id st_accel_id_table[] = {
|
||||
{ LSM303DLH_ACCEL_DEV_NAME },
|
||||
{ LSM303DLHC_ACCEL_DEV_NAME },
|
||||
{ LIS3DH_ACCEL_DEV_NAME },
|
||||
{ LSM330D_ACCEL_DEV_NAME },
|
||||
{ LSM330DL_ACCEL_DEV_NAME },
|
||||
{ LSM330DLC_ACCEL_DEV_NAME },
|
||||
{ LIS331DLH_ACCEL_DEV_NAME },
|
||||
{ LSM303DL_ACCEL_DEV_NAME },
|
||||
{ LSM303DLM_ACCEL_DEV_NAME },
|
||||
{ LSM330_ACCEL_DEV_NAME },
|
||||
{ LSM303AGR_ACCEL_DEV_NAME },
|
||||
{ LIS2DH12_ACCEL_DEV_NAME },
|
||||
{ LIS3L02DQ_ACCEL_DEV_NAME },
|
||||
{ LNG2DM_ACCEL_DEV_NAME },
|
||||
{ H3LIS331DL_ACCEL_DEV_NAME },
|
||||
{ LIS331DL_ACCEL_DEV_NAME },
|
||||
{ LIS3LV02DL_ACCEL_DEV_NAME },
|
||||
{ LIS2DW12_ACCEL_DEV_NAME },
|
||||
{ LIS3DE_ACCEL_DEV_NAME },
|
||||
{ LIS2DE12_ACCEL_DEV_NAME },
|
||||
{ LIS2DS12_ACCEL_DEV_NAME },
|
||||
{ LIS2HH12_ACCEL_DEV_NAME },
|
||||
{ LIS302DL_ACCEL_DEV_NAME },
|
||||
{ LSM303C_ACCEL_DEV_NAME },
|
||||
{ SC7A20_ACCEL_DEV_NAME },
|
||||
{ IIS328DQ_ACCEL_DEV_NAME },
|
||||
{ .name = LSM303DLH_ACCEL_DEV_NAME },
|
||||
{ .name = LSM303DLHC_ACCEL_DEV_NAME },
|
||||
{ .name = LIS3DH_ACCEL_DEV_NAME },
|
||||
{ .name = LSM330D_ACCEL_DEV_NAME },
|
||||
{ .name = LSM330DL_ACCEL_DEV_NAME },
|
||||
{ .name = LSM330DLC_ACCEL_DEV_NAME },
|
||||
{ .name = LIS331DLH_ACCEL_DEV_NAME },
|
||||
{ .name = LSM303DL_ACCEL_DEV_NAME },
|
||||
{ .name = LSM303DLM_ACCEL_DEV_NAME },
|
||||
{ .name = LSM330_ACCEL_DEV_NAME },
|
||||
{ .name = LSM303AGR_ACCEL_DEV_NAME },
|
||||
{ .name = LIS2DH12_ACCEL_DEV_NAME },
|
||||
{ .name = LIS3L02DQ_ACCEL_DEV_NAME },
|
||||
{ .name = LNG2DM_ACCEL_DEV_NAME },
|
||||
{ .name = H3LIS331DL_ACCEL_DEV_NAME },
|
||||
{ .name = LIS331DL_ACCEL_DEV_NAME },
|
||||
{ .name = LIS3LV02DL_ACCEL_DEV_NAME },
|
||||
{ .name = LIS2DW12_ACCEL_DEV_NAME },
|
||||
{ .name = LIS3DE_ACCEL_DEV_NAME },
|
||||
{ .name = LIS2DE12_ACCEL_DEV_NAME },
|
||||
{ .name = LIS2DS12_ACCEL_DEV_NAME },
|
||||
{ .name = LIS2HH12_ACCEL_DEV_NAME },
|
||||
{ .name = LIS302DL_ACCEL_DEV_NAME },
|
||||
{ .name = LSM303C_ACCEL_DEV_NAME },
|
||||
{ .name = SC7A20_ACCEL_DEV_NAME },
|
||||
{ .name = IIS328DQ_ACCEL_DEV_NAME },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
|
||||
|
|
|
|||
|
|
@ -630,8 +630,8 @@ static DEFINE_SIMPLE_DEV_PM_OPS(stk8312_pm_ops, stk8312_suspend,
|
|||
|
||||
static const struct i2c_device_id stk8312_i2c_id[] = {
|
||||
/* Deprecated in favour of lowercase form */
|
||||
{ "STK8312" },
|
||||
{ "stk8312" },
|
||||
{ .name = "STK8312" },
|
||||
{ .name = "stk8312" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, stk8312_i2c_id);
|
||||
|
|
|
|||
|
|
@ -519,7 +519,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(stk8ba50_pm_ops, stk8ba50_suspend,
|
|||
stk8ba50_resume);
|
||||
|
||||
static const struct i2c_device_id stk8ba50_i2c_id[] = {
|
||||
{ "stk8ba50" },
|
||||
{ .name = "stk8ba50" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, stk8ba50_i2c_id);
|
||||
|
|
|
|||
|
|
@ -373,7 +373,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(pm886_gpadc_pm_ops,
|
|||
pm886_gpadc_runtime_resume, NULL);
|
||||
|
||||
static const struct platform_device_id pm886_gpadc_id[] = {
|
||||
{ "88pm886-gpadc" },
|
||||
{ .name = "88pm886-gpadc" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, pm886_gpadc_id);
|
||||
|
|
|
|||
|
|
@ -144,6 +144,22 @@ config AD4170_4
|
|||
To compile this driver as a module, choose M here: the module will be
|
||||
called ad4170-4.
|
||||
|
||||
config AD4691
|
||||
tristate "Analog Devices AD4691 Family ADC Driver"
|
||||
depends on SPI
|
||||
depends on REGULATOR || COMPILE_TEST
|
||||
select IIO_BUFFER
|
||||
select IIO_BUFFER_DMAENGINE
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
select REGMAP
|
||||
select SPI_OFFLOAD
|
||||
help
|
||||
Say yes here to build support for Analog Devices AD4691 Family MuxSAR
|
||||
SPI analog to digital converters (ADC).
|
||||
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
called ad4691.
|
||||
|
||||
config AD4695
|
||||
tristate "Analog Device AD4695 ADC Driver"
|
||||
depends on SPI
|
||||
|
|
@ -1354,7 +1370,7 @@ config QCOM_SPMI_VADC
|
|||
be called qcom-spmi-vadc.
|
||||
|
||||
config QCOM_SPMI_ADC5
|
||||
tristate "Qualcomm Technologies Inc. SPMI PMIC5 ADC"
|
||||
tristate "Qualcomm SPMI PMIC5 ADC"
|
||||
depends on SPMI
|
||||
select REGMAP_SPMI
|
||||
select QCOM_VADC_COMMON
|
||||
|
|
@ -1374,7 +1390,7 @@ config QCOM_SPMI_ADC5
|
|||
be called qcom-spmi-adc5.
|
||||
|
||||
config QCOM_SPMI_ADC5_GEN3
|
||||
tristate "Qualcomm Technologies Inc. SPMI PMIC5 GEN3 ADC"
|
||||
tristate "Qualcomm SPMI PMIC5 GEN3 ADC"
|
||||
depends on SPMI && THERMAL
|
||||
select REGMAP_SPMI
|
||||
select QCOM_VADC_COMMON
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ obj-$(CONFIG_AD4080) += ad4080.o
|
|||
obj-$(CONFIG_AD4130) += ad4130.o
|
||||
obj-$(CONFIG_AD4134) += ad4134.o
|
||||
obj-$(CONFIG_AD4170_4) += ad4170-4.o
|
||||
obj-$(CONFIG_AD4691) += ad4691.o
|
||||
obj-$(CONFIG_AD4695) += ad4695.o
|
||||
obj-$(CONFIG_AD4851) += ad4851.o
|
||||
obj-$(CONFIG_AD7091R) += ad7091r-base.o
|
||||
|
|
|
|||
|
|
@ -436,10 +436,9 @@ static int ad4062_check_ids(struct ad4062_state *st)
|
|||
return ret;
|
||||
|
||||
val = be16_to_cpu(st->buf.be16);
|
||||
if (val != AD4062_I3C_VENDOR) {
|
||||
dev_err(dev, "Vendor ID x%x does not match expected value\n", val);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (val != AD4062_I3C_VENDOR)
|
||||
return dev_err_probe(dev, -ENODEV,
|
||||
"Vendor ID x%x does not match expected value\n", val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
|
@ -134,6 +135,10 @@
|
|||
#define AD4086_CHIP_ID 0x0056
|
||||
#define AD4087_CHIP_ID 0x0057
|
||||
#define AD4088_CHIP_ID 0x0058
|
||||
#define AD4880_CHIP_ID 0x0059
|
||||
#define AD4884_CHIP_ID 0x005C
|
||||
|
||||
#define AD4080_MAX_CHANNELS 2
|
||||
|
||||
#define AD4080_LVDS_CNV_CLK_CNT_MAX 7
|
||||
|
||||
|
|
@ -179,8 +184,9 @@ struct ad4080_chip_info {
|
|||
};
|
||||
|
||||
struct ad4080_state {
|
||||
struct regmap *regmap;
|
||||
struct iio_backend *back;
|
||||
struct spi_device *spi[AD4080_MAX_CHANNELS];
|
||||
struct regmap *regmap[AD4080_MAX_CHANNELS];
|
||||
struct iio_backend *back[AD4080_MAX_CHANNELS];
|
||||
const struct ad4080_chip_info *info;
|
||||
/*
|
||||
* Synchronize access to members the of driver state, and ensure
|
||||
|
|
@ -189,7 +195,7 @@ struct ad4080_state {
|
|||
struct mutex lock;
|
||||
unsigned int num_lanes;
|
||||
unsigned long clk_rate;
|
||||
enum ad4080_filter_type filter_type;
|
||||
enum ad4080_filter_type filter_type[AD4080_MAX_CHANNELS];
|
||||
bool lvds_cnv_en;
|
||||
};
|
||||
|
||||
|
|
@ -206,9 +212,9 @@ static int ad4080_reg_access(struct iio_dev *indio_dev, unsigned int reg,
|
|||
struct ad4080_state *st = iio_priv(indio_dev);
|
||||
|
||||
if (readval)
|
||||
return regmap_read(st->regmap, reg, readval);
|
||||
return regmap_read(st->regmap[0], reg, readval);
|
||||
|
||||
return regmap_write(st->regmap, reg, writeval);
|
||||
return regmap_write(st->regmap[0], reg, writeval);
|
||||
}
|
||||
|
||||
static int ad4080_get_scale(struct ad4080_state *st, int *val, int *val2)
|
||||
|
|
@ -229,8 +235,9 @@ static unsigned int ad4080_get_dec_rate(struct iio_dev *dev,
|
|||
struct ad4080_state *st = iio_priv(dev);
|
||||
int ret;
|
||||
unsigned int data;
|
||||
unsigned int ch = chan->channel;
|
||||
|
||||
ret = regmap_read(st->regmap, AD4080_REG_FILTER_CONFIG, &data);
|
||||
ret = regmap_read(st->regmap[ch], AD4080_REG_FILTER_CONFIG, &data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -242,13 +249,14 @@ static int ad4080_set_dec_rate(struct iio_dev *dev,
|
|||
unsigned int mode)
|
||||
{
|
||||
struct ad4080_state *st = iio_priv(dev);
|
||||
unsigned int ch = chan->channel;
|
||||
|
||||
guard(mutex)(&st->lock);
|
||||
|
||||
if ((st->filter_type >= SINC_5 && mode >= 512) || mode < 2)
|
||||
if ((st->filter_type[ch] >= SINC_5 && mode >= 512) || mode < 2)
|
||||
return -EINVAL;
|
||||
|
||||
return regmap_update_bits(st->regmap, AD4080_REG_FILTER_CONFIG,
|
||||
return regmap_update_bits(st->regmap[ch], AD4080_REG_FILTER_CONFIG,
|
||||
AD4080_FILTER_CONFIG_SINC_DEC_RATE_MSK,
|
||||
FIELD_PREP(AD4080_FILTER_CONFIG_SINC_DEC_RATE_MSK,
|
||||
(ilog2(mode) - 1)));
|
||||
|
|
@ -268,15 +276,15 @@ static int ad4080_read_raw(struct iio_dev *indio_dev,
|
|||
dec_rate = ad4080_get_dec_rate(indio_dev, chan);
|
||||
if (dec_rate < 0)
|
||||
return dec_rate;
|
||||
if (st->filter_type == SINC_5_COMP)
|
||||
if (st->filter_type[chan->channel] == SINC_5_COMP)
|
||||
dec_rate *= 2;
|
||||
if (st->filter_type)
|
||||
if (st->filter_type[chan->channel])
|
||||
*val = DIV_ROUND_CLOSEST(st->clk_rate, dec_rate);
|
||||
else
|
||||
*val = st->clk_rate;
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
|
||||
if (st->filter_type == FILTER_NONE) {
|
||||
if (st->filter_type[chan->channel] == FILTER_NONE) {
|
||||
*val = 1;
|
||||
} else {
|
||||
*val = ad4080_get_dec_rate(indio_dev, chan);
|
||||
|
|
@ -297,7 +305,7 @@ static int ad4080_write_raw(struct iio_dev *indio_dev,
|
|||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
|
||||
if (st->filter_type == FILTER_NONE && val > 1)
|
||||
if (st->filter_type[chan->channel] == FILTER_NONE && val > 1)
|
||||
return -EINVAL;
|
||||
|
||||
return ad4080_set_dec_rate(indio_dev, chan, val);
|
||||
|
|
@ -306,23 +314,23 @@ static int ad4080_write_raw(struct iio_dev *indio_dev,
|
|||
}
|
||||
}
|
||||
|
||||
static int ad4080_lvds_sync_write(struct ad4080_state *st)
|
||||
static int ad4080_lvds_sync_write(struct ad4080_state *st, unsigned int ch)
|
||||
{
|
||||
struct device *dev = regmap_get_device(st->regmap);
|
||||
struct device *dev = regmap_get_device(st->regmap[ch]);
|
||||
int ret;
|
||||
|
||||
ret = regmap_set_bits(st->regmap, AD4080_REG_ADC_DATA_INTF_CONFIG_A,
|
||||
ret = regmap_set_bits(st->regmap[ch], AD4080_REG_ADC_DATA_INTF_CONFIG_A,
|
||||
AD4080_ADC_DATA_INTF_CONFIG_A_INTF_CHK_EN);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iio_backend_interface_data_align(st->back, 10000);
|
||||
ret = iio_backend_interface_data_align(st->back[ch], 10000);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"Data alignment process failed\n");
|
||||
|
||||
dev_dbg(dev, "Success: Pattern correct and Locked!\n");
|
||||
return regmap_clear_bits(st->regmap, AD4080_REG_ADC_DATA_INTF_CONFIG_A,
|
||||
return regmap_clear_bits(st->regmap[ch], AD4080_REG_ADC_DATA_INTF_CONFIG_A,
|
||||
AD4080_ADC_DATA_INTF_CONFIG_A_INTF_CHK_EN);
|
||||
}
|
||||
|
||||
|
|
@ -331,9 +339,10 @@ static int ad4080_get_filter_type(struct iio_dev *dev,
|
|||
{
|
||||
struct ad4080_state *st = iio_priv(dev);
|
||||
unsigned int data;
|
||||
unsigned int ch = chan->channel;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(st->regmap, AD4080_REG_FILTER_CONFIG, &data);
|
||||
ret = regmap_read(st->regmap[ch], AD4080_REG_FILTER_CONFIG, &data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -345,6 +354,7 @@ static int ad4080_set_filter_type(struct iio_dev *dev,
|
|||
unsigned int mode)
|
||||
{
|
||||
struct ad4080_state *st = iio_priv(dev);
|
||||
unsigned int ch = chan->channel;
|
||||
int dec_rate;
|
||||
int ret;
|
||||
|
||||
|
|
@ -357,18 +367,18 @@ static int ad4080_set_filter_type(struct iio_dev *dev,
|
|||
if (mode >= SINC_5 && dec_rate >= 512)
|
||||
return -EINVAL;
|
||||
|
||||
ret = iio_backend_filter_type_set(st->back, mode);
|
||||
ret = iio_backend_filter_type_set(st->back[ch], mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_update_bits(st->regmap, AD4080_REG_FILTER_CONFIG,
|
||||
ret = regmap_update_bits(st->regmap[ch], AD4080_REG_FILTER_CONFIG,
|
||||
AD4080_FILTER_CONFIG_FILTER_SEL_MSK,
|
||||
FIELD_PREP(AD4080_FILTER_CONFIG_FILTER_SEL_MSK,
|
||||
mode));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
st->filter_type = mode;
|
||||
st->filter_type[ch] = mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -382,14 +392,14 @@ static int ad4080_read_avail(struct iio_dev *indio_dev,
|
|||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
|
||||
switch (st->filter_type) {
|
||||
switch (st->filter_type[chan->channel]) {
|
||||
case FILTER_NONE:
|
||||
*vals = ad4080_dec_rate_none;
|
||||
*length = ARRAY_SIZE(ad4080_dec_rate_none);
|
||||
break;
|
||||
default:
|
||||
*vals = ad4080_dec_rate_avail;
|
||||
*length = st->filter_type >= SINC_5 ?
|
||||
*length = st->filter_type[chan->channel] >= SINC_5 ?
|
||||
(ARRAY_SIZE(ad4080_dec_rate_avail) - 2) :
|
||||
ARRAY_SIZE(ad4080_dec_rate_avail);
|
||||
break;
|
||||
|
|
@ -401,6 +411,28 @@ static int ad4080_read_avail(struct iio_dev *indio_dev,
|
|||
}
|
||||
}
|
||||
|
||||
static int ad4880_update_scan_mode(struct iio_dev *indio_dev,
|
||||
const unsigned long *scan_mask)
|
||||
{
|
||||
struct ad4080_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
for (unsigned int ch = 0; ch < st->info->num_channels; ch++) {
|
||||
/*
|
||||
* Each backend has a single channel (channel 0 from the
|
||||
* backend's perspective), so always use channel index 0.
|
||||
*/
|
||||
if (test_bit(ch, scan_mask))
|
||||
ret = iio_backend_chan_enable(st->back[ch], 0);
|
||||
else
|
||||
ret = iio_backend_chan_disable(st->back[ch], 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct iio_info ad4080_iio_info = {
|
||||
.debugfs_reg_access = ad4080_reg_access,
|
||||
.read_raw = ad4080_read_raw,
|
||||
|
|
@ -408,6 +440,19 @@ static const struct iio_info ad4080_iio_info = {
|
|||
.read_avail = ad4080_read_avail,
|
||||
};
|
||||
|
||||
/*
|
||||
* AD4880 needs update_scan_mode to enable/disable individual backend channels.
|
||||
* Single-channel devices don't need this as their backends may not implement
|
||||
* chan_enable/chan_disable operations.
|
||||
*/
|
||||
static const struct iio_info ad4880_iio_info = {
|
||||
.debugfs_reg_access = ad4080_reg_access,
|
||||
.read_raw = ad4080_read_raw,
|
||||
.write_raw = ad4080_write_raw,
|
||||
.read_avail = ad4080_read_avail,
|
||||
.update_scan_mode = ad4880_update_scan_mode,
|
||||
};
|
||||
|
||||
static const struct iio_enum ad4080_filter_type_enum = {
|
||||
.items = ad4080_filter_type_iio_enum,
|
||||
.num_items = ARRAY_SIZE(ad4080_filter_type_iio_enum),
|
||||
|
|
@ -422,17 +467,28 @@ static struct iio_chan_spec_ext_info ad4080_ext_info[] = {
|
|||
{ }
|
||||
};
|
||||
|
||||
#define AD4080_CHANNEL_DEFINE(bits, storage) { \
|
||||
/*
|
||||
* AD4880 needs per-channel filter configuration since each channel has
|
||||
* its own independent ADC with separate SPI interface.
|
||||
*/
|
||||
static struct iio_chan_spec_ext_info ad4880_ext_info[] = {
|
||||
IIO_ENUM("filter_type", IIO_SEPARATE, &ad4080_filter_type_enum),
|
||||
IIO_ENUM_AVAILABLE("filter_type", IIO_SEPARATE,
|
||||
&ad4080_filter_type_enum),
|
||||
{ }
|
||||
};
|
||||
|
||||
#define AD4080_CHANNEL_DEFINE(bits, storage, idx) { \
|
||||
.type = IIO_VOLTAGE, \
|
||||
.indexed = 1, \
|
||||
.channel = 0, \
|
||||
.channel = (idx), \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_SCALE), \
|
||||
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
|
||||
.info_mask_shared_by_all_available = \
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
|
||||
.ext_info = ad4080_ext_info, \
|
||||
.scan_index = 0, \
|
||||
.scan_index = (idx), \
|
||||
.scan_type = { \
|
||||
.sign = 's', \
|
||||
.realbits = (bits), \
|
||||
|
|
@ -440,23 +496,56 @@ static struct iio_chan_spec_ext_info ad4080_ext_info[] = {
|
|||
}, \
|
||||
}
|
||||
|
||||
static const struct iio_chan_spec ad4080_channel = AD4080_CHANNEL_DEFINE(20, 32);
|
||||
/*
|
||||
* AD4880 has per-channel attributes (filter_type, oversampling_ratio,
|
||||
* sampling_frequency) since each channel has its own independent ADC
|
||||
* with separate SPI configuration interface.
|
||||
*/
|
||||
#define AD4880_CHANNEL_DEFINE(bits, storage, idx) { \
|
||||
.type = IIO_VOLTAGE, \
|
||||
.indexed = 1, \
|
||||
.channel = (idx), \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_SCALE) | \
|
||||
BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
|
||||
.info_mask_separate_available = \
|
||||
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
|
||||
.ext_info = ad4880_ext_info, \
|
||||
.scan_index = (idx), \
|
||||
.scan_type = { \
|
||||
.sign = 's', \
|
||||
.realbits = (bits), \
|
||||
.storagebits = (storage), \
|
||||
}, \
|
||||
}
|
||||
|
||||
static const struct iio_chan_spec ad4081_channel = AD4080_CHANNEL_DEFINE(20, 32);
|
||||
static const struct iio_chan_spec ad4080_channel = AD4080_CHANNEL_DEFINE(20, 32, 0);
|
||||
|
||||
static const struct iio_chan_spec ad4082_channel = AD4080_CHANNEL_DEFINE(20, 32);
|
||||
static const struct iio_chan_spec ad4081_channel = AD4080_CHANNEL_DEFINE(20, 32, 0);
|
||||
|
||||
static const struct iio_chan_spec ad4083_channel = AD4080_CHANNEL_DEFINE(16, 16);
|
||||
static const struct iio_chan_spec ad4082_channel = AD4080_CHANNEL_DEFINE(20, 32, 0);
|
||||
|
||||
static const struct iio_chan_spec ad4084_channel = AD4080_CHANNEL_DEFINE(16, 16);
|
||||
static const struct iio_chan_spec ad4083_channel = AD4080_CHANNEL_DEFINE(16, 16, 0);
|
||||
|
||||
static const struct iio_chan_spec ad4085_channel = AD4080_CHANNEL_DEFINE(16, 16);
|
||||
static const struct iio_chan_spec ad4084_channel = AD4080_CHANNEL_DEFINE(16, 16, 0);
|
||||
|
||||
static const struct iio_chan_spec ad4086_channel = AD4080_CHANNEL_DEFINE(14, 16);
|
||||
static const struct iio_chan_spec ad4085_channel = AD4080_CHANNEL_DEFINE(16, 16, 0);
|
||||
|
||||
static const struct iio_chan_spec ad4087_channel = AD4080_CHANNEL_DEFINE(14, 16);
|
||||
static const struct iio_chan_spec ad4086_channel = AD4080_CHANNEL_DEFINE(14, 16, 0);
|
||||
|
||||
static const struct iio_chan_spec ad4088_channel = AD4080_CHANNEL_DEFINE(14, 16);
|
||||
static const struct iio_chan_spec ad4087_channel = AD4080_CHANNEL_DEFINE(14, 16, 0);
|
||||
|
||||
static const struct iio_chan_spec ad4088_channel = AD4080_CHANNEL_DEFINE(14, 16, 0);
|
||||
|
||||
static const struct iio_chan_spec ad4880_channels[] = {
|
||||
AD4880_CHANNEL_DEFINE(20, 32, 0),
|
||||
AD4880_CHANNEL_DEFINE(20, 32, 1),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec ad4884_channels[] = {
|
||||
AD4880_CHANNEL_DEFINE(16, 16, 0),
|
||||
AD4880_CHANNEL_DEFINE(16, 16, 1),
|
||||
};
|
||||
|
||||
static const struct ad4080_chip_info ad4080_chip_info = {
|
||||
.name = "ad4080",
|
||||
|
|
@ -548,25 +637,44 @@ static const struct ad4080_chip_info ad4088_chip_info = {
|
|||
.lvds_cnv_clk_cnt_max = 8,
|
||||
};
|
||||
|
||||
static int ad4080_setup(struct iio_dev *indio_dev)
|
||||
static const struct ad4080_chip_info ad4880_chip_info = {
|
||||
.name = "ad4880",
|
||||
.product_id = AD4880_CHIP_ID,
|
||||
.scale_table = ad4080_scale_table,
|
||||
.num_scales = ARRAY_SIZE(ad4080_scale_table),
|
||||
.num_channels = 2,
|
||||
.channels = ad4880_channels,
|
||||
.lvds_cnv_clk_cnt_max = AD4080_LVDS_CNV_CLK_CNT_MAX,
|
||||
};
|
||||
|
||||
static const struct ad4080_chip_info ad4884_chip_info = {
|
||||
.name = "ad4884",
|
||||
.product_id = AD4884_CHIP_ID,
|
||||
.scale_table = ad4080_scale_table,
|
||||
.num_scales = ARRAY_SIZE(ad4080_scale_table),
|
||||
.num_channels = 2,
|
||||
.channels = ad4884_channels,
|
||||
.lvds_cnv_clk_cnt_max = 2,
|
||||
};
|
||||
|
||||
static int ad4080_setup_channel(struct ad4080_state *st, unsigned int ch)
|
||||
{
|
||||
struct ad4080_state *st = iio_priv(indio_dev);
|
||||
struct device *dev = regmap_get_device(st->regmap);
|
||||
struct device *dev = regmap_get_device(st->regmap[ch]);
|
||||
__le16 id_le;
|
||||
u16 id;
|
||||
int ret;
|
||||
|
||||
ret = regmap_write(st->regmap, AD4080_REG_INTERFACE_CONFIG_A,
|
||||
ret = regmap_write(st->regmap[ch], AD4080_REG_INTERFACE_CONFIG_A,
|
||||
AD4080_INTERFACE_CONFIG_A_SW_RESET);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_write(st->regmap, AD4080_REG_INTERFACE_CONFIG_A,
|
||||
ret = regmap_write(st->regmap[ch], AD4080_REG_INTERFACE_CONFIG_A,
|
||||
AD4080_INTERFACE_CONFIG_A_SDO_ENABLE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_bulk_read(st->regmap, AD4080_REG_PRODUCT_ID_L, &id_le,
|
||||
ret = regmap_bulk_read(st->regmap[ch], AD4080_REG_PRODUCT_ID_L, &id_le,
|
||||
sizeof(id_le));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -575,18 +683,18 @@ static int ad4080_setup(struct iio_dev *indio_dev)
|
|||
if (id != st->info->product_id)
|
||||
dev_info(dev, "Unrecognized CHIP_ID 0x%X\n", id);
|
||||
|
||||
ret = regmap_set_bits(st->regmap, AD4080_REG_GPIO_CONFIG_A,
|
||||
ret = regmap_set_bits(st->regmap[ch], AD4080_REG_GPIO_CONFIG_A,
|
||||
AD4080_GPIO_CONFIG_A_GPO_1_EN);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_write(st->regmap, AD4080_REG_GPIO_CONFIG_B,
|
||||
ret = regmap_write(st->regmap[ch], AD4080_REG_GPIO_CONFIG_B,
|
||||
FIELD_PREP(AD4080_GPIO_CONFIG_B_GPIO_1_SEL_MSK,
|
||||
AD4080_GPIO_CONFIG_B_GPIO_FILTER_RES_RDY));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iio_backend_num_lanes_set(st->back, st->num_lanes);
|
||||
ret = iio_backend_num_lanes_set(st->back[ch], st->num_lanes);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -594,7 +702,7 @@ static int ad4080_setup(struct iio_dev *indio_dev)
|
|||
return 0;
|
||||
|
||||
/* Set maximum LVDS Data Transfer Latency */
|
||||
ret = regmap_update_bits(st->regmap,
|
||||
ret = regmap_update_bits(st->regmap[ch],
|
||||
AD4080_REG_ADC_DATA_INTF_CONFIG_B,
|
||||
AD4080_ADC_DATA_INTF_CONFIG_B_LVDS_CNV_CLK_CNT_MSK,
|
||||
FIELD_PREP(AD4080_ADC_DATA_INTF_CONFIG_B_LVDS_CNV_CLK_CNT_MSK,
|
||||
|
|
@ -603,24 +711,38 @@ static int ad4080_setup(struct iio_dev *indio_dev)
|
|||
return ret;
|
||||
|
||||
if (st->num_lanes > 1) {
|
||||
ret = regmap_set_bits(st->regmap, AD4080_REG_ADC_DATA_INTF_CONFIG_A,
|
||||
ret = regmap_set_bits(st->regmap[ch], AD4080_REG_ADC_DATA_INTF_CONFIG_A,
|
||||
AD4080_ADC_DATA_INTF_CONFIG_A_SPI_LVDS_LANES);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_set_bits(st->regmap,
|
||||
ret = regmap_set_bits(st->regmap[ch],
|
||||
AD4080_REG_ADC_DATA_INTF_CONFIG_B,
|
||||
AD4080_ADC_DATA_INTF_CONFIG_B_LVDS_CNV_EN);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ad4080_lvds_sync_write(st);
|
||||
return ad4080_lvds_sync_write(st, ch);
|
||||
}
|
||||
|
||||
static int ad4080_properties_parse(struct ad4080_state *st)
|
||||
static int ad4080_setup(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct ad4080_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
for (unsigned int ch = 0; ch < st->info->num_channels; ch++) {
|
||||
ret = ad4080_setup_channel(st, ch);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ad4080_properties_parse(struct ad4080_state *st,
|
||||
struct device *dev)
|
||||
{
|
||||
struct device *dev = regmap_get_device(st->regmap);
|
||||
|
||||
st->lvds_cnv_en = device_property_read_bool(dev, "adi,lvds-cnv-enable");
|
||||
|
||||
|
|
@ -655,14 +777,28 @@ static int ad4080_probe(struct spi_device *spi)
|
|||
return dev_err_probe(dev, ret,
|
||||
"failed to get and enable supplies\n");
|
||||
|
||||
st->regmap = devm_regmap_init_spi(spi, &ad4080_regmap_config);
|
||||
if (IS_ERR(st->regmap))
|
||||
return PTR_ERR(st->regmap);
|
||||
/* Setup primary SPI device (channel 0) */
|
||||
st->spi[0] = spi;
|
||||
st->regmap[0] = devm_regmap_init_spi(spi, &ad4080_regmap_config);
|
||||
if (IS_ERR(st->regmap[0]))
|
||||
return PTR_ERR(st->regmap[0]);
|
||||
|
||||
st->info = spi_get_device_match_data(spi);
|
||||
if (!st->info)
|
||||
return -ENODEV;
|
||||
|
||||
/* Setup ancillary SPI devices for additional channels */
|
||||
for (unsigned int ch = 1; ch < st->info->num_channels; ch++) {
|
||||
st->spi[ch] = devm_spi_new_ancillary_device(spi, spi_get_chipselect(spi, ch));
|
||||
if (IS_ERR(st->spi[ch]))
|
||||
return dev_err_probe(dev, PTR_ERR(st->spi[ch]),
|
||||
"failed to register ancillary device\n");
|
||||
|
||||
st->regmap[ch] = devm_regmap_init_spi(st->spi[ch], &ad4080_regmap_config);
|
||||
if (IS_ERR(st->regmap[ch]))
|
||||
return PTR_ERR(st->regmap[ch]);
|
||||
}
|
||||
|
||||
ret = devm_mutex_init(dev, &st->lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -670,9 +806,10 @@ static int ad4080_probe(struct spi_device *spi)
|
|||
indio_dev->name = st->info->name;
|
||||
indio_dev->channels = st->info->channels;
|
||||
indio_dev->num_channels = st->info->num_channels;
|
||||
indio_dev->info = &ad4080_iio_info;
|
||||
indio_dev->info = st->info->num_channels > 1 ?
|
||||
&ad4880_iio_info : &ad4080_iio_info;
|
||||
|
||||
ret = ad4080_properties_parse(st);
|
||||
ret = ad4080_properties_parse(st, dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -682,15 +819,25 @@ static int ad4080_probe(struct spi_device *spi)
|
|||
|
||||
st->clk_rate = clk_get_rate(clk);
|
||||
|
||||
st->back = devm_iio_backend_get(dev, NULL);
|
||||
if (IS_ERR(st->back))
|
||||
return PTR_ERR(st->back);
|
||||
/* Get backends for all channels */
|
||||
for (unsigned int ch = 0; ch < st->info->num_channels; ch++) {
|
||||
st->back[ch] = devm_iio_backend_get_by_index(dev, ch);
|
||||
if (IS_ERR(st->back[ch]))
|
||||
return PTR_ERR(st->back[ch]);
|
||||
|
||||
ret = devm_iio_backend_request_buffer(dev, st->back, indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = devm_iio_backend_enable(dev, st->back[ch]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_iio_backend_enable(dev, st->back);
|
||||
/*
|
||||
* Request buffer from the first backend only. For multi-channel
|
||||
* devices (e.g., AD4880), the FPGA uses two axi_ad408x IP instances
|
||||
* (one per ADC channel) whose outputs are combined by a packer block
|
||||
* that interleaves all channel data into a single DMA stream routed
|
||||
* through the first backend's clock domain.
|
||||
*/
|
||||
ret = devm_iio_backend_request_buffer(dev, st->back[0], indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -711,6 +858,8 @@ static const struct spi_device_id ad4080_id[] = {
|
|||
{ "ad4086", (kernel_ulong_t)&ad4086_chip_info },
|
||||
{ "ad4087", (kernel_ulong_t)&ad4087_chip_info },
|
||||
{ "ad4088", (kernel_ulong_t)&ad4088_chip_info },
|
||||
{ "ad4880", (kernel_ulong_t)&ad4880_chip_info },
|
||||
{ "ad4884", (kernel_ulong_t)&ad4884_chip_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, ad4080_id);
|
||||
|
|
@ -725,6 +874,8 @@ static const struct of_device_id ad4080_of_match[] = {
|
|||
{ .compatible = "adi,ad4086", &ad4086_chip_info },
|
||||
{ .compatible = "adi,ad4087", &ad4087_chip_info },
|
||||
{ .compatible = "adi,ad4088", &ad4088_chip_info },
|
||||
{ .compatible = "adi,ad4880", &ad4880_chip_info },
|
||||
{ .compatible = "adi,ad4884", &ad4884_chip_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ad4080_of_match);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/cleanup.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
|
|
@ -21,6 +22,7 @@
|
|||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#include <asm/div64.h>
|
||||
|
|
@ -30,6 +32,9 @@
|
|||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/kfifo_buf.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/trigger.h>
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/iio/triggered_buffer.h>
|
||||
|
||||
#define AD4130_NAME "ad4130"
|
||||
|
||||
|
|
@ -40,6 +45,7 @@
|
|||
#define AD4130_ADC_CONTROL_REG 0x01
|
||||
#define AD4130_ADC_CONTROL_BIPOLAR_MASK BIT(14)
|
||||
#define AD4130_ADC_CONTROL_INT_REF_VAL_MASK BIT(13)
|
||||
#define AD4130_ADC_CONTROL_CONT_READ_MASK BIT(11)
|
||||
#define AD4130_INT_REF_2_5V 2500000
|
||||
#define AD4130_INT_REF_1_25V 1250000
|
||||
#define AD4130_ADC_CONTROL_CSB_EN_MASK BIT(9)
|
||||
|
|
@ -54,7 +60,9 @@
|
|||
#define AD4130_IO_CONTROL_REG 0x03
|
||||
#define AD4130_IO_CONTROL_INT_PIN_SEL_MASK GENMASK(9, 8)
|
||||
#define AD4130_IO_CONTROL_GPIO_DATA_MASK GENMASK(7, 4)
|
||||
#define AD4130_4_IO_CONTROL_GPIO_DATA_MASK GENMASK(7, 6)
|
||||
#define AD4130_IO_CONTROL_GPIO_CTRL_MASK GENMASK(3, 0)
|
||||
#define AD4130_4_IO_CONTROL_GPIO_CTRL_MASK GENMASK(3, 2)
|
||||
|
||||
#define AD4130_VBIAS_REG 0x04
|
||||
|
||||
|
|
@ -125,6 +133,28 @@
|
|||
|
||||
#define AD4130_INVALID_SLOT -1
|
||||
|
||||
static const unsigned int ad4129_reg_size[] = {
|
||||
[AD4130_STATUS_REG] = 1,
|
||||
[AD4130_ADC_CONTROL_REG] = 2,
|
||||
[AD4130_DATA_REG] = 2,
|
||||
[AD4130_IO_CONTROL_REG] = 2,
|
||||
[AD4130_VBIAS_REG] = 2,
|
||||
[AD4130_ID_REG] = 1,
|
||||
[AD4130_ERROR_REG] = 2,
|
||||
[AD4130_ERROR_EN_REG] = 2,
|
||||
[AD4130_MCLK_COUNT_REG] = 1,
|
||||
[AD4130_CHANNEL_X_REG(0) ... AD4130_CHANNEL_X_REG(AD4130_MAX_CHANNELS - 1)] = 3,
|
||||
[AD4130_CONFIG_X_REG(0) ... AD4130_CONFIG_X_REG(AD4130_MAX_SETUPS - 1)] = 2,
|
||||
[AD4130_FILTER_X_REG(0) ... AD4130_FILTER_X_REG(AD4130_MAX_SETUPS - 1)] = 3,
|
||||
[AD4130_OFFSET_X_REG(0) ... AD4130_OFFSET_X_REG(AD4130_MAX_SETUPS - 1)] = 2,
|
||||
[AD4130_GAIN_X_REG(0) ... AD4130_GAIN_X_REG(AD4130_MAX_SETUPS - 1)] = 2,
|
||||
[AD4130_MISC_REG] = 2,
|
||||
[AD4130_FIFO_CONTROL_REG] = 3,
|
||||
[AD4130_FIFO_STATUS_REG] = 1,
|
||||
[AD4130_FIFO_THRESHOLD_REG] = 3,
|
||||
[AD4130_FIFO_DATA_REG] = 2,
|
||||
};
|
||||
|
||||
static const unsigned int ad4130_reg_size[] = {
|
||||
[AD4130_STATUS_REG] = 1,
|
||||
[AD4130_ADC_CONTROL_REG] = 2,
|
||||
|
|
@ -147,6 +177,24 @@ static const unsigned int ad4130_reg_size[] = {
|
|||
[AD4130_FIFO_DATA_REG] = 3,
|
||||
};
|
||||
|
||||
static const unsigned int ad4131_reg_size[] = {
|
||||
[AD4130_STATUS_REG] = 1,
|
||||
[AD4130_ADC_CONTROL_REG] = 2,
|
||||
[AD4130_DATA_REG] = 2,
|
||||
[AD4130_IO_CONTROL_REG] = 2,
|
||||
[AD4130_VBIAS_REG] = 2,
|
||||
[AD4130_ID_REG] = 1,
|
||||
[AD4130_ERROR_REG] = 2,
|
||||
[AD4130_ERROR_EN_REG] = 2,
|
||||
[AD4130_MCLK_COUNT_REG] = 1,
|
||||
[AD4130_CHANNEL_X_REG(0) ... AD4130_CHANNEL_X_REG(AD4130_MAX_CHANNELS - 1)] = 3,
|
||||
[AD4130_CONFIG_X_REG(0) ... AD4130_CONFIG_X_REG(AD4130_MAX_SETUPS - 1)] = 2,
|
||||
[AD4130_FILTER_X_REG(0) ... AD4130_FILTER_X_REG(AD4130_MAX_SETUPS - 1)] = 3,
|
||||
[AD4130_OFFSET_X_REG(0) ... AD4130_OFFSET_X_REG(AD4130_MAX_SETUPS - 1)] = 2,
|
||||
[AD4130_GAIN_X_REG(0) ... AD4130_GAIN_X_REG(AD4130_MAX_SETUPS - 1)] = 2,
|
||||
[AD4130_MISC_REG] = 2,
|
||||
};
|
||||
|
||||
enum ad4130_int_ref_val {
|
||||
AD4130_INT_REF_VAL_2_5V,
|
||||
AD4130_INT_REF_VAL_1_25V,
|
||||
|
|
@ -224,6 +272,28 @@ enum ad4130_pin_function {
|
|||
AD4130_PIN_FN_VBIAS = BIT(3),
|
||||
};
|
||||
|
||||
/* Pin mapping for AIN0..AIN7, VBIAS_0..VBIAS_7 */
|
||||
static const u8 ad4130_4_pin_map[] = {
|
||||
0x00, 0x01, 0x04, 0x05, 0x0A, 0x0B, 0x0E, 0x0F, /* 0 - 7 */
|
||||
};
|
||||
|
||||
/* Pin mapping for AIN0..AIN15, VBIAS_0..VBIAS_15 */
|
||||
static const u8 ad4130_8_pin_map[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0 - 7 */
|
||||
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 8 - 15 */
|
||||
};
|
||||
|
||||
struct ad4130_chip_info {
|
||||
const char *name;
|
||||
unsigned int max_analog_pins;
|
||||
unsigned int num_gpios;
|
||||
const struct iio_info *info;
|
||||
const unsigned int *reg_size;
|
||||
const unsigned int reg_size_length;
|
||||
const u8 *pin_map;
|
||||
bool has_fifo;
|
||||
};
|
||||
|
||||
/*
|
||||
* If you make adaptations in this struct, you most likely also have to adapt
|
||||
* ad4130_setup_info_eq(), too.
|
||||
|
|
@ -268,6 +338,7 @@ struct ad4130_state {
|
|||
struct regmap *regmap;
|
||||
struct spi_device *spi;
|
||||
struct clk *mclk;
|
||||
const struct ad4130_chip_info *chip_info;
|
||||
struct regulator_bulk_data regulators[4];
|
||||
u32 irq_trigger;
|
||||
u32 inv_irq_trigger;
|
||||
|
|
@ -294,6 +365,7 @@ struct ad4130_state {
|
|||
u32 mclk_sel;
|
||||
bool int_ref_en;
|
||||
bool bipolar;
|
||||
bool buffer_wait_for_irq;
|
||||
|
||||
unsigned int num_enabled_channels;
|
||||
unsigned int effective_watermark;
|
||||
|
|
@ -301,6 +373,7 @@ struct ad4130_state {
|
|||
|
||||
struct spi_message fifo_msg;
|
||||
struct spi_transfer fifo_xfer[2];
|
||||
struct iio_trigger *trig;
|
||||
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) requires any transfer
|
||||
|
|
@ -312,9 +385,13 @@ struct ad4130_state {
|
|||
u8 reg_write_tx_buf[4];
|
||||
u8 reg_read_tx_buf[1];
|
||||
u8 reg_read_rx_buf[3];
|
||||
u8 fifo_tx_buf[2];
|
||||
u8 fifo_rx_buf[AD4130_FIFO_SIZE *
|
||||
AD4130_FIFO_MAX_SAMPLE_SIZE];
|
||||
union {
|
||||
struct {
|
||||
u8 fifo_tx_buf[2];
|
||||
u8 fifo_rx_buf[AD4130_FIFO_SIZE * AD4130_FIFO_MAX_SAMPLE_SIZE];
|
||||
};
|
||||
IIO_DECLARE_BUFFER_WITH_TS(u32, scan_channels, AD4130_MAX_CHANNELS);
|
||||
};
|
||||
};
|
||||
|
||||
static const char * const ad4130_int_pin_names[] = {
|
||||
|
|
@ -394,10 +471,10 @@ static const char * const ad4130_filter_types_str[] = {
|
|||
static int ad4130_get_reg_size(struct ad4130_state *st, unsigned int reg,
|
||||
unsigned int *size)
|
||||
{
|
||||
if (reg >= ARRAY_SIZE(ad4130_reg_size))
|
||||
if (reg >= st->chip_info->reg_size_length)
|
||||
return -EINVAL;
|
||||
|
||||
*size = ad4130_reg_size[reg];
|
||||
*size = st->chip_info->reg_size[reg];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -505,7 +582,8 @@ static int ad4130_gpio_init_valid_mask(struct gpio_chip *gc,
|
|||
|
||||
/*
|
||||
* Output-only GPIO functionality is available on pins AIN2 through
|
||||
* AIN5. If these pins are used for anything else, do not expose them.
|
||||
* AIN5 for some parts and AIN2 through AIN3 for others. If these pins
|
||||
* are used for anything else, do not expose them.
|
||||
*/
|
||||
for (i = 0; i < ngpios; i++) {
|
||||
unsigned int pin = i + AD4130_AIN2_P1;
|
||||
|
|
@ -526,8 +604,14 @@ 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));
|
||||
unsigned int mask;
|
||||
|
||||
if (st->chip_info->num_gpios == AD4130_MAX_GPIOS)
|
||||
mask = FIELD_PREP(AD4130_IO_CONTROL_GPIO_DATA_MASK,
|
||||
BIT(offset));
|
||||
else
|
||||
mask = FIELD_PREP(AD4130_4_IO_CONTROL_GPIO_DATA_MASK,
|
||||
BIT(offset));
|
||||
|
||||
return regmap_update_bits(st->regmap, AD4130_IO_CONTROL_REG, mask,
|
||||
value ? mask : 0);
|
||||
|
|
@ -588,10 +672,43 @@ static irqreturn_t ad4130_irq_handler(int irq, void *private)
|
|||
struct iio_dev *indio_dev = private;
|
||||
struct ad4130_state *st = iio_priv(indio_dev);
|
||||
|
||||
if (iio_buffer_enabled(indio_dev))
|
||||
ad4130_push_fifo_data(indio_dev);
|
||||
else
|
||||
if (iio_buffer_enabled(indio_dev)) {
|
||||
if (st->chip_info->has_fifo)
|
||||
ad4130_push_fifo_data(indio_dev);
|
||||
else if (st->buffer_wait_for_irq)
|
||||
complete(&st->completion);
|
||||
else
|
||||
iio_trigger_poll(st->trig);
|
||||
} else {
|
||||
complete(&st->completion);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t ad4130_trigger_handler(int irq, void *p)
|
||||
{
|
||||
struct iio_poll_func *pf = p;
|
||||
struct iio_dev *indio_dev = pf->indio_dev;
|
||||
struct ad4130_state *st = iio_priv(indio_dev);
|
||||
unsigned int data_reg_size = ad4130_data_reg_size(st);
|
||||
struct spi_transfer xfer = { };
|
||||
unsigned int num_en_chn;
|
||||
int ret;
|
||||
|
||||
num_en_chn = bitmap_weight(indio_dev->active_scan_mask,
|
||||
iio_get_masklength(indio_dev));
|
||||
xfer.rx_buf = st->scan_channels;
|
||||
xfer.len = data_reg_size * num_en_chn;
|
||||
ret = spi_sync_transfer(st->spi, &xfer, 1);
|
||||
if (ret < 0)
|
||||
goto err_out;
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &st->scan_channels,
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
err_out:
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
|
@ -1291,6 +1408,79 @@ static const struct iio_info ad4130_info = {
|
|||
.debugfs_reg_access = ad4130_reg_access,
|
||||
};
|
||||
|
||||
static const struct iio_info ad4131_info = {
|
||||
.read_raw = ad4130_read_raw,
|
||||
.read_avail = ad4130_read_avail,
|
||||
.write_raw_get_fmt = ad4130_write_raw_get_fmt,
|
||||
.write_raw = ad4130_write_raw,
|
||||
.update_scan_mode = ad4130_update_scan_mode,
|
||||
.debugfs_reg_access = ad4130_reg_access,
|
||||
};
|
||||
|
||||
static const struct ad4130_chip_info ad4129_4_chip_info = {
|
||||
.name = "ad4129-4",
|
||||
.max_analog_pins = 8,
|
||||
.num_gpios = 2,
|
||||
.info = &ad4130_info,
|
||||
.reg_size = ad4129_reg_size,
|
||||
.reg_size_length = ARRAY_SIZE(ad4129_reg_size),
|
||||
.has_fifo = true,
|
||||
.pin_map = ad4130_4_pin_map,
|
||||
};
|
||||
|
||||
static const struct ad4130_chip_info ad4129_8_chip_info = {
|
||||
.name = "ad4129-8",
|
||||
.max_analog_pins = 16,
|
||||
.num_gpios = 4,
|
||||
.info = &ad4130_info,
|
||||
.reg_size = ad4129_reg_size,
|
||||
.reg_size_length = ARRAY_SIZE(ad4129_reg_size),
|
||||
.has_fifo = true,
|
||||
.pin_map = ad4130_8_pin_map,
|
||||
};
|
||||
|
||||
static const struct ad4130_chip_info ad4130_4_chip_info = {
|
||||
.name = "ad4130-4",
|
||||
.max_analog_pins = 16,
|
||||
.num_gpios = 2,
|
||||
.info = &ad4130_info,
|
||||
.reg_size = ad4130_reg_size,
|
||||
.reg_size_length = ARRAY_SIZE(ad4130_reg_size),
|
||||
.has_fifo = true,
|
||||
.pin_map = ad4130_4_pin_map,
|
||||
};
|
||||
|
||||
static const struct ad4130_chip_info ad4130_8_chip_info = {
|
||||
.name = "ad4130-8",
|
||||
.max_analog_pins = 16,
|
||||
.num_gpios = 4,
|
||||
.info = &ad4130_info,
|
||||
.reg_size = ad4130_reg_size,
|
||||
.reg_size_length = ARRAY_SIZE(ad4130_reg_size),
|
||||
.has_fifo = true,
|
||||
.pin_map = ad4130_8_pin_map,
|
||||
};
|
||||
|
||||
static const struct ad4130_chip_info ad4131_4_chip_info = {
|
||||
.name = "ad4131-4",
|
||||
.max_analog_pins = 8,
|
||||
.num_gpios = 2,
|
||||
.info = &ad4131_info,
|
||||
.reg_size = ad4131_reg_size,
|
||||
.reg_size_length = ARRAY_SIZE(ad4131_reg_size),
|
||||
.pin_map = ad4130_4_pin_map,
|
||||
};
|
||||
|
||||
static const struct ad4130_chip_info ad4131_8_chip_info = {
|
||||
.name = "ad4131-8",
|
||||
.max_analog_pins = 16,
|
||||
.num_gpios = 4,
|
||||
.info = &ad4131_info,
|
||||
.reg_size = ad4131_reg_size,
|
||||
.reg_size_length = ARRAY_SIZE(ad4131_reg_size),
|
||||
.pin_map = ad4130_8_pin_map,
|
||||
};
|
||||
|
||||
static int ad4130_buffer_postenable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct ad4130_state *st = iio_priv(indio_dev);
|
||||
|
|
@ -1298,44 +1488,89 @@ static int ad4130_buffer_postenable(struct iio_dev *indio_dev)
|
|||
|
||||
guard(mutex)(&st->lock);
|
||||
|
||||
ret = ad4130_set_watermark_interrupt_en(st, true);
|
||||
if (st->chip_info->has_fifo) {
|
||||
ret = ad4130_set_watermark_interrupt_en(st, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = irq_set_irq_type(st->spi->irq, st->inv_irq_trigger);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_WM);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ad4130_set_mode(st, AD4130_MODE_CONTINUOUS);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = irq_set_irq_type(st->spi->irq, st->inv_irq_trigger);
|
||||
if (ret)
|
||||
return ret;
|
||||
/*
|
||||
* When using triggered buffer, Entering continuous read mode must
|
||||
* be the last command sent. No configuration changes are allowed until
|
||||
* exiting this mode.
|
||||
*/
|
||||
if (!st->chip_info->has_fifo) {
|
||||
ret = regmap_update_bits(st->regmap, AD4130_ADC_CONTROL_REG,
|
||||
AD4130_ADC_CONTROL_CONT_READ_MASK,
|
||||
FIELD_PREP(AD4130_ADC_CONTROL_CONT_READ_MASK, 1));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_WM);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ad4130_set_mode(st, AD4130_MODE_CONTINUOUS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ad4130_buffer_predisable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct ad4130_state *st = iio_priv(indio_dev);
|
||||
unsigned int i;
|
||||
u32 temp;
|
||||
int ret;
|
||||
|
||||
guard(mutex)(&st->lock);
|
||||
|
||||
if (!st->chip_info->has_fifo) {
|
||||
temp = 0x42;
|
||||
reinit_completion(&st->completion);
|
||||
|
||||
/*
|
||||
* In continuous read mode, when all samples are read, the data
|
||||
* ready signal returns high until the next conversion result is
|
||||
* ready. To exit this mode, the command must be sent when data
|
||||
* ready is low. In order to ensure that condition, wait for the
|
||||
* next interrupt (when the new conversion is finished), allowing
|
||||
* data ready to return low before sending the exit command.
|
||||
*/
|
||||
st->buffer_wait_for_irq = true;
|
||||
if (!wait_for_completion_timeout(&st->completion, msecs_to_jiffies(1000)))
|
||||
dev_warn(&st->spi->dev, "Conversion timed out\n");
|
||||
st->buffer_wait_for_irq = false;
|
||||
|
||||
/* Perform a read data command to exit continuous read mode (0x42) */
|
||||
ret = spi_write(st->spi, &temp, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ad4130_set_mode(st, AD4130_MODE_IDLE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = irq_set_irq_type(st->spi->irq, st->irq_trigger);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (st->chip_info->has_fifo) {
|
||||
ret = irq_set_irq_type(st->spi->irq, st->irq_trigger);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_DISABLED);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_DISABLED);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ad4130_set_watermark_interrupt_en(st, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = ad4130_set_watermark_interrupt_en(st, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* update_scan_mode() is not called in the disable path, disable all
|
||||
|
|
@ -1410,6 +1645,34 @@ static const struct iio_dev_attr *ad4130_fifo_attributes[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static const struct iio_trigger_ops ad4130_trigger_ops = {
|
||||
.validate_device = iio_trigger_validate_own_device,
|
||||
};
|
||||
|
||||
static int ad4130_triggered_buffer_setup(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct ad4130_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 = &ad4130_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,
|
||||
&ad4130_trigger_handler,
|
||||
&ad4130_buffer_ops);
|
||||
}
|
||||
|
||||
static int _ad4130_find_table_index(const unsigned int *tbl, size_t len,
|
||||
unsigned int val)
|
||||
{
|
||||
|
|
@ -1496,6 +1759,17 @@ static int ad4130_parse_fw_setup(struct ad4130_state *st,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int ad4130_translate_pin(struct ad4130_state *st,
|
||||
unsigned int logical_pin)
|
||||
{
|
||||
/* For analog input pins, use the chip-specific pin mapping */
|
||||
if (logical_pin < st->chip_info->max_analog_pins)
|
||||
return st->chip_info->pin_map[logical_pin];
|
||||
|
||||
/* For internal channels, pass through unchanged */
|
||||
return logical_pin;
|
||||
}
|
||||
|
||||
static int ad4130_validate_diff_channel(struct ad4130_state *st, u32 pin)
|
||||
{
|
||||
struct device *dev = &st->spi->dev;
|
||||
|
|
@ -1504,7 +1778,7 @@ static int ad4130_validate_diff_channel(struct ad4130_state *st, u32 pin)
|
|||
return dev_err_probe(dev, -EINVAL,
|
||||
"Invalid differential channel %u\n", pin);
|
||||
|
||||
if (pin >= AD4130_MAX_ANALOG_PINS)
|
||||
if (pin >= st->chip_info->max_analog_pins)
|
||||
return 0;
|
||||
|
||||
if (st->pins_fn[pin] == AD4130_PIN_FN_SPECIAL)
|
||||
|
|
@ -1536,7 +1810,7 @@ static int ad4130_validate_excitation_pin(struct ad4130_state *st, u32 pin)
|
|||
{
|
||||
struct device *dev = &st->spi->dev;
|
||||
|
||||
if (pin >= AD4130_MAX_ANALOG_PINS)
|
||||
if (pin >= st->chip_info->max_analog_pins)
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"Invalid excitation pin %u\n", pin);
|
||||
|
||||
|
|
@ -1554,7 +1828,7 @@ static int ad4130_validate_vbias_pin(struct ad4130_state *st, u32 pin)
|
|||
{
|
||||
struct device *dev = &st->spi->dev;
|
||||
|
||||
if (pin >= AD4130_MAX_ANALOG_PINS)
|
||||
if (pin >= st->chip_info->max_analog_pins)
|
||||
return dev_err_probe(dev, -EINVAL, "Invalid vbias pin %u\n",
|
||||
pin);
|
||||
|
||||
|
|
@ -1730,7 +2004,7 @@ static int ad4310_parse_fw(struct iio_dev *indio_dev)
|
|||
|
||||
ret = device_property_count_u32(dev, "adi,vbias-pins");
|
||||
if (ret > 0) {
|
||||
if (ret > AD4130_MAX_ANALOG_PINS)
|
||||
if (ret > st->chip_info->max_analog_pins)
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"Too many vbias pins %u\n", ret);
|
||||
|
||||
|
|
@ -1914,9 +2188,14 @@ static int ad4130_setup(struct iio_dev *indio_dev)
|
|||
* function of P2 takes priority over the GPIO out function.
|
||||
*/
|
||||
val = 0;
|
||||
for (i = 0; i < AD4130_MAX_GPIOS; i++)
|
||||
if (st->pins_fn[i + AD4130_AIN2_P1] == AD4130_PIN_FN_NONE)
|
||||
val |= FIELD_PREP(AD4130_IO_CONTROL_GPIO_CTRL_MASK, BIT(i));
|
||||
for (i = 0; i < st->chip_info->num_gpios; i++) {
|
||||
if (st->pins_fn[i + AD4130_AIN2_P1] == AD4130_PIN_FN_NONE) {
|
||||
if (st->chip_info->num_gpios == 2)
|
||||
val |= FIELD_PREP(AD4130_4_IO_CONTROL_GPIO_CTRL_MASK, BIT(i));
|
||||
else
|
||||
val |= FIELD_PREP(AD4130_IO_CONTROL_GPIO_CTRL_MASK, BIT(i));
|
||||
}
|
||||
}
|
||||
|
||||
val |= FIELD_PREP(AD4130_IO_CONTROL_INT_PIN_SEL_MASK, st->int_pin_sel);
|
||||
|
||||
|
|
@ -1926,21 +2205,23 @@ static int ad4130_setup(struct iio_dev *indio_dev)
|
|||
|
||||
val = 0;
|
||||
for (i = 0; i < st->num_vbias_pins; i++)
|
||||
val |= BIT(st->vbias_pins[i]);
|
||||
val |= BIT(ad4130_translate_pin(st, st->vbias_pins[i]));
|
||||
|
||||
ret = regmap_write(st->regmap, AD4130_VBIAS_REG, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_clear_bits(st->regmap, AD4130_FIFO_CONTROL_REG,
|
||||
AD4130_FIFO_CONTROL_HEADER_MASK);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (st->chip_info->has_fifo) {
|
||||
ret = regmap_clear_bits(st->regmap, AD4130_FIFO_CONTROL_REG,
|
||||
AD4130_FIFO_CONTROL_HEADER_MASK);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* FIFO watermark interrupt starts out as enabled, disable it. */
|
||||
ret = ad4130_set_watermark_interrupt_en(st, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* FIFO watermark interrupt starts out as enabled, disable it. */
|
||||
ret = ad4130_set_watermark_interrupt_en(st, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Setup channels. */
|
||||
for (i = 0; i < indio_dev->num_channels; i++) {
|
||||
|
|
@ -1948,10 +2229,14 @@ static int ad4130_setup(struct iio_dev *indio_dev)
|
|||
struct iio_chan_spec *chan = &st->chans[i];
|
||||
unsigned int val;
|
||||
|
||||
val = FIELD_PREP(AD4130_CHANNEL_AINP_MASK, chan->channel) |
|
||||
FIELD_PREP(AD4130_CHANNEL_AINM_MASK, chan->channel2) |
|
||||
FIELD_PREP(AD4130_CHANNEL_IOUT1_MASK, chan_info->iout0) |
|
||||
FIELD_PREP(AD4130_CHANNEL_IOUT2_MASK, chan_info->iout1);
|
||||
val = FIELD_PREP(AD4130_CHANNEL_AINP_MASK,
|
||||
ad4130_translate_pin(st, chan->channel)) |
|
||||
FIELD_PREP(AD4130_CHANNEL_AINM_MASK,
|
||||
ad4130_translate_pin(st, chan->channel2)) |
|
||||
FIELD_PREP(AD4130_CHANNEL_IOUT1_MASK,
|
||||
ad4130_translate_pin(st, chan_info->iout0)) |
|
||||
FIELD_PREP(AD4130_CHANNEL_IOUT2_MASK,
|
||||
ad4130_translate_pin(st, chan_info->iout1));
|
||||
|
||||
ret = regmap_write(st->regmap, AD4130_CHANNEL_X_REG(i), val);
|
||||
if (ret)
|
||||
|
|
@ -1994,26 +2279,30 @@ static int ad4130_probe(struct spi_device *spi)
|
|||
|
||||
st = iio_priv(indio_dev);
|
||||
|
||||
st->chip_info = device_get_match_data(dev);
|
||||
|
||||
memset(st->reset_buf, 0xff, sizeof(st->reset_buf));
|
||||
init_completion(&st->completion);
|
||||
mutex_init(&st->lock);
|
||||
st->spi = spi;
|
||||
|
||||
/*
|
||||
* Xfer: [ XFR1 ] [ XFR2 ]
|
||||
* Master: 0x7D N ......................
|
||||
* Slave: ...... DATA1 DATA2 ... DATAN
|
||||
*/
|
||||
st->fifo_tx_buf[0] = AD4130_COMMS_READ_MASK | AD4130_FIFO_DATA_REG;
|
||||
st->fifo_xfer[0].tx_buf = st->fifo_tx_buf;
|
||||
st->fifo_xfer[0].len = sizeof(st->fifo_tx_buf);
|
||||
st->fifo_xfer[1].rx_buf = st->fifo_rx_buf;
|
||||
spi_message_init_with_transfers(&st->fifo_msg, st->fifo_xfer,
|
||||
ARRAY_SIZE(st->fifo_xfer));
|
||||
if (st->chip_info->has_fifo) {
|
||||
/*
|
||||
* Xfer: [ XFR1 ] [ XFR2 ]
|
||||
* Master: 0x7D N ......................
|
||||
* Slave: ...... DATA1 DATA2 ... DATAN
|
||||
*/
|
||||
st->fifo_tx_buf[0] = AD4130_COMMS_READ_MASK | AD4130_FIFO_DATA_REG;
|
||||
st->fifo_xfer[0].tx_buf = st->fifo_tx_buf;
|
||||
st->fifo_xfer[0].len = sizeof(st->fifo_tx_buf);
|
||||
st->fifo_xfer[1].rx_buf = st->fifo_rx_buf;
|
||||
spi_message_init_with_transfers(&st->fifo_msg, st->fifo_xfer,
|
||||
ARRAY_SIZE(st->fifo_xfer));
|
||||
}
|
||||
|
||||
indio_dev->name = AD4130_NAME;
|
||||
indio_dev->name = st->chip_info->name;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->info = &ad4130_info;
|
||||
indio_dev->info = st->chip_info->info;
|
||||
|
||||
st->regmap = devm_regmap_init(dev, NULL, st, &ad4130_regmap_config);
|
||||
if (IS_ERR(st->regmap))
|
||||
|
|
@ -2056,9 +2345,9 @@ static int ad4130_probe(struct spi_device *spi)
|
|||
ad4130_fill_scale_tbls(st);
|
||||
|
||||
st->gc.owner = THIS_MODULE;
|
||||
st->gc.label = AD4130_NAME;
|
||||
st->gc.label = st->chip_info->name;
|
||||
st->gc.base = -1;
|
||||
st->gc.ngpio = AD4130_MAX_GPIOS;
|
||||
st->gc.ngpio = st->chip_info->num_gpios;
|
||||
st->gc.parent = dev;
|
||||
st->gc.can_sleep = true;
|
||||
st->gc.init_valid_mask = ad4130_gpio_init_valid_mask;
|
||||
|
|
@ -2069,9 +2358,12 @@ static int ad4130_probe(struct spi_device *spi)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_iio_kfifo_buffer_setup_ext(dev, indio_dev,
|
||||
&ad4130_buffer_ops,
|
||||
ad4130_fifo_attributes);
|
||||
if (st->chip_info->has_fifo)
|
||||
ret = devm_iio_kfifo_buffer_setup_ext(dev, indio_dev,
|
||||
&ad4130_buffer_ops,
|
||||
ad4130_fifo_attributes);
|
||||
else
|
||||
ret = ad4130_triggered_buffer_setup(indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -2081,40 +2373,75 @@ static int ad4130_probe(struct spi_device *spi)
|
|||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to request irq\n");
|
||||
|
||||
/*
|
||||
* When the chip enters FIFO mode, IRQ polarity is inverted.
|
||||
* When the chip exits FIFO mode, IRQ polarity returns to normal.
|
||||
* See datasheet pages: 65, FIFO Watermark Interrupt section,
|
||||
* and 71, Bit Descriptions for STATUS Register, RDYB.
|
||||
* Cache the normal and inverted IRQ triggers to set them when
|
||||
* entering and exiting FIFO mode.
|
||||
*/
|
||||
st->irq_trigger = irq_get_trigger_type(spi->irq);
|
||||
if (st->irq_trigger & IRQF_TRIGGER_RISING)
|
||||
st->inv_irq_trigger = IRQF_TRIGGER_FALLING;
|
||||
else if (st->irq_trigger & IRQF_TRIGGER_FALLING)
|
||||
st->inv_irq_trigger = IRQF_TRIGGER_RISING;
|
||||
else
|
||||
return dev_err_probe(dev, -EINVAL, "Invalid irq flags: %u\n",
|
||||
st->irq_trigger);
|
||||
if (st->chip_info->has_fifo) {
|
||||
/*
|
||||
* When the chip enters FIFO mode, IRQ polarity is inverted.
|
||||
* When the chip exits FIFO mode, IRQ polarity returns to normal.
|
||||
* See datasheet pages: 65, FIFO Watermark Interrupt section,
|
||||
* and 71, Bit Descriptions for STATUS Register, RDYB.
|
||||
* Cache the normal and inverted IRQ triggers to set them when
|
||||
* entering and exiting FIFO mode.
|
||||
*/
|
||||
st->irq_trigger = irq_get_trigger_type(spi->irq);
|
||||
if (st->irq_trigger & IRQF_TRIGGER_RISING)
|
||||
st->inv_irq_trigger = IRQF_TRIGGER_FALLING;
|
||||
else if (st->irq_trigger & IRQF_TRIGGER_FALLING)
|
||||
st->inv_irq_trigger = IRQF_TRIGGER_RISING;
|
||||
else
|
||||
return dev_err_probe(dev, -EINVAL, "Invalid irq flags: %u\n",
|
||||
st->irq_trigger);
|
||||
}
|
||||
|
||||
return devm_iio_device_register(dev, indio_dev);
|
||||
}
|
||||
|
||||
static const struct of_device_id ad4130_of_match[] = {
|
||||
{
|
||||
.compatible = "adi,ad4129-4",
|
||||
.data = &ad4129_4_chip_info
|
||||
},
|
||||
{
|
||||
.compatible = "adi,ad4129-8",
|
||||
.data = &ad4129_8_chip_info
|
||||
},
|
||||
{
|
||||
.compatible = "adi,ad4130-4",
|
||||
.data = &ad4130_4_chip_info
|
||||
},
|
||||
{
|
||||
.compatible = "adi,ad4130",
|
||||
.data = &ad4130_8_chip_info
|
||||
},
|
||||
{
|
||||
.compatible = "adi,ad4131-4",
|
||||
.data = &ad4131_4_chip_info
|
||||
},
|
||||
{
|
||||
.compatible = "adi,ad4131-8",
|
||||
.data = &ad4131_8_chip_info
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ad4130_of_match);
|
||||
|
||||
static const struct spi_device_id ad4130_id_table[] = {
|
||||
{ "ad4129-4", (kernel_ulong_t)&ad4129_4_chip_info },
|
||||
{ "ad4129-8", (kernel_ulong_t)&ad4129_8_chip_info },
|
||||
{ "ad4130-4", (kernel_ulong_t)&ad4130_4_chip_info },
|
||||
{ "ad4130", (kernel_ulong_t)&ad4130_8_chip_info },
|
||||
{ "ad4131-4", (kernel_ulong_t)&ad4131_4_chip_info },
|
||||
{ "ad4131-8", (kernel_ulong_t)&ad4131_8_chip_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, ad4130_id_table);
|
||||
|
||||
static struct spi_driver ad4130_driver = {
|
||||
.driver = {
|
||||
.name = AD4130_NAME,
|
||||
.of_match_table = ad4130_of_match,
|
||||
},
|
||||
.probe = ad4130_probe,
|
||||
.id_table = ad4130_id_table,
|
||||
};
|
||||
module_spi_driver(ad4130_driver);
|
||||
|
||||
|
|
|
|||
|
|
@ -1699,34 +1699,29 @@ static int ad4170_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static const unsigned long gpio_masks[] = {
|
||||
AD4170_GPIO_MODE_GPIO0_MSK,
|
||||
AD4170_GPIO_MODE_GPIO1_MSK,
|
||||
AD4170_GPIO_MODE_GPIO2_MSK,
|
||||
AD4170_GPIO_MODE_GPIO3_MSK,
|
||||
};
|
||||
|
||||
static int ad4170_gpio_direction_input(struct gpio_chip *gc, unsigned int offset)
|
||||
{
|
||||
struct iio_dev *indio_dev = gpiochip_get_data(gc);
|
||||
struct ad4170_state *st = iio_priv(indio_dev);
|
||||
unsigned long gpio_mask;
|
||||
int ret;
|
||||
|
||||
if (!iio_device_claim_direct(indio_dev))
|
||||
return -EBUSY;
|
||||
|
||||
switch (offset) {
|
||||
case 0:
|
||||
gpio_mask = AD4170_GPIO_MODE_GPIO0_MSK;
|
||||
break;
|
||||
case 1:
|
||||
gpio_mask = AD4170_GPIO_MODE_GPIO1_MSK;
|
||||
break;
|
||||
case 2:
|
||||
gpio_mask = AD4170_GPIO_MODE_GPIO2_MSK;
|
||||
break;
|
||||
case 3:
|
||||
gpio_mask = AD4170_GPIO_MODE_GPIO3_MSK;
|
||||
break;
|
||||
default:
|
||||
if (offset >= ARRAY_SIZE(gpio_masks)) {
|
||||
ret = -EINVAL;
|
||||
goto err_release;
|
||||
}
|
||||
ret = regmap_update_bits(st->regmap, AD4170_GPIO_MODE_REG, gpio_mask,
|
||||
|
||||
ret = regmap_update_bits(st->regmap, AD4170_GPIO_MODE_REG,
|
||||
gpio_masks[offset],
|
||||
AD4170_GPIO_MODE_GPIO_INPUT << (2 * offset));
|
||||
|
||||
err_release:
|
||||
|
|
@ -1740,7 +1735,6 @@ static int ad4170_gpio_direction_output(struct gpio_chip *gc,
|
|||
{
|
||||
struct iio_dev *indio_dev = gpiochip_get_data(gc);
|
||||
struct ad4170_state *st = iio_priv(indio_dev);
|
||||
unsigned long gpio_mask;
|
||||
int ret;
|
||||
|
||||
ret = ad4170_gpio_set(gc, offset, value);
|
||||
|
|
@ -1750,24 +1744,13 @@ static int ad4170_gpio_direction_output(struct gpio_chip *gc,
|
|||
if (!iio_device_claim_direct(indio_dev))
|
||||
return -EBUSY;
|
||||
|
||||
switch (offset) {
|
||||
case 0:
|
||||
gpio_mask = AD4170_GPIO_MODE_GPIO0_MSK;
|
||||
break;
|
||||
case 1:
|
||||
gpio_mask = AD4170_GPIO_MODE_GPIO1_MSK;
|
||||
break;
|
||||
case 2:
|
||||
gpio_mask = AD4170_GPIO_MODE_GPIO2_MSK;
|
||||
break;
|
||||
case 3:
|
||||
gpio_mask = AD4170_GPIO_MODE_GPIO3_MSK;
|
||||
break;
|
||||
default:
|
||||
if (offset >= ARRAY_SIZE(gpio_masks)) {
|
||||
ret = -EINVAL;
|
||||
goto err_release;
|
||||
}
|
||||
ret = regmap_update_bits(st->regmap, AD4170_GPIO_MODE_REG, gpio_mask,
|
||||
|
||||
ret = regmap_update_bits(st->regmap, AD4170_GPIO_MODE_REG,
|
||||
gpio_masks[offset],
|
||||
AD4170_GPIO_MODE_GPIO_OUTPUT << (2 * offset));
|
||||
|
||||
err_release:
|
||||
|
|
|
|||
2084
drivers/iio/adc/ad4691.c
Normal file
2084
drivers/iio/adc/ad4691.c
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -101,23 +101,17 @@ static const struct ad7091r_init_info ad7091r5_init_info = {
|
|||
|
||||
static int ad7091r5_i2c_probe(struct i2c_client *i2c)
|
||||
{
|
||||
const struct ad7091r_init_info *init_info;
|
||||
|
||||
init_info = i2c_get_match_data(i2c);
|
||||
if (!init_info)
|
||||
return -EINVAL;
|
||||
|
||||
return ad7091r_probe(&i2c->dev, init_info, i2c->irq);
|
||||
return ad7091r_probe(&i2c->dev, &ad7091r5_init_info, i2c->irq);
|
||||
}
|
||||
|
||||
static const struct of_device_id ad7091r5_dt_ids[] = {
|
||||
{ .compatible = "adi,ad7091r5", .data = &ad7091r5_init_info },
|
||||
{ .compatible = "adi,ad7091r5" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ad7091r5_dt_ids);
|
||||
|
||||
static const struct i2c_device_id ad7091r5_i2c_ids[] = {
|
||||
{ "ad7091r5", (kernel_ulong_t)&ad7091r5_init_info },
|
||||
{ .name = "ad7091r5" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ad7091r5_i2c_ids);
|
||||
|
|
|
|||
|
|
@ -154,27 +154,18 @@ static int ad7191_config_setup(struct iio_dev *indio_dev)
|
|||
const u32 gain[4] = { 1, 8, 64, 128 };
|
||||
static u32 scale_buffer[4][2];
|
||||
int odr_value, odr_index = 0, pga_value, pga_index = 0, i, ret;
|
||||
const char *propname;
|
||||
u64 scale_uv;
|
||||
|
||||
st->samp_freq_index = 0;
|
||||
st->scale_index = 0;
|
||||
|
||||
ret = device_property_read_u32(dev, "adi,odr-value", &odr_value);
|
||||
if (ret && ret != -EINVAL)
|
||||
return dev_err_probe(dev, ret, "Failed to get odr value.\n");
|
||||
propname = "adi,odr-value";
|
||||
if (device_property_present(dev, propname)) {
|
||||
ret = device_property_read_u32(dev, propname, &odr_value);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to get %s.\n", propname);
|
||||
|
||||
if (ret == -EINVAL) {
|
||||
st->odr_gpios = devm_gpiod_get_array(dev, "odr", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(st->odr_gpios))
|
||||
return dev_err_probe(dev, PTR_ERR(st->odr_gpios),
|
||||
"Failed to get odr gpios.\n");
|
||||
|
||||
if (st->odr_gpios->ndescs != 2)
|
||||
return dev_err_probe(dev, -EINVAL, "Expected 2 odr gpio pins.\n");
|
||||
|
||||
st->samp_freq_avail = samp_freq;
|
||||
st->samp_freq_avail_size = ARRAY_SIZE(samp_freq);
|
||||
} else {
|
||||
for (i = 0; i < ARRAY_SIZE(samp_freq); i++) {
|
||||
if (odr_value != samp_freq[i])
|
||||
continue;
|
||||
|
|
@ -186,6 +177,17 @@ static int ad7191_config_setup(struct iio_dev *indio_dev)
|
|||
st->samp_freq_avail_size = 1;
|
||||
|
||||
st->odr_gpios = NULL;
|
||||
} else {
|
||||
st->odr_gpios = devm_gpiod_get_array(dev, "odr", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(st->odr_gpios))
|
||||
return dev_err_probe(dev, PTR_ERR(st->odr_gpios),
|
||||
"Failed to get odr gpios.\n");
|
||||
|
||||
if (st->odr_gpios->ndescs != 2)
|
||||
return dev_err_probe(dev, -EINVAL, "Expected 2 odr gpio pins.\n");
|
||||
|
||||
st->samp_freq_avail = samp_freq;
|
||||
st->samp_freq_avail_size = ARRAY_SIZE(samp_freq);
|
||||
}
|
||||
|
||||
mutex_lock(&st->lock);
|
||||
|
|
@ -200,22 +202,12 @@ static int ad7191_config_setup(struct iio_dev *indio_dev)
|
|||
|
||||
mutex_unlock(&st->lock);
|
||||
|
||||
ret = device_property_read_u32(dev, "adi,pga-value", &pga_value);
|
||||
if (ret && ret != -EINVAL)
|
||||
return dev_err_probe(dev, ret, "Failed to get pga value.\n");
|
||||
propname = "adi,pga-value";
|
||||
if (device_property_present(dev, propname)) {
|
||||
ret = device_property_read_u32(dev, propname, &pga_value);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to get %s.\n", propname);
|
||||
|
||||
if (ret == -EINVAL) {
|
||||
st->pga_gpios = devm_gpiod_get_array(dev, "pga", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(st->pga_gpios))
|
||||
return dev_err_probe(dev, PTR_ERR(st->pga_gpios),
|
||||
"Failed to get pga gpios.\n");
|
||||
|
||||
if (st->pga_gpios->ndescs != 2)
|
||||
return dev_err_probe(dev, -EINVAL, "Expected 2 pga gpio pins.\n");
|
||||
|
||||
st->scale_avail = scale_buffer;
|
||||
st->scale_avail_size = ARRAY_SIZE(scale_buffer);
|
||||
} else {
|
||||
for (i = 0; i < ARRAY_SIZE(gain); i++) {
|
||||
if (pga_value != gain[i])
|
||||
continue;
|
||||
|
|
@ -227,6 +219,17 @@ static int ad7191_config_setup(struct iio_dev *indio_dev)
|
|||
st->scale_avail_size = 1;
|
||||
|
||||
st->pga_gpios = NULL;
|
||||
} else {
|
||||
st->pga_gpios = devm_gpiod_get_array(dev, "pga", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(st->pga_gpios))
|
||||
return dev_err_probe(dev, PTR_ERR(st->pga_gpios),
|
||||
"Failed to get pga gpios.\n");
|
||||
|
||||
if (st->pga_gpios->ndescs != 2)
|
||||
return dev_err_probe(dev, -EINVAL, "Expected 2 pga gpio pins.\n");
|
||||
|
||||
st->scale_avail = scale_buffer;
|
||||
st->scale_avail_size = ARRAY_SIZE(scale_buffer);
|
||||
}
|
||||
|
||||
st->temp_gpio = devm_gpiod_get(dev, "temp", GPIOD_OUT_LOW);
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
#define AD7192_REG_CONF 2 /* Configuration Register (RW, 24-bit) */
|
||||
#define AD7192_REG_DATA 3 /* Data Register (RO, 24/32-bit) */
|
||||
#define AD7192_REG_ID 4 /* ID Register (RO, 8-bit) */
|
||||
#define AD7192_REG_GPOCON 5 /* GPOCON Register (RO, 8-bit) */
|
||||
#define AD7192_REG_GPOCON 5 /* GPOCON Register (RW, 8-bit) */
|
||||
#define AD7192_REG_OFFSET 6 /* Offset Register (RW, 16-bit */
|
||||
/* (AD7792)/24-bit (AD7192)) */
|
||||
#define AD7192_REG_FULLSALE 7 /* Full-Scale Register */
|
||||
|
|
@ -576,7 +576,12 @@ static int ad7192_setup(struct iio_dev *indio_dev, struct device *dev)
|
|||
ret = ad_sd_reset(&st->sd);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
usleep_range(500, 1000); /* Wait for at least 500us */
|
||||
|
||||
/*
|
||||
* Per AD7192 datasheet (Rev. A, page 34, RESET section), allow
|
||||
* 500 us after a reset before accessing on-chip registers.
|
||||
*/
|
||||
fsleep(500);
|
||||
|
||||
/* write/read test for device presence */
|
||||
ret = ad_sd_read_reg(&st->sd, AD7192_REG_ID, 1, &id);
|
||||
|
|
|
|||
|
|
@ -496,7 +496,8 @@ static ssize_t ad7280_store_balance_sw(struct iio_dev *indio_dev,
|
|||
devaddr = chan->address >> 8;
|
||||
ch = chan->address & 0xFF;
|
||||
|
||||
mutex_lock(&st->lock);
|
||||
guard(mutex)(&st->lock);
|
||||
|
||||
if (readin)
|
||||
st->cb_mask[devaddr] |= BIT(ch);
|
||||
else
|
||||
|
|
@ -505,7 +506,6 @@ static ssize_t ad7280_store_balance_sw(struct iio_dev *indio_dev,
|
|||
ret = ad7280_write(st, devaddr, AD7280A_CELL_BALANCE_REG, 0,
|
||||
FIELD_PREP(AD7280A_CELL_BALANCE_CHAN_BITMAP_MSK,
|
||||
st->cb_mask[devaddr]));
|
||||
mutex_unlock(&st->lock);
|
||||
|
||||
return ret ? ret : len;
|
||||
}
|
||||
|
|
@ -516,14 +516,13 @@ static ssize_t ad7280_show_balance_timer(struct iio_dev *indio_dev,
|
|||
char *buf)
|
||||
{
|
||||
struct ad7280_state *st = iio_priv(indio_dev);
|
||||
u8 devaddr = chan->address >> 8;
|
||||
u8 ch = chan->address & 0xFF;
|
||||
unsigned int msecs;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&st->lock);
|
||||
ret = ad7280_read_reg(st, chan->address >> 8,
|
||||
(chan->address & 0xFF) + AD7280A_CB1_TIMER_REG);
|
||||
mutex_unlock(&st->lock);
|
||||
|
||||
scoped_guard(mutex, &st->lock)
|
||||
ret = ad7280_read_reg(st, devaddr, ch + AD7280A_CB1_TIMER_REG);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
@ -538,6 +537,8 @@ static ssize_t ad7280_store_balance_timer(struct iio_dev *indio_dev,
|
|||
const char *buf, size_t len)
|
||||
{
|
||||
struct ad7280_state *st = iio_priv(indio_dev);
|
||||
u8 devaddr = chan->address >> 8;
|
||||
u8 ch = chan->address & 0xFF;
|
||||
int val, val2;
|
||||
int ret;
|
||||
|
||||
|
|
@ -551,11 +552,10 @@ static ssize_t ad7280_store_balance_timer(struct iio_dev *indio_dev,
|
|||
if (val > 31)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&st->lock);
|
||||
ret = ad7280_write(st, chan->address >> 8,
|
||||
(chan->address & 0xFF) + AD7280A_CB1_TIMER_REG, 0,
|
||||
guard(mutex)(&st->lock);
|
||||
|
||||
ret = ad7280_write(st, devaddr, ch + AD7280A_CB1_TIMER_REG, 0,
|
||||
FIELD_PREP(AD7280A_CB_TIMER_VAL_MSK, val));
|
||||
mutex_unlock(&st->lock);
|
||||
|
||||
return ret ? ret : len;
|
||||
}
|
||||
|
|
@ -737,7 +737,8 @@ static int ad7280a_write_thresh(struct iio_dev *indio_dev,
|
|||
if (val2 != 0)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&st->lock);
|
||||
guard(mutex)(&st->lock);
|
||||
|
||||
switch (chan->type) {
|
||||
case IIO_VOLTAGE:
|
||||
value = ((val - 1000) * 100) / 1568; /* LSB 15.68mV */
|
||||
|
|
@ -748,22 +749,20 @@ static int ad7280a_write_thresh(struct iio_dev *indio_dev,
|
|||
ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, addr,
|
||||
1, value);
|
||||
if (ret)
|
||||
break;
|
||||
return ret;
|
||||
st->cell_threshhigh = value;
|
||||
break;
|
||||
return 0;
|
||||
case IIO_EV_DIR_FALLING:
|
||||
addr = AD7280A_CELL_UNDERVOLTAGE_REG;
|
||||
ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, addr,
|
||||
1, value);
|
||||
if (ret)
|
||||
break;
|
||||
return ret;
|
||||
st->cell_threshlow = value;
|
||||
break;
|
||||
return 0;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto err_unlock;
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case IIO_TEMP:
|
||||
value = (val * 10) / 196; /* LSB 19.6mV */
|
||||
value = clamp(value, 0L, 0xFFL);
|
||||
|
|
@ -773,31 +772,23 @@ static int ad7280a_write_thresh(struct iio_dev *indio_dev,
|
|||
ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, addr,
|
||||
1, value);
|
||||
if (ret)
|
||||
break;
|
||||
return ret;
|
||||
st->aux_threshhigh = value;
|
||||
break;
|
||||
return 0;
|
||||
case IIO_EV_DIR_FALLING:
|
||||
addr = AD7280A_AUX_ADC_UNDERVOLTAGE_REG;
|
||||
ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, addr,
|
||||
1, value);
|
||||
if (ret)
|
||||
break;
|
||||
return ret;
|
||||
st->aux_threshlow = value;
|
||||
break;
|
||||
return 0;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto err_unlock;
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto err_unlock;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err_unlock:
|
||||
mutex_unlock(&st->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t ad7280_event_handler(int irq, void *private)
|
||||
|
|
@ -881,17 +872,18 @@ static int ad7280_read_raw(struct iio_dev *indio_dev,
|
|||
long m)
|
||||
{
|
||||
struct ad7280_state *st = iio_priv(indio_dev);
|
||||
u8 devaddr = chan->address >> 8;
|
||||
u8 ch = chan->address & 0xFF;
|
||||
int ret;
|
||||
|
||||
switch (m) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
mutex_lock(&st->lock);
|
||||
case IIO_CHAN_INFO_RAW: {
|
||||
guard(mutex)(&st->lock);
|
||||
|
||||
if (chan->address == AD7280A_ALL_CELLS)
|
||||
ret = ad7280_read_all_channels(st, st->scan_cnt, NULL);
|
||||
else
|
||||
ret = ad7280_read_channel(st, chan->address >> 8,
|
||||
chan->address & 0xFF);
|
||||
mutex_unlock(&st->lock);
|
||||
ret = ad7280_read_channel(st, devaddr, ch);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
@ -899,8 +891,9 @@ static int ad7280_read_raw(struct iio_dev *indio_dev,
|
|||
*val = ret;
|
||||
|
||||
return IIO_VAL_INT;
|
||||
}
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
if ((chan->address & 0xFF) <= AD7280A_CELL_VOLTAGE_6_REG)
|
||||
if (ch <= AD7280A_CELL_VOLTAGE_6_REG)
|
||||
*val = 4000;
|
||||
else
|
||||
*val = 5000;
|
||||
|
|
@ -990,8 +983,8 @@ static int ad7280_probe(struct spi_device *spi)
|
|||
st->acquisition_time = AD7280A_CTRL_LB_ACQ_TIME_1600ns;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Firmware provided acquisition time is invalid\n");
|
||||
return -EINVAL;
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"Firmware provided acquisition time is invalid\n");
|
||||
}
|
||||
} else {
|
||||
st->acquisition_time = AD7280A_CTRL_LB_ACQ_TIME_400ns;
|
||||
|
|
|
|||
|
|
@ -536,7 +536,7 @@ static int ad7291_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id ad7291_id[] = {
|
||||
{ "ad7291" },
|
||||
{ .name = "ad7291" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -253,12 +253,13 @@ static const struct iio_info ad7292_info = {
|
|||
|
||||
static int ad7292_probe(struct spi_device *spi)
|
||||
{
|
||||
struct device *dev = &spi->dev;
|
||||
struct ad7292_state *st;
|
||||
struct iio_dev *indio_dev;
|
||||
bool diff_channels = false;
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -266,12 +267,11 @@ static int ad7292_probe(struct spi_device *spi)
|
|||
st->spi = spi;
|
||||
|
||||
ret = ad7292_spi_reg_read(st, AD7292_REG_VENDOR_ID);
|
||||
if (ret != ADI_VENDOR_ID) {
|
||||
dev_err(&spi->dev, "Wrong vendor id 0x%x\n", ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (ret != ADI_VENDOR_ID)
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"Wrong vendor id 0x%x\n", ret);
|
||||
|
||||
ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref");
|
||||
ret = devm_regulator_get_enable_read_voltage(dev, "vref");
|
||||
if (ret < 0 && ret != -ENODEV)
|
||||
return ret;
|
||||
|
||||
|
|
@ -281,7 +281,7 @@ static int ad7292_probe(struct spi_device *spi)
|
|||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->info = &ad7292_info;
|
||||
|
||||
device_for_each_child_node_scoped(&spi->dev, child) {
|
||||
device_for_each_child_node_scoped(dev, child) {
|
||||
diff_channels = fwnode_property_read_bool(child,
|
||||
"diff-channels");
|
||||
if (diff_channels)
|
||||
|
|
@ -296,7 +296,7 @@ static int ad7292_probe(struct spi_device *spi)
|
|||
indio_dev->channels = ad7292_channels;
|
||||
}
|
||||
|
||||
return devm_iio_device_register(&spi->dev, indio_dev);
|
||||
return devm_iio_device_register(dev, indio_dev);
|
||||
}
|
||||
|
||||
static const struct spi_device_id ad7292_id_table[] = {
|
||||
|
|
|
|||
|
|
@ -1475,7 +1475,7 @@ static int ad7606_probe_channels(struct iio_dev *indio_dev)
|
|||
}
|
||||
|
||||
if (slow_bus)
|
||||
channels[i] = (struct iio_chan_spec)IIO_CHAN_SOFT_TIMESTAMP(i);
|
||||
channels[i] = IIO_CHAN_SOFT_TIMESTAMP(i);
|
||||
|
||||
indio_dev->channels = channels;
|
||||
|
||||
|
|
|
|||
|
|
@ -175,12 +175,12 @@ enum ad7960_mode {
|
|||
|
||||
static int ad7625_set_sampling_freq(struct ad7625_state *st, u32 freq)
|
||||
{
|
||||
u32 target;
|
||||
struct pwm_waveform clk_gate_wf = { }, cnv_wf = { };
|
||||
unsigned long target;
|
||||
int ret;
|
||||
|
||||
target = DIV_ROUND_UP(NSEC_PER_SEC, freq);
|
||||
cnv_wf.period_length_ns = clamp(target, 100, 10 * KILO);
|
||||
cnv_wf.period_length_ns = clamp(target, 100UL, 10UL * NSEC_PER_USEC);
|
||||
|
||||
/*
|
||||
* Use the maximum conversion time t_CNVH from the datasheet as
|
||||
|
|
|
|||
|
|
@ -1871,10 +1871,8 @@ static int ad7768_probe(struct spi_device *spi)
|
|||
return ret;
|
||||
|
||||
ret = ad7768_setup(indio_dev);
|
||||
if (ret < 0) {
|
||||
dev_err(&spi->dev, "AD7768 setup failed\n");
|
||||
return ret;
|
||||
}
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "AD7768 setup failed\n");
|
||||
|
||||
init_completion(&st->completion);
|
||||
ret = devm_mutex_init(&spi->dev, &st->pga_lock);
|
||||
|
|
|
|||
|
|
@ -264,16 +264,12 @@ static const struct iio_info ad7780_info = {
|
|||
|
||||
static int ad7780_init_gpios(struct device *dev, struct ad7780_state *st)
|
||||
{
|
||||
int ret;
|
||||
|
||||
st->powerdown_gpio = devm_gpiod_get_optional(dev,
|
||||
"powerdown",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(st->powerdown_gpio)) {
|
||||
ret = PTR_ERR(st->powerdown_gpio);
|
||||
dev_err(dev, "Failed to request powerdown GPIO: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (IS_ERR(st->powerdown_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(st->powerdown_gpio),
|
||||
"Failed to request powerdown GPIO\n");
|
||||
|
||||
if (!st->chip_info->is_ad778x)
|
||||
return 0;
|
||||
|
|
@ -282,20 +278,16 @@ static int ad7780_init_gpios(struct device *dev, struct ad7780_state *st)
|
|||
st->gain_gpio = devm_gpiod_get_optional(dev,
|
||||
"adi,gain",
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(st->gain_gpio)) {
|
||||
ret = PTR_ERR(st->gain_gpio);
|
||||
dev_err(dev, "Failed to request gain GPIO: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (IS_ERR(st->gain_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(st->gain_gpio),
|
||||
"Failed to request gain GPIO\n");
|
||||
|
||||
st->filter_gpio = devm_gpiod_get_optional(dev,
|
||||
"adi,filter",
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(st->filter_gpio)) {
|
||||
ret = PTR_ERR(st->filter_gpio);
|
||||
dev_err(dev, "Failed to request filter GPIO: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (IS_ERR(st->filter_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(st->filter_gpio),
|
||||
"Failed to request filter GPIO\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -307,11 +299,12 @@ static void ad7780_reg_disable(void *reg)
|
|||
|
||||
static int ad7780_probe(struct spi_device *spi)
|
||||
{
|
||||
struct device *dev = &spi->dev;
|
||||
struct ad7780_state *st;
|
||||
struct iio_dev *indio_dev;
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -329,29 +322,28 @@ static int ad7780_probe(struct spi_device *spi)
|
|||
indio_dev->num_channels = 1;
|
||||
indio_dev->info = &ad7780_info;
|
||||
|
||||
ret = ad7780_init_gpios(&spi->dev, st);
|
||||
ret = ad7780_init_gpios(dev, st);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
st->reg = devm_regulator_get(&spi->dev, "avdd");
|
||||
st->reg = devm_regulator_get(dev, "avdd");
|
||||
if (IS_ERR(st->reg))
|
||||
return PTR_ERR(st->reg);
|
||||
|
||||
ret = regulator_enable(st->reg);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Failed to enable specified AVdd supply\n");
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"Failed to enable specified AVdd supply\n");
|
||||
|
||||
ret = devm_add_action_or_reset(&spi->dev, ad7780_reg_disable, st->reg);
|
||||
ret = devm_add_action_or_reset(dev, ad7780_reg_disable, st->reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_ad_sd_setup_buffer_and_trigger(&spi->dev, indio_dev);
|
||||
ret = devm_ad_sd_setup_buffer_and_trigger(dev, indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return devm_iio_device_register(&spi->dev, indio_dev);
|
||||
return devm_iio_device_register(dev, indio_dev);
|
||||
}
|
||||
|
||||
static const struct spi_device_id ad7780_id[] = {
|
||||
|
|
|
|||
|
|
@ -407,23 +407,22 @@ static void ad7791_reg_disable(void *reg)
|
|||
|
||||
static int ad7791_probe(struct spi_device *spi)
|
||||
{
|
||||
const struct ad7791_platform_data *pdata = dev_get_platdata(&spi->dev);
|
||||
struct device *dev = &spi->dev;
|
||||
const struct ad7791_platform_data *pdata = dev_get_platdata(dev);
|
||||
struct iio_dev *indio_dev;
|
||||
struct ad7791_state *st;
|
||||
int ret;
|
||||
|
||||
if (!spi->irq) {
|
||||
dev_err(&spi->dev, "Missing IRQ.\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
if (!spi->irq)
|
||||
return dev_err_probe(dev, -ENXIO, "Missing IRQ.\n");
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
|
||||
st->reg = devm_regulator_get(&spi->dev, "refin");
|
||||
st->reg = devm_regulator_get(dev, "refin");
|
||||
if (IS_ERR(st->reg))
|
||||
return PTR_ERR(st->reg);
|
||||
|
||||
|
|
@ -431,7 +430,7 @@ static int ad7791_probe(struct spi_device *spi)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(&spi->dev, ad7791_reg_disable, st->reg);
|
||||
ret = devm_add_action_or_reset(dev, ad7791_reg_disable, st->reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -447,7 +446,7 @@ static int ad7791_probe(struct spi_device *spi)
|
|||
else
|
||||
indio_dev->info = &ad7791_no_filter_info;
|
||||
|
||||
ret = devm_ad_sd_setup_buffer_and_trigger(&spi->dev, indio_dev);
|
||||
ret = devm_ad_sd_setup_buffer_and_trigger(dev, indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -455,7 +454,7 @@ static int ad7791_probe(struct spi_device *spi)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
return devm_iio_device_register(&spi->dev, indio_dev);
|
||||
return devm_iio_device_register(dev, indio_dev);
|
||||
}
|
||||
|
||||
static const struct spi_device_id ad7791_spi_ids[] = {
|
||||
|
|
|
|||
|
|
@ -268,7 +268,12 @@ static int ad7793_setup(struct iio_dev *indio_dev,
|
|||
ret = ad_sd_reset(&st->sd);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
usleep_range(500, 2000); /* Wait for at least 500us */
|
||||
|
||||
/*
|
||||
* Per AD7792/AD7793 datasheet (Rev. B, page 25, RESET section),
|
||||
* allow 500 us after a reset before accessing on-chip registers.
|
||||
*/
|
||||
fsleep(500);
|
||||
|
||||
/* write/read test for device presence */
|
||||
ret = ad_sd_read_reg(&st->sd, AD7793_REG_ID, 1, &id);
|
||||
|
|
@ -278,8 +283,8 @@ static int ad7793_setup(struct iio_dev *indio_dev,
|
|||
id &= AD7793_ID_MASK;
|
||||
|
||||
if (id != st->chip_info->id) {
|
||||
ret = -ENODEV;
|
||||
dev_err(&st->sd.spi->dev, "device ID query failed\n");
|
||||
ret = dev_err_probe(&st->sd.spi->dev, -ENODEV,
|
||||
"device ID query failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -338,8 +343,7 @@ static int ad7793_setup(struct iio_dev *indio_dev,
|
|||
|
||||
return 0;
|
||||
out:
|
||||
dev_err(&st->sd.spi->dev, "setup failed\n");
|
||||
return ret;
|
||||
return dev_err_probe(&st->sd.spi->dev, ret, "setup failed\n");
|
||||
}
|
||||
|
||||
static const u16 ad7793_sample_freq_avail[16] = {0, 470, 242, 123, 62, 50, 39,
|
||||
|
|
@ -774,22 +778,19 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
|
|||
|
||||
static int ad7793_probe(struct spi_device *spi)
|
||||
{
|
||||
const struct ad7793_platform_data *pdata = dev_get_platdata(&spi->dev);
|
||||
struct device *dev = &spi->dev;
|
||||
const struct ad7793_platform_data *pdata = dev_get_platdata(dev);
|
||||
struct ad7793_state *st;
|
||||
struct iio_dev *indio_dev;
|
||||
int ret, vref_mv = 0;
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(&spi->dev, "no platform data?\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (!pdata)
|
||||
return dev_err_probe(dev, -ENODEV, "no platform data?\n");
|
||||
|
||||
if (!spi->irq) {
|
||||
dev_err(&spi->dev, "no IRQ?\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (!spi->irq)
|
||||
return dev_err_probe(dev, -ENODEV, "no IRQ?\n");
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -798,7 +799,7 @@ static int ad7793_probe(struct spi_device *spi)
|
|||
ad_sd_init(&st->sd, indio_dev, spi, &ad7793_sigma_delta_info);
|
||||
|
||||
if (pdata->refsel != AD7793_REFSEL_INTERNAL) {
|
||||
ret = devm_regulator_get_enable_read_voltage(&spi->dev, "refin");
|
||||
ret = devm_regulator_get_enable_read_voltage(dev, "refin");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
@ -816,7 +817,7 @@ static int ad7793_probe(struct spi_device *spi)
|
|||
indio_dev->num_channels = st->chip_info->num_channels;
|
||||
indio_dev->info = st->chip_info->iio_info;
|
||||
|
||||
ret = devm_ad_sd_setup_buffer_and_trigger(&spi->dev, indio_dev);
|
||||
ret = devm_ad_sd_setup_buffer_and_trigger(dev, indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -824,7 +825,7 @@ static int ad7793_probe(struct spi_device *spi)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
return devm_iio_device_register(&spi->dev, indio_dev);
|
||||
return devm_iio_device_register(dev, indio_dev);
|
||||
}
|
||||
|
||||
static const struct spi_device_id ad7793_id[] = {
|
||||
|
|
|
|||
|
|
@ -341,8 +341,8 @@ static int ad7949_spi_probe(struct spi_device *spi)
|
|||
} else if (spi_is_bpw_supported(spi, 8)) {
|
||||
spi->bits_per_word = 8;
|
||||
} else {
|
||||
dev_err(dev, "unable to find common BPW with spi controller\n");
|
||||
return -EINVAL;
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"unable to find common BPW with spi controller\n");
|
||||
}
|
||||
|
||||
/* Setup internal voltage reference */
|
||||
|
|
@ -357,8 +357,8 @@ static int ad7949_spi_probe(struct spi_device *spi)
|
|||
ad7949_adc->refsel = AD7949_CFG_VAL_REF_INT_4096;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "unsupported internal voltage reference\n");
|
||||
return -EINVAL;
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"unsupported internal voltage reference\n");
|
||||
}
|
||||
|
||||
/* Setup external voltage reference, buffered? */
|
||||
|
|
@ -382,10 +382,9 @@ static int ad7949_spi_probe(struct spi_device *spi)
|
|||
|
||||
if (ad7949_adc->refsel & AD7949_CFG_VAL_REF_EXTERNAL) {
|
||||
ret = regulator_enable(ad7949_adc->vref);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "fail to enable regulator\n");
|
||||
return ret;
|
||||
}
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret,
|
||||
"fail to enable regulator\n");
|
||||
|
||||
ret = devm_add_action_or_reset(dev, ad7949_disable_reg,
|
||||
ad7949_adc->vref);
|
||||
|
|
@ -396,16 +395,10 @@ static int ad7949_spi_probe(struct spi_device *spi)
|
|||
mutex_init(&ad7949_adc->lock);
|
||||
|
||||
ret = ad7949_spi_init(ad7949_adc);
|
||||
if (ret) {
|
||||
dev_err(dev, "fail to init this device: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_iio_device_register(dev, indio_dev);
|
||||
if (ret)
|
||||
dev_err(dev, "fail to register iio device: %d\n", ret);
|
||||
return dev_err_probe(dev, ret, "fail to init this device\n");
|
||||
|
||||
return ret;
|
||||
return devm_iio_device_register(dev, indio_dev);
|
||||
}
|
||||
|
||||
static const struct of_device_id ad7949_spi_of_id[] = {
|
||||
|
|
|
|||
|
|
@ -18,27 +18,29 @@
|
|||
* ad7998 and similar chips.
|
||||
*/
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/events.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/events.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/iio/triggered_buffer.h>
|
||||
|
||||
#define AD799X_CHANNEL_SHIFT 4
|
||||
#define AD799X_MAX_CHANNELS 8
|
||||
|
||||
/*
|
||||
* AD7991, AD7995 and AD7999 defines
|
||||
|
|
@ -133,8 +135,11 @@ struct ad799x_state {
|
|||
unsigned int id;
|
||||
u16 config;
|
||||
|
||||
u8 *rx_buf;
|
||||
unsigned int transfer_size;
|
||||
|
||||
int vref_uV;
|
||||
|
||||
IIO_DECLARE_BUFFER_WITH_TS(__be16, rx_buf, AD799X_MAX_CHANNELS);
|
||||
};
|
||||
|
||||
static int ad799x_write_config(struct ad799x_state *st, u16 val)
|
||||
|
|
@ -217,7 +222,8 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p)
|
|||
}
|
||||
|
||||
b_sent = i2c_smbus_read_i2c_block_data(st->client,
|
||||
cmd, st->transfer_size, st->rx_buf);
|
||||
cmd, st->transfer_size,
|
||||
(u8 *)st->rx_buf);
|
||||
if (b_sent < 0)
|
||||
goto out;
|
||||
|
||||
|
|
@ -234,11 +240,6 @@ static int ad799x_update_scan_mode(struct iio_dev *indio_dev,
|
|||
{
|
||||
struct ad799x_state *st = iio_priv(indio_dev);
|
||||
|
||||
kfree(st->rx_buf);
|
||||
st->rx_buf = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
|
||||
if (!st->rx_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
st->transfer_size = bitmap_weight(scan_mask,
|
||||
iio_get_masklength(indio_dev)) * 2;
|
||||
|
||||
|
|
@ -306,14 +307,7 @@ static int ad799x_read_raw(struct iio_dev *indio_dev,
|
|||
GENMASK(chan->scan_type.realbits - 1, 0);
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
if (st->vref)
|
||||
ret = regulator_get_voltage(st->vref);
|
||||
else
|
||||
ret = regulator_get_voltage(st->reg);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*val = ret / 1000;
|
||||
*val = st->vref_uV / (MICRO / MILLI);
|
||||
*val2 = chan->scan_type.realbits;
|
||||
return IIO_VAL_FRACTIONAL_LOG2;
|
||||
}
|
||||
|
|
@ -781,8 +775,14 @@ static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static void ad799x_reg_disable(void *reg)
|
||||
{
|
||||
regulator_disable(reg);
|
||||
}
|
||||
|
||||
static int ad799x_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||
int ret;
|
||||
int extra_config = 0;
|
||||
|
|
@ -791,7 +791,7 @@ static int ad799x_probe(struct i2c_client *client)
|
|||
const struct ad799x_chip_info *chip_info =
|
||||
&ad799x_chip_info_tbl[id->driver_data];
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
|
||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -799,6 +799,10 @@ static int ad799x_probe(struct i2c_client *client)
|
|||
/* this is only used for device removal purposes */
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
|
||||
ret = devm_mutex_init(dev, &st->lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
st->id = id->driver_data;
|
||||
if (client->irq > 0 && chip_info->irq_config.info)
|
||||
st->chip_config = &chip_info->irq_config;
|
||||
|
|
@ -807,33 +811,53 @@ static int ad799x_probe(struct i2c_client *client)
|
|||
|
||||
/* TODO: Add pdata options for filtering and bit delay */
|
||||
|
||||
st->reg = devm_regulator_get(&client->dev, "vcc");
|
||||
st->reg = devm_regulator_get(dev, "vcc");
|
||||
if (IS_ERR(st->reg))
|
||||
return PTR_ERR(st->reg);
|
||||
ret = regulator_enable(st->reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, ad799x_reg_disable, st->reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* check if an external reference is supplied */
|
||||
if (chip_info->has_vref) {
|
||||
st->vref = devm_regulator_get_optional(&client->dev, "vref");
|
||||
st->vref = devm_regulator_get_optional(dev, "vref");
|
||||
ret = PTR_ERR_OR_ZERO(st->vref);
|
||||
if (ret) {
|
||||
if (ret != -ENODEV)
|
||||
goto error_disable_reg;
|
||||
if (ret == -ENODEV) {
|
||||
st->vref = NULL;
|
||||
dev_info(&client->dev, "Using VCC reference voltage\n");
|
||||
dev_info(dev, "Using VCC reference voltage\n");
|
||||
} else if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (st->vref) {
|
||||
dev_info(&client->dev, "Using external reference voltage\n");
|
||||
dev_info(dev, "Using external reference voltage\n");
|
||||
extra_config |= AD7991_REF_SEL;
|
||||
ret = regulator_enable(st->vref);
|
||||
if (ret)
|
||||
goto error_disable_reg;
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, ad799x_reg_disable, st->vref);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regulator_get_voltage(st->vref);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
st->vref_uV = ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (!st->vref) {
|
||||
ret = regulator_get_voltage(st->reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
st->vref_uV = ret;
|
||||
}
|
||||
|
||||
st->client = client;
|
||||
|
||||
indio_dev->name = id->name;
|
||||
|
|
@ -845,15 +869,15 @@ static int ad799x_probe(struct i2c_client *client)
|
|||
|
||||
ret = ad799x_update_config(st, st->chip_config->default_config | extra_config);
|
||||
if (ret)
|
||||
goto error_disable_vref;
|
||||
return ret;
|
||||
|
||||
ret = iio_triggered_buffer_setup(indio_dev, NULL,
|
||||
ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
|
||||
&ad799x_trigger_handler, NULL);
|
||||
if (ret)
|
||||
goto error_disable_vref;
|
||||
return ret;
|
||||
|
||||
if (client->irq > 0) {
|
||||
ret = devm_request_threaded_irq(&client->dev,
|
||||
ret = devm_request_threaded_irq(dev,
|
||||
client->irq,
|
||||
NULL,
|
||||
ad799x_event_handler,
|
||||
|
|
@ -862,40 +886,10 @@ static int ad799x_probe(struct i2c_client *client)
|
|||
client->name,
|
||||
indio_dev);
|
||||
if (ret)
|
||||
goto error_cleanup_ring;
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_init(&st->lock);
|
||||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret)
|
||||
goto error_cleanup_ring;
|
||||
|
||||
return 0;
|
||||
|
||||
error_cleanup_ring:
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
error_disable_vref:
|
||||
if (st->vref)
|
||||
regulator_disable(st->vref);
|
||||
error_disable_reg:
|
||||
regulator_disable(st->reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ad799x_remove(struct i2c_client *client)
|
||||
{
|
||||
struct iio_dev *indio_dev = i2c_get_clientdata(client);
|
||||
struct ad799x_state *st = iio_priv(indio_dev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
if (st->vref)
|
||||
regulator_disable(st->vref);
|
||||
regulator_disable(st->reg);
|
||||
kfree(st->rx_buf);
|
||||
return devm_iio_device_register(dev, indio_dev);
|
||||
}
|
||||
|
||||
static int ad799x_suspend(struct device *dev)
|
||||
|
|
@ -946,14 +940,14 @@ static int ad799x_resume(struct device *dev)
|
|||
static DEFINE_SIMPLE_DEV_PM_OPS(ad799x_pm_ops, ad799x_suspend, ad799x_resume);
|
||||
|
||||
static const struct i2c_device_id ad799x_id[] = {
|
||||
{ "ad7991", ad7991 },
|
||||
{ "ad7995", ad7995 },
|
||||
{ "ad7999", ad7999 },
|
||||
{ "ad7992", ad7992 },
|
||||
{ "ad7993", ad7993 },
|
||||
{ "ad7994", ad7994 },
|
||||
{ "ad7997", ad7997 },
|
||||
{ "ad7998", ad7998 },
|
||||
{ .name = "ad7991", .driver_data = ad7991 },
|
||||
{ .name = "ad7995", .driver_data = ad7995 },
|
||||
{ .name = "ad7999", .driver_data = ad7999 },
|
||||
{ .name = "ad7992", .driver_data = ad7992 },
|
||||
{ .name = "ad7993", .driver_data = ad7993 },
|
||||
{ .name = "ad7994", .driver_data = ad7994 },
|
||||
{ .name = "ad7997", .driver_data = ad7997 },
|
||||
{ .name = "ad7998", .driver_data = ad7998 },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
@ -965,7 +959,6 @@ static struct i2c_driver ad799x_driver = {
|
|||
.pm = pm_sleep_ptr(&ad799x_pm_ops),
|
||||
},
|
||||
.probe = ad799x_probe,
|
||||
.remove = ad799x_remove,
|
||||
.id_table = ad799x_id,
|
||||
};
|
||||
module_i2c_driver(ad799x_driver);
|
||||
|
|
|
|||
|
|
@ -1349,11 +1349,10 @@ static int ad9467_probe(struct spi_device *spi)
|
|||
return ret;
|
||||
|
||||
id = ad9467_spi_read(st, AN877_ADC_REG_CHIP_ID);
|
||||
if (id != st->info->id) {
|
||||
dev_err(dev, "Mismatch CHIP_ID, got 0x%X, expected 0x%X\n",
|
||||
id, st->info->id);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (id != st->info->id)
|
||||
return dev_err_probe(dev, -ENODEV,
|
||||
"Mismatch CHIP_ID, got 0x%X, expected 0x%X\n",
|
||||
id, st->info->id);
|
||||
|
||||
if (st->info->num_scales > 1)
|
||||
indio_dev->info = &ad9467_info;
|
||||
|
|
|
|||
|
|
@ -481,7 +481,7 @@ static irqreturn_t at91_adc_9x5_interrupt(int irq, void *private)
|
|||
static int at91_adc_channel_init(struct iio_dev *idev)
|
||||
{
|
||||
struct at91_adc_state *st = iio_priv(idev);
|
||||
struct iio_chan_spec *chan_array, *timestamp;
|
||||
struct iio_chan_spec *chan_array;
|
||||
int bit, idx = 0;
|
||||
unsigned long rsvd_mask = 0;
|
||||
|
||||
|
|
@ -519,14 +519,8 @@ static int at91_adc_channel_init(struct iio_dev *idev)
|
|||
chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
|
||||
idx++;
|
||||
}
|
||||
timestamp = chan_array + idx;
|
||||
|
||||
timestamp->type = IIO_TIMESTAMP;
|
||||
timestamp->channel = -1;
|
||||
timestamp->scan_index = idx;
|
||||
timestamp->scan_type.sign = 's';
|
||||
timestamp->scan_type.realbits = 64;
|
||||
timestamp->scan_type.storagebits = 64;
|
||||
chan_array[idx] = IIO_CHAN_SOFT_TIMESTAMP(idx);
|
||||
|
||||
idev->channels = chan_array;
|
||||
return idev->num_channels;
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@ static const struct iio_info cc10001_adc_info = {
|
|||
static int cc10001_adc_channel_init(struct iio_dev *indio_dev,
|
||||
unsigned long channel_map)
|
||||
{
|
||||
struct iio_chan_spec *chan_array, *timestamp;
|
||||
struct iio_chan_spec *chan_array;
|
||||
unsigned int bit, idx = 0;
|
||||
|
||||
indio_dev->num_channels = bitmap_weight(&channel_map,
|
||||
|
|
@ -289,13 +289,7 @@ static int cc10001_adc_channel_init(struct iio_dev *indio_dev,
|
|||
idx++;
|
||||
}
|
||||
|
||||
timestamp = &chan_array[idx];
|
||||
timestamp->type = IIO_TIMESTAMP;
|
||||
timestamp->channel = -1;
|
||||
timestamp->scan_index = idx;
|
||||
timestamp->scan_type.sign = 's';
|
||||
timestamp->scan_type.realbits = 64;
|
||||
timestamp->scan_type.storagebits = 64;
|
||||
chan_array[idx] = IIO_CHAN_SOFT_TIMESTAMP(idx);
|
||||
|
||||
indio_dev->channels = chan_array;
|
||||
|
||||
|
|
|
|||
|
|
@ -444,16 +444,6 @@ static int dln2_update_scan_mode(struct iio_dev *indio_dev,
|
|||
lval.scan_type.endianness = IIO_LE; \
|
||||
}
|
||||
|
||||
/* Assignment version of IIO_CHAN_SOFT_TIMESTAMP */
|
||||
#define IIO_CHAN_SOFT_TIMESTAMP_ASSIGN(lval, _si) { \
|
||||
lval.type = IIO_TIMESTAMP; \
|
||||
lval.channel = -1; \
|
||||
lval.scan_index = _si; \
|
||||
lval.scan_type.sign = 's'; \
|
||||
lval.scan_type.realbits = 64; \
|
||||
lval.scan_type.storagebits = 64; \
|
||||
}
|
||||
|
||||
static const struct iio_info dln2_adc_info = {
|
||||
.read_raw = dln2_adc_read_raw,
|
||||
.write_raw = dln2_adc_write_raw,
|
||||
|
|
@ -614,7 +604,7 @@ static int dln2_adc_probe(struct platform_device *pdev)
|
|||
|
||||
for (i = 0; i < chans; ++i)
|
||||
DLN2_ADC_CHAN(dln2->iio_channels[i], i)
|
||||
IIO_CHAN_SOFT_TIMESTAMP_ASSIGN(dln2->iio_channels[i], i);
|
||||
dln2->iio_channels[i] = IIO_CHAN_SOFT_TIMESTAMP(i);
|
||||
|
||||
indio_dev->name = DLN2_ADC_MOD_NAME;
|
||||
indio_dev->info = &dln2_adc_info;
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ static const struct of_device_id pmc_adc_of_match[] = {
|
|||
MODULE_DEVICE_TABLE(of, pmc_adc_of_match);
|
||||
|
||||
static const struct i2c_device_id pmc_adc_id_table[] = {
|
||||
{ "pmc-adc" },
|
||||
{ .name = "pmc-adc" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, pmc_adc_id_table);
|
||||
|
|
|
|||
|
|
@ -28,22 +28,20 @@
|
|||
struct hx711_gain_to_scale {
|
||||
int gain;
|
||||
int gain_pulse;
|
||||
int scale;
|
||||
int channel;
|
||||
};
|
||||
|
||||
/*
|
||||
* .scale depends on AVDD which in turn is known as soon as the regulator
|
||||
* is available
|
||||
* therefore we set .scale in hx711_probe()
|
||||
* is available; it is stored per device in hx711_data.gain_scale[]
|
||||
*
|
||||
* channel A in documentation is channel 0 in source code
|
||||
* channel B in documentation is channel 1 in source code
|
||||
*/
|
||||
static struct hx711_gain_to_scale hx711_gain_to_scale[HX711_GAIN_MAX] = {
|
||||
{ 128, 1, 0, 0 },
|
||||
{ 32, 2, 0, 1 },
|
||||
{ 64, 3, 0, 0 }
|
||||
static const struct hx711_gain_to_scale hx711_gain_to_scale[HX711_GAIN_MAX] = {
|
||||
{ 128, 1, 0 },
|
||||
{ 32, 2, 1 },
|
||||
{ 64, 3, 0 },
|
||||
};
|
||||
|
||||
static int hx711_get_gain_to_pulse(int gain)
|
||||
|
|
@ -56,22 +54,22 @@ static int hx711_get_gain_to_pulse(int gain)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int hx711_get_gain_to_scale(int gain)
|
||||
static int hx711_get_gain_to_scale(const int *gain_scale, int gain)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < HX711_GAIN_MAX; i++)
|
||||
if (hx711_gain_to_scale[i].gain == gain)
|
||||
return hx711_gain_to_scale[i].scale;
|
||||
return gain_scale[i];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hx711_get_scale_to_gain(int scale)
|
||||
static int hx711_get_scale_to_gain(const int *gain_scale, int scale)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < HX711_GAIN_MAX; i++)
|
||||
if (hx711_gain_to_scale[i].scale == scale)
|
||||
if (gain_scale[i] == scale)
|
||||
return hx711_gain_to_scale[i].gain;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -82,6 +80,7 @@ struct hx711_data {
|
|||
struct gpio_desc *gpiod_dout;
|
||||
int gain_set; /* gain set on device */
|
||||
int gain_chan_a; /* gain for channel A */
|
||||
int gain_scale[HX711_GAIN_MAX];
|
||||
struct mutex lock;
|
||||
/*
|
||||
* triggered buffer
|
||||
|
|
@ -290,7 +289,8 @@ static int hx711_read_raw(struct iio_dev *indio_dev,
|
|||
*val = 0;
|
||||
mutex_lock(&hx711_data->lock);
|
||||
|
||||
*val2 = hx711_get_gain_to_scale(hx711_data->gain_set);
|
||||
*val2 = hx711_get_gain_to_scale(hx711_data->gain_scale,
|
||||
hx711_data->gain_set);
|
||||
|
||||
mutex_unlock(&hx711_data->lock);
|
||||
|
||||
|
|
@ -321,7 +321,7 @@ static int hx711_write_raw(struct iio_dev *indio_dev,
|
|||
|
||||
mutex_lock(&hx711_data->lock);
|
||||
|
||||
gain = hx711_get_scale_to_gain(val2);
|
||||
gain = hx711_get_scale_to_gain(hx711_data->gain_scale, val2);
|
||||
if (gain < 0) {
|
||||
mutex_unlock(&hx711_data->lock);
|
||||
return gain;
|
||||
|
|
@ -386,6 +386,7 @@ static ssize_t hx711_scale_available_show(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct hx711_data *hx711_data = iio_priv(dev_to_iio_dev(dev));
|
||||
struct iio_dev_attr *iio_attr = to_iio_dev_attr(attr);
|
||||
int channel = iio_attr->address;
|
||||
int i, len = 0;
|
||||
|
|
@ -393,7 +394,7 @@ static ssize_t hx711_scale_available_show(struct device *dev,
|
|||
for (i = 0; i < HX711_GAIN_MAX; i++)
|
||||
if (hx711_gain_to_scale[i].channel == channel)
|
||||
len += sprintf(buf + len, "0.%09d ",
|
||||
hx711_gain_to_scale[i].scale);
|
||||
hx711_data->gain_scale[i]);
|
||||
|
||||
len += sprintf(buf + len, "\n");
|
||||
|
||||
|
|
@ -511,7 +512,7 @@ static int hx711_probe(struct platform_device *pdev)
|
|||
ret *= 100;
|
||||
|
||||
for (i = 0; i < HX711_GAIN_MAX; i++)
|
||||
hx711_gain_to_scale[i].scale =
|
||||
hx711_data->gain_scale[i] =
|
||||
ret / hx711_gain_to_scale[i].gain / 1678;
|
||||
|
||||
hx711_data->gain_set = 128;
|
||||
|
|
|
|||
|
|
@ -1078,12 +1078,12 @@ static void ina2xx_remove(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id ina2xx_id[] = {
|
||||
{ "ina219", ina219 },
|
||||
{ "ina220", ina219 },
|
||||
{ "ina226", ina226 },
|
||||
{ "ina230", ina226 },
|
||||
{ "ina231", ina226 },
|
||||
{ "ina236", ina236 },
|
||||
{ .name = "ina219", .driver_data = ina219 },
|
||||
{ .name = "ina220", .driver_data = ina219 },
|
||||
{ .name = "ina226", .driver_data = ina226 },
|
||||
{ .name = "ina230", .driver_data = ina226 },
|
||||
{ .name = "ina231", .driver_data = ina226 },
|
||||
{ .name = "ina236", .driver_data = ina236 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ina2xx_id);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
*/
|
||||
|
||||
#include <dt-bindings/iio/adc/ingenic,adc.h>
|
||||
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/iio.h>
|
||||
|
|
@ -115,7 +117,7 @@ static void ingenic_adc_set_adcmd(struct iio_dev *iio_dev, unsigned long mask)
|
|||
{
|
||||
struct ingenic_adc *adc = iio_priv(iio_dev);
|
||||
|
||||
mutex_lock(&adc->lock);
|
||||
guard(mutex)(&adc->lock);
|
||||
|
||||
/* Init ADCMD */
|
||||
readl(adc->base + JZ_ADC_REG_ADCMD);
|
||||
|
|
@ -162,8 +164,6 @@ static void ingenic_adc_set_adcmd(struct iio_dev *iio_dev, unsigned long mask)
|
|||
|
||||
/* We're done */
|
||||
writel(0, adc->base + JZ_ADC_REG_ADCMD);
|
||||
|
||||
mutex_unlock(&adc->lock);
|
||||
}
|
||||
|
||||
static void ingenic_adc_set_config(struct ingenic_adc *adc,
|
||||
|
|
@ -172,18 +172,15 @@ static void ingenic_adc_set_config(struct ingenic_adc *adc,
|
|||
{
|
||||
uint32_t cfg;
|
||||
|
||||
mutex_lock(&adc->lock);
|
||||
guard(mutex)(&adc->lock);
|
||||
|
||||
cfg = readl(adc->base + JZ_ADC_REG_CFG) & ~mask;
|
||||
cfg |= val;
|
||||
writel(cfg, adc->base + JZ_ADC_REG_CFG);
|
||||
|
||||
mutex_unlock(&adc->lock);
|
||||
}
|
||||
|
||||
static void ingenic_adc_enable_unlocked(struct ingenic_adc *adc,
|
||||
int engine,
|
||||
bool enabled)
|
||||
static void __ingenic_adc_enable(struct ingenic_adc *adc, int engine,
|
||||
bool enabled)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
|
|
@ -201,9 +198,8 @@ static void ingenic_adc_enable(struct ingenic_adc *adc,
|
|||
int engine,
|
||||
bool enabled)
|
||||
{
|
||||
mutex_lock(&adc->lock);
|
||||
ingenic_adc_enable_unlocked(adc, engine, enabled);
|
||||
mutex_unlock(&adc->lock);
|
||||
guard(mutex)(&adc->lock);
|
||||
__ingenic_adc_enable(adc, engine, enabled);
|
||||
}
|
||||
|
||||
static int ingenic_adc_capture(struct ingenic_adc *adc,
|
||||
|
|
@ -218,18 +214,17 @@ static int ingenic_adc_capture(struct ingenic_adc *adc,
|
|||
* probably due to the switch of VREF. We must keep the lock here to
|
||||
* avoid races with the buffer enable/disable functions.
|
||||
*/
|
||||
mutex_lock(&adc->lock);
|
||||
guard(mutex)(&adc->lock);
|
||||
cfg = readl(adc->base + JZ_ADC_REG_CFG);
|
||||
writel(cfg & ~JZ_ADC_REG_CFG_CMD_SEL, adc->base + JZ_ADC_REG_CFG);
|
||||
|
||||
ingenic_adc_enable_unlocked(adc, engine, true);
|
||||
__ingenic_adc_enable(adc, engine, true);
|
||||
ret = readb_poll_timeout(adc->base + JZ_ADC_REG_ENABLE, val,
|
||||
!(val & BIT(engine)), 250, 1000);
|
||||
if (ret)
|
||||
ingenic_adc_enable_unlocked(adc, engine, false);
|
||||
__ingenic_adc_enable(adc, engine, false);
|
||||
|
||||
writel(cfg, adc->base + JZ_ADC_REG_CFG);
|
||||
mutex_unlock(&adc->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -628,22 +623,12 @@ static int ingenic_adc_read_avail(struct iio_dev *iio_dev,
|
|||
}
|
||||
}
|
||||
|
||||
static int ingenic_adc_read_chan_info_raw(struct iio_dev *iio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val)
|
||||
static int __ingenic_adc_read_chan(struct ingenic_adc *adc,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val)
|
||||
{
|
||||
int cmd, ret, engine = (chan->channel == INGENIC_ADC_BATTERY);
|
||||
struct ingenic_adc *adc = iio_priv(iio_dev);
|
||||
|
||||
ret = clk_enable(adc->clk);
|
||||
if (ret) {
|
||||
dev_err(iio_dev->dev.parent, "Failed to enable clock: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* We cannot sample the aux channels in parallel. */
|
||||
mutex_lock(&adc->aux_lock);
|
||||
if (adc->soc_data->has_aux_md && engine == 0) {
|
||||
switch (chan->channel) {
|
||||
case INGENIC_ADC_AUX0:
|
||||
|
|
@ -662,7 +647,7 @@ static int ingenic_adc_read_chan_info_raw(struct iio_dev *iio_dev,
|
|||
|
||||
ret = ingenic_adc_capture(adc, engine);
|
||||
if (ret)
|
||||
goto out;
|
||||
return ret;
|
||||
|
||||
switch (chan->channel) {
|
||||
case INGENIC_ADC_AUX0:
|
||||
|
|
@ -675,9 +660,26 @@ static int ingenic_adc_read_chan_info_raw(struct iio_dev *iio_dev,
|
|||
break;
|
||||
}
|
||||
|
||||
ret = IIO_VAL_INT;
|
||||
out:
|
||||
mutex_unlock(&adc->aux_lock);
|
||||
return IIO_VAL_INT;
|
||||
}
|
||||
|
||||
static int ingenic_adc_read_chan_info_raw(struct iio_dev *iio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val)
|
||||
{
|
||||
struct ingenic_adc *adc = iio_priv(iio_dev);
|
||||
int ret;
|
||||
|
||||
ret = clk_enable(adc->clk);
|
||||
if (ret) {
|
||||
dev_err(iio_dev->dev.parent, "Failed to enable clock: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* We cannot sample the aux channels in parallel. */
|
||||
scoped_guard(mutex, &adc->aux_lock)
|
||||
ret = __ingenic_adc_read_chan(adc, chan, val);
|
||||
|
||||
clk_disable(adc->clk);
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@
|
|||
*
|
||||
* Copyright (c) 2023, Liam Beguin <liambeguin@gmail.com>
|
||||
*/
|
||||
#include <linux/array_size.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/kernel.h>
|
||||
|
|
@ -34,12 +36,14 @@
|
|||
* @client: I2C reference
|
||||
* @lock: Lock to serialize data access
|
||||
* @vref_mv: Internal voltage reference
|
||||
* @read_delay_us: Chip-specific read delay in microseconds
|
||||
*/
|
||||
struct ltc2309 {
|
||||
struct device *dev;
|
||||
struct i2c_client *client;
|
||||
struct mutex lock; /* serialize data access */
|
||||
int vref_mv;
|
||||
unsigned int read_delay_us;
|
||||
};
|
||||
|
||||
/* Order matches expected channel address, See datasheet Table 1. */
|
||||
|
|
@ -117,20 +121,22 @@ static const struct iio_chan_spec ltc2309_channels[] = {
|
|||
|
||||
struct ltc2309_chip_info {
|
||||
const char *name;
|
||||
const struct iio_chan_spec *channels;
|
||||
unsigned int read_delay_us;
|
||||
int num_channels;
|
||||
const struct iio_chan_spec *channels __counted_by_ptr(num_channels);
|
||||
};
|
||||
|
||||
static const struct ltc2309_chip_info ltc2305_chip_info = {
|
||||
.name = "ltc2305",
|
||||
.channels = ltc2305_channels,
|
||||
.read_delay_us = 2,
|
||||
.num_channels = ARRAY_SIZE(ltc2305_channels),
|
||||
.channels = ltc2305_channels,
|
||||
};
|
||||
|
||||
static const struct ltc2309_chip_info ltc2309_chip_info = {
|
||||
.name = "ltc2309",
|
||||
.channels = ltc2309_channels,
|
||||
.num_channels = ARRAY_SIZE(ltc2309_channels),
|
||||
.channels = ltc2309_channels,
|
||||
};
|
||||
|
||||
static int ltc2309_read_raw_channel(struct ltc2309 *ltc2309,
|
||||
|
|
@ -151,6 +157,9 @@ static int ltc2309_read_raw_channel(struct ltc2309 *ltc2309,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (ltc2309->read_delay_us)
|
||||
fsleep(ltc2309->read_delay_us);
|
||||
|
||||
ret = i2c_master_recv(ltc2309->client, (char *)&buf, 2);
|
||||
if (ret < 0) {
|
||||
dev_err(ltc2309->dev, "i2c read failed: %pe\n", ERR_PTR(ret));
|
||||
|
|
@ -206,6 +215,7 @@ static int ltc2309_probe(struct i2c_client *client)
|
|||
|
||||
ltc2309->dev = &indio_dev->dev;
|
||||
ltc2309->client = client;
|
||||
ltc2309->read_delay_us = chip_info->read_delay_us;
|
||||
|
||||
indio_dev->name = chip_info->name;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
|
@ -233,8 +243,8 @@ static const struct of_device_id ltc2309_of_match[] = {
|
|||
MODULE_DEVICE_TABLE(of, ltc2309_of_match);
|
||||
|
||||
static const struct i2c_device_id ltc2309_id[] = {
|
||||
{ "ltc2305", (kernel_ulong_t)<c2305_chip_info },
|
||||
{ "ltc2309", (kernel_ulong_t)<c2309_chip_info },
|
||||
{ .name = "ltc2305", .driver_data = (kernel_ulong_t)<c2305_chip_info },
|
||||
{ .name = "ltc2309", .driver_data = (kernel_ulong_t)<c2309_chip_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ltc2309_id);
|
||||
|
|
|
|||
|
|
@ -136,8 +136,8 @@ static int ltc2471_i2c_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id ltc2471_i2c_id[] = {
|
||||
{ "ltc2471", ltc2471 },
|
||||
{ "ltc2473", ltc2473 },
|
||||
{ .name = "ltc2471", .driver_data = ltc2471 },
|
||||
{ .name = "ltc2473", .driver_data = ltc2473 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ltc2471_i2c_id);
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ static int ltc2485_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id ltc2485_id[] = {
|
||||
{ "ltc2485" },
|
||||
{ .name = "ltc2485" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ltc2485_id);
|
||||
|
|
|
|||
|
|
@ -142,8 +142,8 @@ static const struct ltc2497_chip_info ltc2497_info[] = {
|
|||
};
|
||||
|
||||
static const struct i2c_device_id ltc2497_id[] = {
|
||||
{ "ltc2497", (kernel_ulong_t)<c2497_info[TYPE_LTC2497] },
|
||||
{ "ltc2499", (kernel_ulong_t)<c2497_info[TYPE_LTC2499] },
|
||||
{ .name = "ltc2497", .driver_data = (kernel_ulong_t)<c2497_info[TYPE_LTC2497] },
|
||||
{ .name = "ltc2499", .driver_data = (kernel_ulong_t)<c2497_info[TYPE_LTC2499] },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ltc2497_id);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user