IIO: 1st set of new device support, features and cleanup for 6.7

Particularly great to see a resolver driver move out of staging via a
 massive set of changes.  Only took 13 years :)
 
 One small patch added then reverted due to a report of test breakage
 (ashai-kasei,ak8975: Drop deprecated enums.)
 
 An immutable branch was used for some hid-senors changes in case
 there was a need to take them into the HID tree as well.
 
 New device support
 -----------------
 
 adi,hmc425a
   - Add support for HMC540SLP3E broadband 4-bit digital attenuator.
 kionix,kx022a
   - Add support for the kx132-1211 accelerometer. Require significant
     driver rework to enable this including add a chip type specific
     structure to deal with the chip differences.
   - Add support for the kx132acr-lbz accelerometer (subset of the kx022a
     feature set).
 lltc,ltc2309
   - New driver for this 8 channel ADC.
 microchip,mcp3911
   - Add support for rest of mcp391x family of ADCs (there are various
     differences beyond simple channel count variation.
     Series includes some general driver cleanup.
 microchip,mcp3564
   - New driver for MCP3461, MCP3462, MCP3464, MCP3541, MCP3562, MCP3564
     and their R variants of 16/24bit ADCs. A few minor fixed followed.
 rohm,bu1390
   - New driver for this pressure sensor.
 
 Staging graduation
 ------------------
 
 adi,ad1210 (after 13 or so years :)
   - More or less a complete (step-wise) rewrite of this resolver driver
     to bring it up to date with modern IIO standards.  The fault signal
     handling mapping to event channels was particularly complex and
     significant part of the changes.
 
 Features
 --------
 
 iio-core
  - Add chromacity and color temperature channel types.
 adi,ad7192
   - Oversampling ratio control (called fast settling in datasheet).
 adi,adis16475
   - Add core support and then driver support for delta angle and delta
     velocity channels. These are intended for summation to establish
     angle and velocity changes over larger timescales.  Fix was
     needed for alignment after the temperature channel.  Further fix
     reduced set of devices for which the buffer support was applicable
     as seems burst reads don't cover these on all devices.
 hid-sensors-als
   - Chromacity and color temperatures support including in amd sfh.
 stx104
   - Add support for counter subsystem to this multipurpose device.
 ti,twl6030
   - Add missing device tree binding description.
 
 Clean up and minor fixes.
 ------------------------
 
 treewide
   - Drop some unused declarations across IIO.
   - Make more use of device_get_match_data() instead of OF specific
     approaches.
 Similar cleanup to sets of drivers.
   - Stop platform remove callbacks returning anything by using the
     temporary remove_new() callback.
   - Use i2c_get_match_data() to cope nicely with all types of ID table
     entry.
   - Use device_get_match_data() for various platform device to cope
     with more types of firmware.
   - Convert from enum to pointer in ID tables allowing use of
     i2c_get_match_data().
   - Fix sorting on some ID tables.
   - Include specific string helper headers rather than simply string_helpers.h
 docs
   - Better description of the ordering requirements etc for
     available_scan_masks.
 tools
   - Handle alignment of mixed sizes where the last element isn't the biggest
     correctly. Seems that doesn't happen often!
 adi,ad2s1210
   - Lots of work from David Lechner on this driver including a few fixes
     that are going with the rework to avoid slowing that down.
 adi,ad4310
   - Replace deprecated devm_clk_register()
 adi,ad74413r
   - Bring the channel function setting inline with the datasheet.
 adi,ad7192
   - Change to FIELD_PREP(), FIELD_GET().
   - Calculate f_order from the sinc filter and chop filter states.
   - Move more per chip config into data in struct ad7192_chip_info
   - Cleanup unused parameter in channel macros.
 adi,adf4350
   - Make use of devm_* to simplify error handling for many of the setup
     calls in probe() / tear down in remove() and error paths.  Some more
     work to be done on this one.
   - Use dev_err_probe() for errors in probe() callback.
 adi,adf4413
   - Typo in function name prefix.
 adi,adxl345
   - Add channel scale to the chip type specific structure and drop
     using a type field previously used for indirection.
 asahi,ak8985
   - Fix a mismatch introduced when switching from enum->pointers
     in the match tables.
 amlogic,meson
   - Expand error logging during probe.
 invensense,mpu6050
   - Support level-shifter control. Whilst no one is sure exactly what this
     is doing it is needed for some old boards.
   - Document mount-matrix dt-binding.
 mediatek,mt6577
   - Use devm_clk_get_enabled() to replace open coded version and move
     everything over to being device managed. Drop now empty remove()
     callback. Fix follows to put the drvdata back.
   - Use dev_err_probe() for error reporting in probe() callback.
 memsic,mxc4005
   - Add of_match_table.
 microchip,mcp4725
   - Move various chip specific data from being looked up by chip ID to
     data in the chip type specific structure.
 silicon-labs,si7005
   - Add of_match_table and entry in trivial-devices.yaml
 st,lsm6dsx
   - Add missing mount-matrix dt binding documentation.
 st,spear
   - Use devm_clk_get_enabled() and some other devm calls to move everything
     over to being device managed.  Drop now empty remove() callback.
   - Use dev_err_probe() to better handled deferred probing and tidy up
     error reporting in probe() callback.
 st,stm32-adc
   - Add a bit of additional checking in probe() to protect against a NULL
     pointer (no known path to trigger it today).
   - Replace deprecated strncpy()
 ti,ads1015
   - Allow for edge triggers.
   - Document interrupt in dt-bindings.
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCAAvFiEEbilms4eEBlKRJoGxVIU0mcT0FogFAmUu3sURHGppYzIzQGtl
 cm5lbC5vcmcACgkQVIU0mcT0FohL9w/+PVaeiYsmuJfWcxjVhiGFz+HBbwSFcHFp
 ASXuYq9rYoea62JlvcLB3GJ43ziB80Am5qA5bWTkPHFqbAPZlgDzoGZGPMrpjfI1
 iV6NwiPigRRTw2JjB0TDS8HepQomA1qA0FwXngLrSy1eQmN0/NJOp0k8m54OpCV+
 FdW3dDy7UomXyVCb+OAOWNYvV20ZOK1/WK9yWCpPWZtOKMfX2cLLqiwtjm6VdXTg
 wtqSRVfBB/p7k3UapXiLuz4fExEancW4z2qYEaBK2beba6LFuFzvfwq/t6CJwVWD
 wd6mif+1eTtR9wxZcsmefsbB6r9zOd4eWRaCBjmW3fm9xNY2UDzWT29YpyDOyA8R
 llu44gDtlJvDpyUYi44rLDyZO886fJtlVLyOHOaVJy77SV+so16P9qC2qd9dJXtw
 8/exWxNmiA/LwVq+SvvVgfY33yCynKv5St1cHMDDFzC1eZMnVGAaZ4HBp1wiGGuN
 T1ZWKMDWViH5F7ug2pKopKoemQyhmsa8JbUQc+NZS+5efdn6LlVhe1BVZ+4/A3jb
 BQ838lkl3O8D0XkS7urM6Ggs8m/D0eBLBpfgID/C4OaEJnn6G1ZVvNue5r99SNws
 JV9T7zJQ8G1NKl3s1+JrwBf7XeSKtlZa0cbWejbe4Ib2u+G9M863YS0Ivrk5yH+C
 XIojuxjOOmQ=
 =wth0
 -----END PGP SIGNATURE-----

Merge tag 'iio-for-6.7a' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into char-misc-next

Jonathan writes:

IIO: 1st set of new device support, features and cleanup for 6.7

Particularly great to see a resolver driver move out of staging via a
massive set of changes.  Only took 13 years :)

One small patch added then reverted due to a report of test breakage
(ashai-kasei,ak8975: Drop deprecated enums.)

An immutable branch was used for some hid-senors changes in case
there was a need to take them into the HID tree as well.

New device support
-----------------

adi,hmc425a
  - Add support for HMC540SLP3E broadband 4-bit digital attenuator.
kionix,kx022a
  - Add support for the kx132-1211 accelerometer. Require significant
    driver rework to enable this including add a chip type specific
    structure to deal with the chip differences.
  - Add support for the kx132acr-lbz accelerometer (subset of the kx022a
    feature set).
lltc,ltc2309
  - New driver for this 8 channel ADC.
microchip,mcp3911
  - Add support for rest of mcp391x family of ADCs (there are various
    differences beyond simple channel count variation.
    Series includes some general driver cleanup.
microchip,mcp3564
  - New driver for MCP3461, MCP3462, MCP3464, MCP3541, MCP3562, MCP3564
    and their R variants of 16/24bit ADCs. A few minor fixed followed.
rohm,bu1390
  - New driver for this pressure sensor.

Staging graduation
------------------

adi,ad1210 (after 13 or so years :)
  - More or less a complete (step-wise) rewrite of this resolver driver
    to bring it up to date with modern IIO standards.  The fault signal
    handling mapping to event channels was particularly complex and
    significant part of the changes.

Features
--------

iio-core
 - Add chromacity and color temperature channel types.
adi,ad7192
  - Oversampling ratio control (called fast settling in datasheet).
adi,adis16475
  - Add core support and then driver support for delta angle and delta
    velocity channels. These are intended for summation to establish
    angle and velocity changes over larger timescales.  Fix was
    needed for alignment after the temperature channel.  Further fix
    reduced set of devices for which the buffer support was applicable
    as seems burst reads don't cover these on all devices.
hid-sensors-als
  - Chromacity and color temperatures support including in amd sfh.
stx104
  - Add support for counter subsystem to this multipurpose device.
ti,twl6030
  - Add missing device tree binding description.

Clean up and minor fixes.
------------------------

treewide
  - Drop some unused declarations across IIO.
  - Make more use of device_get_match_data() instead of OF specific
    approaches.
Similar cleanup to sets of drivers.
  - Stop platform remove callbacks returning anything by using the
    temporary remove_new() callback.
  - Use i2c_get_match_data() to cope nicely with all types of ID table
    entry.
  - Use device_get_match_data() for various platform device to cope
    with more types of firmware.
  - Convert from enum to pointer in ID tables allowing use of
    i2c_get_match_data().
  - Fix sorting on some ID tables.
  - Include specific string helper headers rather than simply string_helpers.h
docs
  - Better description of the ordering requirements etc for
    available_scan_masks.
tools
  - Handle alignment of mixed sizes where the last element isn't the biggest
    correctly. Seems that doesn't happen often!
adi,ad2s1210
  - Lots of work from David Lechner on this driver including a few fixes
    that are going with the rework to avoid slowing that down.
adi,ad4310
  - Replace deprecated devm_clk_register()
adi,ad74413r
  - Bring the channel function setting inline with the datasheet.
adi,ad7192
  - Change to FIELD_PREP(), FIELD_GET().
  - Calculate f_order from the sinc filter and chop filter states.
  - Move more per chip config into data in struct ad7192_chip_info
  - Cleanup unused parameter in channel macros.
adi,adf4350
  - Make use of devm_* to simplify error handling for many of the setup
    calls in probe() / tear down in remove() and error paths.  Some more
    work to be done on this one.
  - Use dev_err_probe() for errors in probe() callback.
adi,adf4413
  - Typo in function name prefix.
adi,adxl345
  - Add channel scale to the chip type specific structure and drop
    using a type field previously used for indirection.
asahi,ak8985
  - Fix a mismatch introduced when switching from enum->pointers
    in the match tables.
amlogic,meson
  - Expand error logging during probe.
invensense,mpu6050
  - Support level-shifter control. Whilst no one is sure exactly what this
    is doing it is needed for some old boards.
  - Document mount-matrix dt-binding.
mediatek,mt6577
  - Use devm_clk_get_enabled() to replace open coded version and move
    everything over to being device managed. Drop now empty remove()
    callback. Fix follows to put the drvdata back.
  - Use dev_err_probe() for error reporting in probe() callback.
memsic,mxc4005
  - Add of_match_table.
microchip,mcp4725
  - Move various chip specific data from being looked up by chip ID to
    data in the chip type specific structure.
silicon-labs,si7005
  - Add of_match_table and entry in trivial-devices.yaml
st,lsm6dsx
  - Add missing mount-matrix dt binding documentation.
st,spear
  - Use devm_clk_get_enabled() and some other devm calls to move everything
    over to being device managed.  Drop now empty remove() callback.
  - Use dev_err_probe() to better handled deferred probing and tidy up
    error reporting in probe() callback.
st,stm32-adc
  - Add a bit of additional checking in probe() to protect against a NULL
    pointer (no known path to trigger it today).
  - Replace deprecated strncpy()
ti,ads1015
  - Allow for edge triggers.
  - Document interrupt in dt-bindings.

* tag 'iio-for-6.7a' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (201 commits)
  iio: Use device_get_match_data()
  iio: adc: MCP3564: fix warn: unsigned '__x' is never less than zero.
  dt-bindings: trivial-devices: add silabs,si7005
  iio: si7005: Add device tree support
  drivers: imu: adis16475.c: Remove scan index from delta channels
  dt-bindings: iio: imu: st,lsm6dsx: add mount-matrix property
  iio: resolver: ad2s1210: remove of_match_ptr()
  iio: resolver: ad2s1210: remove DRV_NAME macro
  iio: resolver: ad2s1210: move out of staging
  staging: iio: resolver: ad2s1210: simplify code with guard(mutex)
  staging: iio: resolver: ad2s1210: clear faults after soft reset
  staging: iio: resolver: ad2s1210: refactor sample toggle
  staging: iio: resolver: ad2s1210: remove fault attribute
  staging: iio: resolver: ad2s1210: add label attribute support
  staging: iio: resolver: ad2s1210: add register/fault support summary
  staging: iio: resolver: ad2s1210: implement fault events
  iio: event: add optional event label support
  staging: iio: resolver: ad2s1210: rename DOS reset min/max attrs
  staging: iio: resolver: ad2s1210: convert DOS mismatch threshold to event attr
  staging: iio: resolver: ad2s1210: convert DOS overrange threshold to event attr
  ...
This commit is contained in:
Greg Kroah-Hartman 2023-10-20 07:54:15 +02:00
commit b4b6cc10c6
147 changed files with 7204 additions and 2001 deletions

View File

@ -279,6 +279,35 @@ Description:
but should match other such assignments on device).
Units after application of scale and offset are m/s^2.
What: /sys/bus/iio/devices/iio:deviceX/in_deltaangl_x_raw
What: /sys/bus/iio/devices/iio:deviceX/in_deltaangl_y_raw
What: /sys/bus/iio/devices/iio:deviceX/in_deltaangl_z_raw
KernelVersion: 6.5
Contact: linux-iio@vger.kernel.org
Description:
Angular displacement between two consecutive samples on x, y or
z (may be arbitrarily assigned but should match other such
assignments on device).
In order to compute the total angular displacement during a
desired period of time, the application should sum-up the delta
angle samples acquired during that time.
Units after application of scale and offset are radians.
What: /sys/bus/iio/devices/iio:deviceX/in_deltavelocity_x_raw
What: /sys/bus/iio/devices/iio:deviceX/in_deltavelocity_y_raw
What: /sys/bus/iio/devices/iio:deviceX/in_deltavelocity_z_raw
KernelVersion: 6.5
Contact: linux-iio@vger.kernel.org
Description:
The linear velocity change between two consecutive samples on x,
y or z (may be arbitrarily assigned but should match other such
assignments on device).
In order to compute the total linear velocity change during a
desired period of time, the application should sum-up the delta
velocity samples acquired during that time.
Units after application of scale and offset are meters per
second.
What: /sys/bus/iio/devices/iio:deviceX/in_angl_raw
What: /sys/bus/iio/devices/iio:deviceX/in_anglY_raw
KernelVersion: 4.17
@ -461,6 +490,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_humidityrelative_scale
What: /sys/bus/iio/devices/iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_scale
What: /sys/bus/iio/devices/iio:deviceX/in_illuminance_scale
What: /sys/bus/iio/devices/iio:deviceX/in_countY_scale
What: /sys/bus/iio/devices/iio:deviceX/in_deltaangl_scale
What: /sys/bus/iio/devices/iio:deviceX/in_deltavelocity_scale
What: /sys/bus/iio/devices/iio:deviceX/in_angl_scale
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_x_scale
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_y_scale
@ -1332,6 +1363,12 @@ Description:
What: /sys/.../iio:deviceX/bufferY/in_accel_x_en
What: /sys/.../iio:deviceX/bufferY/in_accel_y_en
What: /sys/.../iio:deviceX/bufferY/in_accel_z_en
What: /sys/.../iio:deviceX/bufferY/in_deltaangl_x_en
What: /sys/.../iio:deviceX/bufferY/in_deltaangl_y_en
What: /sys/.../iio:deviceX/bufferY/in_deltaangl_z_en
What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_x_en
What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_y_en
What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_z_en
What: /sys/.../iio:deviceX/bufferY/in_anglvel_x_en
What: /sys/.../iio:deviceX/bufferY/in_anglvel_y_en
What: /sys/.../iio:deviceX/bufferY/in_anglvel_z_en
@ -1362,6 +1399,8 @@ Description:
Scan element control for triggered data capture.
What: /sys/.../iio:deviceX/bufferY/in_accel_type
What: /sys/.../iio:deviceX/bufferY/in_deltaangl_type
What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_type
What: /sys/.../iio:deviceX/bufferY/in_anglvel_type
What: /sys/.../iio:deviceX/bufferY/in_magn_type
What: /sys/.../iio:deviceX/bufferY/in_incli_type
@ -1416,6 +1455,12 @@ What: /sys/.../iio:deviceX/bufferY/in_voltage_q_index
What: /sys/.../iio:deviceX/bufferY/in_accel_x_index
What: /sys/.../iio:deviceX/bufferY/in_accel_y_index
What: /sys/.../iio:deviceX/bufferY/in_accel_z_index
What: /sys/.../iio:deviceX/bufferY/in_deltaangl_x_index
What: /sys/.../iio:deviceX/bufferY/in_deltaangl_y_index
What: /sys/.../iio:deviceX/bufferY/in_deltaangl_z_index
What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_x_index
What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_y_index
What: /sys/.../iio:deviceX/bufferY/in_deltavelocity_z_index
What: /sys/.../iio:deviceX/bufferY/in_anglvel_x_index
What: /sys/.../iio:deviceX/bufferY/in_anglvel_y_index
What: /sys/.../iio:deviceX/bufferY/in_anglvel_z_index
@ -2179,3 +2224,33 @@ Contact: linux-iio@vger.kernel.org
Description:
Number of conditions that must occur, during a running
period, before an event is generated.
What: /sys/bus/iio/devices/iio:deviceX/in_colortemp_raw
KernelVersion: 6.7
Contact: linux-iio@vger.kernel.org
Description:
Represents light color temperature, which measures light color
temperature in Kelvin.
What: /sys/bus/iio/devices/iio:deviceX/in_chromaticity_x_raw
What: /sys/bus/iio/devices/iio:deviceX/in_chromaticity_y_raw
KernelVersion: 6.7
Contact: linux-iio@vger.kernel.org
Description:
The x and y light color coordinate on the CIE 1931 chromaticity
diagram.
What: /sys/bus/iio/devices/iio:deviceX/events/in_altvoltageY_mag_either_label
What: /sys/bus/iio/devices/iio:deviceX/events/in_altvoltageY_mag_rising_label
What: /sys/bus/iio/devices/iio:deviceX/events/in_altvoltageY_thresh_falling_label
What: /sys/bus/iio/devices/iio:deviceX/events/in_altvoltageY_thresh_rising_label
What: /sys/bus/iio/devices/iio:deviceX/events/in_anglvelY_mag_rising_label
What: /sys/bus/iio/devices/iio:deviceX/events/in_anglY_thresh_rising_label
What: /sys/bus/iio/devices/iio:deviceX/events/in_phaseY_mag_rising_label
KernelVersion: 6.7
Contact: linux-iio@vger.kernel.org
Description:
Optional symbolic label to a device channel event.
If a label is defined for this event add that to the event
specific attributes. This is useful for userspace to be able to
better identify an individual event.

View File

@ -0,0 +1,53 @@
What: /sys/bus/iio/devices/iio:deviceX/boost_current_gain
KernelVersion: 6.4
Contact: linux-iio@vger.kernel.org
Description:
This attribute is used to set the gain of the biasing current
circuit of the Delta-Sigma modulator. The different BOOST
settings are applied to the entire modulator circuit, including
the voltage reference buffers.
What: /sys/bus/iio/devices/iio:deviceX/boost_current_gain_available
KernelVersion: 6.4
Contact: linux-iio@vger.kernel.org
Description:
Reading returns a list with the possible gain values for
the current biasing circuit of the Delta-Sigma modulator.
What: /sys/bus/iio/devices/iio:deviceX/auto_zeroing_mux_enable
KernelVersion: 6.4
Contact: linux-iio@vger.kernel.org
Description:
This attribute is used to enable the analog input multiplexer
auto-zeroing algorithm (the input multiplexer and the ADC
include an offset cancellation algorithm that cancels the offset
contribution of the ADC). When the offset cancellation algorithm
is enabled, ADC takes two conversions, one with the differential
input as VIN+/VIN-, one with VIN+/VIN- inverted. In this case the
conversion time is multiplied by two compared to the default
case where the algorithm is disabled. This technique allows the
cancellation of the ADC offset error and the achievement of
ultra-low offset without any digital calibration. The resulting
offset is the residue of the difference between the two
conversions, which is on the order of magnitude of the noise
floor. This offset is effectively canceled at every conversion,
so the residual offset error temperature drift is extremely low.
Write '1' to enable it, write '0' to disable it.
What: /sys/bus/iio/devices/iio:deviceX/auto_zeroing_ref_enable
KernelVersion: 6.4
Contact: linux-iio@vger.kernel.org
Description:
This attribute is used to enable the chopping algorithm for the
internal voltage reference buffer. This setting has no effect
when external voltage reference is selected.
Internal voltage reference buffer injects a certain quantity of
1/f noise into the system that can be modulated with the
incoming input signals and can limit the SNR performance at
higher Oversampling Ratio values (over 256). To overcome this
limitation, the buffer includes an auto-zeroing algorithm that
greatly reduces (cancels out) the 1/f noise and cancels the
offset value of the reference buffer. As a result, the SNR of
the system is not affected by this 1/f noise component of the
reference buffer, even at maximum oversampling ratio values.
Write '1' to enable it, write '0' to disable it.

View File

@ -0,0 +1,27 @@
What: /sys/bus/iio/devices/iio:deviceX/events/in_altvoltage0_mag_rising_reset_max
KernelVersion: 6.7
Contact: linux-iio@vger.kernel.org
Description:
Reading returns the current Degradation of Signal Reset Maximum
Threshold value in millivolts. Writing sets the value.
What: /sys/bus/iio/devices/iio:deviceX/events/in_altvoltage0_mag_rising_reset_max_available
KernelVersion: 6.7
Contact: linux-iio@vger.kernel.org
Description:
Reading returns the allowable voltage range for
in_altvoltage0_mag_rising_reset_max.
What: /sys/bus/iio/devices/iio:deviceX/events/in_altvoltage0_mag_rising_reset_min
KernelVersion: 6.7
Contact: linux-iio@vger.kernel.org
Description:
Reading returns the current Degradation of Signal Reset Minimum
Threshold value in millivolts. Writing sets the value.
What: /sys/bus/iio/devices/iio:deviceX/events/in_altvoltage0_mag_rising_reset_min_available
KernelVersion: 6.7
Contact: linux-iio@vger.kernel.org
Description:
Reading returns the allowable voltage range for
in_altvoltage0_mag_rising_reset_min.

View File

@ -4,19 +4,23 @@
$id: http://devicetree.org/schemas/iio/accel/kionix,kx022a.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ROHM/Kionix KX022A Accelerometer
title: ROHM/Kionix KX022A, KX132-1211 and KX132ACR-LBZ Accelerometers
maintainers:
- Matti Vaittinen <mazziesaccount@gmail.com>
description: |
KX022A is a 3-axis accelerometer supporting +/- 2G, 4G, 8G and 16G ranges,
output data-rates from 0.78Hz to 1600Hz and a hardware-fifo buffering.
KX022A can be accessed either via I2C or SPI.
KX022A, KX132ACR-LBZ and KX132-1211 are 3-axis accelerometers supporting
+/- 2G, 4G, 8G and 16G ranges, variable output data-rates and a
hardware-fifo buffering. These accelerometers can be accessed either
via I2C or SPI.
properties:
compatible:
const: kionix,kx022a
enum:
- kionix,kx022a
- kionix,kx132-1211
- rohm,kx132acr-lbz
reg:
maxItems: 1

View File

@ -4,21 +4,31 @@
$id: http://devicetree.org/schemas/iio/adc/lltc,ltc2497.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Linear Technology / Analog Devices LTC2497 ADC
title: Linear Technology / Analog Devices LTC2497 and LTC2309 ADC
maintainers:
- Michael Hennerich <michael.hennerich@analog.com>
- Liam Beguin <liambeguin@gmail.com>
description: |
16bit ADC supporting up to 16 single ended or 8 differential inputs.
I2C interface.
LTC2309:
low noise, low power, 8-channel, 12-bit successive approximation ADC with an
I2C compatible serial interface.
https://www.analog.com/media/en/technical-documentation/data-sheets/2497fb.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/2499fe.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/2309fd.pdf
LTC2497:
LTC2499:
16bit ADC supporting up to 16 single ended or 8 differential inputs.
I2C interface.
https://www.analog.com/media/en/technical-documentation/data-sheets/2497fb.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/2499fe.pdf
properties:
compatible:
enum:
- lltc,ltc2309
- lltc,ltc2497
- lltc,ltc2499

View File

@ -0,0 +1,205 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/microchip,mcp3564.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Microchip MCP346X and MCP356X ADC Family
maintainers:
- Marius Cristea <marius.cristea@microchip.com>
description: |
Bindings for the Microchip family of 153.6 ksps, Low-Noise 16/24-Bit
Delta-Sigma ADCs with an SPI interface. Datasheet can be found here:
Datasheet for MCP3561, MCP3562, MCP3564 can be found here:
https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/MCP3561-2-4-Family-Data-Sheet-DS20006181C.pdf
Datasheet for MCP3561R, MCP3562R, MCP3564R can be found here:
https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/MCP3561_2_4R-Data-Sheet-DS200006391C.pdf
Datasheet for MCP3461, MCP3462, MCP3464 can be found here:
https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/MCP3461-2-4-Two-Four-Eight-Channel-153.6-ksps-Low-Noise-16-Bit-Delta-Sigma-ADC-Data-Sheet-20006180D.pdf
Datasheet for MCP3461R, MCP3462R, MCP3464R can be found here:
https://ww1.microchip.com/downloads/aemDocuments/documents/APID/ProductDocuments/DataSheets/MCP3461-2-4R-Family-Data-Sheet-DS20006404C.pdf
properties:
compatible:
enum:
- microchip,mcp3461
- microchip,mcp3462
- microchip,mcp3464
- microchip,mcp3461r
- microchip,mcp3462r
- microchip,mcp3464r
- microchip,mcp3561
- microchip,mcp3562
- microchip,mcp3564
- microchip,mcp3561r
- microchip,mcp3562r
- microchip,mcp3564r
reg:
maxItems: 1
spi-max-frequency:
maximum: 20000000
spi-cpha: true
spi-cpol: true
vdd-supply: true
avdd-supply: true
clocks:
description:
Phandle and clock identifier for external sampling clock.
If not specified, the internal crystal oscillator will be used.
maxItems: 1
interrupts:
description: IRQ line of the ADC
maxItems: 1
drive-open-drain:
description:
Whether to drive the IRQ signal as push-pull (default) or open-drain. Note
that the device requires this pin to become "high", otherwise it will stop
converting.
type: boolean
vref-supply:
description:
Some devices have a specific reference voltage supplied on a different
pin to the other supplies. Needed to be able to establish channel scaling
unless there is also an internal reference available (e.g. mcp3564r). In
case of "r" devices (e. g. mcp3564r), if it does not exists the internal
reference will be used.
microchip,hw-device-address:
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 3
description:
The address is set on a per-device basis by fuses in the factory,
configured on request. If not requested, the fuses are set for 0x1.
The device address is part of the device markings to avoid
potential confusion. This address is coded on two bits, so four possible
addresses are available when multiple devices are present on the same
SPI bus with only one Chip Select line for all devices.
Each device communication starts by a CS falling edge, followed by the
clocking of the device address (BITS[7:6] - top two bits of COMMAND BYTE
which is first one on the wire).
"#io-channel-cells":
const: 1
"#address-cells":
const: 1
"#size-cells":
const: 0
patternProperties:
"^channel@([0-9]|([1-7][0-9]))$":
$ref: adc.yaml
type: object
unevaluatedProperties: false
description: Represents the external channels which are connected to the ADC.
properties:
reg:
description: The channel number in single-ended and differential mode.
minimum: 0
maximum: 79
required:
- reg
dependencies:
spi-cpol: [ spi-cpha ]
spi-cpha: [ spi-cpol ]
required:
- compatible
- reg
- microchip,hw-device-address
- spi-max-frequency
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
- # External vref, no internal reference
if:
properties:
compatible:
contains:
enum:
- microchip,mcp3461
- microchip,mcp3462
- microchip,mcp3464
- microchip,mcp3561
- microchip,mcp3562
- microchip,mcp3564
then:
required:
- vref-supply
unevaluatedProperties: false
examples:
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
adc@0 {
compatible = "microchip,mcp3564r";
reg = <0>;
vref-supply = <&vref_reg>;
spi-cpha;
spi-cpol;
spi-max-frequency = <10000000>;
microchip,hw-device-address = <1>;
#address-cells = <1>;
#size-cells = <0>;
channel@0 {
/* CH0 to AGND */
reg = <0>;
label = "CH0";
};
channel@1 {
/* CH1 to AGND */
reg = <1>;
label = "CH1";
};
/* diff-channels */
channel@11 {
reg = <11>;
/* CN0, CN1 */
diff-channels = <0 1>;
label = "CH0_CH1";
};
channel@22 {
reg = <0x22>;
/* CN1, CN2 */
diff-channels = <1 2>;
label = "CH1_CH3";
};
channel@23 {
reg = <0x23>;
/* CN1, CN3 */
diff-channels = <1 3>;
label = "CH1_CH3";
};
};
};
...

View File

@ -18,7 +18,13 @@ description: |
properties:
compatible:
enum:
- microchip,mcp3910
- microchip,mcp3911
- microchip,mcp3912
- microchip,mcp3913
- microchip,mcp3914
- microchip,mcp3918
- microchip,mcp3919
reg:
maxItems: 1

View File

@ -23,6 +23,9 @@ properties:
reg:
maxItems: 1
interrupts:
maxItems: 1
"#address-cells":
const: 1

View File

@ -0,0 +1,43 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/ti,twl6030-gpadc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: GPADC subsystem in the TWL6030 power module
maintainers:
- Andreas Kemnade <andreas@kemnade.info>
description:
The GPADC subsystem in the TWL603X consists of a 10-bit ADC
combined with a 15-input analog multiplexer in the TWL6030 resp. a
19-input analog muliplexer in the TWL6032.
properties:
compatible:
enum:
- ti,twl6030-gpadc
- ti,twl6032-gpadc
interrupts:
maxItems: 1
"#io-channel-cells":
const: 1
required:
- compatible
- interrupts
- "#io-channel-cells"
additionalProperties: false
examples:
- |
gpadc {
compatible = "ti,twl6030-gpadc";
interrupts = <3>;
#io-channel-cells = <1>;
};
...

View File

@ -4,20 +4,26 @@
$id: http://devicetree.org/schemas/iio/amplifiers/adi,hmc425a.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: HMC425A 6-bit Digital Step Attenuator
title: Analog Devices HMC425A and similar Digital Step Attenuators
maintainers:
- Michael Hennerich <michael.hennerich@analog.com>
description: |
Digital Step Attenuator IIO device with gpio interface.
Digital Step Attenuator IIO devices with gpio interface.
Offer various frequency and attenuation ranges.
HMC425A 0.5 dB LSB GaAs MMIC 6-BIT DIGITAL POSITIVE CONTROL ATTENUATOR, 2.2 - 8.0 GHz
https://www.analog.com/media/en/technical-documentation/data-sheets/hmc425A.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/hmc425A.pdf
HMC540S 1 dB LSB Silicon MMIC 4-Bit Digital Positive Control Attenuator, 0.1 - 8 GHz
https://www.analog.com/media/en/technical-documentation/data-sheets/hmc540s.pdf
properties:
compatible:
enum:
- adi,hmc425a
- adi,hmc540s
vcc-supply: true

View File

@ -48,6 +48,11 @@ properties:
mount-matrix: true
invensense,level-shifter:
type: boolean
description: |
From ancient platform data struct: false: VLogic, true: VDD
i2c-gate:
$ref: /schemas/i2c/i2c-controller.yaml
unevaluatedProperties: false

View File

@ -93,6 +93,9 @@ properties:
wakeup-source:
$ref: /schemas/types.yaml#/definitions/flag
mount-matrix:
description: an optional 3x3 mounting rotation matrix
required:
- compatible
- reg

View File

@ -0,0 +1,52 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/pressure/rohm,bm1390.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: ROHM BM1390 pressure sensor
maintainers:
- Matti Vaittinen <mazziesaccount@gmail.com>
description:
BM1390GLV-Z is a pressure sensor which performs internal temperature
compensation for the MEMS. Pressure range is from 300 hPa to 1300 hPa
and sample averaging and IIR filtering is built in. Temperature
measurement is also supported.
properties:
compatible:
const: rohm,bm1390glv-z
reg:
maxItems: 1
interrupts:
maxItems: 1
vdd-supply: true
required:
- compatible
- reg
- vdd-supply
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
pressure-sensor@5d {
compatible = "rohm,bm1390glv-z";
reg = <0x5d>;
interrupt-parent = <&gpio1>;
interrupts = <29 IRQ_TYPE_LEVEL_LOW>;
vdd-supply = <&vdd>;
};
};

View File

@ -0,0 +1,177 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/resolver/adi,ad2s1210.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices AD2S1210 Resolver-to-Digital Converter
maintainers:
- Michael Hennerich <michael.hennerich@analog.com>
description: |
The AD2S1210 is a complete 10-bit to 16-bit resolution tracking
resolver-to-digital converter, integrating an on-board programmable
sinusoidal oscillator that provides sine wave excitation for
resolvers.
The AD2S1210 allows the user to read the angular position or the
angular velocity data directly from the parallel outputs or through
the serial interface.
The mode of operation of the communication channel (parallel or serial) is
selected by the A0 and A1 input pins. In normal mode, data is latched by
toggling the SAMPLE line and can then be read directly. In configuration mode,
data is read or written using a register access scheme (address byte with
read/write flag and data byte).
A1 A0 Result
0 0 Normal mode - position output
0 1 Normal mode - velocity output
1 0 Reserved
1 1 Configuration mode
In normal mode, the resolution of the digital output is selected using
the RES0 and RES1 input pins. In configuration mode, the resolution is
selected by setting the RES0 and RES1 bits in the control register.
RES1 RES0 Resolution (Bits)
0 0 10
0 1 12
1 0 14
1 1 16
Note on SPI connections: The CS line on the AD2S1210 should hard-wired to
logic low and the WR/FSYNC line on the AD2S1210 should be connected to the
SPI CSn output of the SPI controller.
Datasheet:
https://www.analog.com/media/en/technical-documentation/data-sheets/ad2s1210.pdf
properties:
compatible:
const: adi,ad2s1210
reg:
maxItems: 1
spi-max-frequency:
maximum: 25000000
spi-cpha: true
avdd-supply:
description:
A 4.75 to 5.25 V regulator that powers the Analog Supply Voltage (AVDD)
pin.
dvdd-supply:
description:
A 4.75 to 5.25 V regulator that powers the Digital Supply Voltage (DVDD)
pin.
vdrive-supply:
description:
A 2.3 to 5.25 V regulator that powers the Logic Power Supply Input
(VDrive) pin.
clocks:
maxItems: 1
description: External oscillator clock (CLKIN).
reset-gpios:
description:
GPIO connected to the /RESET pin. As the line needs to be low for the
reset to be active, it should be configured as GPIO_ACTIVE_LOW.
maxItems: 1
sample-gpios:
description:
GPIO connected to the /SAMPLE pin. As the line needs to be low to trigger
a sample, it should be configured as GPIO_ACTIVE_LOW.
maxItems: 1
mode-gpios:
description:
GPIO lines connected to the A0 and A1 pins. These pins select the data
transfer mode.
minItems: 2
maxItems: 2
resolution-gpios:
description:
GPIO lines connected to the RES0 and RES1 pins. These pins select the
resolution of the digital output. If omitted, it is assumed that the
RES0 and RES1 pins are hard-wired to match the assigned-resolution-bits
property.
minItems: 2
maxItems: 2
fault-gpios:
description:
GPIO lines connected to the LOT and DOS pins. These pins combined indicate
the type of fault present, if any. As these pins a pulled low to indicate
a fault condition, they should be configured as GPIO_ACTIVE_LOW.
minItems: 2
maxItems: 2
adi,fixed-mode:
description:
This is used to indicate the selected mode if A0 and A1 are hard-wired
instead of connected to GPIOS (i.e. mode-gpios is omitted).
$ref: /schemas/types.yaml#/definitions/string
enum: [config, velocity, position]
assigned-resolution-bits:
description:
Resolution of the digital output required by the application. This
determines the precision of the angle and/or the maximum speed that can
be measured. If resolution-gpios is omitted, it is assumed that RES0 and
RES1 are hard-wired to match this value.
enum: [10, 12, 14, 16]
required:
- compatible
- reg
- spi-cpha
- avdd-supply
- dvdd-supply
- vdrive-supply
- clocks
- sample-gpios
- assigned-resolution-bits
oneOf:
- required:
- mode-gpios
- required:
- adi,fixed-mode
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
resolver@0 {
compatible = "adi,ad2s1210";
reg = <0>;
spi-max-frequency = <20000000>;
spi-cpha;
avdd-supply = <&avdd_regulator>;
dvdd-supply = <&dvdd_regulator>;
vdrive-supply = <&vdrive_regulator>;
clocks = <&ext_osc>;
sample-gpios = <&gpio0 90 GPIO_ACTIVE_LOW>;
mode-gpios = <&gpio0 86 0>, <&gpio0 87 0>;
resolution-gpios = <&gpio0 88 0>, <&gpio0 89 0>;
assigned-resolution-bits = <16>;
};
};

View File

@ -348,6 +348,8 @@ properties:
# Silicon Labs SI3210 Programmable CMOS SLIC/CODEC with SPI interface
- silabs,si3210
# Relative Humidity and Temperature Sensors
- silabs,si7005
# Relative Humidity and Temperature Sensors
- silabs,si7020
# Skyworks SKY81452: Six-Channel White LED Driver with Touch Panel Bias Supply
- skyworks,sky81452

View File

@ -1118,7 +1118,7 @@ ANALOG DEVICES INC AD4130 DRIVER
M: Cosmin Tanislav <cosmin.tanislav@analog.com>
L: linux-iio@vger.kernel.org
S: Supported
W: http://ez.analog.com/community/linux-device-drivers
W: https://ez.analog.com/linux-software-drivers
F: Documentation/ABI/testing/sysfs-bus-iio-adc-ad4130
F: Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml
F: drivers/iio/adc/ad4130.c
@ -1151,7 +1151,7 @@ ANALOG DEVICES INC AD74115 DRIVER
M: Cosmin Tanislav <cosmin.tanislav@analog.com>
L: linux-iio@vger.kernel.org
S: Supported
W: http://ez.analog.com/community/linux-device-drivers
W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/iio/addac/adi,ad74115.yaml
F: drivers/iio/addac/ad74115.c
@ -12811,7 +12811,7 @@ MAX31827 TEMPERATURE SWITCH DRIVER
M: Daniel Matyas <daniel.matyas@analog.com>
L: linux-hwmon@vger.kernel.org
S: Supported
W: http://ez.analog.com/community/linux-device-drivers
W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/hwmon/adi,max31827.yaml
F: Documentation/hwmon/max31827.rst
F: drivers/hwmon/max31827.c
@ -14011,6 +14011,13 @@ S: Supported
F: Documentation/devicetree/bindings/regulator/mcp16502-regulator.txt
F: drivers/regulator/mcp16502.c
MICROCHIP MCP3564 ADC DRIVER
M: Marius Cristea <marius.cristea@microchip.com>
L: linux-iio@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/iio/adc/microchip,mcp3564.yaml
F: drivers/iio/adc/mcp3564.c
MICROCHIP MCP3911 ADC DRIVER
M: Marcus Folkesson <marcus.folkesson@gmail.com>
M: Kent Gustavsson <kent@minoris.se>
@ -18555,6 +18562,12 @@ S: Maintained
F: Documentation/devicetree/bindings/iio/light/bh1750.yaml
F: drivers/iio/light/bh1750.c
ROHM BM1390 PRESSURE SENSOR DRIVER
M: Matti Vaittinen <mazziesaccount@gmail.com>
L: linux-iio@vger.kernel.org
S: Supported
F: drivers/iio/pressure/rohm-bm1390.c
ROHM BU270xx LIGHT SENSOR DRIVERs
M: Matti Vaittinen <mazziesaccount@gmail.com>
L: linux-iio@vger.kernel.org

View File

@ -257,6 +257,13 @@ static u8 get_input_report(u8 current_index, int sensor_idx, int report_id,
else
als_input.illuminance_value =
(int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
if (sensor_idx == ACS_IDX) {
als_input.light_color_temp = sensor_virt_addr[1];
als_input.chromaticity_x_value = sensor_virt_addr[2];
als_input.chromaticity_y_value = sensor_virt_addr[3];
}
report_size = sizeof(als_input);
memcpy(input_report, &als_input, sizeof(als_input));
break;

View File

@ -99,6 +99,9 @@ struct als_input_report {
struct common_input_property common_property;
/* values specific to this sensor */
int illuminance_value;
int light_color_temp;
int chromaticity_x_value;
int chromaticity_y_value;
} __packed;
struct hpd_feature_report {

View File

@ -641,6 +641,27 @@ static const u8 als_report_descriptor[] = {
0x75, 32, /* HID report size(32) */
0x95, 1, /* HID report count (1) */
0X81, 0x02, /* HID Input (Data_Arr_Abs) */
0x0A, 0xD2, 0x04, /* HID usage sensor data light temperature */
0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
0x55, 0x0, /* HID unit exponent(0x0) */
0x75, 32, /* HID report size(32) */
0x95, 1, /* HID report count (1) */
0X81, 0x02, /* HID Input (Data_Arr_Abs) */
0x0A, 0xD4, 0x04, /* HID usage sensor data light chromaticity_x */
0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
0x55, 0x0, /* HID unit exponent(0x0) */
0x75, 32, /* HID report size(32) */
0x95, 1, /* HID report count(1) */
0X81, 0x02, /* HID Input (Data_Var_Abs) */
0x0A, 0xD5, 0x04, /* HID usage sensor data light chromaticity_y */
0x17, 0x00, 0x00, 0x01, 0x80, /* HID logical Min_32 */
0x27, 0xFF, 0xFF, 0xFF, 0x7F, /* HID logical Max_32 */
0x55, 0x0, /* HID unit exponent(0x0) */
0x75, 32, /* HID report size(32) */
0x95, 1, /* HID report count (1) */
0X81, 0x02, /* HID Input (Data_Var_Abs) */
0xC0 /* HID end collection */
};

View File

@ -188,6 +188,7 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id,
struct sfh_mag_data mag_data;
struct sfh_als_data als_data;
struct hpd_status hpdstatus;
struct sfh_base_info binfo;
void __iomem *sensoraddr;
u8 report_size = 0;
@ -235,6 +236,14 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id,
memcpy_fromio(&als_data, sensoraddr, sizeof(struct sfh_als_data));
get_common_inputs(&als_input.common_property, report_id);
als_input.illuminance_value = float_to_int(als_data.lux);
memcpy_fromio(&binfo, mp2->vsbase, sizeof(struct sfh_base_info));
if (binfo.sbase.s_prop[ALS_IDX].sf.feat & 0x2) {
als_input.light_color_temp = als_data.light_color_temp;
als_input.chromaticity_x_value = float_to_int(als_data.chromaticity_x);
als_input.chromaticity_y_value = float_to_int(als_data.chromaticity_y);
}
report_size = sizeof(als_input);
memcpy(input_report, &als_input, sizeof(als_input));
break;

View File

@ -88,6 +88,16 @@ struct sfh_sensor_list {
};
};
struct sfh_sensor_prop {
union {
u32 sprop;
struct {
u32 elist : 16;
u32 feat : 16;
} sf;
};
};
struct sfh_base_info {
union {
u32 sfh_base[24];
@ -95,6 +105,8 @@ struct sfh_base_info {
struct sfh_platform_info plat_info;
struct sfh_firmware_info fw_info;
struct sfh_sensor_list s_list;
u32 rsvd;
struct sfh_sensor_prop s_prop[16];
} sbase;
};
};
@ -134,6 +146,9 @@ struct sfh_mag_data {
struct sfh_als_data {
struct sfh_common_data commondata;
u32 lux;
u32 light_color_temp;
u32 chromaticity_x;
u32 chromaticity_y;
};
struct hpd_status {

View File

@ -418,8 +418,9 @@ config IIO_KX022A_SPI
select IIO_KX022A
select REGMAP_SPI
help
Enable support for the Kionix KX022A digital tri-axis
accelerometer connected to I2C interface.
Enable support for the Kionix digital tri-axis accelerometers
connected to SPI interface. Supported devices are:
KX022A, KX132-1211, KX132ACR-LBZ
config IIO_KX022A_I2C
tristate "Kionix KX022A tri-axis digital accelerometer I2C interface"
@ -427,8 +428,9 @@ config IIO_KX022A_I2C
select IIO_KX022A
select REGMAP_I2C
help
Enable support for the Kionix KX022A digital tri-axis
accelerometer connected to I2C interface.
Enable support for the Kionix digital tri-axis accelerometers
connected to I2C interface. Supported devices are:
KX022A, KX132-1211, KX132ACR-LBZ
config KXSD9
tristate "Kionix KXSD9 Accelerometer Driver"

View File

@ -8,9 +8,24 @@
#ifndef _ADXL345_H_
#define _ADXL345_H_
enum adxl345_device_type {
ADXL345 = 1,
ADXL375 = 2,
/*
* In full-resolution mode, scale factor is maintained at ~4 mg/LSB
* in all g ranges.
*
* At +/- 16g with 13-bit resolution, scale is computed as:
* (16 + 16) * 9.81 / (2^13 - 1) = 0.0383
*/
#define ADXL345_USCALE 38300
/*
* The Datasheet lists a resolution of Resolution is ~49 mg per LSB. That's
* ~480mm/s**2 per LSB.
*/
#define ADXL375_USCALE 480000
struct adxl345_chip_info {
const char *name;
int uscale;
};
int adxl345_core_probe(struct device *dev, struct regmap *regmap);

View File

@ -45,25 +45,10 @@
#define ADXL345_DEVID 0xE5
/*
* In full-resolution mode, scale factor is maintained at ~4 mg/LSB
* in all g ranges.
*
* At +/- 16g with 13-bit resolution, scale is computed as:
* (16 + 16) * 9.81 / (2^13 - 1) = 0.0383
*/
static const int adxl345_uscale = 38300;
/*
* The Datasheet lists a resolution of Resolution is ~49 mg per LSB. That's
* ~480mm/s**2 per LSB.
*/
static const int adxl375_uscale = 480000;
struct adxl345_data {
const struct adxl345_chip_info *info;
struct regmap *regmap;
u8 data_range;
enum adxl345_device_type type;
};
#define ADXL345_CHANNEL(index, axis) { \
@ -110,15 +95,7 @@ static int adxl345_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 0;
switch (data->type) {
case ADXL345:
*val2 = adxl345_uscale;
break;
case ADXL375:
*val2 = adxl375_uscale;
break;
}
*val2 = data->info->uscale;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_CALIBBIAS:
ret = regmap_read(data->regmap,
@ -222,25 +199,11 @@ static void adxl345_powerdown(void *regmap)
int adxl345_core_probe(struct device *dev, struct regmap *regmap)
{
enum adxl345_device_type type;
struct adxl345_data *data;
struct iio_dev *indio_dev;
const char *name;
u32 regval;
int ret;
type = (uintptr_t)device_get_match_data(dev);
switch (type) {
case ADXL345:
name = "adxl345";
break;
case ADXL375:
name = "adxl375";
break;
default:
return -EINVAL;
}
ret = regmap_read(regmap, ADXL345_REG_DEVID, &regval);
if (ret < 0)
return dev_err_probe(dev, ret, "Error reading device ID\n");
@ -255,16 +218,18 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap)
data = iio_priv(indio_dev);
data->regmap = regmap;
data->type = type;
/* Enable full-resolution mode */
data->data_range = ADXL345_DATA_FORMAT_FULL_RES;
data->info = device_get_match_data(dev);
if (!data->info)
return -ENODEV;
ret = regmap_write(data->regmap, ADXL345_REG_DATA_FORMAT,
data->data_range);
if (ret < 0)
return dev_err_probe(dev, ret, "Failed to set data range\n");
indio_dev->name = name;
indio_dev->name = data->info->name;
indio_dev->info = &adxl345_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = adxl345_channels;

View File

@ -30,22 +30,32 @@ static int adxl345_i2c_probe(struct i2c_client *client)
return adxl345_core_probe(&client->dev, regmap);
}
static const struct adxl345_chip_info adxl345_i2c_info = {
.name = "adxl345",
.uscale = ADXL345_USCALE,
};
static const struct adxl345_chip_info adxl375_i2c_info = {
.name = "adxl375",
.uscale = ADXL375_USCALE,
};
static const struct i2c_device_id adxl345_i2c_id[] = {
{ "adxl345", ADXL345 },
{ "adxl375", ADXL375 },
{ "adxl345", (kernel_ulong_t)&adxl345_i2c_info },
{ "adxl375", (kernel_ulong_t)&adxl375_i2c_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, adxl345_i2c_id);
static const struct of_device_id adxl345_of_match[] = {
{ .compatible = "adi,adxl345", .data = (const void *)ADXL345 },
{ .compatible = "adi,adxl375", .data = (const void *)ADXL375 },
{ .compatible = "adi,adxl345", .data = &adxl345_i2c_info },
{ .compatible = "adi,adxl375", .data = &adxl375_i2c_info },
{ }
};
MODULE_DEVICE_TABLE(of, adxl345_of_match);
static const struct acpi_device_id adxl345_acpi_match[] = {
{ "ADS0345", ADXL345 },
{ "ADS0345", (kernel_ulong_t)&adxl345_i2c_info },
{ }
};
MODULE_DEVICE_TABLE(acpi, adxl345_acpi_match);

View File

@ -36,22 +36,32 @@ static int adxl345_spi_probe(struct spi_device *spi)
return adxl345_core_probe(&spi->dev, regmap);
}
static const struct adxl345_chip_info adxl345_spi_info = {
.name = "adxl345",
.uscale = ADXL345_USCALE,
};
static const struct adxl345_chip_info adxl375_spi_info = {
.name = "adxl375",
.uscale = ADXL375_USCALE,
};
static const struct spi_device_id adxl345_spi_id[] = {
{ "adxl345", ADXL345 },
{ "adxl375", ADXL375 },
{ "adxl345", (kernel_ulong_t)&adxl345_spi_info },
{ "adxl375", (kernel_ulong_t)&adxl375_spi_info },
{ }
};
MODULE_DEVICE_TABLE(spi, adxl345_spi_id);
static const struct of_device_id adxl345_of_match[] = {
{ .compatible = "adi,adxl345", .data = (const void *)ADXL345 },
{ .compatible = "adi,adxl375", .data = (const void *)ADXL375 },
{ .compatible = "adi,adxl345", .data = &adxl345_spi_info },
{ .compatible = "adi,adxl375", .data = &adxl375_spi_info },
{ }
};
MODULE_DEVICE_TABLE(of, adxl345_of_match);
static const struct acpi_device_id adxl345_acpi_match[] = {
{ "ADS0345", ADXL345 },
{ "ADS0345", (kernel_ulong_t)&adxl345_spi_info },
{ }
};
MODULE_DEVICE_TABLE(acpi, adxl345_acpi_match);

View File

@ -926,7 +926,6 @@ static int bma180_probe(struct i2c_client *client)
struct device *dev = &client->dev;
struct bma180_data *data;
struct iio_dev *indio_dev;
enum chip_ids chip;
int ret;
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
@ -936,11 +935,7 @@ static int bma180_probe(struct i2c_client *client)
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
if (client->dev.of_node)
chip = (uintptr_t)of_device_get_match_data(dev);
else
chip = id->driver_data;
data->part_info = &bma180_part_info[chip];
data->part_info = i2c_get_match_data(client);
ret = iio_read_mount_matrix(dev, &data->orientation);
if (ret)
@ -1092,11 +1087,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", BMA023 },
{ "bma150", BMA150 },
{ "bma180", BMA180 },
{ "bma250", BMA250 },
{ "smb380", BMA150 },
{ "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] },
{ }
};
@ -1105,23 +1100,23 @@ MODULE_DEVICE_TABLE(i2c, bma180_ids);
static const struct of_device_id bma180_of_match[] = {
{
.compatible = "bosch,bma023",
.data = (void *)BMA023
.data = &bma180_part_info[BMA023]
},
{
.compatible = "bosch,bma150",
.data = (void *)BMA150
.data = &bma180_part_info[BMA150]
},
{
.compatible = "bosch,bma180",
.data = (void *)BMA180
.data = &bma180_part_info[BMA180]
},
{
.compatible = "bosch,bma250",
.data = (void *)BMA250
.data = &bma180_part_info[BMA250]
},
{
.compatible = "bosch,smb380",
.data = (void *)BMA150
.data = &bma180_part_info[BMA150]
},
{ }
};

View File

@ -14,7 +14,6 @@ enum {
};
int fxls8962af_core_probe(struct device *dev, struct regmap *regmap, int irq);
int fxls8962af_core_remove(struct device *dev);
extern const struct dev_pm_ops fxls8962af_pm_ops;
extern const struct regmap_config fxls8962af_i2c_regmap_conf;

View File

@ -422,7 +422,7 @@ error_remove_trigger:
}
/* Function to deinitialize the processing for usage id */
static int hid_accel_3d_remove(struct platform_device *pdev)
static void hid_accel_3d_remove(struct platform_device *pdev)
{
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@ -431,8 +431,6 @@ static int hid_accel_3d_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, hsdev->usage);
iio_device_unregister(indio_dev);
hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes);
return 0;
}
static const struct platform_device_id hid_accel_3d_ids[] = {
@ -454,7 +452,7 @@ static struct platform_driver hid_accel_3d_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_accel_3d_probe,
.remove = hid_accel_3d_remove,
.remove_new = hid_accel_3d_remove,
};
module_platform_driver(hid_accel_3d_platform_driver);

View File

@ -2,7 +2,7 @@
/*
* Copyright (C) 2022 ROHM Semiconductors
*
* ROHM/KIONIX KX022A accelerometer driver
* ROHM/KIONIX accelerometer driver
*/
#include <linux/i2c.h>
@ -15,6 +15,7 @@
static int kx022a_i2c_probe(struct i2c_client *i2c)
{
struct device *dev = &i2c->dev;
const struct kx022a_chip_info *chip_info;
struct regmap *regmap;
if (!i2c->irq) {
@ -22,16 +23,30 @@ static int kx022a_i2c_probe(struct i2c_client *i2c)
return -EINVAL;
}
regmap = devm_regmap_init_i2c(i2c, &kx022a_regmap);
chip_info = i2c_get_match_data(i2c);
if (!chip_info)
return -EINVAL;
regmap = devm_regmap_init_i2c(i2c, chip_info->regmap_config);
if (IS_ERR(regmap))
return dev_err_probe(dev, PTR_ERR(regmap),
"Failed to initialize Regmap\n");
return kx022a_probe_internal(dev);
return kx022a_probe_internal(dev, chip_info);
}
static const struct i2c_device_id kx022a_i2c_id[] = {
{ .name = "kx022a", .driver_data = (kernel_ulong_t)&kx022a_chip_info },
{ .name = "kx132-1211", .driver_data = (kernel_ulong_t)&kx132_chip_info },
{ .name = "kx132acr-lbz", .driver_data = (kernel_ulong_t)&kx132acr_chip_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, kx022a_i2c_id);
static const struct of_device_id kx022a_of_match[] = {
{ .compatible = "kionix,kx022a", },
{ .compatible = "kionix,kx022a", .data = &kx022a_chip_info },
{ .compatible = "kionix,kx132-1211", .data = &kx132_chip_info },
{ .compatible = "rohm,kx132acr-lbz", .data = &kx132acr_chip_info },
{ }
};
MODULE_DEVICE_TABLE(of, kx022a_of_match);
@ -43,6 +58,7 @@ static struct i2c_driver kx022a_i2c_driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.probe = kx022a_i2c_probe,
.id_table = kx022a_i2c_id,
};
module_i2c_driver(kx022a_i2c_driver);

View File

@ -2,7 +2,7 @@
/*
* Copyright (C) 2022 ROHM Semiconductors
*
* ROHM/KIONIX KX022A accelerometer driver
* ROHM/KIONIX accelerometer driver
*/
#include <linux/interrupt.h>
@ -15,6 +15,7 @@
static int kx022a_spi_probe(struct spi_device *spi)
{
struct device *dev = &spi->dev;
const struct kx022a_chip_info *chip_info;
struct regmap *regmap;
if (!spi->irq) {
@ -22,22 +23,30 @@ static int kx022a_spi_probe(struct spi_device *spi)
return -EINVAL;
}
regmap = devm_regmap_init_spi(spi, &kx022a_regmap);
chip_info = spi_get_device_match_data(spi);
if (!chip_info)
return -EINVAL;
regmap = devm_regmap_init_spi(spi, chip_info->regmap_config);
if (IS_ERR(regmap))
return dev_err_probe(dev, PTR_ERR(regmap),
"Failed to initialize Regmap\n");
return kx022a_probe_internal(dev);
return kx022a_probe_internal(dev, chip_info);
}
static const struct spi_device_id kx022a_id[] = {
{ "kx022a" },
{ .name = "kx022a", .driver_data = (kernel_ulong_t)&kx022a_chip_info },
{ .name = "kx132-1211", .driver_data = (kernel_ulong_t)&kx132_chip_info },
{ .name = "kx132acr-lbz", .driver_data = (kernel_ulong_t)&kx132acr_chip_info },
{ }
};
MODULE_DEVICE_TABLE(spi, kx022a_id);
static const struct of_device_id kx022a_of_match[] = {
{ .compatible = "kionix,kx022a", },
{ .compatible = "kionix,kx022a", .data = &kx022a_chip_info },
{ .compatible = "kionix,kx132-1211", .data = &kx132_chip_info },
{ .compatible = "rohm,kx132acr-lbz", .data = &kx132acr_chip_info },
{ }
};
MODULE_DEVICE_TABLE(of, kx022a_of_match);

View File

@ -2,7 +2,7 @@
/*
* Copyright (C) 2022 ROHM Semiconductors
*
* ROHM/KIONIX KX022A accelerometer driver
* ROHM/KIONIX accelerometer driver
*/
#include <linux/delay.h>
@ -15,7 +15,7 @@
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/string_helpers.h>
#include <linux/string_choices.h>
#include <linux/units.h>
#include <linux/iio/iio.h>
@ -48,7 +48,7 @@ enum {
KX022A_STATE_FIFO,
};
/* Regmap configs */
/* kx022a Regmap configs */
static const struct regmap_range kx022a_volatile_ranges[] = {
{
.range_min = KX022A_REG_XHP_L,
@ -138,7 +138,7 @@ static const struct regmap_access_table kx022a_nir_regs = {
.n_yes_ranges = ARRAY_SIZE(kx022a_noinc_read_ranges),
};
const struct regmap_config kx022a_regmap = {
static const struct regmap_config kx022a_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.volatile_table = &kx022a_volatile_regs,
@ -149,10 +149,121 @@ const struct regmap_config kx022a_regmap = {
.max_register = KX022A_MAX_REGISTER,
.cache_type = REGCACHE_RBTREE,
};
EXPORT_SYMBOL_NS_GPL(kx022a_regmap, IIO_KX022A);
/* Regmap configs kx132 */
static const struct regmap_range kx132_volatile_ranges[] = {
{
.range_min = KX132_REG_XADP_L,
.range_max = KX132_REG_COTR,
}, {
.range_min = KX132_REG_TSCP,
.range_max = KX132_REG_INT_REL,
}, {
/* The reset bit will be cleared by sensor */
.range_min = KX132_REG_CNTL2,
.range_max = KX132_REG_CNTL2,
}, {
.range_min = KX132_REG_CNTL5,
.range_max = KX132_REG_CNTL5,
}, {
.range_min = KX132_REG_BUF_STATUS_1,
.range_max = KX132_REG_BUF_READ,
},
};
static const struct regmap_access_table kx132_volatile_regs = {
.yes_ranges = &kx132_volatile_ranges[0],
.n_yes_ranges = ARRAY_SIZE(kx132_volatile_ranges),
};
static const struct regmap_range kx132_precious_ranges[] = {
{
.range_min = KX132_REG_INT_REL,
.range_max = KX132_REG_INT_REL,
},
};
static const struct regmap_access_table kx132_precious_regs = {
.yes_ranges = &kx132_precious_ranges[0],
.n_yes_ranges = ARRAY_SIZE(kx132_precious_ranges),
};
static const struct regmap_range kx132_read_only_ranges[] = {
{
.range_min = KX132_REG_XADP_L,
.range_max = KX132_REG_INT_REL,
}, {
.range_min = KX132_REG_BUF_STATUS_1,
.range_max = KX132_REG_BUF_STATUS_2,
}, {
.range_min = KX132_REG_BUF_READ,
.range_max = KX132_REG_BUF_READ,
}, {
/* Kionix reserved registers: should not be written */
.range_min = 0x28,
.range_max = 0x28,
}, {
.range_min = 0x35,
.range_max = 0x36,
}, {
.range_min = 0x3c,
.range_max = 0x48,
}, {
.range_min = 0x4e,
.range_max = 0x5c,
}, {
.range_min = 0x77,
.range_max = 0x7f,
},
};
static const struct regmap_access_table kx132_ro_regs = {
.no_ranges = &kx132_read_only_ranges[0],
.n_no_ranges = ARRAY_SIZE(kx132_read_only_ranges),
};
static const struct regmap_range kx132_write_only_ranges[] = {
{
.range_min = KX132_REG_SELF_TEST,
.range_max = KX132_REG_SELF_TEST,
}, {
.range_min = KX132_REG_BUF_CLEAR,
.range_max = KX132_REG_BUF_CLEAR,
},
};
static const struct regmap_access_table kx132_wo_regs = {
.no_ranges = &kx132_write_only_ranges[0],
.n_no_ranges = ARRAY_SIZE(kx132_write_only_ranges),
};
static const struct regmap_range kx132_noinc_read_ranges[] = {
{
.range_min = KX132_REG_BUF_READ,
.range_max = KX132_REG_BUF_READ,
},
};
static const struct regmap_access_table kx132_nir_regs = {
.yes_ranges = &kx132_noinc_read_ranges[0],
.n_yes_ranges = ARRAY_SIZE(kx132_noinc_read_ranges),
};
static const struct regmap_config kx132_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.volatile_table = &kx132_volatile_regs,
.rd_table = &kx132_wo_regs,
.wr_table = &kx132_ro_regs,
.rd_noinc_table = &kx132_nir_regs,
.precious_table = &kx132_precious_regs,
.max_register = KX132_MAX_REGISTER,
.cache_type = REGCACHE_RBTREE,
};
struct kx022a_data {
struct regmap *regmap;
const struct kx022a_chip_info *chip_info;
struct iio_trigger *trig;
struct device *dev;
struct iio_mount_matrix orientation;
@ -175,6 +286,8 @@ struct kx022a_data {
struct mutex mutex;
u8 watermark;
__le16 *fifo_buffer;
/* 3 x 16bit accel data + timestamp */
__le16 buffer[8] __aligned(IIO_DMA_MINALIGN);
struct {
@ -208,7 +321,7 @@ static const struct iio_chan_spec_ext_info kx022a_ext_info[] = {
{ }
};
#define KX022A_ACCEL_CHAN(axis, index) \
#define KX022A_ACCEL_CHAN(axis, reg, index) \
{ \
.type = IIO_ACCEL, \
.modified = 1, \
@ -220,7 +333,7 @@ static const struct iio_chan_spec_ext_info kx022a_ext_info[] = {
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_SAMP_FREQ), \
.ext_info = kx022a_ext_info, \
.address = KX022A_REG_##axis##OUT_L, \
.address = reg, \
.scan_index = index, \
.scan_type = { \
.sign = 's', \
@ -231,9 +344,16 @@ static const struct iio_chan_spec_ext_info kx022a_ext_info[] = {
}
static const struct iio_chan_spec kx022a_channels[] = {
KX022A_ACCEL_CHAN(X, 0),
KX022A_ACCEL_CHAN(Y, 1),
KX022A_ACCEL_CHAN(Z, 2),
KX022A_ACCEL_CHAN(X, KX022A_REG_XOUT_L, 0),
KX022A_ACCEL_CHAN(Y, KX022A_REG_YOUT_L, 1),
KX022A_ACCEL_CHAN(Z, KX022A_REG_ZOUT_L, 2),
IIO_CHAN_SOFT_TIMESTAMP(3),
};
static const struct iio_chan_spec kx132_channels[] = {
KX022A_ACCEL_CHAN(X, KX132_REG_XOUT_L, 0),
KX022A_ACCEL_CHAN(Y, KX132_REG_YOUT_L, 1),
KX022A_ACCEL_CHAN(Z, KX132_REG_ZOUT_L, 2),
IIO_CHAN_SOFT_TIMESTAMP(3),
};
@ -332,16 +452,15 @@ static int kx022a_turn_on_off_unlocked(struct kx022a_data *data, bool on)
int ret;
if (on)
ret = regmap_set_bits(data->regmap, KX022A_REG_CNTL,
ret = regmap_set_bits(data->regmap, data->chip_info->cntl,
KX022A_MASK_PC1);
else
ret = regmap_clear_bits(data->regmap, KX022A_REG_CNTL,
ret = regmap_clear_bits(data->regmap, data->chip_info->cntl,
KX022A_MASK_PC1);
if (ret)
dev_err(data->dev, "Turn %s fail %d\n", str_on_off(on), ret);
return ret;
}
static int kx022a_turn_off_lock(struct kx022a_data *data)
@ -403,7 +522,7 @@ static int kx022a_write_raw(struct iio_dev *idev,
break;
ret = regmap_update_bits(data->regmap,
KX022A_REG_ODCNTL,
data->chip_info->odcntl,
KX022A_MASK_ODR, n);
data->odr_ns = kx022a_odrs[n];
kx022a_turn_on_unlock(data);
@ -424,7 +543,7 @@ static int kx022a_write_raw(struct iio_dev *idev,
if (ret)
break;
ret = regmap_update_bits(data->regmap, KX022A_REG_CNTL,
ret = regmap_update_bits(data->regmap, data->chip_info->cntl,
KX022A_MASK_GSEL,
n << KX022A_GSEL_SHIFT);
kx022a_turn_on_unlock(data);
@ -446,7 +565,7 @@ static int kx022a_fifo_set_wmi(struct kx022a_data *data)
threshold = data->watermark;
return regmap_update_bits(data->regmap, KX022A_REG_BUF_CNTL1,
return regmap_update_bits(data->regmap, data->chip_info->buf_cntl1,
KX022A_MASK_WM_TH, threshold);
}
@ -489,7 +608,7 @@ static int kx022a_read_raw(struct iio_dev *idev,
return ret;
case IIO_CHAN_INFO_SAMP_FREQ:
ret = regmap_read(data->regmap, KX022A_REG_ODCNTL, &regval);
ret = regmap_read(data->regmap, data->chip_info->odcntl, &regval);
if (ret)
return ret;
@ -504,7 +623,7 @@ static int kx022a_read_raw(struct iio_dev *idev,
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SCALE:
ret = regmap_read(data->regmap, KX022A_REG_CNTL, &regval);
ret = regmap_read(data->regmap, data->chip_info->cntl, &regval);
if (ret < 0)
return ret;
@ -520,8 +639,7 @@ static int kx022a_set_watermark(struct iio_dev *idev, unsigned int val)
{
struct kx022a_data *data = iio_priv(idev);
if (val > KX022A_FIFO_LENGTH)
val = KX022A_FIFO_LENGTH;
val = min(data->chip_info->fifo_length, val);
mutex_lock(&data->mutex);
data->watermark = val;
@ -582,30 +700,56 @@ static int kx022a_drop_fifo_contents(struct kx022a_data *data)
*/
data->timestamp = 0;
return regmap_write(data->regmap, KX022A_REG_BUF_CLEAR, 0x0);
return regmap_write(data->regmap, data->chip_info->buf_clear, 0x0);
}
static int kx022a_get_fifo_bytes_available(struct kx022a_data *data)
{
int ret, fifo_bytes;
ret = regmap_read(data->regmap, KX022A_REG_BUF_STATUS_1, &fifo_bytes);
if (ret) {
dev_err(data->dev, "Error reading buffer status\n");
return ret;
}
if (fifo_bytes == KX022A_FIFO_FULL_VALUE)
return KX022A_FIFO_MAX_BYTES;
return fifo_bytes;
}
static int kx132_get_fifo_bytes_available(struct kx022a_data *data)
{
__le16 buf_status;
int ret, fifo_bytes;
ret = regmap_bulk_read(data->regmap, data->chip_info->buf_status1,
&buf_status, sizeof(buf_status));
if (ret) {
dev_err(data->dev, "Error reading buffer status\n");
return ret;
}
fifo_bytes = le16_to_cpu(buf_status);
fifo_bytes &= data->chip_info->buf_smp_lvl_mask;
fifo_bytes = min((unsigned int)fifo_bytes, data->chip_info->fifo_length *
KX022A_FIFO_SAMPLES_SIZE_BYTES);
return fifo_bytes;
}
static int __kx022a_fifo_flush(struct iio_dev *idev, unsigned int samples,
bool irq)
{
struct kx022a_data *data = iio_priv(idev);
struct device *dev = regmap_get_device(data->regmap);
__le16 buffer[KX022A_FIFO_LENGTH * 3];
uint64_t sample_period;
int count, fifo_bytes;
bool renable = false;
int64_t tstamp;
int ret, i;
ret = regmap_read(data->regmap, KX022A_REG_BUF_STATUS_1, &fifo_bytes);
if (ret) {
dev_err(dev, "Error reading buffer status\n");
return ret;
}
/* Let's not overflow if we for some reason get bogus value from i2c */
if (fifo_bytes == KX022A_FIFO_FULL_VALUE)
fifo_bytes = KX022A_FIFO_MAX_BYTES;
fifo_bytes = data->chip_info->get_fifo_bytes_available(data);
if (fifo_bytes % KX022A_FIFO_SAMPLES_SIZE_BYTES)
dev_warn(data->dev, "Bad FIFO alignment. Data may be corrupt\n");
@ -669,13 +813,13 @@ static int __kx022a_fifo_flush(struct iio_dev *idev, unsigned int samples,
}
fifo_bytes = count * KX022A_FIFO_SAMPLES_SIZE_BYTES;
ret = regmap_noinc_read(data->regmap, KX022A_REG_BUF_READ,
&buffer[0], fifo_bytes);
ret = regmap_noinc_read(data->regmap, data->chip_info->buf_read,
data->fifo_buffer, fifo_bytes);
if (ret)
goto renable_out;
for (i = 0; i < count; i++) {
__le16 *sam = &buffer[i * 3];
__le16 *sam = &data->fifo_buffer[i * 3];
__le16 *chs;
int bit;
@ -722,10 +866,10 @@ static const struct iio_info kx022a_info = {
static int kx022a_set_drdy_irq(struct kx022a_data *data, bool en)
{
if (en)
return regmap_set_bits(data->regmap, KX022A_REG_CNTL,
return regmap_set_bits(data->regmap, data->chip_info->cntl,
KX022A_MASK_DRDY);
return regmap_clear_bits(data->regmap, KX022A_REG_CNTL,
return regmap_clear_bits(data->regmap, data->chip_info->cntl,
KX022A_MASK_DRDY);
}
@ -760,7 +904,7 @@ static int kx022a_fifo_disable(struct kx022a_data *data)
if (ret)
goto unlock_out;
ret = regmap_clear_bits(data->regmap, KX022A_REG_BUF_CNTL2,
ret = regmap_clear_bits(data->regmap, data->chip_info->buf_cntl2,
KX022A_MASK_BUF_EN);
if (ret)
goto unlock_out;
@ -769,6 +913,8 @@ static int kx022a_fifo_disable(struct kx022a_data *data)
kx022a_drop_fifo_contents(data);
kfree(data->fifo_buffer);
return kx022a_turn_on_unlock(data);
unlock_out:
@ -791,6 +937,12 @@ static int kx022a_fifo_enable(struct kx022a_data *data)
{
int ret;
data->fifo_buffer = kmalloc_array(data->chip_info->fifo_length,
KX022A_FIFO_SAMPLES_SIZE_BYTES,
GFP_KERNEL);
if (!data->fifo_buffer)
return -ENOMEM;
ret = kx022a_turn_off_lock(data);
if (ret)
return ret;
@ -801,7 +953,7 @@ static int kx022a_fifo_enable(struct kx022a_data *data)
goto unlock_out;
/* Enable buffer */
ret = regmap_set_bits(data->regmap, KX022A_REG_BUF_CNTL2,
ret = regmap_set_bits(data->regmap, data->chip_info->buf_cntl2,
KX022A_MASK_BUF_EN);
if (ret)
goto unlock_out;
@ -847,7 +999,7 @@ static irqreturn_t kx022a_trigger_handler(int irq, void *p)
struct kx022a_data *data = iio_priv(idev);
int ret;
ret = regmap_bulk_read(data->regmap, KX022A_REG_XOUT_L, data->buffer,
ret = regmap_bulk_read(data->regmap, data->chip_info->xout_l, data->buffer,
KX022A_FIFO_SAMPLES_SIZE_BYTES);
if (ret < 0)
goto err_read;
@ -895,7 +1047,7 @@ static irqreturn_t kx022a_irq_thread_handler(int irq, void *private)
if (data->state & KX022A_STATE_FIFO) {
int ok;
ok = __kx022a_fifo_flush(idev, KX022A_FIFO_LENGTH, true);
ok = __kx022a_fifo_flush(idev, data->chip_info->fifo_length, true);
if (ok > 0)
ret = IRQ_HANDLED;
}
@ -948,7 +1100,7 @@ static int kx022a_chip_init(struct kx022a_data *data)
int ret, val;
/* Reset the senor */
ret = regmap_write(data->regmap, KX022A_REG_CNTL2, KX022A_MASK_SRST);
ret = regmap_write(data->regmap, data->chip_info->cntl2, KX022A_MASK_SRST);
if (ret)
return ret;
@ -958,7 +1110,7 @@ static int kx022a_chip_init(struct kx022a_data *data)
*/
msleep(1);
ret = regmap_read_poll_timeout(data->regmap, KX022A_REG_CNTL2, val,
ret = regmap_read_poll_timeout(data->regmap, data->chip_info->cntl2, val,
!(val & KX022A_MASK_SRST),
KX022A_SOFT_RESET_WAIT_TIME_US,
KX022A_SOFT_RESET_TOTAL_WAIT_TIME_US);
@ -968,14 +1120,14 @@ static int kx022a_chip_init(struct kx022a_data *data)
return ret;
}
ret = regmap_reinit_cache(data->regmap, &kx022a_regmap);
ret = regmap_reinit_cache(data->regmap, data->chip_info->regmap_config);
if (ret) {
dev_err(data->dev, "Failed to reinit reg cache\n");
return ret;
}
/* set data res 16bit */
ret = regmap_set_bits(data->regmap, KX022A_REG_BUF_CNTL2,
ret = regmap_set_bits(data->regmap, data->chip_info->buf_cntl2,
KX022A_MASK_BRES16);
if (ret) {
dev_err(data->dev, "Failed to set data resolution\n");
@ -985,7 +1137,90 @@ static int kx022a_chip_init(struct kx022a_data *data)
return kx022a_prepare_irq_pin(data);
}
int kx022a_probe_internal(struct device *dev)
const struct kx022a_chip_info kx022a_chip_info = {
.name = "kx022-accel",
.regmap_config = &kx022a_regmap_config,
.channels = kx022a_channels,
.num_channels = ARRAY_SIZE(kx022a_channels),
.fifo_length = KX022A_FIFO_LENGTH,
.who = KX022A_REG_WHO,
.id = KX022A_ID,
.cntl = KX022A_REG_CNTL,
.cntl2 = KX022A_REG_CNTL2,
.odcntl = KX022A_REG_ODCNTL,
.buf_cntl1 = KX022A_REG_BUF_CNTL1,
.buf_cntl2 = KX022A_REG_BUF_CNTL2,
.buf_clear = KX022A_REG_BUF_CLEAR,
.buf_status1 = KX022A_REG_BUF_STATUS_1,
.buf_read = KX022A_REG_BUF_READ,
.inc1 = KX022A_REG_INC1,
.inc4 = KX022A_REG_INC4,
.inc5 = KX022A_REG_INC5,
.inc6 = KX022A_REG_INC6,
.xout_l = KX022A_REG_XOUT_L,
.get_fifo_bytes_available = kx022a_get_fifo_bytes_available,
};
EXPORT_SYMBOL_NS_GPL(kx022a_chip_info, IIO_KX022A);
const struct kx022a_chip_info kx132_chip_info = {
.name = "kx132-1211",
.regmap_config = &kx132_regmap_config,
.channels = kx132_channels,
.num_channels = ARRAY_SIZE(kx132_channels),
.fifo_length = KX132_FIFO_LENGTH,
.who = KX132_REG_WHO,
.id = KX132_ID,
.cntl = KX132_REG_CNTL,
.cntl2 = KX132_REG_CNTL2,
.odcntl = KX132_REG_ODCNTL,
.buf_cntl1 = KX132_REG_BUF_CNTL1,
.buf_cntl2 = KX132_REG_BUF_CNTL2,
.buf_clear = KX132_REG_BUF_CLEAR,
.buf_status1 = KX132_REG_BUF_STATUS_1,
.buf_smp_lvl_mask = KX132_MASK_BUF_SMP_LVL,
.buf_read = KX132_REG_BUF_READ,
.inc1 = KX132_REG_INC1,
.inc4 = KX132_REG_INC4,
.inc5 = KX132_REG_INC5,
.inc6 = KX132_REG_INC6,
.xout_l = KX132_REG_XOUT_L,
.get_fifo_bytes_available = kx132_get_fifo_bytes_available,
};
EXPORT_SYMBOL_NS_GPL(kx132_chip_info, IIO_KX022A);
/*
* Despite the naming, KX132ACR-LBZ is not similar to KX132-1211 but it is
* exact subset of KX022A. KX132ACR-LBZ is meant to be used for industrial
* applications and the tap/double tap, free fall and tilt engines were
* removed. Rest of the registers and functionalities (excluding the ID
* register) are exact match to what is found in KX022.
*/
const struct kx022a_chip_info kx132acr_chip_info = {
.name = "kx132acr-lbz",
.regmap_config = &kx022a_regmap_config,
.channels = kx022a_channels,
.num_channels = ARRAY_SIZE(kx022a_channels),
.fifo_length = KX022A_FIFO_LENGTH,
.who = KX022A_REG_WHO,
.id = KX132ACR_LBZ_ID,
.cntl = KX022A_REG_CNTL,
.cntl2 = KX022A_REG_CNTL2,
.odcntl = KX022A_REG_ODCNTL,
.buf_cntl1 = KX022A_REG_BUF_CNTL1,
.buf_cntl2 = KX022A_REG_BUF_CNTL2,
.buf_clear = KX022A_REG_BUF_CLEAR,
.buf_status1 = KX022A_REG_BUF_STATUS_1,
.buf_read = KX022A_REG_BUF_READ,
.inc1 = KX022A_REG_INC1,
.inc4 = KX022A_REG_INC4,
.inc5 = KX022A_REG_INC5,
.inc6 = KX022A_REG_INC6,
.xout_l = KX022A_REG_XOUT_L,
.get_fifo_bytes_available = kx022a_get_fifo_bytes_available,
};
EXPORT_SYMBOL_NS_GPL(kx132acr_chip_info, IIO_KX022A);
int kx022a_probe_internal(struct device *dev, const struct kx022a_chip_info *chip_info)
{
static const char * const regulator_names[] = {"io-vdd", "vdd"};
struct iio_trigger *indio_trig;
@ -1012,6 +1247,7 @@ int kx022a_probe_internal(struct device *dev)
return -ENOMEM;
data = iio_priv(idev);
data->chip_info = chip_info;
/*
* VDD is the analog and digital domain voltage supply and
@ -1022,26 +1258,24 @@ int kx022a_probe_internal(struct device *dev)
if (ret && ret != -ENODEV)
return dev_err_probe(dev, ret, "failed to enable regulator\n");
ret = regmap_read(regmap, KX022A_REG_WHO, &chip_id);
ret = regmap_read(regmap, chip_info->who, &chip_id);
if (ret)
return dev_err_probe(dev, ret, "Failed to access sensor\n");
if (chip_id != KX022A_ID) {
dev_err(dev, "unsupported device 0x%x\n", chip_id);
return -EINVAL;
}
if (chip_id != chip_info->id)
dev_warn(dev, "unknown device 0x%x\n", chip_id);
irq = fwnode_irq_get_byname(fwnode, "INT1");
if (irq > 0) {
data->inc_reg = KX022A_REG_INC1;
data->ien_reg = KX022A_REG_INC4;
data->inc_reg = chip_info->inc1;
data->ien_reg = chip_info->inc4;
} else {
irq = fwnode_irq_get_byname(fwnode, "INT2");
if (irq < 0)
return dev_err_probe(dev, irq, "No suitable IRQ\n");
data->inc_reg = KX022A_REG_INC5;
data->ien_reg = KX022A_REG_INC6;
data->inc_reg = chip_info->inc5;
data->ien_reg = chip_info->inc6;
}
data->regmap = regmap;
@ -1050,9 +1284,9 @@ int kx022a_probe_internal(struct device *dev)
data->odr_ns = KX022A_DEFAULT_PERIOD_NS;
mutex_init(&data->mutex);
idev->channels = kx022a_channels;
idev->num_channels = ARRAY_SIZE(kx022a_channels);
idev->name = "kx022-accel";
idev->channels = chip_info->channels;
idev->num_channels = chip_info->num_channels;
idev->name = chip_info->name;
idev->info = &kx022a_info;
idev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
idev->available_scan_masks = kx022a_scan_masks;
@ -1110,7 +1344,6 @@ int kx022a_probe_internal(struct device *dev)
if (ret)
return dev_err_probe(data->dev, ret, "Could not request IRQ\n");
ret = devm_iio_trigger_register(dev, indio_trig);
if (ret)
return dev_err_probe(data->dev, ret,

View File

@ -13,6 +13,7 @@
#define KX022A_REG_WHO 0x0f
#define KX022A_ID 0xc8
#define KX132ACR_LBZ_ID 0xd8
#define KX022A_REG_CNTL2 0x19
#define KX022A_MASK_SRST BIT(7)
@ -74,9 +75,118 @@
#define KX022A_REG_SELF_TEST 0x60
#define KX022A_MAX_REGISTER 0x60
#define KX132_REG_WHO 0x13
#define KX132_ID 0x3d
#define KX132_FIFO_LENGTH 86
#define KX132_REG_CNTL 0x1b
#define KX132_REG_CNTL2 0x1c
#define KX132_REG_CNTL5 0x1f
#define KX132_MASK_RES BIT(6)
#define KX132_GSEL_2 0x0
#define KX132_GSEL_4 BIT(3)
#define KX132_GSEL_8 BIT(4)
#define KX132_GSEL_16 GENMASK(4, 3)
#define KX132_REG_INS2 0x17
#define KX132_MASK_INS2_WMI BIT(5)
#define KX132_REG_XADP_L 0x02
#define KX132_REG_XOUT_L 0x08
#define KX132_REG_YOUT_L 0x0a
#define KX132_REG_ZOUT_L 0x0c
#define KX132_REG_COTR 0x12
#define KX132_REG_TSCP 0x14
#define KX132_REG_INT_REL 0x1a
#define KX132_REG_ODCNTL 0x21
#define KX132_REG_BTS_WUF_TH 0x4a
#define KX132_REG_BUF_CNTL1 0x5e
#define KX132_REG_BUF_CNTL2 0x5f
#define KX132_REG_BUF_STATUS_1 0x60
#define KX132_REG_BUF_STATUS_2 0x61
#define KX132_MASK_BUF_SMP_LVL GENMASK(9, 0)
#define KX132_REG_BUF_CLEAR 0x62
#define KX132_REG_BUF_READ 0x63
#define KX132_ODR_SHIFT 3
#define KX132_FIFO_MAX_WMI_TH 86
#define KX132_REG_INC1 0x22
#define KX132_REG_INC5 0x26
#define KX132_REG_INC6 0x27
#define KX132_IPOL_LOW 0
#define KX132_IPOL_HIGH KX022A_MASK_IPOL
#define KX132_ITYP_PULSE KX022A_MASK_ITYP
#define KX132_REG_INC4 0x25
#define KX132_REG_SELF_TEST 0x5d
#define KX132_MAX_REGISTER 0x76
struct device;
int kx022a_probe_internal(struct device *dev);
extern const struct regmap_config kx022a_regmap;
struct kx022a_data;
/**
* struct kx022a_chip_info - Kionix accelerometer chip specific information
*
* @name: name of the device
* @regmap_config: pointer to register map configuration
* @channels: pointer to iio_chan_spec array
* @num_channels: number of iio_chan_spec channels
* @fifo_length: number of 16-bit samples in a full buffer
* @buf_smp_lvl_mask: buffer sample level mask
* @who: WHO_AM_I register
* @id: WHO_AM_I register value
* @cntl: control register 1
* @cntl2: control register 2
* @odcntl: output data control register
* @buf_cntl1: buffer control register 1
* @buf_cntl2: buffer control register 2
* @buf_clear: buffer clear register
* @buf_status1: buffer status register 1
* @buf_read: buffer read register
* @inc1: interrupt control register 1
* @inc4: interrupt control register 4
* @inc5: interrupt control register 5
* @inc6: interrupt control register 6
* @xout_l: x-axis output least significant byte
* @get_fifo_bytes_available: function pointer to get amount of acceleration
* data bytes currently stored in the sensor's FIFO
* buffer
*/
struct kx022a_chip_info {
const char *name;
const struct regmap_config *regmap_config;
const struct iio_chan_spec *channels;
unsigned int num_channels;
unsigned int fifo_length;
u16 buf_smp_lvl_mask;
u8 who;
u8 id;
u8 cntl;
u8 cntl2;
u8 odcntl;
u8 buf_cntl1;
u8 buf_cntl2;
u8 buf_clear;
u8 buf_status1;
u8 buf_read;
u8 inc1;
u8 inc4;
u8 inc5;
u8 inc6;
u8 xout_l;
int (*get_fifo_bytes_available)(struct kx022a_data *);
};
int kx022a_probe_internal(struct device *dev, const struct kx022a_chip_info *chip_info);
extern const struct kx022a_chip_info kx022a_chip_info;
extern const struct kx022a_chip_info kx132_chip_info;
extern const struct kx022a_chip_info kx132acr_chip_info;
#endif

View File

@ -1535,19 +1535,18 @@ static int mma8452_reset(struct i2c_client *client)
}
static const struct of_device_id mma8452_dt_ids[] = {
{ .compatible = "fsl,fxls8471", .data = &mma_chip_info_table[fxls8471] },
{ .compatible = "fsl,mma8451", .data = &mma_chip_info_table[mma8451] },
{ .compatible = "fsl,mma8452", .data = &mma_chip_info_table[mma8452] },
{ .compatible = "fsl,mma8453", .data = &mma_chip_info_table[mma8453] },
{ .compatible = "fsl,mma8652", .data = &mma_chip_info_table[mma8652] },
{ .compatible = "fsl,mma8653", .data = &mma_chip_info_table[mma8653] },
{ .compatible = "fsl,fxls8471", .data = &mma_chip_info_table[fxls8471] },
{ }
};
MODULE_DEVICE_TABLE(of, mma8452_dt_ids);
static int mma8452_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct mma8452_data *data;
struct iio_dev *indio_dev;
int ret;
@ -1560,15 +1559,10 @@ static int mma8452_probe(struct i2c_client *client)
data->client = client;
mutex_init(&data->lock);
data->chip_info = device_get_match_data(&client->dev);
if (!data->chip_info) {
if (id) {
data->chip_info = &mma_chip_info_table[id->driver_data];
} else {
dev_err(&client->dev, "unknown device model\n");
return -ENODEV;
}
}
data->chip_info = i2c_get_match_data(client);
if (!data->chip_info)
return dev_err_probe(&client->dev, -ENODEV,
"unknown device model\n");
ret = iio_read_mount_matrix(&client->dev, &data->orientation);
if (ret)
@ -1830,12 +1824,12 @@ static const struct dev_pm_ops mma8452_pm_ops = {
};
static const struct i2c_device_id mma8452_id[] = {
{ "mma8451", mma8451 },
{ "mma8452", mma8452 },
{ "mma8453", mma8453 },
{ "mma8652", mma8652 },
{ "mma8653", mma8653 },
{ "fxls8471", fxls8471 },
{ "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] },
{ }
};
MODULE_DEVICE_TABLE(i2c, mma8452_id);

View File

@ -33,7 +33,7 @@
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/string_helpers.h>
#include <linux/string_choices.h>
#include <linux/units.h>
#include <linux/iio/buffer.h>

View File

@ -476,6 +476,13 @@ static const struct acpi_device_id mxc4005_acpi_match[] = {
};
MODULE_DEVICE_TABLE(acpi, mxc4005_acpi_match);
static const struct of_device_id mxc4005_of_match[] = {
{ .compatible = "memsic,mxc4005", },
{ .compatible = "memsic,mxc6655", },
{ },
};
MODULE_DEVICE_TABLE(of, mxc4005_of_match);
static const struct i2c_device_id mxc4005_id[] = {
{"mxc4005", 0},
{"mxc6655", 0},
@ -487,6 +494,7 @@ static struct i2c_driver mxc4005_driver = {
.driver = {
.name = MXC4005_DRV_NAME,
.acpi_match_table = ACPI_PTR(mxc4005_acpi_match),
.of_match_table = mxc4005_of_match,
},
.probe = mxc4005_probe,
.id_table = mxc4005_id,

View File

@ -607,6 +607,16 @@ config LPC32XX_ADC
activate only one via device tree selection. Provides direct access
via sysfs.
config LTC2309
tristate "Linear Technology LTC2309 ADC driver"
depends on I2C
help
Say yes here to build support for Linear Technology LTC2309, a low
noise, low power, 8-channel, 12-bit SAR ADC
This driver can also be built as a module. If so, the module will
be called ltc2309.
config LTC2471
tristate "Linear Technology LTC2471 and LTC2473 ADC driver"
depends on I2C
@ -779,14 +789,29 @@ config MCP3422
This driver can also be built as a module. If so, the module will be
called mcp3422.
config MCP3564
tristate "Microchip Technology MCP3461/2/4/R, MCP3561/2/4/R driver"
depends on SPI
depends on IIO
help
Say yes here to build support for Microchip Technology's MCP3461,
MCP3462, MCP3464, MCP3461R, MCP3462R, MCP3464R, MCP3561, MCP3562,
MCP3564, MCP3561R, MCP3562R and MCP3564R analog to digital
converters.
This driver can also be built as a module. If so, the module will be
called mcp3564.
config MCP3911
tristate "Microchip Technology MCP3911 driver"
depends on SPI
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for Microchip Technology's MCP3911
analog to digital converter.
Say yes here to build support for one of the following
Microchip Technology's analog to digital converters:
MCP3910, MCP3911, MCP3912, MCP3913, MCP3914,
MCP3918 and MCP3919.
This driver can also be built as a module. If so, the module will be
called mcp3911.

View File

@ -56,6 +56,7 @@ obj-$(CONFIG_INTEL_MRFLD_ADC) += intel_mrfld_adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
obj-$(CONFIG_LTC2309) += ltc2309.o
obj-$(CONFIG_LTC2471) += ltc2471.o
obj-$(CONFIG_LTC2485) += ltc2485.o
obj-$(CONFIG_LTC2496) += ltc2496.o ltc2497-core.o
@ -71,6 +72,7 @@ obj-$(CONFIG_MAX77541_ADC) += max77541-adc.o
obj-$(CONFIG_MAX9611) += max9611.o
obj-$(CONFIG_MCP320X) += mcp320x.o
obj-$(CONFIG_MCP3422) += mcp3422.o
obj-$(CONFIG_MCP3564) += mcp3564.o
obj-$(CONFIG_MCP3911) += mcp3911.o
obj-$(CONFIG_MEDIATEK_MT6360_ADC) += mt6360-adc.o
obj-$(CONFIG_MEDIATEK_MT6370_ADC) += mt6370-adc.o

View File

@ -1179,7 +1179,7 @@ out_dis_pm:
return ret;
}
static int ab8500_gpadc_remove(struct platform_device *pdev)
static void ab8500_gpadc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct ab8500_gpadc *gpadc = iio_priv(indio_dev);
@ -1188,8 +1188,6 @@ static int ab8500_gpadc_remove(struct platform_device *pdev)
pm_runtime_put_noidle(gpadc->dev);
pm_runtime_disable(gpadc->dev);
regulator_disable(gpadc->vddadc);
return 0;
}
static DEFINE_RUNTIME_DEV_PM_OPS(ab8500_gpadc_pm_ops,
@ -1198,7 +1196,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(ab8500_gpadc_pm_ops,
static struct platform_driver ab8500_gpadc_driver = {
.probe = ab8500_gpadc_probe,
.remove = ab8500_gpadc_remove,
.remove_new = ab8500_gpadc_remove,
.driver = {
.name = "ab8500-gpadc",
.pm = pm_ptr(&ab8500_gpadc_pm_ops),

View File

@ -1817,18 +1817,12 @@ static const struct clk_ops ad4130_int_clk_ops = {
.unprepare = ad4130_int_clk_unprepare,
};
static void ad4130_clk_del_provider(void *of_node)
{
of_clk_del_provider(of_node);
}
static int ad4130_setup_int_clk(struct ad4130_state *st)
{
struct device *dev = &st->spi->dev;
struct device_node *of_node = dev_of_node(dev);
struct clk_init_data init;
const char *clk_name;
struct clk *clk;
int ret;
if (st->int_pin_sel == AD4130_INT_PIN_CLK ||
@ -1845,15 +1839,12 @@ static int ad4130_setup_int_clk(struct ad4130_state *st)
init.ops = &ad4130_int_clk_ops;
st->int_clk_hw.init = &init;
clk = devm_clk_register(dev, &st->int_clk_hw);
if (IS_ERR(clk))
return PTR_ERR(clk);
ret = of_clk_add_provider(of_node, of_clk_src_simple_get, clk);
ret = devm_clk_hw_register(dev, &st->int_clk_hw);
if (ret)
return ret;
return devm_add_action_or_reset(dev, ad4130_clk_del_provider, of_node);
return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
&st->int_clk_hw);
}
static int ad4130_setup(struct iio_dev *indio_dev)

View File

@ -6,6 +6,7 @@
*/
#include <linux/interrupt.h>
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/kernel.h>
@ -43,7 +44,7 @@
#define AD7192_COMM_WEN BIT(7) /* Write Enable */
#define AD7192_COMM_WRITE 0 /* Write Operation */
#define AD7192_COMM_READ BIT(6) /* Read Operation */
#define AD7192_COMM_ADDR(x) (((x) & 0x7) << 3) /* Register Address */
#define AD7192_COMM_ADDR_MASK GENMASK(5, 3) /* Register Address Mask */
#define AD7192_COMM_CREAD BIT(2) /* Continuous Read of Data Register */
/* Status Register Bit Designations (AD7192_REG_STAT) */
@ -56,17 +57,18 @@
#define AD7192_STAT_CH1 BIT(0) /* Channel 1 */
/* Mode Register Bit Designations (AD7192_REG_MODE) */
#define AD7192_MODE_SEL(x) (((x) & 0x7) << 21) /* Operation Mode Select */
#define AD7192_MODE_SEL_MASK (0x7 << 21) /* Operation Mode Select Mask */
#define AD7192_MODE_STA(x) (((x) & 0x1) << 20) /* Status Register transmission */
#define AD7192_MODE_SEL_MASK GENMASK(23, 21) /* Operation Mode Select Mask */
#define AD7192_MODE_STA_MASK BIT(20) /* Status Register transmission Mask */
#define AD7192_MODE_CLKSRC(x) (((x) & 0x3) << 18) /* Clock Source Select */
#define AD7192_MODE_CLKSRC_MASK GENMASK(19, 18) /* Clock Source Select Mask */
#define AD7192_MODE_AVG_MASK GENMASK(17, 16)
/* Fast Settling Filter Average Select Mask (AD7193 only) */
#define AD7192_MODE_SINC3 BIT(15) /* SINC3 Filter Select */
#define AD7192_MODE_ENPAR BIT(13) /* Parity Enable */
#define AD7192_MODE_CLKDIV BIT(12) /* Clock divide by 2 (AD7190/2 only)*/
#define AD7192_MODE_SCYCLE BIT(11) /* Single cycle conversion */
#define AD7192_MODE_REJ60 BIT(10) /* 50/60Hz notch filter */
#define AD7192_MODE_RATE(x) ((x) & 0x3FF) /* Filter Update Rate Select */
/* Filter Update Rate Select Mask */
#define AD7192_MODE_RATE_MASK GENMASK(9, 0)
/* Mode Register: AD7192_MODE_SEL options */
#define AD7192_MODE_CONT 0 /* Continuous Conversion Mode */
@ -92,13 +94,12 @@
#define AD7192_CONF_CHOP BIT(23) /* CHOP enable */
#define AD7192_CONF_ACX BIT(22) /* AC excitation enable(AD7195 only) */
#define AD7192_CONF_REFSEL BIT(20) /* REFIN1/REFIN2 Reference Select */
#define AD7192_CONF_CHAN(x) ((x) << 8) /* Channel select */
#define AD7192_CONF_CHAN_MASK (0x7FF << 8) /* Channel select mask */
#define AD7192_CONF_CHAN_MASK GENMASK(18, 8) /* Channel select mask */
#define AD7192_CONF_BURN BIT(7) /* Burnout current enable */
#define AD7192_CONF_REFDET BIT(6) /* Reference detect enable */
#define AD7192_CONF_BUF BIT(4) /* Buffered Mode Enable */
#define AD7192_CONF_UNIPOLAR BIT(3) /* Unipolar/Bipolar Enable */
#define AD7192_CONF_GAIN(x) ((x) & 0x7) /* Gain Select */
#define AD7192_CONF_GAIN_MASK GENMASK(2, 0) /* Gain Select */
#define AD7192_CH_AIN1P_AIN2M BIT(0) /* AIN1(+) - AIN2(-) */
#define AD7192_CH_AIN3P_AIN4M BIT(1) /* AIN3(+) - AIN4(-) */
@ -130,7 +131,7 @@
#define CHIPID_AD7192 0x0
#define CHIPID_AD7193 0x2
#define CHIPID_AD7195 0x6
#define AD7192_ID_MASK 0x0F
#define AD7192_ID_MASK GENMASK(3, 0)
/* GPOCON Register Bit Designations (AD7192_REG_GPOCON) */
#define AD7192_GPOCON_BPDSW BIT(6) /* Bridge power-down switch enable */
@ -172,6 +173,9 @@ enum {
struct ad7192_chip_info {
unsigned int chip_id;
const char *name;
const struct iio_chan_spec *channels;
u8 num_channels;
const struct iio_info *info;
};
struct ad7192_state {
@ -181,10 +185,10 @@ struct ad7192_state {
struct clk *mclk;
u16 int_vref_mv;
u32 fclk;
u32 f_order;
u32 mode;
u32 conf;
u32 scale_avail[8][2];
u32 oversampling_ratio_avail[4];
u8 gpocon;
u8 clock_sel;
struct mutex lock; /* protect sensor state */
@ -273,7 +277,7 @@ static int ad7192_set_channel(struct ad_sigma_delta *sd, unsigned int channel)
struct ad7192_state *st = ad_sigma_delta_to_ad7192(sd);
st->conf &= ~AD7192_CONF_CHAN_MASK;
st->conf |= AD7192_CONF_CHAN(channel);
st->conf |= FIELD_PREP(AD7192_CONF_CHAN_MASK, channel);
return ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf);
}
@ -284,7 +288,7 @@ static int ad7192_set_mode(struct ad_sigma_delta *sd,
struct ad7192_state *st = ad_sigma_delta_to_ad7192(sd);
st->mode &= ~AD7192_MODE_SEL_MASK;
st->mode |= AD7192_MODE_SEL(mode);
st->mode |= FIELD_PREP(AD7192_MODE_SEL_MASK, mode);
return ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
}
@ -296,7 +300,7 @@ static int ad7192_append_status(struct ad_sigma_delta *sd, bool append)
int ret;
mode &= ~AD7192_MODE_STA_MASK;
mode |= AD7192_MODE_STA(append);
mode |= FIELD_PREP(AD7192_MODE_STA_MASK, append);
ret = ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, mode);
if (ret < 0)
@ -400,17 +404,17 @@ static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np)
if (ret)
return ret;
id &= AD7192_ID_MASK;
id = FIELD_GET(AD7192_ID_MASK, id);
if (id != st->chip_info->chip_id)
dev_warn(&st->sd.spi->dev, "device ID query failed (0x%X != 0x%X)\n",
id, st->chip_info->chip_id);
st->mode = AD7192_MODE_SEL(AD7192_MODE_IDLE) |
AD7192_MODE_CLKSRC(st->clock_sel) |
AD7192_MODE_RATE(480);
st->mode = FIELD_PREP(AD7192_MODE_SEL_MASK, AD7192_MODE_IDLE) |
FIELD_PREP(AD7192_MODE_CLKSRC_MASK, st->clock_sel) |
FIELD_PREP(AD7192_MODE_RATE_MASK, 480);
st->conf = AD7192_CONF_GAIN(0);
st->conf = FIELD_PREP(AD7192_CONF_GAIN_MASK, 0);
rej60_en = of_property_read_bool(np, "adi,rejection-60-Hz-enable");
if (rej60_en)
@ -421,7 +425,6 @@ static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np)
st->conf |= AD7192_CONF_REFSEL;
st->conf &= ~AD7192_CONF_CHOP;
st->f_order = AD7192_NO_SYNC_FILTER;
buf_en = of_property_read_bool(np, "adi,buffer-enable");
if (buf_en)
@ -456,13 +459,18 @@ static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np)
for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) {
scale_uv = ((u64)st->int_vref_mv * 100000000)
>> (indio_dev->channels[0].scan_type.realbits -
((st->conf & AD7192_CONF_UNIPOLAR) ? 0 : 1));
!FIELD_GET(AD7192_CONF_UNIPOLAR, st->conf));
scale_uv >>= i;
st->scale_avail[i][1] = do_div(scale_uv, 100000000) * 10;
st->scale_avail[i][0] = scale_uv;
}
st->oversampling_ratio_avail[0] = 1;
st->oversampling_ratio_avail[1] = 2;
st->oversampling_ratio_avail[2] = 8;
st->oversampling_ratio_avail[3] = 16;
return 0;
}
@ -473,7 +481,7 @@ static ssize_t ad7192_show_ac_excitation(struct device *dev,
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7192_state *st = iio_priv(indio_dev);
return sysfs_emit(buf, "%d\n", !!(st->conf & AD7192_CONF_ACX));
return sysfs_emit(buf, "%ld\n", FIELD_GET(AD7192_CONF_ACX, st->conf));
}
static ssize_t ad7192_show_bridge_switch(struct device *dev,
@ -483,7 +491,8 @@ static ssize_t ad7192_show_bridge_switch(struct device *dev,
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7192_state *st = iio_priv(indio_dev);
return sysfs_emit(buf, "%d\n", !!(st->gpocon & AD7192_GPOCON_BPDSW));
return sysfs_emit(buf, "%ld\n",
FIELD_GET(AD7192_GPOCON_BPDSW, st->gpocon));
}
static ssize_t ad7192_set(struct device *dev,
@ -531,22 +540,66 @@ static ssize_t ad7192_set(struct device *dev,
return ret ? ret : len;
}
static int ad7192_compute_f_order(struct ad7192_state *st, bool sinc3_en, bool chop_en)
{
u8 avg_factor_selected, oversampling_ratio;
avg_factor_selected = FIELD_GET(AD7192_MODE_AVG_MASK, st->mode);
if (!avg_factor_selected && !chop_en)
return 1;
oversampling_ratio = st->oversampling_ratio_avail[avg_factor_selected];
if (sinc3_en)
return AD7192_SYNC3_FILTER + oversampling_ratio - 1;
return AD7192_SYNC4_FILTER + oversampling_ratio - 1;
}
static int ad7192_get_f_order(struct ad7192_state *st)
{
bool sinc3_en, chop_en;
sinc3_en = FIELD_GET(AD7192_MODE_SINC3, st->mode);
chop_en = FIELD_GET(AD7192_CONF_CHOP, st->conf);
return ad7192_compute_f_order(st, sinc3_en, chop_en);
}
static int ad7192_compute_f_adc(struct ad7192_state *st, bool sinc3_en,
bool chop_en)
{
unsigned int f_order = ad7192_compute_f_order(st, sinc3_en, chop_en);
return DIV_ROUND_CLOSEST(st->fclk,
f_order * FIELD_GET(AD7192_MODE_RATE_MASK, st->mode));
}
static int ad7192_get_f_adc(struct ad7192_state *st)
{
unsigned int f_order = ad7192_get_f_order(st);
return DIV_ROUND_CLOSEST(st->fclk,
f_order * FIELD_GET(AD7192_MODE_RATE_MASK, st->mode));
}
static void ad7192_get_available_filter_freq(struct ad7192_state *st,
int *freq)
{
unsigned int fadc;
/* Formulas for filter at page 25 of the datasheet */
fadc = DIV_ROUND_CLOSEST(st->fclk,
AD7192_SYNC4_FILTER * AD7192_MODE_RATE(st->mode));
fadc = ad7192_compute_f_adc(st, false, true);
freq[0] = DIV_ROUND_CLOSEST(fadc * 240, 1024);
fadc = DIV_ROUND_CLOSEST(st->fclk,
AD7192_SYNC3_FILTER * AD7192_MODE_RATE(st->mode));
fadc = ad7192_compute_f_adc(st, true, true);
freq[1] = DIV_ROUND_CLOSEST(fadc * 240, 1024);
fadc = DIV_ROUND_CLOSEST(st->fclk, AD7192_MODE_RATE(st->mode));
fadc = ad7192_compute_f_adc(st, false, false);
freq[2] = DIV_ROUND_CLOSEST(fadc * 230, 1024);
fadc = ad7192_compute_f_adc(st, true, false);
freq[3] = DIV_ROUND_CLOSEST(fadc * 272, 1024);
}
@ -629,25 +682,21 @@ static int ad7192_set_3db_filter_freq(struct ad7192_state *st,
switch (idx) {
case 0:
st->f_order = AD7192_SYNC4_FILTER;
st->mode &= ~AD7192_MODE_SINC3;
st->conf |= AD7192_CONF_CHOP;
break;
case 1:
st->f_order = AD7192_SYNC3_FILTER;
st->mode |= AD7192_MODE_SINC3;
st->conf |= AD7192_CONF_CHOP;
break;
case 2:
st->f_order = AD7192_NO_SYNC_FILTER;
st->mode &= ~AD7192_MODE_SINC3;
st->conf &= ~AD7192_CONF_CHOP;
break;
case 3:
st->f_order = AD7192_NO_SYNC_FILTER;
st->mode |= AD7192_MODE_SINC3;
st->conf &= ~AD7192_CONF_CHOP;
@ -665,12 +714,11 @@ static int ad7192_get_3db_filter_freq(struct ad7192_state *st)
{
unsigned int fadc;
fadc = DIV_ROUND_CLOSEST(st->fclk,
st->f_order * AD7192_MODE_RATE(st->mode));
fadc = ad7192_get_f_adc(st);
if (st->conf & AD7192_CONF_CHOP)
if (FIELD_GET(AD7192_CONF_CHOP, st->conf))
return DIV_ROUND_CLOSEST(fadc * 240, 1024);
if (st->mode & AD7192_MODE_SINC3)
if (FIELD_GET(AD7192_MODE_SINC3, st->mode))
return DIV_ROUND_CLOSEST(fadc * 272, 1024);
else
return DIV_ROUND_CLOSEST(fadc * 230, 1024);
@ -683,7 +731,8 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,
long m)
{
struct ad7192_state *st = iio_priv(indio_dev);
bool unipolar = !!(st->conf & AD7192_CONF_UNIPOLAR);
bool unipolar = FIELD_GET(AD7192_CONF_UNIPOLAR, st->conf);
u8 gain = FIELD_GET(AD7192_CONF_GAIN_MASK, st->conf);
switch (m) {
case IIO_CHAN_INFO_RAW:
@ -692,8 +741,8 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,
switch (chan->type) {
case IIO_VOLTAGE:
mutex_lock(&st->lock);
*val = st->scale_avail[AD7192_CONF_GAIN(st->conf)][0];
*val2 = st->scale_avail[AD7192_CONF_GAIN(st->conf)][1];
*val = st->scale_avail[gain][0];
*val2 = st->scale_avail[gain][1];
mutex_unlock(&st->lock);
return IIO_VAL_INT_PLUS_NANO;
case IIO_TEMP:
@ -713,13 +762,15 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,
*val -= 273 * ad7192_get_temp_scale(unipolar);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SAMP_FREQ:
*val = st->fclk /
(st->f_order * 1024 * AD7192_MODE_RATE(st->mode));
*val = DIV_ROUND_CLOSEST(ad7192_get_f_adc(st), 1024);
return IIO_VAL_INT;
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
*val = ad7192_get_3db_filter_freq(st);
*val2 = 1000;
return IIO_VAL_FRACTIONAL;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
*val = st->oversampling_ratio_avail[FIELD_GET(AD7192_MODE_AVG_MASK, st->mode)];
return IIO_VAL_INT;
}
return -EINVAL;
@ -747,8 +798,8 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
if (val2 == st->scale_avail[i][1]) {
ret = 0;
tmp = st->conf;
st->conf &= ~AD7192_CONF_GAIN(-1);
st->conf |= AD7192_CONF_GAIN(i);
st->conf &= ~AD7192_CONF_GAIN_MASK;
st->conf |= FIELD_PREP(AD7192_CONF_GAIN_MASK, i);
if (tmp == st->conf)
break;
ad_sd_write_reg(&st->sd, AD7192_REG_CONF,
@ -764,19 +815,36 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
break;
}
div = st->fclk / (val * st->f_order * 1024);
div = st->fclk / (val * ad7192_get_f_order(st) * 1024);
if (div < 1 || div > 1023) {
ret = -EINVAL;
break;
}
st->mode &= ~AD7192_MODE_RATE(-1);
st->mode |= AD7192_MODE_RATE(div);
st->mode &= ~AD7192_MODE_RATE_MASK;
st->mode |= FIELD_PREP(AD7192_MODE_RATE_MASK, div);
ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
break;
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
ret = ad7192_set_3db_filter_freq(st, val, val2 / 1000);
break;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
ret = -EINVAL;
mutex_lock(&st->lock);
for (i = 0; i < ARRAY_SIZE(st->oversampling_ratio_avail); i++)
if (val == st->oversampling_ratio_avail[i]) {
ret = 0;
tmp = st->mode;
st->mode &= ~AD7192_MODE_AVG_MASK;
st->mode |= FIELD_PREP(AD7192_MODE_AVG_MASK, i);
if (tmp == st->mode)
break;
ad_sd_write_reg(&st->sd, AD7192_REG_MODE,
3, st->mode);
break;
}
mutex_unlock(&st->lock);
break;
default:
ret = -EINVAL;
}
@ -797,6 +865,8 @@ static int ad7192_write_raw_get_fmt(struct iio_dev *indio_dev,
return IIO_VAL_INT;
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
return IIO_VAL_INT;
default:
return -EINVAL;
}
@ -816,6 +886,12 @@ static int ad7192_read_avail(struct iio_dev *indio_dev,
/* Values are stored in a 2D matrix */
*length = ARRAY_SIZE(st->scale_avail) * 2;
return IIO_AVAIL_LIST;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
*vals = (int *)st->oversampling_ratio_avail;
*type = IIO_VAL_INT;
*length = ARRAY_SIZE(st->oversampling_ratio_avail);
return IIO_AVAIL_LIST;
}
@ -831,7 +907,7 @@ static int ad7192_update_scan_mode(struct iio_dev *indio_dev, const unsigned lon
conf &= ~AD7192_CONF_CHAN_MASK;
for_each_set_bit(i, scan_mask, 8)
conf |= AD7192_CONF_CHAN(i);
conf |= FIELD_PREP(AD7192_CONF_CHAN_MASK, i);
ret = ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, conf);
if (ret < 0)
@ -862,8 +938,8 @@ static const struct iio_info ad7195_info = {
.update_scan_mode = ad7192_update_scan_mode,
};
#define __AD719x_CHANNEL(_si, _channel1, _channel2, _address, _extend_name, \
_type, _mask_type_av, _ext_info) \
#define __AD719x_CHANNEL(_si, _channel1, _channel2, _address, _type, \
_mask_all, _mask_type_av, _mask_all_av, _ext_info) \
{ \
.type = (_type), \
.differential = ((_channel2) == -1 ? 0 : 1), \
@ -871,13 +947,14 @@ static const struct iio_info ad7195_info = {
.channel = (_channel1), \
.channel2 = (_channel2), \
.address = (_address), \
.extend_name = (_extend_name), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_OFFSET), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \
(_mask_all), \
.info_mask_shared_by_type_available = (_mask_type_av), \
.info_mask_shared_by_all_available = (_mask_all_av), \
.ext_info = (_ext_info), \
.scan_index = (_si), \
.scan_type = { \
@ -889,16 +966,26 @@ static const struct iio_info ad7195_info = {
}
#define AD719x_DIFF_CHANNEL(_si, _channel1, _channel2, _address) \
__AD719x_CHANNEL(_si, _channel1, _channel2, _address, NULL, \
IIO_VOLTAGE, BIT(IIO_CHAN_INFO_SCALE), \
ad7192_calibsys_ext_info)
__AD719x_CHANNEL(_si, _channel1, _channel2, _address, IIO_VOLTAGE, 0, \
BIT(IIO_CHAN_INFO_SCALE), 0, ad7192_calibsys_ext_info)
#define AD719x_CHANNEL(_si, _channel1, _address) \
__AD719x_CHANNEL(_si, _channel1, -1, _address, NULL, IIO_VOLTAGE, \
BIT(IIO_CHAN_INFO_SCALE), ad7192_calibsys_ext_info)
__AD719x_CHANNEL(_si, _channel1, -1, _address, IIO_VOLTAGE, 0, \
BIT(IIO_CHAN_INFO_SCALE), 0, ad7192_calibsys_ext_info)
#define AD719x_TEMP_CHANNEL(_si, _address) \
__AD719x_CHANNEL(_si, 0, -1, _address, NULL, IIO_TEMP, 0, NULL)
__AD719x_CHANNEL(_si, 0, -1, _address, IIO_TEMP, 0, 0, 0, NULL)
#define AD7193_DIFF_CHANNEL(_si, _channel1, _channel2, _address) \
__AD719x_CHANNEL(_si, _channel1, _channel2, _address, \
IIO_VOLTAGE, \
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
BIT(IIO_CHAN_INFO_SCALE), \
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
ad7192_calibsys_ext_info)
#define AD7193_CHANNEL(_si, _channel1, _address) \
AD7193_DIFF_CHANNEL(_si, _channel1, -1, _address)
static const struct iio_chan_spec ad7192_channels[] = {
AD719x_DIFF_CHANNEL(0, 1, 2, AD7192_CH_AIN1P_AIN2M),
@ -913,20 +1000,20 @@ static const struct iio_chan_spec ad7192_channels[] = {
};
static const struct iio_chan_spec ad7193_channels[] = {
AD719x_DIFF_CHANNEL(0, 1, 2, AD7193_CH_AIN1P_AIN2M),
AD719x_DIFF_CHANNEL(1, 3, 4, AD7193_CH_AIN3P_AIN4M),
AD719x_DIFF_CHANNEL(2, 5, 6, AD7193_CH_AIN5P_AIN6M),
AD719x_DIFF_CHANNEL(3, 7, 8, AD7193_CH_AIN7P_AIN8M),
AD7193_DIFF_CHANNEL(0, 1, 2, AD7193_CH_AIN1P_AIN2M),
AD7193_DIFF_CHANNEL(1, 3, 4, AD7193_CH_AIN3P_AIN4M),
AD7193_DIFF_CHANNEL(2, 5, 6, AD7193_CH_AIN5P_AIN6M),
AD7193_DIFF_CHANNEL(3, 7, 8, AD7193_CH_AIN7P_AIN8M),
AD719x_TEMP_CHANNEL(4, AD7193_CH_TEMP),
AD719x_DIFF_CHANNEL(5, 2, 2, AD7193_CH_AIN2P_AIN2M),
AD719x_CHANNEL(6, 1, AD7193_CH_AIN1),
AD719x_CHANNEL(7, 2, AD7193_CH_AIN2),
AD719x_CHANNEL(8, 3, AD7193_CH_AIN3),
AD719x_CHANNEL(9, 4, AD7193_CH_AIN4),
AD719x_CHANNEL(10, 5, AD7193_CH_AIN5),
AD719x_CHANNEL(11, 6, AD7193_CH_AIN6),
AD719x_CHANNEL(12, 7, AD7193_CH_AIN7),
AD719x_CHANNEL(13, 8, AD7193_CH_AIN8),
AD7193_DIFF_CHANNEL(5, 2, 2, AD7193_CH_AIN2P_AIN2M),
AD7193_CHANNEL(6, 1, AD7193_CH_AIN1),
AD7193_CHANNEL(7, 2, AD7193_CH_AIN2),
AD7193_CHANNEL(8, 3, AD7193_CH_AIN3),
AD7193_CHANNEL(9, 4, AD7193_CH_AIN4),
AD7193_CHANNEL(10, 5, AD7193_CH_AIN5),
AD7193_CHANNEL(11, 6, AD7193_CH_AIN6),
AD7193_CHANNEL(12, 7, AD7193_CH_AIN7),
AD7193_CHANNEL(13, 8, AD7193_CH_AIN8),
IIO_CHAN_SOFT_TIMESTAMP(14),
};
@ -934,39 +1021,33 @@ static const struct ad7192_chip_info ad7192_chip_info_tbl[] = {
[ID_AD7190] = {
.chip_id = CHIPID_AD7190,
.name = "ad7190",
.channels = ad7192_channels,
.num_channels = ARRAY_SIZE(ad7192_channels),
.info = &ad7192_info,
},
[ID_AD7192] = {
.chip_id = CHIPID_AD7192,
.name = "ad7192",
.channels = ad7192_channels,
.num_channels = ARRAY_SIZE(ad7192_channels),
.info = &ad7192_info,
},
[ID_AD7193] = {
.chip_id = CHIPID_AD7193,
.name = "ad7193",
.channels = ad7193_channels,
.num_channels = ARRAY_SIZE(ad7193_channels),
.info = &ad7192_info,
},
[ID_AD7195] = {
.chip_id = CHIPID_AD7195,
.name = "ad7195",
.channels = ad7192_channels,
.num_channels = ARRAY_SIZE(ad7192_channels),
.info = &ad7195_info,
},
};
static int ad7192_channels_config(struct iio_dev *indio_dev)
{
struct ad7192_state *st = iio_priv(indio_dev);
switch (st->chip_info->chip_id) {
case CHIPID_AD7193:
indio_dev->channels = ad7193_channels;
indio_dev->num_channels = ARRAY_SIZE(ad7193_channels);
break;
default:
indio_dev->channels = ad7192_channels;
indio_dev->num_channels = ARRAY_SIZE(ad7192_channels);
break;
}
return 0;
}
static void ad7192_reg_disable(void *reg)
{
regulator_disable(reg);
@ -1041,15 +1122,9 @@ static int ad7192_probe(struct spi_device *spi)
st->chip_info = (void *)spi_get_device_id(spi)->driver_data;
indio_dev->name = st->chip_info->name;
indio_dev->modes = INDIO_DIRECT_MODE;
ret = ad7192_channels_config(indio_dev);
if (ret < 0)
return ret;
if (st->chip_info->chip_id == CHIPID_AD7195)
indio_dev->info = &ad7195_info;
else
indio_dev->info = &ad7192_info;
indio_dev->channels = st->chip_info->channels;
indio_dev->num_channels = st->chip_info->num_channels;
indio_dev->info = st->chip_info->info;
ret = ad_sd_init(&st->sd, indio_dev, spi, &ad7192_sigma_delta_info);
if (ret)

View File

@ -2486,7 +2486,7 @@ reg_disable:
return ret;
}
static int at91_adc_remove(struct platform_device *pdev)
static void at91_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct at91_adc_state *st = iio_priv(indio_dev);
@ -2501,8 +2501,6 @@ static int at91_adc_remove(struct platform_device *pdev)
regulator_disable(st->vref);
regulator_disable(st->reg);
return 0;
}
static int at91_adc_suspend(struct device *dev)
@ -2627,7 +2625,7 @@ MODULE_DEVICE_TABLE(of, at91_adc_dt_match);
static struct platform_driver at91_adc_driver = {
.probe = at91_adc_probe,
.remove = at91_adc_remove,
.remove_new = at91_adc_remove,
.driver = {
.name = "at91-sama5d2_adc",
.of_match_table = at91_adc_dt_match,

View File

@ -1013,28 +1013,25 @@ static int at91_adc_probe(struct platform_device *pdev)
st->use_external = of_property_read_bool(node, "atmel,adc-use-external-triggers");
if (of_property_read_u32(node, "atmel,adc-channels-used", &prop)) {
dev_err(&idev->dev, "Missing adc-channels-used property in the DT.\n");
return -EINVAL;
}
if (of_property_read_u32(node, "atmel,adc-channels-used", &prop))
return dev_err_probe(&idev->dev, -EINVAL,
"Missing adc-channels-used property in the DT.\n");
st->channels_mask = prop;
st->sleep_mode = of_property_read_bool(node, "atmel,adc-sleep-mode");
if (of_property_read_u32(node, "atmel,adc-startup-time", &prop)) {
dev_err(&idev->dev, "Missing adc-startup-time property in the DT.\n");
return -EINVAL;
}
if (of_property_read_u32(node, "atmel,adc-startup-time", &prop))
return dev_err_probe(&idev->dev, -EINVAL,
"Missing adc-startup-time property in the DT.\n");
st->startup_time = prop;
prop = 0;
of_property_read_u32(node, "atmel,adc-sample-hold-time", &prop);
st->sample_hold_time = prop;
if (of_property_read_u32(node, "atmel,adc-vref", &prop)) {
dev_err(&idev->dev, "Missing adc-vref property in the DT.\n");
return -EINVAL;
}
if (of_property_read_u32(node, "atmel,adc-vref", &prop))
return dev_err_probe(&idev->dev, -EINVAL,
"Missing adc-vref property in the DT.\n");
st->vref_mv = prop;
st->res = st->caps->high_res_bits;
@ -1069,7 +1066,6 @@ static int at91_adc_probe(struct platform_device *pdev)
if (IS_ERR(st->reg_base))
return PTR_ERR(st->reg_base);
/*
* Disable all IRQs before setting up the handler
*/
@ -1077,43 +1073,26 @@ static int at91_adc_probe(struct platform_device *pdev)
at91_adc_writel(st, AT91_ADC_IDR, 0xFFFFFFFF);
if (st->caps->has_tsmr)
ret = request_irq(st->irq, at91_adc_9x5_interrupt, 0,
pdev->dev.driver->name, idev);
ret = devm_request_irq(&pdev->dev, st->irq,
at91_adc_9x5_interrupt, 0,
pdev->dev.driver->name, idev);
else
ret = request_irq(st->irq, at91_adc_rl_interrupt, 0,
pdev->dev.driver->name, idev);
if (ret) {
dev_err(&pdev->dev, "Failed to allocate IRQ.\n");
return ret;
}
ret = devm_request_irq(&pdev->dev, st->irq,
at91_adc_rl_interrupt, 0,
pdev->dev.driver->name, idev);
if (ret)
return dev_err_probe(&pdev->dev, ret,
"Failed to allocate IRQ.\n");
st->clk = devm_clk_get(&pdev->dev, "adc_clk");
if (IS_ERR(st->clk)) {
dev_err(&pdev->dev, "Failed to get the clock.\n");
ret = PTR_ERR(st->clk);
goto error_free_irq;
}
st->clk = devm_clk_get_enabled(&pdev->dev, "adc_clk");
if (IS_ERR(st->clk))
return dev_err_probe(&pdev->dev, PTR_ERR(st->clk),
"Could not prepare or enable the clock.\n");
ret = clk_prepare_enable(st->clk);
if (ret) {
dev_err(&pdev->dev,
"Could not prepare or enable the clock.\n");
goto error_free_irq;
}
st->adc_clk = devm_clk_get(&pdev->dev, "adc_op_clk");
if (IS_ERR(st->adc_clk)) {
dev_err(&pdev->dev, "Failed to get the ADC clock.\n");
ret = PTR_ERR(st->adc_clk);
goto error_disable_clk;
}
ret = clk_prepare_enable(st->adc_clk);
if (ret) {
dev_err(&pdev->dev,
"Could not prepare or enable the ADC clock.\n");
goto error_disable_clk;
}
st->adc_clk = devm_clk_get_enabled(&pdev->dev, "adc_op_clk");
if (IS_ERR(st->adc_clk))
return dev_err_probe(&pdev->dev, PTR_ERR(st->adc_clk),
"Could not prepare or enable the ADC clock.\n");
/*
* Prescaler rate computation using the formula from the Atmel's
@ -1129,11 +1108,9 @@ static int at91_adc_probe(struct platform_device *pdev)
prsc = (mstrclk / (2 * adc_clk)) - 1;
if (!st->startup_time) {
dev_err(&pdev->dev, "No startup time available.\n");
ret = -EINVAL;
goto error_disable_adc_clk;
}
if (!st->startup_time)
return dev_err_probe(&pdev->dev, -EINVAL,
"No startup time available.\n");
ticks = (*st->caps->calc_startup_ticks)(st->startup_time, adc_clk_khz);
/*
@ -1158,10 +1135,9 @@ static int at91_adc_probe(struct platform_device *pdev)
/* Setup the ADC channels available on the board */
ret = at91_adc_channel_init(idev);
if (ret < 0) {
dev_err(&pdev->dev, "Couldn't initialize the channels.\n");
goto error_disable_adc_clk;
}
if (ret < 0)
return dev_err_probe(&pdev->dev, ret,
"Couldn't initialize the channels.\n");
init_waitqueue_head(&st->wq_data_avail);
mutex_init(&st->lock);
@ -1173,21 +1149,20 @@ static int at91_adc_probe(struct platform_device *pdev)
*/
if (!st->touchscreen_type) {
ret = at91_adc_buffer_init(idev);
if (ret < 0) {
dev_err(&pdev->dev, "Couldn't initialize the buffer.\n");
goto error_disable_adc_clk;
}
if (ret < 0)
return dev_err_probe(&pdev->dev, ret,
"Couldn't initialize the buffer.\n");
ret = at91_adc_trigger_init(idev);
if (ret < 0) {
dev_err(&pdev->dev, "Couldn't setup the triggers.\n");
at91_adc_buffer_remove(idev);
goto error_disable_adc_clk;
return ret;
}
} else {
ret = at91_ts_register(idev, pdev);
if (ret)
goto error_disable_adc_clk;
return ret;
at91_ts_hw_init(idev, adc_clk_khz);
}
@ -1207,16 +1182,10 @@ error_iio_device_register:
} else {
at91_ts_unregister(st);
}
error_disable_adc_clk:
clk_disable_unprepare(st->adc_clk);
error_disable_clk:
clk_disable_unprepare(st->clk);
error_free_irq:
free_irq(st->irq, idev);
return ret;
}
static int at91_adc_remove(struct platform_device *pdev)
static void at91_adc_remove(struct platform_device *pdev)
{
struct iio_dev *idev = platform_get_drvdata(pdev);
struct at91_adc_state *st = iio_priv(idev);
@ -1228,11 +1197,6 @@ static int at91_adc_remove(struct platform_device *pdev)
} else {
at91_ts_unregister(st);
}
clk_disable_unprepare(st->adc_clk);
clk_disable_unprepare(st->clk);
free_irq(st->irq, idev);
return 0;
}
static int at91_adc_suspend(struct device *dev)
@ -1382,7 +1346,7 @@ MODULE_DEVICE_TABLE(of, at91_adc_dt_ids);
static struct platform_driver at91_adc_driver = {
.probe = at91_adc_probe,
.remove = at91_adc_remove,
.remove_new = at91_adc_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = at91_adc_dt_ids,

View File

@ -745,7 +745,7 @@ fail_map:
return ret;
}
static int axp20x_remove(struct platform_device *pdev)
static void axp20x_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct axp20x_adc_iio *info = iio_priv(indio_dev);
@ -757,8 +757,6 @@ static int axp20x_remove(struct platform_device *pdev)
if (info->data->adc_en2_mask)
regmap_write(info->regmap, AXP20X_ADC_EN2, 0);
return 0;
}
static struct platform_driver axp20x_adc_driver = {
@ -768,7 +766,7 @@ static struct platform_driver axp20x_adc_driver = {
},
.id_table = axp20x_adc_id_match,
.probe = axp20x_probe,
.remove = axp20x_remove,
.remove_new = axp20x_remove,
};
module_platform_driver(axp20x_adc_driver);

View File

@ -594,7 +594,7 @@ err_adc_enable:
return ret;
}
static int iproc_adc_remove(struct platform_device *pdev)
static void iproc_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct iproc_adc_priv *adc_priv = iio_priv(indio_dev);
@ -602,8 +602,6 @@ static int iproc_adc_remove(struct platform_device *pdev)
iio_device_unregister(indio_dev);
iproc_adc_disable(indio_dev);
clk_disable_unprepare(adc_priv->adc_clk);
return 0;
}
static const struct of_device_id iproc_adc_of_match[] = {
@ -614,7 +612,7 @@ MODULE_DEVICE_TABLE(of, iproc_adc_of_match);
static struct platform_driver iproc_adc_driver = {
.probe = iproc_adc_probe,
.remove = iproc_adc_remove,
.remove_new = iproc_adc_remove,
.driver = {
.name = "iproc-static-adc",
.of_match_table = iproc_adc_of_match,

View File

@ -691,19 +691,18 @@ unregister_event:
return ret;
}
static int dln2_adc_remove(struct platform_device *pdev)
static void dln2_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
iio_device_unregister(indio_dev);
dln2_unregister_event_cb(pdev, DLN2_ADC_CONDITION_MET_EV);
return 0;
}
static struct platform_driver dln2_adc_driver = {
.driver.name = DLN2_ADC_MOD_NAME,
.probe = dln2_adc_probe,
.remove = dln2_adc_remove,
.remove_new = dln2_adc_remove,
};
module_platform_driver(dln2_adc_driver);

View File

@ -217,15 +217,13 @@ static int ep93xx_adc_probe(struct platform_device *pdev)
return ret;
}
static int ep93xx_adc_remove(struct platform_device *pdev)
static void ep93xx_adc_remove(struct platform_device *pdev)
{
struct iio_dev *iiodev = platform_get_drvdata(pdev);
struct ep93xx_adc_priv *priv = iio_priv(iiodev);
iio_device_unregister(iiodev);
clk_disable_unprepare(priv->clk);
return 0;
}
static const struct of_device_id ep93xx_adc_of_ids[] = {
@ -240,7 +238,7 @@ static struct platform_driver ep93xx_adc_driver = {
.of_match_table = ep93xx_adc_of_ids,
},
.probe = ep93xx_adc_probe,
.remove = ep93xx_adc_remove,
.remove_new = ep93xx_adc_remove,
};
module_platform_driver(ep93xx_adc_driver);

View File

@ -946,7 +946,7 @@ err_disable_reg:
return ret;
}
static int exynos_adc_remove(struct platform_device *pdev)
static void exynos_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct exynos_adc *info = iio_priv(indio_dev);
@ -964,8 +964,6 @@ static int exynos_adc_remove(struct platform_device *pdev)
exynos_adc_disable_clk(info);
exynos_adc_unprepare_clk(info);
regulator_disable(info->vdd);
return 0;
}
static int exynos_adc_suspend(struct device *dev)
@ -1006,7 +1004,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(exynos_adc_pm_ops, exynos_adc_suspend,
static struct platform_driver exynos_adc_driver = {
.probe = exynos_adc_probe,
.remove = exynos_adc_remove,
.remove_new = exynos_adc_remove,
.driver = {
.name = "exynos-adc",
.of_match_table = exynos_adc_match,

View File

@ -384,7 +384,7 @@ err_regulator_disable:
return ret;
}
static int mx25_gcq_remove(struct platform_device *pdev)
static void mx25_gcq_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct mx25_gcq_priv *priv = iio_priv(indio_dev);
@ -397,8 +397,6 @@ static int mx25_gcq_remove(struct platform_device *pdev)
if (priv->vref[i])
regulator_disable(priv->vref[i]);
}
return 0;
}
static const struct of_device_id mx25_gcq_ids[] = {
@ -413,7 +411,7 @@ static struct platform_driver mx25_gcq_driver = {
.of_match_table = mx25_gcq_ids,
},
.probe = mx25_gcq_probe,
.remove = mx25_gcq_remove,
.remove_new = mx25_gcq_remove,
};
module_platform_driver(mx25_gcq_driver);

View File

@ -580,7 +580,7 @@ error_regulator:
return ret;
}
static int hx711_remove(struct platform_device *pdev)
static void hx711_remove(struct platform_device *pdev)
{
struct hx711_data *hx711_data;
struct iio_dev *indio_dev;
@ -593,8 +593,6 @@ static int hx711_remove(struct platform_device *pdev)
iio_triggered_buffer_cleanup(indio_dev);
regulator_disable(hx711_data->reg_avdd);
return 0;
}
static const struct of_device_id of_hx711_match[] = {
@ -606,7 +604,7 @@ MODULE_DEVICE_TABLE(of, of_hx711_match);
static struct platform_driver hx711_driver = {
.probe = hx711_probe,
.remove = hx711_remove,
.remove_new = hx711_remove,
.driver = {
.name = "hx711-gpio",
.of_match_table = of_hx711_match,

View File

@ -404,7 +404,7 @@ error_regulator_disable:
return ret;
}
static int imx8qxp_adc_remove(struct platform_device *pdev)
static void imx8qxp_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct imx8qxp_adc *adc = iio_priv(indio_dev);
@ -422,8 +422,6 @@ static int imx8qxp_adc_remove(struct platform_device *pdev)
pm_runtime_disable(dev);
pm_runtime_put_noidle(dev);
return 0;
}
static int imx8qxp_adc_runtime_suspend(struct device *dev)
@ -489,7 +487,7 @@ MODULE_DEVICE_TABLE(of, imx8qxp_adc_match);
static struct platform_driver imx8qxp_adc_driver = {
.probe = imx8qxp_adc_probe,
.remove = imx8qxp_adc_remove,
.remove_new = imx8qxp_adc_remove,
.driver = {
.name = ADC_DRIVER_NAME,
.of_match_table = imx8qxp_adc_match,

View File

@ -392,7 +392,7 @@ error_regulator_disable:
return ret;
}
static int imx93_adc_remove(struct platform_device *pdev)
static void imx93_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct imx93_adc *adc = iio_priv(indio_dev);
@ -410,8 +410,6 @@ static int imx93_adc_remove(struct platform_device *pdev)
free_irq(adc->irq, adc);
clk_disable_unprepare(adc->ipg_clk);
regulator_disable(adc->vref);
return 0;
}
static int imx93_adc_runtime_suspend(struct device *dev)
@ -468,7 +466,7 @@ MODULE_DEVICE_TABLE(of, imx93_adc_match);
static struct platform_driver imx93_adc_driver = {
.probe = imx93_adc_probe,
.remove = imx93_adc_remove,
.remove_new = imx93_adc_remove,
.driver = {
.name = IMX93_ADC_DRIVER_NAME,
.of_match_table = imx93_adc_match,

246
drivers/iio/adc/ltc2309.c Normal file
View File

@ -0,0 +1,246 @@
// SPDX-License-Identifier: GPL-2.0
/*
* The LTC2309 is an 8-Channel, 12-Bit SAR ADC with an I2C Interface.
*
* Datasheet:
* https://www.analog.com/media/en/technical-documentation/data-sheets/2309fd.pdf
*
* Copyright (c) 2023, Liam Beguin <liambeguin@gmail.com>
*/
#include <linux/bitfield.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/regulator/consumer.h>
#define LTC2309_ADC_RESOLUTION 12
#define LTC2309_DIN_CH_MASK GENMASK(7, 4)
#define LTC2309_DIN_SDN BIT(7)
#define LTC2309_DIN_OSN BIT(6)
#define LTC2309_DIN_S1 BIT(5)
#define LTC2309_DIN_S0 BIT(4)
#define LTC2309_DIN_UNI BIT(3)
#define LTC2309_DIN_SLEEP BIT(2)
/**
* struct ltc2309 - internal device data structure
* @dev: Device reference
* @client: I2C reference
* @vref: External reference source
* @lock: Lock to serialize data access
* @vref_mv: Internal voltage reference
*/
struct ltc2309 {
struct device *dev;
struct i2c_client *client;
struct regulator *vref;
struct mutex lock; /* serialize data access */
int vref_mv;
};
/* Order matches expected channel address, See datasheet Table 1. */
enum ltc2309_channels {
LTC2309_CH0_CH1 = 0,
LTC2309_CH2_CH3,
LTC2309_CH4_CH5,
LTC2309_CH6_CH7,
LTC2309_CH1_CH0,
LTC2309_CH3_CH2,
LTC2309_CH5_CH4,
LTC2309_CH7_CH6,
LTC2309_CH0,
LTC2309_CH2,
LTC2309_CH4,
LTC2309_CH6,
LTC2309_CH1,
LTC2309_CH3,
LTC2309_CH5,
LTC2309_CH7,
};
#define LTC2309_CHAN(_chan, _addr) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.address = _addr, \
.channel = _chan, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
}
#define LTC2309_DIFF_CHAN(_chan, _chan2, _addr) { \
.type = IIO_VOLTAGE, \
.differential = 1, \
.indexed = 1, \
.address = _addr, \
.channel = _chan, \
.channel2 = _chan2, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
}
static const struct iio_chan_spec ltc2309_channels[] = {
LTC2309_CHAN(0, LTC2309_CH0),
LTC2309_CHAN(1, LTC2309_CH1),
LTC2309_CHAN(2, LTC2309_CH2),
LTC2309_CHAN(3, LTC2309_CH3),
LTC2309_CHAN(4, LTC2309_CH4),
LTC2309_CHAN(5, LTC2309_CH5),
LTC2309_CHAN(6, LTC2309_CH6),
LTC2309_CHAN(7, LTC2309_CH7),
LTC2309_DIFF_CHAN(0, 1, LTC2309_CH0_CH1),
LTC2309_DIFF_CHAN(2, 3, LTC2309_CH2_CH3),
LTC2309_DIFF_CHAN(4, 5, LTC2309_CH4_CH5),
LTC2309_DIFF_CHAN(6, 7, LTC2309_CH6_CH7),
LTC2309_DIFF_CHAN(1, 0, LTC2309_CH1_CH0),
LTC2309_DIFF_CHAN(3, 2, LTC2309_CH3_CH2),
LTC2309_DIFF_CHAN(5, 4, LTC2309_CH5_CH4),
LTC2309_DIFF_CHAN(7, 6, LTC2309_CH7_CH6),
};
static int ltc2309_read_raw_channel(struct ltc2309 *ltc2309,
unsigned long address, int *val)
{
int ret;
u16 buf;
u8 din;
din = FIELD_PREP(LTC2309_DIN_CH_MASK, address & 0x0f) |
FIELD_PREP(LTC2309_DIN_UNI, 1) |
FIELD_PREP(LTC2309_DIN_SLEEP, 0);
ret = i2c_smbus_write_byte(ltc2309->client, din);
if (ret < 0) {
dev_err(ltc2309->dev, "i2c command failed: %pe\n",
ERR_PTR(ret));
return ret;
}
ret = i2c_master_recv(ltc2309->client, (char *)&buf, 2);
if (ret < 0) {
dev_err(ltc2309->dev, "i2c read failed: %pe\n", ERR_PTR(ret));
return ret;
}
*val = be16_to_cpu(buf) >> 4;
return ret;
}
static int ltc2309_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val,
int *val2, long mask)
{
struct ltc2309 *ltc2309 = iio_priv(indio_dev);
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&ltc2309->lock);
ret = ltc2309_read_raw_channel(ltc2309, chan->address, val);
mutex_unlock(&ltc2309->lock);
if (ret < 0)
return -EINVAL;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = ltc2309->vref_mv;
*val2 = LTC2309_ADC_RESOLUTION;
return IIO_VAL_FRACTIONAL_LOG2;
default:
return -EINVAL;
}
}
static const struct iio_info ltc2309_info = {
.read_raw = ltc2309_read_raw,
};
static void ltc2309_regulator_disable(void *regulator)
{
regulator_disable(regulator);
}
static int ltc2309_probe(struct i2c_client *client)
{
struct iio_dev *indio_dev;
struct ltc2309 *ltc2309;
int ret;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*ltc2309));
if (!indio_dev)
return -ENOMEM;
ltc2309 = iio_priv(indio_dev);
ltc2309->dev = &indio_dev->dev;
ltc2309->client = client;
ltc2309->vref_mv = 4096; /* Default to the internal ref */
indio_dev->name = "ltc2309";
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = ltc2309_channels;
indio_dev->num_channels = ARRAY_SIZE(ltc2309_channels);
indio_dev->info = &ltc2309_info;
ltc2309->vref = devm_regulator_get_optional(&client->dev, "vref");
if (IS_ERR(ltc2309->vref)) {
ret = PTR_ERR(ltc2309->vref);
if (ret == -ENODEV)
ltc2309->vref = NULL;
else
return ret;
}
if (ltc2309->vref) {
ret = regulator_enable(ltc2309->vref);
if (ret)
return dev_err_probe(ltc2309->dev, ret,
"failed to enable vref\n");
ret = devm_add_action_or_reset(ltc2309->dev,
ltc2309_regulator_disable,
ltc2309->vref);
if (ret) {
return dev_err_probe(ltc2309->dev, ret,
"failed to add regulator_disable action: %d\n",
ret);
}
ret = regulator_get_voltage(ltc2309->vref);
if (ret < 0)
return ret;
ltc2309->vref_mv = ret / 1000;
}
mutex_init(&ltc2309->lock);
return devm_iio_device_register(&client->dev, indio_dev);
}
static const struct of_device_id ltc2309_of_match[] = {
{ .compatible = "lltc,ltc2309" },
{ }
};
MODULE_DEVICE_TABLE(of, ltc2309_of_match);
static const struct i2c_device_id ltc2309_id[] = {
{ "ltc2309" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ltc2309_id);
static struct i2c_driver ltc2309_driver = {
.driver = {
.name = "ltc2309",
.of_match_table = ltc2309_of_match,
},
.probe = ltc2309_probe,
.id_table = ltc2309_id,
};
module_i2c_driver(ltc2309_driver);
MODULE_AUTHOR("Liam Beguin <liambeguin@gmail.com>");
MODULE_DESCRIPTION("Linear Technology LTC2309 ADC");
MODULE_LICENSE("GPL v2");

View File

@ -95,7 +95,6 @@ static int ltc2497_result_and_measure(struct ltc2497core_driverdata *ddata,
static int ltc2497_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
const struct ltc2497_chip_info *chip_info;
struct iio_dev *indio_dev;
struct ltc2497_driverdata *st;
@ -115,9 +114,7 @@ static int ltc2497_probe(struct i2c_client *client)
st->client = client;
st->common_ddata.result_and_measure = ltc2497_result_and_measure;
chip_info = device_get_match_data(dev);
if (!chip_info)
chip_info = (const struct ltc2497_chip_info *)id->driver_data;
chip_info = i2c_get_match_data(client);
st->common_ddata.chip_info = chip_info;
resolution = chip_info->resolution;

View File

@ -1599,9 +1599,7 @@ static int max1363_probe(struct i2c_client *client)
if (ret)
return ret;
st->chip_info = device_get_match_data(&client->dev);
if (!st->chip_info)
st->chip_info = &max1363_chip_info_tbl[id->driver_data];
st->chip_info = i2c_get_match_data(client);
st->client = client;
st->vref_uv = st->chip_info->int_vref_mv * 1000;
@ -1669,46 +1667,51 @@ static int max1363_probe(struct i2c_client *client)
return devm_iio_device_register(&client->dev, indio_dev);
}
#define MAX1363_ID_TABLE(_name, cfg) { \
.name = _name, \
.driver_data = (kernel_ulong_t)&max1363_chip_info_tbl[cfg], \
}
static const struct i2c_device_id max1363_id[] = {
{ "max1361", max1361 },
{ "max1362", max1362 },
{ "max1363", max1363 },
{ "max1364", max1364 },
{ "max1036", max1036 },
{ "max1037", max1037 },
{ "max1038", max1038 },
{ "max1039", max1039 },
{ "max1136", max1136 },
{ "max1137", max1137 },
{ "max1138", max1138 },
{ "max1139", max1139 },
{ "max1236", max1236 },
{ "max1237", max1237 },
{ "max1238", max1238 },
{ "max1239", max1239 },
{ "max11600", max11600 },
{ "max11601", max11601 },
{ "max11602", max11602 },
{ "max11603", max11603 },
{ "max11604", max11604 },
{ "max11605", max11605 },
{ "max11606", max11606 },
{ "max11607", max11607 },
{ "max11608", max11608 },
{ "max11609", max11609 },
{ "max11610", max11610 },
{ "max11611", max11611 },
{ "max11612", max11612 },
{ "max11613", max11613 },
{ "max11614", max11614 },
{ "max11615", max11615 },
{ "max11616", max11616 },
{ "max11617", max11617 },
{ "max11644", max11644 },
{ "max11645", max11645 },
{ "max11646", max11646 },
{ "max11647", max11647 },
{}
MAX1363_ID_TABLE("max1361", max1361),
MAX1363_ID_TABLE("max1362", max1362),
MAX1363_ID_TABLE("max1363", max1363),
MAX1363_ID_TABLE("max1364", max1364),
MAX1363_ID_TABLE("max1036", max1036),
MAX1363_ID_TABLE("max1037", max1037),
MAX1363_ID_TABLE("max1038", max1038),
MAX1363_ID_TABLE("max1039", max1039),
MAX1363_ID_TABLE("max1136", max1136),
MAX1363_ID_TABLE("max1137", max1137),
MAX1363_ID_TABLE("max1138", max1138),
MAX1363_ID_TABLE("max1139", max1139),
MAX1363_ID_TABLE("max1236", max1236),
MAX1363_ID_TABLE("max1237", max1237),
MAX1363_ID_TABLE("max1238", max1238),
MAX1363_ID_TABLE("max1239", max1239),
MAX1363_ID_TABLE("max11600", max11600),
MAX1363_ID_TABLE("max11601", max11601),
MAX1363_ID_TABLE("max11602", max11602),
MAX1363_ID_TABLE("max11603", max11603),
MAX1363_ID_TABLE("max11604", max11604),
MAX1363_ID_TABLE("max11605", max11605),
MAX1363_ID_TABLE("max11606", max11606),
MAX1363_ID_TABLE("max11607", max11607),
MAX1363_ID_TABLE("max11608", max11608),
MAX1363_ID_TABLE("max11609", max11609),
MAX1363_ID_TABLE("max11610", max11610),
MAX1363_ID_TABLE("max11611", max11611),
MAX1363_ID_TABLE("max11612", max11612),
MAX1363_ID_TABLE("max11613", max11613),
MAX1363_ID_TABLE("max11614", max11614),
MAX1363_ID_TABLE("max11615", max11615),
MAX1363_ID_TABLE("max11616", max11616),
MAX1363_ID_TABLE("max11617", max11617),
MAX1363_ID_TABLE("max11644", max11644),
MAX1363_ID_TABLE("max11645", max11645),
MAX1363_ID_TABLE("max11646", max11646),
MAX1363_ID_TABLE("max11647", max11647),
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, max1363_id);

1513
drivers/iio/adc/mcp3564.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -29,11 +29,11 @@
#define MCP3911_REG_MOD 0x06
#define MCP3911_REG_PHASE 0x07
#define MCP3911_REG_GAIN 0x09
#define MCP3911_GAIN_MASK(ch) (GENMASK(2, 0) << 3 * ch)
#define MCP3911_GAIN_VAL(ch, val) ((val << 3 * ch) & MCP3911_GAIN_MASK(ch))
#define MCP3911_GAIN_MASK(ch) (GENMASK(2, 0) << 3 * (ch))
#define MCP3911_GAIN_VAL(ch, val) ((val << 3 * (ch)) & MCP3911_GAIN_MASK(ch))
#define MCP3911_REG_STATUSCOM 0x0a
#define MCP3911_STATUSCOM_DRHIZ BIT(12)
#define MCP3911_STATUSCOM_DRHIZ BIT(12)
#define MCP3911_STATUSCOM_READ GENMASK(7, 6)
#define MCP3911_STATUSCOM_CH1_24WIDTH BIT(4)
#define MCP3911_STATUSCOM_CH0_24WIDTH BIT(3)
@ -51,8 +51,8 @@
#define MCP3911_REG_GAINCAL_CH1 0x17
#define MCP3911_REG_VREFCAL 0x1a
#define MCP3911_CHANNEL(x) (MCP3911_REG_CHANNEL0 + x * 3)
#define MCP3911_OFFCAL(x) (MCP3911_REG_OFFCAL_CH0 + x * 6)
#define MCP3911_CHANNEL(ch) (MCP3911_REG_CHANNEL0 + (ch) * 3)
#define MCP3911_OFFCAL(ch) (MCP3911_REG_OFFCAL_CH0 + (ch) * 6)
/* Internal voltage reference in mV */
#define MCP3911_INT_VREF_MV 1200
@ -61,12 +61,56 @@
#define MCP3911_REG_WRITE(reg, id) ((((reg) << 1) | ((id) << 6) | (0 << 0)) & 0xff)
#define MCP3911_REG_MASK GENMASK(4, 1)
#define MCP3911_NUM_CHANNELS 2
#define MCP3911_NUM_SCALES 6
/* Registers compatible with MCP3910 */
#define MCP3910_REG_STATUSCOM 0x0c
#define MCP3910_STATUSCOM_READ GENMASK(23, 22)
#define MCP3910_STATUSCOM_DRHIZ BIT(20)
#define MCP3910_REG_GAIN 0x0b
#define MCP3910_REG_CONFIG0 0x0d
#define MCP3910_CONFIG0_EN_OFFCAL BIT(23)
#define MCP3910_CONFIG0_OSR GENMASK(15, 13)
#define MCP3910_REG_CONFIG1 0x0e
#define MCP3910_CONFIG1_CLKEXT BIT(6)
#define MCP3910_CONFIG1_VREFEXT BIT(7)
#define MCP3910_REG_OFFCAL_CH0 0x0f
#define MCP3910_OFFCAL(ch) (MCP3910_REG_OFFCAL_CH0 + (ch) * 6)
/* Maximal number of channels used by the MCP39XX family */
#define MCP39XX_MAX_NUM_CHANNELS 8
static const int mcp3911_osr_table[] = { 32, 64, 128, 256, 512, 1024, 2048, 4096 };
static u32 mcp3911_scale_table[MCP3911_NUM_SCALES][2];
enum mcp3911_id {
MCP3910,
MCP3911,
MCP3912,
MCP3913,
MCP3914,
MCP3918,
MCP3919,
};
struct mcp3911;
struct mcp3911_chip_info {
const struct iio_chan_spec *channels;
unsigned int num_channels;
int (*config)(struct mcp3911 *adc);
int (*get_osr)(struct mcp3911 *adc, u32 *val);
int (*set_osr)(struct mcp3911 *adc, u32 val);
int (*enable_offset)(struct mcp3911 *adc, bool enable);
int (*get_offset)(struct mcp3911 *adc, int channel, int *val);
int (*set_offset)(struct mcp3911 *adc, int channel, int val);
int (*set_scale)(struct mcp3911 *adc, int channel, u32 val);
};
struct mcp3911 {
struct spi_device *spi;
struct mutex lock;
@ -74,14 +118,15 @@ struct mcp3911 {
struct clk *clki;
u32 dev_addr;
struct iio_trigger *trig;
u32 gain[MCP3911_NUM_CHANNELS];
u32 gain[MCP39XX_MAX_NUM_CHANNELS];
const struct mcp3911_chip_info *chip;
struct {
u32 channels[MCP3911_NUM_CHANNELS];
u32 channels[MCP39XX_MAX_NUM_CHANNELS];
s64 ts __aligned(8);
} scan;
u8 tx_buf __aligned(IIO_DMA_MINALIGN);
u8 rx_buf[MCP3911_NUM_CHANNELS * 3];
u8 rx_buf[MCP39XX_MAX_NUM_CHANNELS * 3];
};
static int mcp3911_read(struct mcp3911 *adc, u8 reg, u32 *val, u8 len)
@ -111,8 +156,7 @@ static int mcp3911_write(struct mcp3911 *adc, u8 reg, u32 val, u8 len)
return spi_write(adc->spi, &val, len + 1);
}
static int mcp3911_update(struct mcp3911 *adc, u8 reg, u32 mask,
u32 val, u8 len)
static int mcp3911_update(struct mcp3911 *adc, u8 reg, u32 mask, u32 val, u8 len)
{
u32 tmp;
int ret;
@ -126,9 +170,115 @@ static int mcp3911_update(struct mcp3911 *adc, u8 reg, u32 mask,
return mcp3911_write(adc, reg, val, len);
}
static int mcp3910_enable_offset(struct mcp3911 *adc, bool enable)
{
unsigned int mask = MCP3910_CONFIG0_EN_OFFCAL;
unsigned int value = enable ? mask : 0;
return mcp3911_update(adc, MCP3910_REG_CONFIG0, mask, value, 3);
}
static int mcp3910_get_offset(struct mcp3911 *adc, int channel, int *val)
{
return mcp3911_read(adc, MCP3910_OFFCAL(channel), val, 3);
}
static int mcp3910_set_offset(struct mcp3911 *adc, int channel, int val)
{
int ret;
ret = mcp3911_write(adc, MCP3910_OFFCAL(channel), val, 3);
if (ret)
return ret;
return adc->chip->enable_offset(adc, 1);
}
static int mcp3911_enable_offset(struct mcp3911 *adc, bool enable)
{
unsigned int mask = MCP3911_STATUSCOM_EN_OFFCAL;
unsigned int value = enable ? mask : 0;
return mcp3911_update(adc, MCP3911_REG_STATUSCOM, mask, value, 2);
}
static int mcp3911_get_offset(struct mcp3911 *adc, int channel, int *val)
{
return mcp3911_read(adc, MCP3911_OFFCAL(channel), val, 3);
}
static int mcp3911_set_offset(struct mcp3911 *adc, int channel, int val)
{
int ret;
ret = mcp3911_write(adc, MCP3911_OFFCAL(channel), val, 3);
if (ret)
return ret;
return adc->chip->enable_offset(adc, 1);
}
static int mcp3910_get_osr(struct mcp3911 *adc, u32 *val)
{
int ret;
unsigned int osr;
ret = mcp3911_read(adc, MCP3910_REG_CONFIG0, val, 3);
if (ret)
return ret;
osr = FIELD_GET(MCP3910_CONFIG0_OSR, *val);
*val = 32 << osr;
return 0;
}
static int mcp3910_set_osr(struct mcp3911 *adc, u32 val)
{
unsigned int osr = FIELD_PREP(MCP3910_CONFIG0_OSR, val);
unsigned int mask = MCP3910_CONFIG0_OSR;
return mcp3911_update(adc, MCP3910_REG_CONFIG0, mask, osr, 3);
}
static int mcp3911_set_osr(struct mcp3911 *adc, u32 val)
{
unsigned int osr = FIELD_PREP(MCP3911_CONFIG_OSR, val);
unsigned int mask = MCP3911_CONFIG_OSR;
return mcp3911_update(adc, MCP3911_REG_CONFIG, mask, osr, 2);
}
static int mcp3911_get_osr(struct mcp3911 *adc, u32 *val)
{
int ret;
unsigned int osr;
ret = mcp3911_read(adc, MCP3911_REG_CONFIG, val, 2);
if (ret)
return ret;
osr = FIELD_GET(MCP3911_CONFIG_OSR, *val);
*val = 32 << osr;
return ret;
}
static int mcp3910_set_scale(struct mcp3911 *adc, int channel, u32 val)
{
return mcp3911_update(adc, MCP3910_REG_GAIN,
MCP3911_GAIN_MASK(channel),
MCP3911_GAIN_VAL(channel, val), 3);
}
static int mcp3911_set_scale(struct mcp3911 *adc, int channel, u32 val)
{
return mcp3911_update(adc, MCP3911_REG_GAIN,
MCP3911_GAIN_MASK(channel),
MCP3911_GAIN_VAL(channel, val), 1);
}
static int mcp3911_write_raw_get_fmt(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
long mask)
struct iio_chan_spec const *chan,
long mask)
{
switch (mask) {
case IIO_CHAN_INFO_SCALE:
@ -141,9 +291,9 @@ static int mcp3911_write_raw_get_fmt(struct iio_dev *indio_dev,
}
static int mcp3911_read_avail(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
const int **vals, int *type, int *length,
long info)
struct iio_chan_spec const *chan,
const int **vals, int *type, int *length,
long info)
{
switch (info) {
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
@ -182,20 +332,18 @@ static int mcp3911_read_raw(struct iio_dev *indio_dev,
break;
case IIO_CHAN_INFO_OFFSET:
ret = mcp3911_read(adc,
MCP3911_OFFCAL(channel->channel), val, 3);
ret = adc->chip->get_offset(adc, channel->channel, val);
if (ret)
goto out;
ret = IIO_VAL_INT;
break;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
ret = mcp3911_read(adc, MCP3911_REG_CONFIG, val, 2);
ret = adc->chip->get_osr(adc, val);
if (ret)
goto out;
*val = FIELD_GET(MCP3911_CONFIG_OSR, *val);
*val = 32 << *val;
ret = IIO_VAL_INT;
break;
@ -212,8 +360,8 @@ out:
}
static int mcp3911_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *channel, int val,
int val2, long mask)
struct iio_chan_spec const *channel, int val,
int val2, long mask)
{
struct mcp3911 *adc = iio_priv(indio_dev);
int ret = -EINVAL;
@ -223,12 +371,10 @@ static int mcp3911_write_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SCALE:
for (int i = 0; i < MCP3911_NUM_SCALES; i++) {
if (val == mcp3911_scale_table[i][0] &&
val2 == mcp3911_scale_table[i][1]) {
val2 == mcp3911_scale_table[i][1]) {
adc->gain[channel->channel] = BIT(i);
ret = mcp3911_update(adc, MCP3911_REG_GAIN,
MCP3911_GAIN_MASK(channel->channel),
MCP3911_GAIN_VAL(channel->channel, i), 1);
ret = adc->chip->set_scale(adc, channel->channel, i);
}
}
break;
@ -238,24 +384,13 @@ static int mcp3911_write_raw(struct iio_dev *indio_dev,
goto out;
}
/* Write offset */
ret = mcp3911_write(adc, MCP3911_OFFCAL(channel->channel), val,
3);
if (ret)
goto out;
/* Enable offset*/
ret = mcp3911_update(adc, MCP3911_REG_STATUSCOM,
MCP3911_STATUSCOM_EN_OFFCAL,
MCP3911_STATUSCOM_EN_OFFCAL, 2);
ret = adc->chip->set_offset(adc, channel->channel, val);
break;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
for (int i = 0; i < ARRAY_SIZE(mcp3911_osr_table); i++) {
if (val == mcp3911_osr_table[i]) {
val = FIELD_PREP(MCP3911_CONFIG_OSR, i);
ret = mcp3911_update(adc, MCP3911_REG_CONFIG, MCP3911_CONFIG_OSR,
val, 2);
ret = adc->chip->set_osr(adc, i);
break;
}
}
@ -269,6 +404,7 @@ out:
static int mcp3911_calc_scale_table(struct mcp3911 *adc)
{
struct device *dev = &adc->spi->dev;
u32 ref = MCP3911_INT_VREF_MV;
u32 div;
int ret;
@ -277,10 +413,7 @@ static int mcp3911_calc_scale_table(struct mcp3911 *adc)
if (adc->vref) {
ret = regulator_get_voltage(adc->vref);
if (ret < 0) {
dev_err(&adc->spi->dev,
"failed to get vref voltage: %d\n",
ret);
return ret;
return dev_err_probe(dev, ret, "failed to get vref voltage\n");
}
ref = ret / 1000;
@ -326,24 +459,73 @@ static int mcp3911_calc_scale_table(struct mcp3911 *adc)
}, \
}
static const struct iio_chan_spec mcp3910_channels[] = {
MCP3911_CHAN(0),
MCP3911_CHAN(1),
IIO_CHAN_SOFT_TIMESTAMP(2),
};
static const struct iio_chan_spec mcp3911_channels[] = {
MCP3911_CHAN(0),
MCP3911_CHAN(1),
IIO_CHAN_SOFT_TIMESTAMP(2),
};
static const struct iio_chan_spec mcp3912_channels[] = {
MCP3911_CHAN(0),
MCP3911_CHAN(1),
MCP3911_CHAN(2),
MCP3911_CHAN(3),
IIO_CHAN_SOFT_TIMESTAMP(4),
};
static const struct iio_chan_spec mcp3913_channels[] = {
MCP3911_CHAN(0),
MCP3911_CHAN(1),
MCP3911_CHAN(2),
MCP3911_CHAN(3),
MCP3911_CHAN(4),
MCP3911_CHAN(5),
IIO_CHAN_SOFT_TIMESTAMP(6),
};
static const struct iio_chan_spec mcp3914_channels[] = {
MCP3911_CHAN(0),
MCP3911_CHAN(1),
MCP3911_CHAN(2),
MCP3911_CHAN(3),
MCP3911_CHAN(4),
MCP3911_CHAN(5),
MCP3911_CHAN(6),
MCP3911_CHAN(7),
IIO_CHAN_SOFT_TIMESTAMP(8),
};
static const struct iio_chan_spec mcp3918_channels[] = {
MCP3911_CHAN(0),
IIO_CHAN_SOFT_TIMESTAMP(1),
};
static const struct iio_chan_spec mcp3919_channels[] = {
MCP3911_CHAN(0),
MCP3911_CHAN(1),
MCP3911_CHAN(2),
IIO_CHAN_SOFT_TIMESTAMP(3),
};
static irqreturn_t mcp3911_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct mcp3911 *adc = iio_priv(indio_dev);
struct device *dev = &adc->spi->dev;
struct spi_transfer xfer[] = {
{
.tx_buf = &adc->tx_buf,
.len = 1,
}, {
.rx_buf = adc->rx_buf,
.len = sizeof(adc->rx_buf),
.len = (adc->chip->num_channels - 1) * 3,
},
};
int scan_index;
@ -354,8 +536,7 @@ static irqreturn_t mcp3911_trigger_handler(int irq, void *p)
adc->tx_buf = MCP3911_REG_READ(MCP3911_CHANNEL(0), adc->dev_addr);
ret = spi_sync_transfer(adc->spi, xfer, ARRAY_SIZE(xfer));
if (ret < 0) {
dev_warn(&adc->spi->dev,
"failed to get conversion data\n");
dev_warn(dev, "failed to get conversion data\n");
goto out;
}
@ -387,43 +568,25 @@ static int mcp3911_config(struct mcp3911 *adc)
u32 regval;
int ret;
ret = device_property_read_u32(dev, "microchip,device-addr", &adc->dev_addr);
/*
* Fallback to "device-addr" due to historical mismatch between
* dt-bindings and implementation
*/
if (ret)
device_property_read_u32(dev, "device-addr", &adc->dev_addr);
if (adc->dev_addr > 3) {
dev_err(&adc->spi->dev,
"invalid device address (%i). Must be in range 0-3.\n",
adc->dev_addr);
return -EINVAL;
}
dev_dbg(&adc->spi->dev, "use device address %i\n", adc->dev_addr);
ret = mcp3911_read(adc, MCP3911_REG_CONFIG, &regval, 2);
if (ret)
return ret;
regval &= ~MCP3911_CONFIG_VREFEXT;
if (adc->vref) {
dev_dbg(&adc->spi->dev, "use external voltage reference\n");
dev_dbg(dev, "use external voltage reference\n");
regval |= FIELD_PREP(MCP3911_CONFIG_VREFEXT, 1);
} else {
dev_dbg(&adc->spi->dev,
"use internal voltage reference (1.2V)\n");
dev_dbg(dev, "use internal voltage reference (1.2V)\n");
regval |= FIELD_PREP(MCP3911_CONFIG_VREFEXT, 0);
}
regval &= ~MCP3911_CONFIG_CLKEXT;
if (adc->clki) {
dev_dbg(&adc->spi->dev, "use external clock as clocksource\n");
dev_dbg(dev, "use external clock as clocksource\n");
regval |= FIELD_PREP(MCP3911_CONFIG_CLKEXT, 1);
} else {
dev_dbg(&adc->spi->dev,
"use crystal oscillator as clocksource\n");
dev_dbg(dev, "use crystal oscillator as clocksource\n");
regval |= FIELD_PREP(MCP3911_CONFIG_CLKEXT, 0);
}
@ -439,7 +602,97 @@ static int mcp3911_config(struct mcp3911 *adc)
regval &= ~MCP3911_STATUSCOM_READ;
regval |= FIELD_PREP(MCP3911_STATUSCOM_READ, 0x02);
return mcp3911_write(adc, MCP3911_REG_STATUSCOM, regval, 2);
regval &= ~MCP3911_STATUSCOM_DRHIZ;
if (device_property_read_bool(dev, "microchip,data-ready-hiz"))
regval |= FIELD_PREP(MCP3911_STATUSCOM_DRHIZ, 0);
else
regval |= FIELD_PREP(MCP3911_STATUSCOM_DRHIZ, 1);
/* Disable offset to ignore any old values in offset register */
regval &= ~MCP3911_STATUSCOM_EN_OFFCAL;
ret = mcp3911_write(adc, MCP3911_REG_STATUSCOM, regval, 2);
if (ret)
return ret;
/* Set gain to 1 for all channels */
ret = mcp3911_read(adc, MCP3911_REG_GAIN, &regval, 1);
if (ret)
return ret;
for (int i = 0; i < adc->chip->num_channels - 1; i++) {
adc->gain[i] = 1;
regval &= ~MCP3911_GAIN_MASK(i);
}
return mcp3911_write(adc, MCP3911_REG_GAIN, regval, 1);
}
static int mcp3910_config(struct mcp3911 *adc)
{
struct device *dev = &adc->spi->dev;
u32 regval;
int ret;
ret = mcp3911_read(adc, MCP3910_REG_CONFIG1, &regval, 3);
if (ret)
return ret;
regval &= ~MCP3910_CONFIG1_VREFEXT;
if (adc->vref) {
dev_dbg(dev, "use external voltage reference\n");
regval |= FIELD_PREP(MCP3910_CONFIG1_VREFEXT, 1);
} else {
dev_dbg(dev, "use internal voltage reference (1.2V)\n");
regval |= FIELD_PREP(MCP3910_CONFIG1_VREFEXT, 0);
}
regval &= ~MCP3910_CONFIG1_CLKEXT;
if (adc->clki) {
dev_dbg(dev, "use external clock as clocksource\n");
regval |= FIELD_PREP(MCP3910_CONFIG1_CLKEXT, 1);
} else {
dev_dbg(dev, "use crystal oscillator as clocksource\n");
regval |= FIELD_PREP(MCP3910_CONFIG1_CLKEXT, 0);
}
ret = mcp3911_write(adc, MCP3910_REG_CONFIG1, regval, 3);
if (ret)
return ret;
ret = mcp3911_read(adc, MCP3910_REG_STATUSCOM, &regval, 3);
if (ret)
return ret;
/* Address counter incremented, cycle through register types */
regval &= ~MCP3910_STATUSCOM_READ;
regval |= FIELD_PREP(MCP3910_STATUSCOM_READ, 0x02);
regval &= ~MCP3910_STATUSCOM_DRHIZ;
if (device_property_read_bool(dev, "microchip,data-ready-hiz"))
regval |= FIELD_PREP(MCP3910_STATUSCOM_DRHIZ, 0);
else
regval |= FIELD_PREP(MCP3910_STATUSCOM_DRHIZ, 1);
ret = mcp3911_write(adc, MCP3910_REG_STATUSCOM, regval, 3);
if (ret)
return ret;
/* Set gain to 1 for all channels */
ret = mcp3911_read(adc, MCP3910_REG_GAIN, &regval, 3);
if (ret)
return ret;
for (int i = 0; i < adc->chip->num_channels - 1; i++) {
adc->gain[i] = 1;
regval &= ~MCP3911_GAIN_MASK(i);
}
ret = mcp3911_write(adc, MCP3910_REG_GAIN, regval, 3);
if (ret)
return ret;
/* Disable offset to ignore any old values in offset register */
return adc->chip->enable_offset(adc, 0);
}
static void mcp3911_cleanup_regulator(void *vref)
@ -466,26 +719,25 @@ static const struct iio_trigger_ops mcp3911_trigger_ops = {
static int mcp3911_probe(struct spi_device *spi)
{
struct device *dev = &spi->dev;
struct iio_dev *indio_dev;
struct mcp3911 *adc;
int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc));
indio_dev = devm_iio_device_alloc(dev, sizeof(*adc));
if (!indio_dev)
return -ENOMEM;
adc = iio_priv(indio_dev);
adc->spi = spi;
adc->chip = spi_get_device_match_data(spi);
adc->vref = devm_regulator_get_optional(&adc->spi->dev, "vref");
adc->vref = devm_regulator_get_optional(dev, "vref");
if (IS_ERR(adc->vref)) {
if (PTR_ERR(adc->vref) == -ENODEV) {
adc->vref = NULL;
} else {
dev_err(&adc->spi->dev,
"failed to get regulator (%ld)\n",
PTR_ERR(adc->vref));
return PTR_ERR(adc->vref);
return dev_err_probe(dev, PTR_ERR(adc->vref), "failed to get regulator\n");
}
} else {
@ -493,34 +745,35 @@ static int mcp3911_probe(struct spi_device *spi)
if (ret)
return ret;
ret = devm_add_action_or_reset(&spi->dev,
mcp3911_cleanup_regulator, adc->vref);
ret = devm_add_action_or_reset(dev, mcp3911_cleanup_regulator, adc->vref);
if (ret)
return ret;
}
adc->clki = devm_clk_get_enabled(&adc->spi->dev, NULL);
adc->clki = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(adc->clki)) {
if (PTR_ERR(adc->clki) == -ENOENT) {
adc->clki = NULL;
} else {
dev_err(&adc->spi->dev,
"failed to get adc clk (%ld)\n",
PTR_ERR(adc->clki));
return PTR_ERR(adc->clki);
return dev_err_probe(dev, PTR_ERR(adc->clki), "failed to get adc clk\n");
}
}
ret = mcp3911_config(adc);
/*
* Fallback to "device-addr" due to historical mismatch between
* dt-bindings and implementation.
*/
ret = device_property_read_u32(dev, "microchip,device-addr", &adc->dev_addr);
if (ret)
return ret;
device_property_read_u32(dev, "device-addr", &adc->dev_addr);
if (adc->dev_addr > 3) {
return dev_err_probe(dev, -EINVAL,
"invalid device address (%i). Must be in range 0-3.\n",
adc->dev_addr);
}
dev_dbg(dev, "use device address %i\n", adc->dev_addr);
if (device_property_read_bool(&adc->spi->dev, "microchip,data-ready-hiz"))
ret = mcp3911_update(adc, MCP3911_REG_STATUSCOM, MCP3911_STATUSCOM_DRHIZ,
0, 2);
else
ret = mcp3911_update(adc, MCP3911_REG_STATUSCOM, MCP3911_STATUSCOM_DRHIZ,
MCP3911_STATUSCOM_DRHIZ, 2);
ret = adc->chip->config(adc);
if (ret)
return ret;
@ -528,12 +781,12 @@ static int mcp3911_probe(struct spi_device *spi)
if (ret)
return ret;
/* Set gain to 1 for all channels */
for (int i = 0; i < MCP3911_NUM_CHANNELS; i++) {
/* Set gain to 1 for all channels */
for (int i = 0; i < adc->chip->num_channels - 1; i++) {
adc->gain[i] = 1;
ret = mcp3911_update(adc, MCP3911_REG_GAIN,
MCP3911_GAIN_MASK(i),
MCP3911_GAIN_VAL(i, 0), 1);
MCP3911_GAIN_MASK(i),
MCP3911_GAIN_VAL(i, 0), 1);
if (ret)
return ret;
}
@ -543,21 +796,20 @@ static int mcp3911_probe(struct spi_device *spi)
indio_dev->info = &mcp3911_info;
spi_set_drvdata(spi, indio_dev);
indio_dev->channels = mcp3911_channels;
indio_dev->num_channels = ARRAY_SIZE(mcp3911_channels);
indio_dev->channels = adc->chip->channels;
indio_dev->num_channels = adc->chip->num_channels;
mutex_init(&adc->lock);
if (spi->irq > 0) {
adc->trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d",
indio_dev->name,
iio_device_id(indio_dev));
adc->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name,
iio_device_id(indio_dev));
if (!adc->trig)
return -ENOMEM;
adc->trig->ops = &mcp3911_trigger_ops;
iio_trigger_set_drvdata(adc->trig, adc);
ret = devm_iio_trigger_register(&spi->dev, adc->trig);
ret = devm_iio_trigger_register(dev, adc->trig);
if (ret)
return ret;
@ -566,30 +818,120 @@ static int mcp3911_probe(struct spi_device *spi)
* Some platforms might not allow the option to power it down so
* don't enable the interrupt to avoid extra load on the system.
*/
ret = devm_request_irq(&spi->dev, spi->irq,
&iio_trigger_generic_data_rdy_poll, IRQF_NO_AUTOEN | IRQF_ONESHOT,
indio_dev->name, adc->trig);
ret = devm_request_irq(dev, spi->irq, &iio_trigger_generic_data_rdy_poll,
IRQF_NO_AUTOEN | IRQF_ONESHOT,
indio_dev->name, adc->trig);
if (ret)
return ret;
}
ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
NULL,
mcp3911_trigger_handler, NULL);
ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
mcp3911_trigger_handler, NULL);
if (ret)
return ret;
return devm_iio_device_register(&adc->spi->dev, indio_dev);
return devm_iio_device_register(dev, indio_dev);
}
static const struct mcp3911_chip_info mcp3911_chip_info[] = {
[MCP3910] = {
.channels = mcp3910_channels,
.num_channels = ARRAY_SIZE(mcp3910_channels),
.config = mcp3910_config,
.get_osr = mcp3910_get_osr,
.set_osr = mcp3910_set_osr,
.enable_offset = mcp3910_enable_offset,
.get_offset = mcp3910_get_offset,
.set_offset = mcp3910_set_offset,
.set_scale = mcp3910_set_scale,
},
[MCP3911] = {
.channels = mcp3911_channels,
.num_channels = ARRAY_SIZE(mcp3911_channels),
.config = mcp3911_config,
.get_osr = mcp3911_get_osr,
.set_osr = mcp3911_set_osr,
.enable_offset = mcp3911_enable_offset,
.get_offset = mcp3911_get_offset,
.set_offset = mcp3911_set_offset,
.set_scale = mcp3911_set_scale,
},
[MCP3912] = {
.channels = mcp3912_channels,
.num_channels = ARRAY_SIZE(mcp3912_channels),
.config = mcp3910_config,
.get_osr = mcp3910_get_osr,
.set_osr = mcp3910_set_osr,
.enable_offset = mcp3910_enable_offset,
.get_offset = mcp3910_get_offset,
.set_offset = mcp3910_set_offset,
.set_scale = mcp3910_set_scale,
},
[MCP3913] = {
.channels = mcp3913_channels,
.num_channels = ARRAY_SIZE(mcp3913_channels),
.config = mcp3910_config,
.get_osr = mcp3910_get_osr,
.set_osr = mcp3910_set_osr,
.enable_offset = mcp3910_enable_offset,
.get_offset = mcp3910_get_offset,
.set_offset = mcp3910_set_offset,
.set_scale = mcp3910_set_scale,
},
[MCP3914] = {
.channels = mcp3914_channels,
.num_channels = ARRAY_SIZE(mcp3914_channels),
.config = mcp3910_config,
.get_osr = mcp3910_get_osr,
.set_osr = mcp3910_set_osr,
.enable_offset = mcp3910_enable_offset,
.get_offset = mcp3910_get_offset,
.set_offset = mcp3910_set_offset,
.set_scale = mcp3910_set_scale,
},
[MCP3918] = {
.channels = mcp3918_channels,
.num_channels = ARRAY_SIZE(mcp3918_channels),
.config = mcp3910_config,
.get_osr = mcp3910_get_osr,
.set_osr = mcp3910_set_osr,
.enable_offset = mcp3910_enable_offset,
.get_offset = mcp3910_get_offset,
.set_offset = mcp3910_set_offset,
.set_scale = mcp3910_set_scale,
},
[MCP3919] = {
.channels = mcp3919_channels,
.num_channels = ARRAY_SIZE(mcp3919_channels),
.config = mcp3910_config,
.get_osr = mcp3910_get_osr,
.set_osr = mcp3910_set_osr,
.enable_offset = mcp3910_enable_offset,
.get_offset = mcp3910_get_offset,
.set_offset = mcp3910_set_offset,
.set_scale = mcp3910_set_scale,
},
};
static const struct of_device_id mcp3911_dt_ids[] = {
{ .compatible = "microchip,mcp3911" },
{ .compatible = "microchip,mcp3910", .data = &mcp3911_chip_info[MCP3910] },
{ .compatible = "microchip,mcp3911", .data = &mcp3911_chip_info[MCP3911] },
{ .compatible = "microchip,mcp3912", .data = &mcp3911_chip_info[MCP3912] },
{ .compatible = "microchip,mcp3913", .data = &mcp3911_chip_info[MCP3913] },
{ .compatible = "microchip,mcp3914", .data = &mcp3911_chip_info[MCP3914] },
{ .compatible = "microchip,mcp3918", .data = &mcp3911_chip_info[MCP3918] },
{ .compatible = "microchip,mcp3919", .data = &mcp3911_chip_info[MCP3919] },
{ }
};
MODULE_DEVICE_TABLE(of, mcp3911_dt_ids);
static const struct spi_device_id mcp3911_id[] = {
{ "mcp3911", 0 },
{ "mcp3910", (kernel_ulong_t)&mcp3911_chip_info[MCP3910] },
{ "mcp3911", (kernel_ulong_t)&mcp3911_chip_info[MCP3911] },
{ "mcp3912", (kernel_ulong_t)&mcp3911_chip_info[MCP3912] },
{ "mcp3913", (kernel_ulong_t)&mcp3911_chip_info[MCP3913] },
{ "mcp3914", (kernel_ulong_t)&mcp3911_chip_info[MCP3914] },
{ "mcp3918", (kernel_ulong_t)&mcp3911_chip_info[MCP3918] },
{ "mcp3919", (kernel_ulong_t)&mcp3911_chip_info[MCP3919] },
{ }
};
MODULE_DEVICE_TABLE(spi, mcp3911_id);

View File

@ -1045,8 +1045,10 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
u32 regval;
ret = meson_sar_adc_lock(indio_dev);
if (ret)
if (ret) {
dev_err(dev, "failed to lock adc\n");
goto err_lock;
}
ret = regulator_enable(priv->vref);
if (ret < 0) {
@ -1354,15 +1356,15 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
priv->regmap = devm_regmap_init_mmio(dev, base, priv->param->regmap_config);
if (IS_ERR(priv->regmap))
return PTR_ERR(priv->regmap);
return dev_err_probe(dev, PTR_ERR(priv->regmap), "failed to init regmap\n");
irq = irq_of_parse_and_map(dev->of_node, 0);
if (!irq)
return -EINVAL;
return dev_err_probe(dev, -EINVAL, "failed to get irq\n");
ret = devm_request_irq(dev, irq, meson_sar_adc_irq, IRQF_SHARED, dev_name(dev), indio_dev);
if (ret)
return ret;
return dev_err_probe(dev, ret, "failed to request irq\n");
priv->clkin = devm_clk_get(dev, "clkin");
if (IS_ERR(priv->clkin))
@ -1384,7 +1386,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
if (!priv->adc_clk) {
ret = meson_sar_adc_clk_init(indio_dev, base);
if (ret)
return ret;
return dev_err_probe(dev, ret, "failed to init internal clk\n");
}
priv->vref = devm_regulator_get(dev, "vref");
@ -1426,8 +1428,10 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, indio_dev);
ret = iio_device_register(indio_dev);
if (ret)
if (ret) {
dev_err_probe(dev, ret, "failed to register iio device\n");
goto err_hw;
}
return 0;
@ -1437,15 +1441,13 @@ err:
return ret;
}
static int meson_sar_adc_remove(struct platform_device *pdev)
static void meson_sar_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
iio_device_unregister(indio_dev);
meson_sar_adc_hw_disable(indio_dev);
return 0;
}
static int meson_sar_adc_suspend(struct device *dev)
@ -1480,7 +1482,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(meson_sar_adc_pm_ops,
static struct platform_driver meson_sar_adc_driver = {
.probe = meson_sar_adc_probe,
.remove = meson_sar_adc_remove,
.remove_new = meson_sar_adc_remove,
.driver = {
.name = "meson-saradc",
.of_match_table = meson_sar_adc_of_match,

View File

@ -171,7 +171,7 @@ fail_disable:
return ret;
}
static int mp2629_adc_remove(struct platform_device *pdev)
static void mp2629_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct mp2629_adc *info = iio_priv(indio_dev);
@ -184,8 +184,6 @@ static int mp2629_adc_remove(struct platform_device *pdev)
MP2629_ADC_CONTINUOUS, 0);
regmap_update_bits(info->regmap, MP2629_REG_ADC_CTRL,
MP2629_ADC_START, 0);
return 0;
}
static const struct of_device_id mp2629_adc_of_match[] = {
@ -200,7 +198,7 @@ static struct platform_driver mp2629_adc_driver = {
.of_match_table = mp2629_adc_of_match,
},
.probe = mp2629_adc_probe,
.remove = mp2629_adc_remove,
.remove_new = mp2629_adc_remove,
};
module_platform_driver(mp2629_adc_driver);

View File

@ -246,6 +246,14 @@ static int mt6577_auxadc_suspend(struct device *dev)
return 0;
}
static void mt6577_power_off(void *data)
{
struct mt6577_auxadc_device *adc_dev = data;
mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
0, MT6577_AUXADC_PDN_EN);
}
static int mt6577_auxadc_probe(struct platform_device *pdev)
{
struct mt6577_auxadc_device *adc_dev;
@ -265,29 +273,18 @@ static int mt6577_auxadc_probe(struct platform_device *pdev)
indio_dev->num_channels = ARRAY_SIZE(mt6577_auxadc_iio_channels);
adc_dev->reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(adc_dev->reg_base)) {
dev_err(&pdev->dev, "failed to get auxadc base address\n");
return PTR_ERR(adc_dev->reg_base);
}
if (IS_ERR(adc_dev->reg_base))
return dev_err_probe(&pdev->dev, PTR_ERR(adc_dev->reg_base),
"failed to get auxadc base address\n");
adc_dev->adc_clk = devm_clk_get(&pdev->dev, "main");
if (IS_ERR(adc_dev->adc_clk)) {
dev_err(&pdev->dev, "failed to get auxadc clock\n");
return PTR_ERR(adc_dev->adc_clk);
}
ret = clk_prepare_enable(adc_dev->adc_clk);
if (ret) {
dev_err(&pdev->dev, "failed to enable auxadc clock\n");
return ret;
}
adc_dev->adc_clk = devm_clk_get_enabled(&pdev->dev, "main");
if (IS_ERR(adc_dev->adc_clk))
return dev_err_probe(&pdev->dev, PTR_ERR(adc_dev->adc_clk),
"failed to enable auxadc clock\n");
adc_clk_rate = clk_get_rate(adc_dev->adc_clk);
if (!adc_clk_rate) {
ret = -EINVAL;
dev_err(&pdev->dev, "null clock rate\n");
goto err_disable_clk;
}
if (!adc_clk_rate)
return dev_err_probe(&pdev->dev, -EINVAL, "null clock rate\n");
adc_dev->dev_comp = device_get_match_data(&pdev->dev);
@ -296,36 +293,16 @@ static int mt6577_auxadc_probe(struct platform_device *pdev)
mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
MT6577_AUXADC_PDN_EN, 0);
mdelay(MT6577_AUXADC_POWER_READY_MS);
platform_set_drvdata(pdev, indio_dev);
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&pdev->dev, "failed to register iio device\n");
goto err_power_off;
}
ret = devm_add_action_or_reset(&pdev->dev, mt6577_power_off, adc_dev);
if (ret)
return dev_err_probe(&pdev->dev, ret,
"Failed to add action to managed power off\n");
return 0;
err_power_off:
mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
0, MT6577_AUXADC_PDN_EN);
err_disable_clk:
clk_disable_unprepare(adc_dev->adc_clk);
return ret;
}
static int mt6577_auxadc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct mt6577_auxadc_device *adc_dev = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
0, MT6577_AUXADC_PDN_EN);
clk_disable_unprepare(adc_dev->adc_clk);
ret = devm_iio_device_register(&pdev->dev, indio_dev);
if (ret < 0)
return dev_err_probe(&pdev->dev, ret, "failed to register iio device\n");
return 0;
}
@ -352,7 +329,6 @@ static struct platform_driver mt6577_auxadc_driver = {
.pm = pm_sleep_ptr(&mt6577_auxadc_pm_ops),
},
.probe = mt6577_auxadc_probe,
.remove = mt6577_auxadc_remove,
};
module_platform_driver(mt6577_auxadc_driver);

View File

@ -807,7 +807,7 @@ err_trig:
return ret;
}
static int mxs_lradc_adc_remove(struct platform_device *pdev)
static void mxs_lradc_adc_remove(struct platform_device *pdev)
{
struct iio_dev *iio = platform_get_drvdata(pdev);
struct mxs_lradc_adc *adc = iio_priv(iio);
@ -816,8 +816,6 @@ static int mxs_lradc_adc_remove(struct platform_device *pdev)
mxs_lradc_adc_hw_stop(adc);
iio_triggered_buffer_cleanup(iio);
mxs_lradc_adc_trigger_remove(iio);
return 0;
}
static struct platform_driver mxs_lradc_adc_driver = {
@ -825,7 +823,7 @@ static struct platform_driver mxs_lradc_adc_driver = {
.name = "mxs-lradc-adc",
},
.probe = mxs_lradc_adc_probe,
.remove = mxs_lradc_adc_remove,
.remove_new = mxs_lradc_adc_remove,
};
module_platform_driver(mxs_lradc_adc_driver);

View File

@ -320,7 +320,7 @@ err_disable_clk:
return ret;
}
static int npcm_adc_remove(struct platform_device *pdev)
static void npcm_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct npcm_adc *info = iio_priv(indio_dev);
@ -333,13 +333,11 @@ static int npcm_adc_remove(struct platform_device *pdev)
if (!IS_ERR(info->vref))
regulator_disable(info->vref);
clk_disable_unprepare(info->adc_clk);
return 0;
}
static struct platform_driver npcm_adc_driver = {
.probe = npcm_adc_probe,
.remove = npcm_adc_remove,
.remove_new = npcm_adc_remove,
.driver = {
.name = "npcm_adc",
.of_match_table = npcm_adc_match,

View File

@ -457,7 +457,7 @@ static int palmas_gpadc_get_calibrated_code(struct palmas_gpadc *adc,
*
* The gain error include both gain error, as specified in the datasheet, and
* the gain error drift. These paramenters vary depending on device and whether
* the the channel is calibrated (trimmed) or not.
* the channel is calibrated (trimmed) or not.
*/
static int palmas_gpadc_threshold_with_tolerance(int val, const int INL,
const int gain_error,

View File

@ -957,7 +957,7 @@ out_disable_vref:
return ret;
}
static int pm8xxx_xoadc_remove(struct platform_device *pdev)
static void pm8xxx_xoadc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct pm8xxx_xoadc *adc = iio_priv(indio_dev);
@ -965,8 +965,6 @@ static int pm8xxx_xoadc_remove(struct platform_device *pdev)
iio_device_unregister(indio_dev);
regulator_disable(adc->vref);
return 0;
}
static const struct xoadc_variant pm8018_variant = {
@ -1019,7 +1017,7 @@ static struct platform_driver pm8xxx_xoadc_driver = {
.of_match_table = pm8xxx_xoadc_id_table,
},
.probe = pm8xxx_xoadc_probe,
.remove = pm8xxx_xoadc_remove,
.remove_new = pm8xxx_xoadc_remove,
};
module_platform_driver(pm8xxx_xoadc_driver);

View File

@ -559,7 +559,7 @@ err_clk_if_enable:
return ret;
}
static int rcar_gyroadc_remove(struct platform_device *pdev)
static void rcar_gyroadc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct rcar_gyroadc *priv = iio_priv(indio_dev);
@ -573,8 +573,6 @@ static int rcar_gyroadc_remove(struct platform_device *pdev)
pm_runtime_set_suspended(dev);
clk_disable_unprepare(priv->clk);
rcar_gyroadc_deinit_supplies(indio_dev);
return 0;
}
static int rcar_gyroadc_suspend(struct device *dev)
@ -603,7 +601,7 @@ static const struct dev_pm_ops rcar_gyroadc_pm_ops = {
static struct platform_driver rcar_gyroadc_driver = {
.probe = rcar_gyroadc_probe,
.remove = rcar_gyroadc_remove,
.remove_new = rcar_gyroadc_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = rcar_gyroadc_match,

View File

@ -274,10 +274,9 @@ static int spear_adc_probe(struct platform_device *pdev)
int irq;
indio_dev = devm_iio_device_alloc(dev, sizeof(struct spear_adc_state));
if (!indio_dev) {
dev_err(dev, "failed allocating iio device\n");
return -ENOMEM;
}
if (!indio_dev)
return dev_err_probe(dev, -ENOMEM,
"failed allocating iio device\n");
st = iio_priv(indio_dev);
@ -297,37 +296,24 @@ static int spear_adc_probe(struct platform_device *pdev)
st->adc_base_spear3xx =
(struct adc_regs_spear3xx __iomem *)st->adc_base_spear6xx;
st->clk = devm_clk_get(dev, NULL);
if (IS_ERR(st->clk)) {
dev_err(dev, "failed getting clock\n");
return PTR_ERR(st->clk);
}
ret = clk_prepare_enable(st->clk);
if (ret) {
dev_err(dev, "failed enabling clock\n");
return ret;
}
st->clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(st->clk))
return dev_err_probe(dev, PTR_ERR(st->clk),
"failed enabling clock\n");
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
ret = irq;
goto errout2;
}
if (irq < 0)
return irq;
ret = devm_request_irq(dev, irq, spear_adc_isr, 0, SPEAR_ADC_MOD_NAME,
st);
if (ret < 0) {
dev_err(dev, "failed requesting interrupt\n");
goto errout2;
}
if (ret < 0)
return dev_err_probe(dev, ret, "failed requesting interrupt\n");
if (of_property_read_u32(np, "sampling-frequency",
&st->sampling_freq)) {
dev_err(dev, "sampling-frequency missing in DT\n");
ret = -EINVAL;
goto errout2;
}
&st->sampling_freq))
return dev_err_probe(dev, -EINVAL,
"sampling-frequency missing in DT\n");
/*
* Optional avg_samples defaults to 0, resulting in single data
@ -343,8 +329,6 @@ static int spear_adc_probe(struct platform_device *pdev)
spear_adc_configure(st);
platform_set_drvdata(pdev, indio_dev);
init_completion(&st->completion);
indio_dev->name = SPEAR_ADC_MOD_NAME;
@ -353,27 +337,12 @@ static int spear_adc_probe(struct platform_device *pdev)
indio_dev->channels = spear_adc_iio_channels;
indio_dev->num_channels = ARRAY_SIZE(spear_adc_iio_channels);
ret = iio_device_register(indio_dev);
ret = devm_iio_device_register(dev, indio_dev);
if (ret)
goto errout2;
return ret;
dev_info(dev, "SPEAR ADC driver loaded, IRQ %d\n", irq);
return 0;
errout2:
clk_disable_unprepare(st->clk);
return ret;
}
static int spear_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct spear_adc_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
clk_disable_unprepare(st->clk);
return 0;
}
@ -387,7 +356,6 @@ MODULE_DEVICE_TABLE(of, spear_adc_dt_ids);
static struct platform_driver spear_adc_driver = {
.probe = spear_adc_probe,
.remove = spear_adc_remove,
.driver = {
.name = SPEAR_ADC_MOD_NAME,
.of_match_table = of_match_ptr(spear_adc_dt_ids),

View File

@ -17,10 +17,11 @@
#include <linux/irqdomain.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
@ -720,8 +721,7 @@ static int stm32_adc_probe(struct platform_device *pdev)
return -ENOMEM;
platform_set_drvdata(pdev, &priv->common);
priv->cfg = (const struct stm32_adc_priv_cfg *)
of_match_device(dev->driver->of_match_table, dev)->data;
priv->cfg = device_get_match_data(dev);
priv->nb_adc_max = priv->cfg->num_adcs;
spin_lock_init(&priv->common.lock);
@ -814,7 +814,7 @@ err_pm_stop:
return ret;
}
static int stm32_adc_remove(struct platform_device *pdev)
static void stm32_adc_remove(struct platform_device *pdev)
{
struct stm32_adc_common *common = platform_get_drvdata(pdev);
struct stm32_adc_priv *priv = to_stm32_adc_priv(common);
@ -826,8 +826,6 @@ static int stm32_adc_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
return 0;
}
static int stm32_adc_core_runtime_suspend(struct device *dev)
@ -908,7 +906,7 @@ MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
static struct platform_driver stm32_adc_driver = {
.probe = stm32_adc_probe,
.remove = stm32_adc_remove,
.remove_new = stm32_adc_remove,
.driver = {
.name = "stm32-adc-core",
.of_match_table = stm32_adc_of_match,

View File

@ -2209,7 +2209,7 @@ static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev,
ret = -EINVAL;
goto err;
}
strncpy(adc->chan_name[val], name, STM32_ADC_CH_SZ);
strscpy(adc->chan_name[val], name, STM32_ADC_CH_SZ);
ret = stm32_adc_populate_int_ch(indio_dev, name, val);
if (ret == -ENOENT)
continue;
@ -2513,7 +2513,7 @@ err_dma_disable:
return ret;
}
static int stm32_adc_remove(struct platform_device *pdev)
static void stm32_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct stm32_adc *adc = iio_priv(indio_dev);
@ -2532,8 +2532,6 @@ static int stm32_adc_remove(struct platform_device *pdev)
adc->rx_buf, adc->rx_dma_buf);
dma_release_channel(adc->dma_chan);
}
return 0;
}
static int stm32_adc_suspend(struct device *dev)
@ -2659,7 +2657,7 @@ MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
static struct platform_driver stm32_adc_driver = {
.probe = stm32_adc_probe,
.remove = stm32_adc_remove,
.remove_new = stm32_adc_remove,
.driver = {
.name = "stm32-adc",
.of_match_table = stm32_adc_of_match,

View File

@ -1620,7 +1620,7 @@ err_cleanup:
return ret;
}
static int stm32_dfsdm_adc_remove(struct platform_device *pdev)
static void stm32_dfsdm_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
@ -1629,8 +1629,6 @@ static int stm32_dfsdm_adc_remove(struct platform_device *pdev)
of_platform_depopulate(&pdev->dev);
iio_device_unregister(indio_dev);
stm32_dfsdm_dma_release(indio_dev);
return 0;
}
static int stm32_dfsdm_adc_suspend(struct device *dev)
@ -1677,7 +1675,7 @@ static struct platform_driver stm32_dfsdm_adc_driver = {
.pm = pm_sleep_ptr(&stm32_dfsdm_adc_pm_ops),
},
.probe = stm32_dfsdm_adc_probe,
.remove = stm32_dfsdm_adc_remove,
.remove_new = stm32_dfsdm_adc_remove,
};
module_platform_driver(stm32_dfsdm_adc_driver);

View File

@ -436,7 +436,7 @@ pm_put:
return ret;
}
static int stm32_dfsdm_core_remove(struct platform_device *pdev)
static void stm32_dfsdm_core_remove(struct platform_device *pdev)
{
struct stm32_dfsdm *dfsdm = platform_get_drvdata(pdev);
@ -446,8 +446,6 @@ static int stm32_dfsdm_core_remove(struct platform_device *pdev)
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
stm32_dfsdm_clk_disable_unprepare(dfsdm);
return 0;
}
static int stm32_dfsdm_core_suspend(struct device *dev)
@ -508,7 +506,7 @@ static const struct dev_pm_ops stm32_dfsdm_core_pm_ops = {
static struct platform_driver stm32_dfsdm_driver = {
.probe = stm32_dfsdm_probe,
.remove = stm32_dfsdm_core_remove,
.remove_new = stm32_dfsdm_core_remove,
.driver = {
.name = "stm32-dfsdm",
.of_match_table = stm32_dfsdm_of_match,

View File

@ -669,7 +669,7 @@ err_map:
return ret;
}
static int sun4i_gpadc_remove(struct platform_device *pdev)
static void sun4i_gpadc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
@ -678,12 +678,10 @@ static int sun4i_gpadc_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
if (!IS_ENABLED(CONFIG_THERMAL_OF))
return 0;
return;
if (!info->no_irq)
iio_map_array_unregister(indio_dev);
return 0;
}
static const struct platform_device_id sun4i_gpadc_id[] = {
@ -702,7 +700,7 @@ static struct platform_driver sun4i_gpadc_driver = {
},
.id_table = sun4i_gpadc_id,
.probe = sun4i_gpadc_probe,
.remove = sun4i_gpadc_remove,
.remove_new = sun4i_gpadc_remove,
};
MODULE_DEVICE_TABLE(of, sun4i_gpadc_of_id);

View File

@ -154,7 +154,6 @@ static void adc081c_reg_disable(void *reg)
static int adc081c_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct iio_dev *iio;
struct adc081c *adc;
const struct adcxx1c_model *model;
@ -163,10 +162,7 @@ static int adc081c_probe(struct i2c_client *client)
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
return -EOPNOTSUPP;
if (dev_fwnode(&client->dev))
model = device_get_match_data(&client->dev);
else
model = &adcxx1c_models[id->driver_data];
model = i2c_get_match_data(client);
iio = devm_iio_device_alloc(&client->dev, sizeof(*adc));
if (!iio)
@ -207,9 +203,9 @@ static int adc081c_probe(struct i2c_client *client)
}
static const struct i2c_device_id adc081c_id[] = {
{ "adc081c", ADC081C },
{ "adc101c", ADC101C },
{ "adc121c", ADC121C },
{ "adc081c", (kernel_ulong_t)&adcxx1c_models[ADC081C] },
{ "adc101c", (kernel_ulong_t)&adcxx1c_models[ADC101C] },
{ "adc121c", (kernel_ulong_t)&adcxx1c_models[ADC121C] },
{ }
};
MODULE_DEVICE_TABLE(i2c, adc081c_id);

View File

@ -976,16 +976,13 @@ static int ads1015_set_conv_mode(struct ads1015_data *data, int mode)
static int ads1015_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
const struct ads1015_chip_data *chip;
struct iio_dev *indio_dev;
struct ads1015_data *data;
int ret;
int i;
chip = device_get_match_data(&client->dev);
if (!chip)
chip = (const struct ads1015_chip_data *)id->driver_data;
chip = i2c_get_match_data(client);
if (!chip)
return dev_err_probe(&client->dev, -EINVAL, "Unknown chip\n");
@ -1047,11 +1044,13 @@ static int ads1015_probe(struct i2c_client *client)
1 << ADS1015_CFG_COMP_LAT_SHIFT;
switch (irq_trig) {
case IRQF_TRIGGER_FALLING:
case IRQF_TRIGGER_LOW:
cfg_comp |= ADS1015_CFG_COMP_POL_LOW <<
ADS1015_CFG_COMP_POL_SHIFT;
break;
case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING:
cfg_comp |= ADS1015_CFG_COMP_POL_HIGH <<
ADS1015_CFG_COMP_POL_SHIFT;
break;

View File

@ -681,7 +681,7 @@ err_dma:
return err;
}
static int tiadc_remove(struct platform_device *pdev)
static void tiadc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct tiadc_device *adc_dev = iio_priv(indio_dev);
@ -697,8 +697,6 @@ static int tiadc_remove(struct platform_device *pdev)
step_en = get_adc_step_mask(adc_dev);
am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
return 0;
}
static int tiadc_suspend(struct device *dev)
@ -747,7 +745,7 @@ static struct platform_driver tiadc_driver = {
.of_match_table = ti_adc_dt_ids,
},
.probe = tiadc_probe,
.remove = tiadc_remove,
.remove_new = tiadc_remove,
};
module_platform_driver(tiadc_driver);

View File

@ -892,7 +892,7 @@ err_current_generator:
return ret;
}
static int twl4030_madc_remove(struct platform_device *pdev)
static void twl4030_madc_remove(struct platform_device *pdev)
{
struct iio_dev *iio_dev = platform_get_drvdata(pdev);
struct twl4030_madc_data *madc = iio_priv(iio_dev);
@ -903,8 +903,6 @@ static int twl4030_madc_remove(struct platform_device *pdev)
twl4030_madc_set_power(madc, 0);
regulator_disable(madc->usb3v1);
return 0;
}
#ifdef CONFIG_OF
@ -917,7 +915,7 @@ MODULE_DEVICE_TABLE(of, twl_madc_of_match);
static struct platform_driver twl4030_madc_driver = {
.probe = twl4030_madc_probe,
.remove = twl4030_madc_remove,
.remove_new = twl4030_madc_remove,
.driver = {
.name = "twl4030_madc",
.of_match_table = of_match_ptr(twl_madc_of_match),

View File

@ -16,9 +16,10 @@
*/
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/property.h>
#include <linux/mfd/twl.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@ -879,17 +880,14 @@ static int twl6030_gpadc_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct twl6030_gpadc_data *gpadc;
const struct twl6030_gpadc_platform_data *pdata;
const struct of_device_id *match;
struct iio_dev *indio_dev;
int irq;
int ret;
match = of_match_device(of_twl6030_match_tbl, dev);
if (!match)
pdata = device_get_match_data(&pdev->dev);
if (!pdata)
return -EINVAL;
pdata = match->data;
indio_dev = devm_iio_device_alloc(dev, sizeof(*gpadc));
if (!indio_dev)
return -ENOMEM;
@ -968,14 +966,12 @@ static int twl6030_gpadc_probe(struct platform_device *pdev)
return iio_device_register(indio_dev);
}
static int twl6030_gpadc_remove(struct platform_device *pdev)
static void twl6030_gpadc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
twl6030_gpadc_disable_irq(TWL6030_GPADC_RT_SW1_EOC_MASK);
iio_device_unregister(indio_dev);
return 0;
}
static int twl6030_gpadc_suspend(struct device *pdev)
@ -1007,7 +1003,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(twl6030_gpadc_pm_ops, twl6030_gpadc_suspend,
static struct platform_driver twl6030_gpadc_driver = {
.probe = twl6030_gpadc_probe,
.remove = twl6030_gpadc_remove,
.remove_new = twl6030_gpadc_remove,
.driver = {
.name = DRIVER_NAME,
.pm = pm_sleep_ptr(&twl6030_gpadc_pm_ops),

View File

@ -916,7 +916,7 @@ error_adc_clk_enable:
return ret;
}
static int vf610_adc_remove(struct platform_device *pdev)
static void vf610_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct vf610_adc *info = iio_priv(indio_dev);
@ -925,8 +925,6 @@ static int vf610_adc_remove(struct platform_device *pdev)
iio_triggered_buffer_cleanup(indio_dev);
regulator_disable(info->vref);
clk_disable_unprepare(info->clk);
return 0;
}
static int vf610_adc_suspend(struct device *dev)
@ -974,7 +972,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(vf610_adc_pm_ops, vf610_adc_suspend,
static struct platform_driver vf610_adc_driver = {
.probe = vf610_adc_probe,
.remove = vf610_adc_remove,
.remove_new = vf610_adc_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = vf610_adc_match,

View File

@ -40,6 +40,7 @@ config STX104
select REGMAP_MMIO
select GPIOLIB
select GPIO_REGMAP
select I8254
help
Say yes here to build support for the Apex Embedded Systems STX104
integrated analog PC/104 card.

View File

@ -441,12 +441,30 @@ static int ad74413r_set_channel_function(struct ad74413r_state *st,
{
int ret;
ret = regmap_update_bits(st->regmap,
AD74413R_REG_CH_FUNC_SETUP_X(channel),
AD74413R_CH_FUNC_SETUP_MASK,
CH_FUNC_HIGH_IMPEDANCE);
if (ret)
return ret;
/* Set DAC code to 0 prior to changing channel function */
ret = ad74413r_set_channel_dac_code(st, channel, 0);
if (ret)
return ret;
/* Delay required before transition to new desired mode */
usleep_range(130, 150);
ret = regmap_update_bits(st->regmap,
AD74413R_REG_CH_FUNC_SETUP_X(channel),
AD74413R_CH_FUNC_SETUP_MASK, func);
if (ret)
return ret;
/* Delay required before updating the new DAC code */
usleep_range(150, 170);
if (func == CH_FUNC_CURRENT_INPUT_LOOP_POWER)
ret = regmap_set_bits(st->regmap,
AD74413R_REG_ADC_CONFIG_X(channel),
@ -705,8 +723,8 @@ static int ad74413r_get_input_current_scale(struct ad74413r_state *st,
return IIO_VAL_FRACTIONAL;
}
static int ad74413_get_input_current_offset(struct ad74413r_state *st,
unsigned int channel, int *val)
static int ad74413r_get_input_current_offset(struct ad74413r_state *st,
unsigned int channel, int *val)
{
unsigned int range;
int voltage_range;
@ -991,7 +1009,7 @@ static int ad74413r_read_raw(struct iio_dev *indio_dev,
return ad74413r_get_input_voltage_offset(st,
chan->channel, val);
case IIO_CURRENT:
return ad74413_get_input_current_offset(st,
return ad74413r_get_input_current_offset(st,
chan->channel, val);
default:
return -EINVAL;

View File

@ -8,6 +8,7 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/gpio/regmap.h>
#include <linux/i8254.h>
#include <linux/iio/iio.h>
#include <linux/iio/types.h>
#include <linux/isa.h>
@ -55,6 +56,7 @@ MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses");
#define STX104_ADC_STATUS (STX104_AIO_BASE + 0x8)
#define STX104_ADC_CONTROL (STX104_AIO_BASE + 0x9)
#define STX104_ADC_CONFIGURATION (STX104_AIO_BASE + 0x11)
#define STX104_I8254_BASE (STX104_AIO_BASE + 0x12)
#define STX104_AIO_DATA_STRIDE 2
#define STX104_DAC_OFFSET(_channel) (STX104_DAC_BASE + STX104_AIO_DATA_STRIDE * (_channel))
@ -77,6 +79,7 @@ MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses");
/* ADC Configuration */
#define STX104_GAIN GENMASK(1, 0)
#define STX104_ADBU BIT(2)
#define STX104_RBK GENMASK(7, 4)
#define STX104_BIPOLAR 0
#define STX104_GAIN_X1 0
#define STX104_GAIN_X2 1
@ -168,6 +171,32 @@ static const struct regmap_config dio_regmap_config = {
.io_port = true,
};
static const struct regmap_range pit_wr_ranges[] = {
regmap_reg_range(0x0, 0x3),
};
static const struct regmap_range pit_rd_ranges[] = {
regmap_reg_range(0x0, 0x2),
};
static const struct regmap_access_table pit_wr_table = {
.yes_ranges = pit_wr_ranges,
.n_yes_ranges = ARRAY_SIZE(pit_wr_ranges),
};
static const struct regmap_access_table pit_rd_table = {
.yes_ranges = pit_rd_ranges,
.n_yes_ranges = ARRAY_SIZE(pit_rd_ranges),
};
static const struct regmap_config pit_regmap_config = {
.name = "i8254",
.reg_bits = 8,
.reg_stride = 1,
.reg_base = STX104_I8254_BASE,
.val_bits = 8,
.io_port = true,
.wr_table = &pit_wr_table,
.rd_table = &pit_rd_table,
};
static int stx104_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val, int *val2, long mask)
{
@ -339,6 +368,21 @@ static const char *stx104_names[STX104_NGPIO] = {
"DIN0", "DIN1", "DIN2", "DIN3", "DOUT0", "DOUT1", "DOUT2", "DOUT3"
};
static int bank_select_i8254(struct regmap *map)
{
const u8 select_i8254[] = { 0x3, 0xB, 0xA };
size_t i;
int err;
for (i = 0; i < ARRAY_SIZE(select_i8254); i++) {
err = regmap_write_bits(map, STX104_ADC_CONFIGURATION, STX104_RBK, select_i8254[i]);
if (err)
return err;
}
return 0;
}
static int stx104_init_hw(struct stx104_iio *const priv)
{
int err;
@ -361,7 +405,7 @@ static int stx104_init_hw(struct stx104_iio *const priv)
if (err)
return err;
return 0;
return bank_select_i8254(priv->aio_ctl_map);
}
static int stx104_probe(struct device *dev, unsigned int id)
@ -369,6 +413,7 @@ static int stx104_probe(struct device *dev, unsigned int id)
struct iio_dev *indio_dev;
struct stx104_iio *priv;
struct gpio_regmap_config gpio_config;
struct i8254_regmap_config pit_config;
void __iomem *stx104_base;
struct regmap *aio_ctl_map;
struct regmap *aio_data_map;
@ -406,6 +451,11 @@ static int stx104_probe(struct device *dev, unsigned int id)
return dev_err_probe(dev, PTR_ERR(dio_map),
"Unable to initialize dio register map\n");
pit_config.map = devm_regmap_init_mmio(dev, stx104_base, &pit_regmap_config);
if (IS_ERR(pit_config.map))
return dev_err_probe(dev, PTR_ERR(pit_config.map),
"Unable to initialize i8254 register map\n");
priv = iio_priv(indio_dev);
priv->aio_ctl_map = aio_ctl_map;
priv->aio_data_map = aio_data_map;
@ -449,7 +499,13 @@ static int stx104_probe(struct device *dev, unsigned int id)
.drvdata = dio_map,
};
return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_config));
err = PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_config));
if (err)
return err;
pit_config.parent = dev;
return devm_i8254_regmap_register(dev, &pit_config);
}
static struct isa_driver stx104_driver = {
@ -464,3 +520,4 @@ module_isa_driver(stx104_driver, num_stx104);
MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
MODULE_DESCRIPTION("Apex Embedded Systems STX104 IIO driver");
MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(I8254);

View File

@ -21,6 +21,7 @@
enum hmc425a_type {
ID_HMC425A,
ID_HMC540S,
};
struct hmc425a_chip_info {
@ -70,6 +71,9 @@ static int hmc425a_read_raw(struct iio_dev *indio_dev,
case ID_HMC425A:
gain = ~code * -500;
break;
case ID_HMC540S:
gain = ~code * -1000;
break;
}
*val = gain / 1000;
@ -106,6 +110,9 @@ static int hmc425a_write_raw(struct iio_dev *indio_dev,
case ID_HMC425A:
code = ~((abs(gain) / 500) & 0x3F);
break;
case ID_HMC540S:
code = ~((abs(gain) / 1000) & 0xF);
break;
}
mutex_lock(&st->lock);
@ -157,6 +164,7 @@ static const struct iio_chan_spec hmc425a_channels[] = {
/* Match table for of_platform binding */
static const struct of_device_id hmc425a_of_match[] = {
{ .compatible = "adi,hmc425a", .data = (void *)ID_HMC425A },
{ .compatible = "adi,hmc540s", .data = (void *)ID_HMC540S },
{},
};
MODULE_DEVICE_TABLE(of, hmc425a_of_match);
@ -171,6 +179,15 @@ static struct hmc425a_chip_info hmc425a_chip_info_tbl[] = {
.gain_max = 0,
.default_gain = -0x40, /* set default gain -31.5db*/
},
[ID_HMC540S] = {
.name = "hmc540s",
.channels = hmc425a_channels,
.num_channels = ARRAY_SIZE(hmc425a_channels),
.num_gpios = 4,
.gain_min = -15000,
.gain_max = 0,
.default_gain = -0x10, /* set default gain -15.0db*/
},
};
static int hmc425a_probe(struct platform_device *pdev)

View File

@ -203,7 +203,6 @@ MODULE_DEVICE_TABLE(of, atlas_ezo_dt_ids);
static int atlas_ezo_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
const struct atlas_ezo_device *chip;
struct atlas_ezo_data *data;
struct iio_dev *indio_dev;
@ -212,10 +211,7 @@ static int atlas_ezo_probe(struct i2c_client *client)
if (!indio_dev)
return -ENOMEM;
if (dev_fwnode(&client->dev))
chip = device_get_match_data(&client->dev);
else
chip = (const struct atlas_ezo_device *)id->driver_data;
chip = i2c_get_match_data(client);
if (!chip)
return -EINVAL;

View File

@ -87,7 +87,7 @@ enum {
struct atlas_data {
struct i2c_client *client;
struct iio_trigger *trig;
struct atlas_device *chip;
const struct atlas_device *chip;
struct regmap *regmap;
struct irq_work work;
unsigned int interrupt_enabled;
@ -353,7 +353,7 @@ struct atlas_device {
int delay;
};
static struct atlas_device atlas_devices[] = {
static const struct atlas_device atlas_devices[] = {
[ATLAS_PH_SM] = {
.channels = atlas_ph_channels,
.num_channels = 3,
@ -589,30 +589,29 @@ static const struct iio_info atlas_info = {
};
static const struct i2c_device_id atlas_id[] = {
{ "atlas-ph-sm", ATLAS_PH_SM },
{ "atlas-ec-sm", ATLAS_EC_SM },
{ "atlas-orp-sm", ATLAS_ORP_SM },
{ "atlas-do-sm", ATLAS_DO_SM },
{ "atlas-rtd-sm", ATLAS_RTD_SM },
{ "atlas-ph-sm", (kernel_ulong_t)&atlas_devices[ATLAS_PH_SM] },
{ "atlas-ec-sm", (kernel_ulong_t)&atlas_devices[ATLAS_EC_SM] },
{ "atlas-orp-sm", (kernel_ulong_t)&atlas_devices[ATLAS_ORP_SM] },
{ "atlas-do-sm", (kernel_ulong_t)&atlas_devices[ATLAS_DO_SM] },
{ "atlas-rtd-sm", (kernel_ulong_t)&atlas_devices[ATLAS_RTD_SM] },
{}
};
MODULE_DEVICE_TABLE(i2c, atlas_id);
static const struct of_device_id atlas_dt_ids[] = {
{ .compatible = "atlas,ph-sm", .data = (void *)ATLAS_PH_SM, },
{ .compatible = "atlas,ec-sm", .data = (void *)ATLAS_EC_SM, },
{ .compatible = "atlas,orp-sm", .data = (void *)ATLAS_ORP_SM, },
{ .compatible = "atlas,do-sm", .data = (void *)ATLAS_DO_SM, },
{ .compatible = "atlas,rtd-sm", .data = (void *)ATLAS_RTD_SM, },
{ .compatible = "atlas,ph-sm", .data = &atlas_devices[ATLAS_PH_SM] },
{ .compatible = "atlas,ec-sm", .data = &atlas_devices[ATLAS_EC_SM] },
{ .compatible = "atlas,orp-sm", .data = &atlas_devices[ATLAS_ORP_SM] },
{ .compatible = "atlas,do-sm", .data = &atlas_devices[ATLAS_DO_SM] },
{ .compatible = "atlas,rtd-sm", .data = &atlas_devices[ATLAS_RTD_SM] },
{ }
};
MODULE_DEVICE_TABLE(of, atlas_dt_ids);
static int atlas_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct atlas_data *data;
struct atlas_device *chip;
const struct atlas_device *chip;
struct iio_trigger *trig;
struct iio_dev *indio_dev;
int ret;
@ -621,10 +620,7 @@ static int atlas_probe(struct i2c_client *client)
if (!indio_dev)
return -ENOMEM;
if (!dev_fwnode(&client->dev))
chip = &atlas_devices[id->driver_data];
else
chip = &atlas_devices[(unsigned long)device_get_match_data(&client->dev)];
chip = i2c_get_match_data(client);
indio_dev->info = &atlas_info;
indio_dev->name = ATLAS_DRV_NAME;

View File

@ -114,6 +114,7 @@ struct sgp_data {
};
struct sgp_device {
unsigned long product_id;
const struct iio_chan_spec *channels;
int num_channels;
};
@ -182,10 +183,12 @@ static const struct iio_chan_spec sgpc3_channels[] = {
static const struct sgp_device sgp_devices[] = {
[SGP30] = {
.product_id = SGP30,
.channels = sgp30_channels,
.num_channels = ARRAY_SIZE(sgp30_channels),
},
[SGPC3] = {
.product_id = SGPC3,
.channels = sgpc3_channels,
.num_channels = ARRAY_SIZE(sgpc3_channels),
},
@ -491,28 +494,25 @@ static const struct iio_info sgp_info = {
};
static const struct of_device_id sgp_dt_ids[] = {
{ .compatible = "sensirion,sgp30", .data = (void *)SGP30 },
{ .compatible = "sensirion,sgpc3", .data = (void *)SGPC3 },
{ .compatible = "sensirion,sgp30", .data = &sgp_devices[SGP30] },
{ .compatible = "sensirion,sgpc3", .data = &sgp_devices[SGPC3] },
{ }
};
static int sgp_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
const struct sgp_device *match_data;
struct device *dev = &client->dev;
struct iio_dev *indio_dev;
struct sgp_data *data;
unsigned long product_id;
int ret;
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
if (dev_fwnode(dev))
product_id = (unsigned long)device_get_match_data(dev);
else
product_id = id->driver_data;
match_data = i2c_get_match_data(client);
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
@ -528,15 +528,15 @@ static int sgp_probe(struct i2c_client *client)
data->feature_set = be16_to_cpu(data->buffer.raw_words[0].value);
ret = sgp_check_compat(data, product_id);
ret = sgp_check_compat(data, match_data->product_id);
if (ret)
return ret;
indio_dev->info = &sgp_info;
indio_dev->name = id->name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = sgp_devices[product_id].channels;
indio_dev->num_channels = sgp_devices[product_id].num_channels;
indio_dev->channels = match_data->channels;
indio_dev->num_channels = match_data->num_channels;
sgp_init(data);
@ -562,8 +562,8 @@ static void sgp_remove(struct i2c_client *client)
}
static const struct i2c_device_id sgp_id[] = {
{ "sgp30", SGP30 },
{ "sgpc3", SGPC3 },
{ "sgp30", (kernel_ulong_t)&sgp_devices[SGP30] },
{ "sgpc3", (kernel_ulong_t)&sgp_devices[SGPC3] },
{ }
};

View File

@ -342,19 +342,17 @@ static const struct vz89x_chip_data vz89x_chips[] = {
};
static const struct of_device_id vz89x_dt_ids[] = {
{ .compatible = "sgx,vz89x", .data = (void *) VZ89X },
{ .compatible = "sgx,vz89te", .data = (void *) VZ89TE },
{ .compatible = "sgx,vz89x", .data = &vz89x_chips[VZ89X] },
{ .compatible = "sgx,vz89te", .data = &vz89x_chips[VZ89TE] },
{ }
};
MODULE_DEVICE_TABLE(of, vz89x_dt_ids);
static int vz89x_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct device *dev = &client->dev;
struct iio_dev *indio_dev;
struct vz89x_data *data;
int chip_id;
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
if (!indio_dev)
@ -369,14 +367,10 @@ static int vz89x_probe(struct i2c_client *client)
else
return -EOPNOTSUPP;
if (!dev_fwnode(dev))
chip_id = id->driver_data;
else
chip_id = (unsigned long)device_get_match_data(dev);
data->chip = i2c_get_match_data(client);
i2c_set_clientdata(client, indio_dev);
data->client = client;
data->chip = &vz89x_chips[chip_id];
data->last_update = jiffies - HZ;
mutex_init(&data->lock);
@ -391,8 +385,8 @@ static int vz89x_probe(struct i2c_client *client)
}
static const struct i2c_device_id vz89x_id[] = {
{ "vz89x", VZ89X },
{ "vz89te", VZ89TE },
{ "vz89x", (kernel_ulong_t)&vz89x_chips[VZ89X] },
{ "vz89te", (kernel_ulong_t)&vz89x_chips[VZ89TE] },
{ }
};
MODULE_DEVICE_TABLE(i2c, vz89x_id);

View File

@ -226,15 +226,13 @@ disable_reg:
return ret;
}
static int dpot_dac_remove(struct platform_device *pdev)
static void dpot_dac_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct dpot_dac *dac = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
regulator_disable(dac->vref);
return 0;
}
static const struct of_device_id dpot_dac_match[] = {
@ -245,7 +243,7 @@ MODULE_DEVICE_TABLE(of, dpot_dac_match);
static struct platform_driver dpot_dac_driver = {
.probe = dpot_dac_probe,
.remove = dpot_dac_remove,
.remove_new = dpot_dac_remove,
.driver = {
.name = "iio-dpot-dac",
.of_match_table = dpot_dac_match,

View File

@ -165,7 +165,7 @@ dis_reg:
return ret;
}
static int lpc18xx_dac_remove(struct platform_device *pdev)
static void lpc18xx_dac_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct lpc18xx_dac *dac = iio_priv(indio_dev);
@ -175,8 +175,6 @@ static int lpc18xx_dac_remove(struct platform_device *pdev)
writel(0, dac->base + LPC18XX_DAC_CTRL);
clk_disable_unprepare(dac->clk);
regulator_disable(dac->vref);
return 0;
}
static const struct of_device_id lpc18xx_dac_match[] = {
@ -187,7 +185,7 @@ MODULE_DEVICE_TABLE(of, lpc18xx_dac_match);
static struct platform_driver lpc18xx_dac_driver = {
.probe = lpc18xx_dac_probe,
.remove = lpc18xx_dac_remove,
.remove_new = lpc18xx_dac_remove,
.driver = {
.name = "lpc18xx-dac",
.of_match_table = lpc18xx_dac_match,

View File

@ -30,9 +30,14 @@
#define MCP472X_REF_VREF_UNBUFFERED 0x02
#define MCP472X_REF_VREF_BUFFERED 0x03
struct mcp4725_chip_info {
const struct iio_chan_spec *chan_spec;
u8 dac_reg_offset;
bool use_ext_ref_voltage;
};
struct mcp4725_data {
struct i2c_client *client;
int id;
unsigned ref_mode;
bool vref_buffered;
u16 dac_value;
@ -384,6 +389,7 @@ static int mcp4725_probe_dt(struct device *dev,
static int mcp4725_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
const struct mcp4725_chip_info *info;
struct mcp4725_data *data;
struct iio_dev *indio_dev;
struct mcp4725_platform_data *pdata, pdata_dt;
@ -398,10 +404,7 @@ static int mcp4725_probe(struct i2c_client *client)
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
if (dev_fwnode(&client->dev))
data->id = (uintptr_t)device_get_match_data(&client->dev);
else
data->id = id->driver_data;
info = i2c_get_match_data(client);
pdata = dev_get_platdata(&client->dev);
if (!pdata) {
@ -414,7 +417,7 @@ static int mcp4725_probe(struct i2c_client *client)
pdata = &pdata_dt;
}
if (data->id == MCP4725 && pdata->use_vref) {
if (info->use_ext_ref_voltage && pdata->use_vref) {
dev_err(&client->dev,
"external reference is unavailable on MCP4725");
return -EINVAL;
@ -455,12 +458,12 @@ static int mcp4725_probe(struct i2c_client *client)
indio_dev->name = id->name;
indio_dev->info = &mcp4725_info;
indio_dev->channels = &mcp472x_channel[id->driver_data];
indio_dev->channels = info->chan_spec;
indio_dev->num_channels = 1;
indio_dev->modes = INDIO_DIRECT_MODE;
/* read current DAC value and settings */
err = i2c_master_recv(client, inbuf, data->id == MCP4725 ? 3 : 4);
err = i2c_master_recv(client, inbuf, info->dac_reg_offset);
if (err < 0) {
dev_err(&client->dev, "failed to read DAC value");
@ -470,10 +473,10 @@ static int mcp4725_probe(struct i2c_client *client)
data->powerdown = pd > 0;
data->powerdown_mode = pd ? pd - 1 : 2; /* largest resistor to gnd */
data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);
if (data->id == MCP4726)
if (!info->use_ext_ref_voltage)
ref = (inbuf[3] >> 3) & 0x3;
if (data->id == MCP4726 && ref != data->ref_mode) {
if (!info->use_ext_ref_voltage && ref != data->ref_mode) {
dev_info(&client->dev,
"voltage reference mode differs (conf: %u, eeprom: %u), setting %u",
data->ref_mode, ref, data->ref_mode);
@ -510,9 +513,20 @@ static void mcp4725_remove(struct i2c_client *client)
regulator_disable(data->vdd_reg);
}
static const struct mcp4725_chip_info mcp4725 = {
.chan_spec = &mcp472x_channel[MCP4725],
.dac_reg_offset = 3,
.use_ext_ref_voltage = true,
};
static const struct mcp4725_chip_info mcp4726 = {
.chan_spec = &mcp472x_channel[MCP4726],
.dac_reg_offset = 4,
};
static const struct i2c_device_id mcp4725_id[] = {
{ "mcp4725", MCP4725 },
{ "mcp4726", MCP4726 },
{ "mcp4725", (kernel_ulong_t)&mcp4725 },
{ "mcp4726", (kernel_ulong_t)&mcp4726 },
{ }
};
MODULE_DEVICE_TABLE(i2c, mcp4725_id);
@ -520,11 +534,11 @@ MODULE_DEVICE_TABLE(i2c, mcp4725_id);
static const struct of_device_id mcp4725_of_match[] = {
{
.compatible = "microchip,mcp4725",
.data = (void *)MCP4725
.data = &mcp4725
},
{
.compatible = "microchip,mcp4726",
.data = (void *)MCP4726
.data = &mcp4726
},
{ }
};

View File

@ -9,9 +9,12 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
@ -94,16 +97,12 @@ static int stm32_dac_probe(struct platform_device *pdev)
struct reset_control *rst;
int ret;
if (!dev->of_node)
return -ENODEV;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
platform_set_drvdata(pdev, &priv->common);
cfg = (const struct stm32_dac_cfg *)
of_match_device(dev->driver->of_match_table, dev)->data;
cfg = device_get_match_data(dev);
mmio = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mmio))
@ -183,7 +182,7 @@ err_pm_stop:
return ret;
}
static int stm32_dac_remove(struct platform_device *pdev)
static void stm32_dac_remove(struct platform_device *pdev)
{
pm_runtime_get_sync(&pdev->dev);
of_platform_depopulate(&pdev->dev);
@ -191,8 +190,6 @@ static int stm32_dac_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
return 0;
}
static int stm32_dac_core_resume(struct device *dev)
@ -249,7 +246,7 @@ MODULE_DEVICE_TABLE(of, stm32_dac_of_match);
static struct platform_driver stm32_dac_driver = {
.probe = stm32_dac_probe,
.remove = stm32_dac_remove,
.remove_new = stm32_dac_remove,
.driver = {
.name = "stm32-dac-core",
.of_match_table = stm32_dac_of_match,

View File

@ -11,12 +11,13 @@
#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/kernel.h>
#include <linux/kstrtox.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/string_helpers.h>
#include <linux/string_choices.h>
#include "stm32-dac-core.h"
@ -361,7 +362,7 @@ err_pm_put:
return ret;
}
static int stm32_dac_remove(struct platform_device *pdev)
static void stm32_dac_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@ -370,8 +371,6 @@ static int stm32_dac_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
return 0;
}
static int stm32_dac_suspend(struct device *dev)
@ -399,7 +398,7 @@ MODULE_DEVICE_TABLE(of, stm32_dac_of_match);
static struct platform_driver stm32_dac_driver = {
.probe = stm32_dac_probe,
.remove = stm32_dac_remove,
.remove_new = stm32_dac_remove,
.driver = {
.name = "stm32-dac",
.of_match_table = stm32_dac_of_match,

View File

@ -313,7 +313,6 @@ static int dac5571_probe(struct i2c_client *client)
const struct dac5571_spec *spec;
struct dac5571_data *data;
struct iio_dev *indio_dev;
enum chip_id chip_id;
int ret, i;
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
@ -329,12 +328,7 @@ static int dac5571_probe(struct i2c_client *client)
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = dac5571_channels;
if (dev_fwnode(dev))
chip_id = (uintptr_t)device_get_match_data(dev);
else
chip_id = id->driver_data;
spec = &dac5571_spec[chip_id];
spec = i2c_get_match_data(client);
indio_dev->num_channels = spec->num_channels;
data->spec = spec;
@ -392,31 +386,31 @@ static void dac5571_remove(struct i2c_client *i2c)
}
static const struct of_device_id dac5571_of_id[] = {
{.compatible = "ti,dac5571", .data = (void *)single_8bit},
{.compatible = "ti,dac6571", .data = (void *)single_10bit},
{.compatible = "ti,dac7571", .data = (void *)single_12bit},
{.compatible = "ti,dac5574", .data = (void *)quad_8bit},
{.compatible = "ti,dac6574", .data = (void *)quad_10bit},
{.compatible = "ti,dac7574", .data = (void *)quad_12bit},
{.compatible = "ti,dac5573", .data = (void *)quad_8bit},
{.compatible = "ti,dac6573", .data = (void *)quad_10bit},
{.compatible = "ti,dac7573", .data = (void *)quad_12bit},
{.compatible = "ti,dac121c081", .data = (void *)single_12bit},
{.compatible = "ti,dac121c081", .data = &dac5571_spec[single_12bit] },
{.compatible = "ti,dac5571", .data = &dac5571_spec[single_8bit] },
{.compatible = "ti,dac6571", .data = &dac5571_spec[single_10bit] },
{.compatible = "ti,dac7571", .data = &dac5571_spec[single_12bit] },
{.compatible = "ti,dac5574", .data = &dac5571_spec[quad_8bit] },
{.compatible = "ti,dac6574", .data = &dac5571_spec[quad_10bit] },
{.compatible = "ti,dac7574", .data = &dac5571_spec[quad_12bit] },
{.compatible = "ti,dac5573", .data = &dac5571_spec[quad_8bit] },
{.compatible = "ti,dac6573", .data = &dac5571_spec[quad_10bit] },
{.compatible = "ti,dac7573", .data = &dac5571_spec[quad_12bit] },
{}
};
MODULE_DEVICE_TABLE(of, dac5571_of_id);
static const struct i2c_device_id dac5571_id[] = {
{"dac5571", single_8bit},
{"dac6571", single_10bit},
{"dac7571", single_12bit},
{"dac5574", quad_8bit},
{"dac6574", quad_10bit},
{"dac7574", quad_12bit},
{"dac5573", quad_8bit},
{"dac6573", quad_10bit},
{"dac7573", quad_12bit},
{"dac121c081", single_12bit},
{"dac121c081", (kernel_ulong_t)&dac5571_spec[single_12bit] },
{"dac5571", (kernel_ulong_t)&dac5571_spec[single_8bit] },
{"dac6571", (kernel_ulong_t)&dac5571_spec[single_10bit] },
{"dac7571", (kernel_ulong_t)&dac5571_spec[single_12bit] },
{"dac5574", (kernel_ulong_t)&dac5571_spec[quad_8bit] },
{"dac6574", (kernel_ulong_t)&dac5571_spec[quad_10bit] },
{"dac7574", (kernel_ulong_t)&dac5571_spec[quad_12bit] },
{"dac5573", (kernel_ulong_t)&dac5571_spec[quad_8bit] },
{"dac6573", (kernel_ulong_t)&dac5571_spec[quad_10bit] },
{"dac7573", (kernel_ulong_t)&dac5571_spec[quad_12bit] },
{}
};
MODULE_DEVICE_TABLE(i2c, dac5571_id);

View File

@ -231,7 +231,7 @@ error_iio_device_register:
return ret;
}
static int vf610_dac_remove(struct platform_device *pdev)
static void vf610_dac_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct vf610_dac *info = iio_priv(indio_dev);
@ -239,8 +239,6 @@ static int vf610_dac_remove(struct platform_device *pdev)
iio_device_unregister(indio_dev);
vf610_dac_exit(info);
clk_disable_unprepare(info->clk);
return 0;
}
static int vf610_dac_suspend(struct device *dev)
@ -274,7 +272,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(vf610_dac_pm_ops, vf610_dac_suspend,
static struct platform_driver vf610_dac_driver = {
.probe = vf610_dac_probe,
.remove = vf610_dac_remove,
.remove_new = vf610_dac_remove,
.driver = {
.name = "vf610-dac",
.of_match_table = vf610_dac_match,

View File

@ -33,7 +33,6 @@ enum {
struct adf4350_state {
struct spi_device *spi;
struct regulator *reg;
struct gpio_desc *lock_detect_gpiod;
struct adf4350_platform_data *pdata;
struct clk *clk;
@ -469,6 +468,15 @@ static struct adf4350_platform_data *adf4350_parse_dt(struct device *dev)
return pdata;
}
static void adf4350_power_down(void *data)
{
struct iio_dev *indio_dev = data;
struct adf4350_state *st = iio_priv(indio_dev);
st->regs[ADF4350_REG2] |= ADF4350_REG2_POWER_DOWN_EN;
adf4350_sync_config(st);
}
static int adf4350_probe(struct spi_device *spi)
{
struct adf4350_platform_data *pdata;
@ -491,31 +499,21 @@ static int adf4350_probe(struct spi_device *spi)
}
if (!pdata->clkin) {
clk = devm_clk_get(&spi->dev, "clkin");
clk = devm_clk_get_enabled(&spi->dev, "clkin");
if (IS_ERR(clk))
return -EPROBE_DEFER;
ret = clk_prepare_enable(clk);
if (ret < 0)
return ret;
return PTR_ERR(clk);
}
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_disable_clk;
}
if (indio_dev == NULL)
return -ENOMEM;
st = iio_priv(indio_dev);
st->reg = devm_regulator_get(&spi->dev, "vcc");
if (!IS_ERR(st->reg)) {
ret = regulator_enable(st->reg);
if (ret)
goto error_disable_clk;
}
ret = devm_regulator_get_enable(&spi->dev, "vcc");
if (ret)
return ret;
spi_set_drvdata(spi, indio_dev);
st->spi = spi;
st->pdata = pdata;
@ -544,47 +542,21 @@ static int adf4350_probe(struct spi_device *spi)
st->lock_detect_gpiod = devm_gpiod_get_optional(&spi->dev, NULL,
GPIOD_IN);
if (IS_ERR(st->lock_detect_gpiod)) {
ret = PTR_ERR(st->lock_detect_gpiod);
goto error_disable_reg;
}
if (IS_ERR(st->lock_detect_gpiod))
return PTR_ERR(st->lock_detect_gpiod);
if (pdata->power_up_frequency) {
ret = adf4350_set_freq(st, pdata->power_up_frequency);
if (ret)
goto error_disable_reg;
return ret;
}
ret = iio_device_register(indio_dev);
ret = devm_add_action_or_reset(&spi->dev, adf4350_power_down, indio_dev);
if (ret)
goto error_disable_reg;
return dev_err_probe(&spi->dev, ret,
"Failed to add action to managed power down\n");
return 0;
error_disable_reg:
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
error_disable_clk:
clk_disable_unprepare(clk);
return ret;
}
static void adf4350_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct adf4350_state *st = iio_priv(indio_dev);
struct regulator *reg = st->reg;
st->regs[ADF4350_REG2] |= ADF4350_REG2_POWER_DOWN_EN;
adf4350_sync_config(st);
iio_device_unregister(indio_dev);
clk_disable_unprepare(st->clk);
if (!IS_ERR(reg))
regulator_disable(reg);
return devm_iio_device_register(&spi->dev, indio_dev);
}
static const struct of_device_id adf4350_of_match[] = {
@ -607,7 +579,6 @@ static struct spi_driver adf4350_driver = {
.of_match_table = adf4350_of_match,
},
.probe = adf4350_probe,
.remove = adf4350_remove,
.id_table = adf4350_id,
};
module_spi_driver(adf4350_driver);

View File

@ -359,7 +359,7 @@ error_remove_trigger:
}
/* Function to deinitialize the processing for usage id */
static int hid_gyro_3d_remove(struct platform_device *pdev)
static void hid_gyro_3d_remove(struct platform_device *pdev)
{
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@ -368,8 +368,6 @@ static int hid_gyro_3d_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_GYRO_3D);
iio_device_unregister(indio_dev);
hid_sensor_remove_trigger(indio_dev, &gyro_state->common_attributes);
return 0;
}
static const struct platform_device_id hid_gyro_3d_ids[] = {
@ -388,7 +386,7 @@ static struct platform_driver hid_gyro_3d_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_gyro_3d_probe,
.remove = hid_gyro_3d_remove,
.remove_new = hid_gyro_3d_remove,
};
module_platform_driver(hid_gyro_3d_platform_driver);

View File

@ -260,7 +260,7 @@ error_remove_trigger:
}
/* Function to deinitialize the processing for usage id */
static int hid_humidity_remove(struct platform_device *pdev)
static void hid_humidity_remove(struct platform_device *pdev)
{
struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@ -269,8 +269,6 @@ static int hid_humidity_remove(struct platform_device *pdev)
iio_device_unregister(indio_dev);
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_HUMIDITY);
hid_sensor_remove_trigger(indio_dev, &humid_st->common_attributes);
return 0;
}
static const struct platform_device_id hid_humidity_ids[] = {
@ -289,7 +287,7 @@ static struct platform_driver hid_humidity_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_humidity_probe,
.remove = hid_humidity_remove,
.remove_new = hid_humidity_remove,
};
module_platform_driver(hid_humidity_platform_driver);

View File

@ -169,9 +169,16 @@ static const struct i2c_device_id si7005_id[] = {
};
MODULE_DEVICE_TABLE(i2c, si7005_id);
static const struct of_device_id si7005_dt_ids[] = {
{ .compatible = "silabs,si7005" },
{ }
};
MODULE_DEVICE_TABLE(of, si7005_dt_ids);
static struct i2c_driver si7005_driver = {
.driver = {
.name = "si7005",
.of_match_table = si7005_dt_ids,
},
.probe = si7005_probe,
.id_table = si7005_id,

View File

@ -30,9 +30,6 @@ struct iio_ioctl_handler {
unsigned int cmd, unsigned long arg);
};
long iio_device_ioctl(struct iio_dev *indio_dev, struct file *filp,
unsigned int cmd, unsigned long arg);
void iio_device_ioctl_handler_register(struct iio_dev *indio_dev,
struct iio_ioctl_handler *h);
void iio_device_ioctl_handler_unregister(struct iio_ioctl_handler *h);

View File

@ -31,6 +31,12 @@
#define ADIS16475_REG_Y_ACCEL_L 0x14
#define ADIS16475_REG_Z_ACCEL_L 0x18
#define ADIS16475_REG_TEMP_OUT 0x1c
#define ADIS16475_REG_X_DELTANG_L 0x24
#define ADIS16475_REG_Y_DELTANG_L 0x28
#define ADIS16475_REG_Z_DELTANG_L 0x2C
#define ADIS16475_REG_X_DELTVEL_L 0x30
#define ADIS16475_REG_Y_DELTVEL_L 0x34
#define ADIS16475_REG_Z_DELTVEL_L 0x38
#define ADIS16475_REG_X_GYRO_BIAS_L 0x40
#define ADIS16475_REG_Y_GYRO_BIAS_L 0x44
#define ADIS16475_REG_Z_GYRO_BIAS_L 0x48
@ -55,6 +61,7 @@
#define ADIS16475_REG_PROD_ID 0x72
#define ADIS16475_REG_SERIAL_NUM 0x74
#define ADIS16475_REG_FLASH_CNT 0x7c
#define ADIS16500_BURST_DATA_SEL_MASK BIT(8)
#define ADIS16500_BURST32_MASK BIT(9)
#define ADIS16500_BURST32(x) FIELD_PREP(ADIS16500_BURST32_MASK, x)
/* number of data elements in burst mode */
@ -65,6 +72,8 @@
#define ADIS16475_BURST_MAX_SPEED 1000000
#define ADIS16475_LSB_DEC_MASK BIT(0)
#define ADIS16475_LSB_FIR_MASK BIT(1)
#define ADIS16500_BURST_DATA_SEL_0_CHN_MASK GENMASK(5, 0)
#define ADIS16500_BURST_DATA_SEL_1_CHN_MASK GENMASK(12, 7)
enum {
ADIS16475_SYNC_DIRECT = 1,
@ -84,16 +93,20 @@ struct adis16475_chip_info {
const struct adis16475_sync *sync;
const struct adis_data adis_data;
const char *name;
#define ADIS16475_HAS_BURST32 BIT(0)
#define ADIS16475_HAS_BURST_DELTA_DATA BIT(1)
const long flags;
u32 num_channels;
u32 gyro_max_val;
u32 gyro_max_scale;
u32 accel_max_val;
u32 accel_max_scale;
u32 temp_scale;
u32 deltang_max_val;
u32 deltvel_max_val;
u32 int_clk;
u16 max_dec;
u8 num_sync;
bool has_burst32;
};
struct adis16475 {
@ -115,6 +128,12 @@ enum {
ADIS16475_SCAN_ACCEL_Y,
ADIS16475_SCAN_ACCEL_Z,
ADIS16475_SCAN_TEMP,
ADIS16475_SCAN_DELTANG_X,
ADIS16475_SCAN_DELTANG_Y,
ADIS16475_SCAN_DELTANG_Z,
ADIS16475_SCAN_DELTVEL_X,
ADIS16475_SCAN_DELTVEL_Y,
ADIS16475_SCAN_DELTVEL_Z,
};
static bool low_rate_allow;
@ -451,6 +470,14 @@ static int adis16475_read_raw(struct iio_dev *indio_dev,
case IIO_TEMP:
*val = st->info->temp_scale;
return IIO_VAL_INT;
case IIO_DELTA_ANGL:
*val = st->info->deltang_max_val;
*val2 = 31;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_DELTA_VELOCITY:
*val = st->info->deltvel_max_val;
*val2 = 31;
return IIO_VAL_FRACTIONAL_LOG2;
default:
return -EINVAL;
}
@ -551,6 +578,57 @@ static int adis16475_write_raw(struct iio_dev *indio_dev,
}, \
}
#define ADIS16475_MOD_CHAN_DELTA(_type, _mod, _address, _si, _r_bits, _s_bits) { \
.type = (_type), \
.modified = 1, \
.channel2 = (_mod), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
.address = (_address), \
.scan_index = _si, \
.scan_type = { \
.sign = 's', \
.realbits = (_r_bits), \
.storagebits = (_s_bits), \
.endianness = IIO_BE, \
}, \
}
#define ADIS16475_DELTANG_CHAN(_mod) \
ADIS16475_MOD_CHAN_DELTA(IIO_DELTA_ANGL, IIO_MOD_ ## _mod, \
ADIS16475_REG_ ## _mod ## _DELTANG_L, ADIS16475_SCAN_DELTANG_ ## _mod, 32, 32)
#define ADIS16475_DELTVEL_CHAN(_mod) \
ADIS16475_MOD_CHAN_DELTA(IIO_DELTA_VELOCITY, IIO_MOD_ ## _mod, \
ADIS16475_REG_ ## _mod ## _DELTVEL_L, ADIS16475_SCAN_DELTVEL_ ## _mod, 32, 32)
#define ADIS16475_DELTANG_CHAN_NO_SCAN(_mod) \
ADIS16475_MOD_CHAN_DELTA(IIO_DELTA_ANGL, IIO_MOD_ ## _mod, \
ADIS16475_REG_ ## _mod ## _DELTANG_L, -1, 32, 32)
#define ADIS16475_DELTVEL_CHAN_NO_SCAN(_mod) \
ADIS16475_MOD_CHAN_DELTA(IIO_DELTA_VELOCITY, IIO_MOD_ ## _mod, \
ADIS16475_REG_ ## _mod ## _DELTVEL_L, -1, 32, 32)
static const struct iio_chan_spec adis16477_channels[] = {
ADIS16475_GYRO_CHANNEL(X),
ADIS16475_GYRO_CHANNEL(Y),
ADIS16475_GYRO_CHANNEL(Z),
ADIS16475_ACCEL_CHANNEL(X),
ADIS16475_ACCEL_CHANNEL(Y),
ADIS16475_ACCEL_CHANNEL(Z),
ADIS16475_TEMP_CHANNEL(),
ADIS16475_DELTANG_CHAN(X),
ADIS16475_DELTANG_CHAN(Y),
ADIS16475_DELTANG_CHAN(Z),
ADIS16475_DELTVEL_CHAN(X),
ADIS16475_DELTVEL_CHAN(Y),
ADIS16475_DELTVEL_CHAN(Z),
IIO_CHAN_SOFT_TIMESTAMP(13)
};
static const struct iio_chan_spec adis16475_channels[] = {
ADIS16475_GYRO_CHANNEL(X),
ADIS16475_GYRO_CHANNEL(Y),
@ -559,6 +637,12 @@ static const struct iio_chan_spec adis16475_channels[] = {
ADIS16475_ACCEL_CHANNEL(Y),
ADIS16475_ACCEL_CHANNEL(Z),
ADIS16475_TEMP_CHANNEL(),
ADIS16475_DELTANG_CHAN_NO_SCAN(X),
ADIS16475_DELTANG_CHAN_NO_SCAN(Y),
ADIS16475_DELTANG_CHAN_NO_SCAN(Z),
ADIS16475_DELTVEL_CHAN_NO_SCAN(X),
ADIS16475_DELTVEL_CHAN_NO_SCAN(Y),
ADIS16475_DELTVEL_CHAN_NO_SCAN(Z),
IIO_CHAN_SOFT_TIMESTAMP(7)
};
@ -662,6 +746,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
.temp_scale = 100,
.deltang_max_val = IIO_DEGREE_TO_RAD(2160),
.deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
@ -677,6 +763,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
.temp_scale = 100,
.deltang_max_val = IIO_DEGREE_TO_RAD(360),
.deltvel_max_val = 100,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
@ -692,6 +780,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
.temp_scale = 100,
.deltang_max_val = IIO_DEGREE_TO_RAD(720),
.deltvel_max_val = 100,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
@ -707,6 +797,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
.temp_scale = 100,
.deltang_max_val = IIO_DEGREE_TO_RAD(2160),
.deltvel_max_val = 100,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
@ -715,50 +807,56 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
},
[ADIS16477_1] = {
.name = "adis16477-1",
.num_channels = ARRAY_SIZE(adis16475_channels),
.channels = adis16475_channels,
.num_channels = ARRAY_SIZE(adis16477_channels),
.channels = adis16477_channels,
.gyro_max_val = 1,
.gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
.temp_scale = 100,
.deltang_max_val = IIO_DEGREE_TO_RAD(360),
.deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
.has_burst32 = true,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16477, &adis16475_timeouts),
},
[ADIS16477_2] = {
.name = "adis16477-2",
.num_channels = ARRAY_SIZE(adis16475_channels),
.channels = adis16475_channels,
.num_channels = ARRAY_SIZE(adis16477_channels),
.channels = adis16477_channels,
.gyro_max_val = 1,
.gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
.temp_scale = 100,
.deltang_max_val = IIO_DEGREE_TO_RAD(720),
.deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
.has_burst32 = true,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16477, &adis16475_timeouts),
},
[ADIS16477_3] = {
.name = "adis16477-3",
.num_channels = ARRAY_SIZE(adis16475_channels),
.channels = adis16475_channels,
.num_channels = ARRAY_SIZE(adis16477_channels),
.channels = adis16477_channels,
.gyro_max_val = 1,
.gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
.temp_scale = 100,
.deltang_max_val = IIO_DEGREE_TO_RAD(2160),
.deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
.num_sync = ARRAY_SIZE(adis16475_sync_mode),
.has_burst32 = true,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16477, &adis16475_timeouts),
},
[ADIS16465_1] = {
@ -770,6 +868,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
.temp_scale = 100,
.deltang_max_val = IIO_DEGREE_TO_RAD(360),
.deltvel_max_val = 100,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
@ -785,6 +885,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
.temp_scale = 100,
.deltang_max_val = IIO_DEGREE_TO_RAD(720),
.deltvel_max_val = 100,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
@ -800,6 +902,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
.temp_scale = 100,
.deltang_max_val = IIO_DEGREE_TO_RAD(2160),
.deltvel_max_val = 100,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
@ -815,6 +919,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
.temp_scale = 100,
.deltang_max_val = IIO_DEGREE_TO_RAD(360),
.deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
@ -830,6 +936,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
.temp_scale = 100,
.deltang_max_val = IIO_DEGREE_TO_RAD(720),
.deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
@ -845,6 +953,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
.accel_max_val = 1,
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
.temp_scale = 100,
.deltang_max_val = IIO_DEGREE_TO_RAD(2160),
.deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
@ -853,129 +963,168 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
},
[ADIS16500] = {
.name = "adis16500",
.num_channels = ARRAY_SIZE(adis16475_channels),
.channels = adis16475_channels,
.num_channels = ARRAY_SIZE(adis16477_channels),
.channels = adis16477_channels,
.gyro_max_val = 1,
.gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
.accel_max_val = 392,
.accel_max_scale = 32000 << 16,
.temp_scale = 100,
.deltang_max_val = IIO_DEGREE_TO_RAD(2160),
.deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.has_burst32 = true,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16500, &adis1650x_timeouts),
},
[ADIS16505_1] = {
.name = "adis16505-1",
.num_channels = ARRAY_SIZE(adis16475_channels),
.channels = adis16475_channels,
.num_channels = ARRAY_SIZE(adis16477_channels),
.channels = adis16477_channels,
.gyro_max_val = 1,
.gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
.accel_max_val = 78,
.accel_max_scale = 32000 << 16,
.temp_scale = 100,
.deltang_max_val = IIO_DEGREE_TO_RAD(360),
.deltvel_max_val = 100,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.has_burst32 = true,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts),
},
[ADIS16505_2] = {
.name = "adis16505-2",
.num_channels = ARRAY_SIZE(adis16475_channels),
.channels = adis16475_channels,
.num_channels = ARRAY_SIZE(adis16477_channels),
.channels = adis16477_channels,
.gyro_max_val = 1,
.gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
.accel_max_val = 78,
.accel_max_scale = 32000 << 16,
.temp_scale = 100,
.deltang_max_val = IIO_DEGREE_TO_RAD(720),
.deltvel_max_val = 100,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.has_burst32 = true,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts),
},
[ADIS16505_3] = {
.name = "adis16505-3",
.num_channels = ARRAY_SIZE(adis16475_channels),
.channels = adis16475_channels,
.num_channels = ARRAY_SIZE(adis16477_channels),
.channels = adis16477_channels,
.gyro_max_val = 1,
.gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
.accel_max_val = 78,
.accel_max_scale = 32000 << 16,
.temp_scale = 100,
.deltang_max_val = IIO_DEGREE_TO_RAD(2160),
.deltvel_max_val = 100,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.has_burst32 = true,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts),
},
[ADIS16507_1] = {
.name = "adis16507-1",
.num_channels = ARRAY_SIZE(adis16475_channels),
.channels = adis16475_channels,
.num_channels = ARRAY_SIZE(adis16477_channels),
.channels = adis16477_channels,
.gyro_max_val = 1,
.gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
.accel_max_val = 392,
.accel_max_scale = 32000 << 16,
.temp_scale = 100,
.deltang_max_val = IIO_DEGREE_TO_RAD(360),
.deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.has_burst32 = true,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts),
},
[ADIS16507_2] = {
.name = "adis16507-2",
.num_channels = ARRAY_SIZE(adis16475_channels),
.channels = adis16475_channels,
.num_channels = ARRAY_SIZE(adis16477_channels),
.channels = adis16477_channels,
.gyro_max_val = 1,
.gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
.accel_max_val = 392,
.accel_max_scale = 32000 << 16,
.temp_scale = 100,
.deltang_max_val = IIO_DEGREE_TO_RAD(720),
.deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.has_burst32 = true,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts),
},
[ADIS16507_3] = {
.name = "adis16507-3",
.num_channels = ARRAY_SIZE(adis16475_channels),
.channels = adis16475_channels,
.num_channels = ARRAY_SIZE(adis16477_channels),
.channels = adis16477_channels,
.gyro_max_val = 1,
.gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
.accel_max_val = 392,
.accel_max_scale = 32000 << 16,
.temp_scale = 100,
.deltang_max_val = IIO_DEGREE_TO_RAD(2160),
.deltvel_max_val = 400,
.int_clk = 2000,
.max_dec = 1999,
.sync = adis16475_sync_mode,
/* pulse sync not supported */
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
.has_burst32 = true,
.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
.adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts),
},
};
static int adis16475_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *scan_mask)
{
u16 en;
int ret;
struct adis16475 *st = iio_priv(indio_dev);
if (st->info->flags & ADIS16475_HAS_BURST_DELTA_DATA) {
if ((*scan_mask & ADIS16500_BURST_DATA_SEL_0_CHN_MASK) &&
(*scan_mask & ADIS16500_BURST_DATA_SEL_1_CHN_MASK))
return -EINVAL;
if (*scan_mask & ADIS16500_BURST_DATA_SEL_0_CHN_MASK)
en = FIELD_PREP(ADIS16500_BURST_DATA_SEL_MASK, 0);
else
en = FIELD_PREP(ADIS16500_BURST_DATA_SEL_MASK, 1);
ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
ADIS16500_BURST_DATA_SEL_MASK, en);
if (ret)
return ret;
}
return adis_update_scan_mode(indio_dev, scan_mask);
}
static const struct iio_info adis16475_info = {
.read_raw = &adis16475_read_raw,
.write_raw = &adis16475_write_raw,
.update_scan_mode = adis_update_scan_mode,
.update_scan_mode = adis16475_update_scan_mode,
.debugfs_reg_access = adis_debugfs_reg_access,
};
@ -998,7 +1147,7 @@ static void adis16475_burst32_check(struct adis16475 *st)
int ret;
struct adis *adis = &st->adis;
if (!st->info->has_burst32)
if (!(st->info->flags & ADIS16475_HAS_BURST32))
return;
if (st->lsb_flag && !st->burst32) {
@ -1044,7 +1193,7 @@ static irqreturn_t adis16475_trigger_handler(int irq, void *p)
struct iio_dev *indio_dev = pf->indio_dev;
struct adis16475 *st = iio_priv(indio_dev);
struct adis *adis = &st->adis;
int ret, bit, i = 0;
int ret, bit, buff_offset = 0, i = 0;
__be16 *buffer;
u16 crc;
bool valid;
@ -1073,7 +1222,20 @@ static irqreturn_t adis16475_trigger_handler(int irq, void *p)
switch (bit) {
case ADIS16475_SCAN_TEMP:
st->data[i++] = buffer[offset];
/*
* The temperature channel has 16-bit storage size.
* We need to perform the padding to have the buffer
* elements naturally aligned in case there are any
* 32-bit storage size channels enabled which have a
* scan index higher than the temperature channel scan
* index.
*/
if (*indio_dev->active_scan_mask & GENMASK(ADIS16475_SCAN_DELTVEL_Z, ADIS16475_SCAN_DELTANG_X))
st->data[i++] = 0;
break;
case ADIS16475_SCAN_DELTANG_X ... ADIS16475_SCAN_DELTVEL_Z:
buff_offset = ADIS16475_SCAN_DELTANG_X;
fallthrough;
case ADIS16475_SCAN_GYRO_X ... ADIS16475_SCAN_ACCEL_Z:
/*
* The first 2 bytes on the received data are the
@ -1081,18 +1243,18 @@ static irqreturn_t adis16475_trigger_handler(int irq, void *p)
*/
if (st->burst32) {
/* upper 16 */
st->data[i++] = buffer[bit * 2 + 2];
st->data[i++] = buffer[(bit - buff_offset) * 2 + 2];
/* lower 16 */
st->data[i++] = buffer[bit * 2 + 1];
st->data[i++] = buffer[(bit - buff_offset) * 2 + 1];
} else {
st->data[i++] = buffer[bit + 1];
st->data[i++] = buffer[(bit - buff_offset) + 1];
/*
* Don't bother in doing the manual read if the
* device supports burst32. burst32 will be
* enabled in the next call to
* adis16475_burst32_check()...
*/
if (st->lsb_flag && !st->info->has_burst32) {
if (st->lsb_flag && !(st->info->flags & ADIS16475_HAS_BURST32)) {
u16 val = 0;
const u32 reg = ADIS16475_REG_X_GYRO_L +
bit * 4;

View File

@ -71,6 +71,19 @@ int inv_mpu_aux_init(const struct inv_mpu6050_state *st)
unsigned int val;
int ret;
/*
* Code based on the vendor Linux kernel v3.0,
* the exact meaning is unknown.
*/
if (st->chip_type == INV_MPU9150) {
unsigned int mask = BIT(7);
val = st->level_shifter ? mask : 0;
ret = regmap_update_bits(st->map, 0x1, mask, val);
if (ret)
return ret;
}
/* configure i2c master */
val = INV_MPU6050_BITS_I2C_MST_CLK_400KHZ |
INV_MPU6050_BIT_WAIT_FOR_ES;

View File

@ -17,6 +17,7 @@
#include <linux/regulator/consumer.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/iio/common/inv_sensors_timestamp.h>
#include <linux/iio/iio.h>
@ -1495,6 +1496,8 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
st->irq = irq;
st->map = regmap;
st->level_shifter = device_property_read_bool(dev,
"invensense,level-shifter");
pdata = dev_get_platdata(dev);
if (!pdata) {
result = iio_read_mount_matrix(dev, &st->orientation);

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