mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
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:
commit
b4b6cc10c6
@ -279,6 +279,35 @@ Description:
|
|||||||
but should match other such assignments on device).
|
but should match other such assignments on device).
|
||||||
Units after application of scale and offset are m/s^2.
|
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_angl_raw
|
||||||
What: /sys/bus/iio/devices/iio:deviceX/in_anglY_raw
|
What: /sys/bus/iio/devices/iio:deviceX/in_anglY_raw
|
||||||
KernelVersion: 4.17
|
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_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_illuminance_scale
|
||||||
What: /sys/bus/iio/devices/iio:deviceX/in_countY_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_angl_scale
|
||||||
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_x_scale
|
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_x_scale
|
||||||
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_y_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_x_en
|
||||||
What: /sys/.../iio:deviceX/bufferY/in_accel_y_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_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_x_en
|
||||||
What: /sys/.../iio:deviceX/bufferY/in_anglvel_y_en
|
What: /sys/.../iio:deviceX/bufferY/in_anglvel_y_en
|
||||||
What: /sys/.../iio:deviceX/bufferY/in_anglvel_z_en
|
What: /sys/.../iio:deviceX/bufferY/in_anglvel_z_en
|
||||||
@ -1362,6 +1399,8 @@ Description:
|
|||||||
Scan element control for triggered data capture.
|
Scan element control for triggered data capture.
|
||||||
|
|
||||||
What: /sys/.../iio:deviceX/bufferY/in_accel_type
|
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_anglvel_type
|
||||||
What: /sys/.../iio:deviceX/bufferY/in_magn_type
|
What: /sys/.../iio:deviceX/bufferY/in_magn_type
|
||||||
What: /sys/.../iio:deviceX/bufferY/in_incli_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_x_index
|
||||||
What: /sys/.../iio:deviceX/bufferY/in_accel_y_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_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_x_index
|
||||||
What: /sys/.../iio:deviceX/bufferY/in_anglvel_y_index
|
What: /sys/.../iio:deviceX/bufferY/in_anglvel_y_index
|
||||||
What: /sys/.../iio:deviceX/bufferY/in_anglvel_z_index
|
What: /sys/.../iio:deviceX/bufferY/in_anglvel_z_index
|
||||||
@ -2179,3 +2224,33 @@ Contact: linux-iio@vger.kernel.org
|
|||||||
Description:
|
Description:
|
||||||
Number of conditions that must occur, during a running
|
Number of conditions that must occur, during a running
|
||||||
period, before an event is generated.
|
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.
|
||||||
|
53
Documentation/ABI/testing/sysfs-bus-iio-adc-mcp3564
Normal file
53
Documentation/ABI/testing/sysfs-bus-iio-adc-mcp3564
Normal 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.
|
27
Documentation/ABI/testing/sysfs-bus-iio-resolver-ad2s1210
Normal file
27
Documentation/ABI/testing/sysfs-bus-iio-resolver-ad2s1210
Normal 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.
|
@ -4,19 +4,23 @@
|
|||||||
$id: http://devicetree.org/schemas/iio/accel/kionix,kx022a.yaml#
|
$id: http://devicetree.org/schemas/iio/accel/kionix,kx022a.yaml#
|
||||||
$schema: http://devicetree.org/meta-schemas/core.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:
|
maintainers:
|
||||||
- Matti Vaittinen <mazziesaccount@gmail.com>
|
- Matti Vaittinen <mazziesaccount@gmail.com>
|
||||||
|
|
||||||
description: |
|
description: |
|
||||||
KX022A is a 3-axis accelerometer supporting +/- 2G, 4G, 8G and 16G ranges,
|
KX022A, KX132ACR-LBZ and KX132-1211 are 3-axis accelerometers supporting
|
||||||
output data-rates from 0.78Hz to 1600Hz and a hardware-fifo buffering.
|
+/- 2G, 4G, 8G and 16G ranges, variable output data-rates and a
|
||||||
KX022A can be accessed either via I2C or SPI.
|
hardware-fifo buffering. These accelerometers can be accessed either
|
||||||
|
via I2C or SPI.
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
const: kionix,kx022a
|
enum:
|
||||||
|
- kionix,kx022a
|
||||||
|
- kionix,kx132-1211
|
||||||
|
- rohm,kx132acr-lbz
|
||||||
|
|
||||||
reg:
|
reg:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
@ -4,21 +4,31 @@
|
|||||||
$id: http://devicetree.org/schemas/iio/adc/lltc,ltc2497.yaml#
|
$id: http://devicetree.org/schemas/iio/adc/lltc,ltc2497.yaml#
|
||||||
$schema: http://devicetree.org/meta-schemas/core.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:
|
maintainers:
|
||||||
- Michael Hennerich <michael.hennerich@analog.com>
|
- Michael Hennerich <michael.hennerich@analog.com>
|
||||||
|
- Liam Beguin <liambeguin@gmail.com>
|
||||||
|
|
||||||
description: |
|
description: |
|
||||||
16bit ADC supporting up to 16 single ended or 8 differential inputs.
|
LTC2309:
|
||||||
I2C interface.
|
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/2309fd.pdf
|
||||||
https://www.analog.com/media/en/technical-documentation/data-sheets/2499fe.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:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
enum:
|
enum:
|
||||||
|
- lltc,ltc2309
|
||||||
- lltc,ltc2497
|
- lltc,ltc2497
|
||||||
- lltc,ltc2499
|
- lltc,ltc2499
|
||||||
|
|
||||||
|
205
Documentation/devicetree/bindings/iio/adc/microchip,mcp3564.yaml
Normal file
205
Documentation/devicetree/bindings/iio/adc/microchip,mcp3564.yaml
Normal 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";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
...
|
@ -18,7 +18,13 @@ description: |
|
|||||||
properties:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
enum:
|
enum:
|
||||||
|
- microchip,mcp3910
|
||||||
- microchip,mcp3911
|
- microchip,mcp3911
|
||||||
|
- microchip,mcp3912
|
||||||
|
- microchip,mcp3913
|
||||||
|
- microchip,mcp3914
|
||||||
|
- microchip,mcp3918
|
||||||
|
- microchip,mcp3919
|
||||||
|
|
||||||
reg:
|
reg:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
@ -23,6 +23,9 @@ properties:
|
|||||||
reg:
|
reg:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
"#address-cells":
|
"#address-cells":
|
||||||
const: 1
|
const: 1
|
||||||
|
|
||||||
|
@ -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>;
|
||||||
|
};
|
||||||
|
...
|
@ -4,20 +4,26 @@
|
|||||||
$id: http://devicetree.org/schemas/iio/amplifiers/adi,hmc425a.yaml#
|
$id: http://devicetree.org/schemas/iio/amplifiers/adi,hmc425a.yaml#
|
||||||
$schema: http://devicetree.org/meta-schemas/core.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:
|
maintainers:
|
||||||
- Michael Hennerich <michael.hennerich@analog.com>
|
- Michael Hennerich <michael.hennerich@analog.com>
|
||||||
|
|
||||||
description: |
|
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
|
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:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
enum:
|
enum:
|
||||||
- adi,hmc425a
|
- adi,hmc425a
|
||||||
|
- adi,hmc540s
|
||||||
|
|
||||||
vcc-supply: true
|
vcc-supply: true
|
||||||
|
|
||||||
|
@ -48,6 +48,11 @@ properties:
|
|||||||
|
|
||||||
mount-matrix: true
|
mount-matrix: true
|
||||||
|
|
||||||
|
invensense,level-shifter:
|
||||||
|
type: boolean
|
||||||
|
description: |
|
||||||
|
From ancient platform data struct: false: VLogic, true: VDD
|
||||||
|
|
||||||
i2c-gate:
|
i2c-gate:
|
||||||
$ref: /schemas/i2c/i2c-controller.yaml
|
$ref: /schemas/i2c/i2c-controller.yaml
|
||||||
unevaluatedProperties: false
|
unevaluatedProperties: false
|
||||||
|
@ -93,6 +93,9 @@ properties:
|
|||||||
wakeup-source:
|
wakeup-source:
|
||||||
$ref: /schemas/types.yaml#/definitions/flag
|
$ref: /schemas/types.yaml#/definitions/flag
|
||||||
|
|
||||||
|
mount-matrix:
|
||||||
|
description: an optional 3x3 mounting rotation matrix
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
- reg
|
- reg
|
||||||
|
@ -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>;
|
||||||
|
};
|
||||||
|
};
|
177
Documentation/devicetree/bindings/iio/resolver/adi,ad2s1210.yaml
Normal file
177
Documentation/devicetree/bindings/iio/resolver/adi,ad2s1210.yaml
Normal 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>;
|
||||||
|
};
|
||||||
|
};
|
@ -348,6 +348,8 @@ properties:
|
|||||||
# Silicon Labs SI3210 Programmable CMOS SLIC/CODEC with SPI interface
|
# Silicon Labs SI3210 Programmable CMOS SLIC/CODEC with SPI interface
|
||||||
- silabs,si3210
|
- silabs,si3210
|
||||||
# Relative Humidity and Temperature Sensors
|
# Relative Humidity and Temperature Sensors
|
||||||
|
- silabs,si7005
|
||||||
|
# Relative Humidity and Temperature Sensors
|
||||||
- silabs,si7020
|
- silabs,si7020
|
||||||
# Skyworks SKY81452: Six-Channel White LED Driver with Touch Panel Bias Supply
|
# Skyworks SKY81452: Six-Channel White LED Driver with Touch Panel Bias Supply
|
||||||
- skyworks,sky81452
|
- skyworks,sky81452
|
||||||
|
19
MAINTAINERS
19
MAINTAINERS
@ -1118,7 +1118,7 @@ ANALOG DEVICES INC AD4130 DRIVER
|
|||||||
M: Cosmin Tanislav <cosmin.tanislav@analog.com>
|
M: Cosmin Tanislav <cosmin.tanislav@analog.com>
|
||||||
L: linux-iio@vger.kernel.org
|
L: linux-iio@vger.kernel.org
|
||||||
S: Supported
|
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/ABI/testing/sysfs-bus-iio-adc-ad4130
|
||||||
F: Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml
|
F: Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml
|
||||||
F: drivers/iio/adc/ad4130.c
|
F: drivers/iio/adc/ad4130.c
|
||||||
@ -1151,7 +1151,7 @@ ANALOG DEVICES INC AD74115 DRIVER
|
|||||||
M: Cosmin Tanislav <cosmin.tanislav@analog.com>
|
M: Cosmin Tanislav <cosmin.tanislav@analog.com>
|
||||||
L: linux-iio@vger.kernel.org
|
L: linux-iio@vger.kernel.org
|
||||||
S: Supported
|
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: Documentation/devicetree/bindings/iio/addac/adi,ad74115.yaml
|
||||||
F: drivers/iio/addac/ad74115.c
|
F: drivers/iio/addac/ad74115.c
|
||||||
|
|
||||||
@ -12811,7 +12811,7 @@ MAX31827 TEMPERATURE SWITCH DRIVER
|
|||||||
M: Daniel Matyas <daniel.matyas@analog.com>
|
M: Daniel Matyas <daniel.matyas@analog.com>
|
||||||
L: linux-hwmon@vger.kernel.org
|
L: linux-hwmon@vger.kernel.org
|
||||||
S: Supported
|
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/devicetree/bindings/hwmon/adi,max31827.yaml
|
||||||
F: Documentation/hwmon/max31827.rst
|
F: Documentation/hwmon/max31827.rst
|
||||||
F: drivers/hwmon/max31827.c
|
F: drivers/hwmon/max31827.c
|
||||||
@ -14011,6 +14011,13 @@ S: Supported
|
|||||||
F: Documentation/devicetree/bindings/regulator/mcp16502-regulator.txt
|
F: Documentation/devicetree/bindings/regulator/mcp16502-regulator.txt
|
||||||
F: drivers/regulator/mcp16502.c
|
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
|
MICROCHIP MCP3911 ADC DRIVER
|
||||||
M: Marcus Folkesson <marcus.folkesson@gmail.com>
|
M: Marcus Folkesson <marcus.folkesson@gmail.com>
|
||||||
M: Kent Gustavsson <kent@minoris.se>
|
M: Kent Gustavsson <kent@minoris.se>
|
||||||
@ -18555,6 +18562,12 @@ S: Maintained
|
|||||||
F: Documentation/devicetree/bindings/iio/light/bh1750.yaml
|
F: Documentation/devicetree/bindings/iio/light/bh1750.yaml
|
||||||
F: drivers/iio/light/bh1750.c
|
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
|
ROHM BU270xx LIGHT SENSOR DRIVERs
|
||||||
M: Matti Vaittinen <mazziesaccount@gmail.com>
|
M: Matti Vaittinen <mazziesaccount@gmail.com>
|
||||||
L: linux-iio@vger.kernel.org
|
L: linux-iio@vger.kernel.org
|
||||||
|
@ -257,6 +257,13 @@ static u8 get_input_report(u8 current_index, int sensor_idx, int report_id,
|
|||||||
else
|
else
|
||||||
als_input.illuminance_value =
|
als_input.illuminance_value =
|
||||||
(int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
|
(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);
|
report_size = sizeof(als_input);
|
||||||
memcpy(input_report, &als_input, sizeof(als_input));
|
memcpy(input_report, &als_input, sizeof(als_input));
|
||||||
break;
|
break;
|
||||||
|
@ -99,6 +99,9 @@ struct als_input_report {
|
|||||||
struct common_input_property common_property;
|
struct common_input_property common_property;
|
||||||
/* values specific to this sensor */
|
/* values specific to this sensor */
|
||||||
int illuminance_value;
|
int illuminance_value;
|
||||||
|
int light_color_temp;
|
||||||
|
int chromaticity_x_value;
|
||||||
|
int chromaticity_y_value;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct hpd_feature_report {
|
struct hpd_feature_report {
|
||||||
|
@ -641,6 +641,27 @@ static const u8 als_report_descriptor[] = {
|
|||||||
0x75, 32, /* HID report size(32) */
|
0x75, 32, /* HID report size(32) */
|
||||||
0x95, 1, /* HID report count (1) */
|
0x95, 1, /* HID report count (1) */
|
||||||
0X81, 0x02, /* HID Input (Data_Arr_Abs) */
|
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 */
|
0xC0 /* HID end collection */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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_mag_data mag_data;
|
||||||
struct sfh_als_data als_data;
|
struct sfh_als_data als_data;
|
||||||
struct hpd_status hpdstatus;
|
struct hpd_status hpdstatus;
|
||||||
|
struct sfh_base_info binfo;
|
||||||
void __iomem *sensoraddr;
|
void __iomem *sensoraddr;
|
||||||
u8 report_size = 0;
|
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));
|
memcpy_fromio(&als_data, sensoraddr, sizeof(struct sfh_als_data));
|
||||||
get_common_inputs(&als_input.common_property, report_id);
|
get_common_inputs(&als_input.common_property, report_id);
|
||||||
als_input.illuminance_value = float_to_int(als_data.lux);
|
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);
|
report_size = sizeof(als_input);
|
||||||
memcpy(input_report, &als_input, sizeof(als_input));
|
memcpy(input_report, &als_input, sizeof(als_input));
|
||||||
break;
|
break;
|
||||||
|
@ -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 {
|
struct sfh_base_info {
|
||||||
union {
|
union {
|
||||||
u32 sfh_base[24];
|
u32 sfh_base[24];
|
||||||
@ -95,6 +105,8 @@ struct sfh_base_info {
|
|||||||
struct sfh_platform_info plat_info;
|
struct sfh_platform_info plat_info;
|
||||||
struct sfh_firmware_info fw_info;
|
struct sfh_firmware_info fw_info;
|
||||||
struct sfh_sensor_list s_list;
|
struct sfh_sensor_list s_list;
|
||||||
|
u32 rsvd;
|
||||||
|
struct sfh_sensor_prop s_prop[16];
|
||||||
} sbase;
|
} sbase;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -134,6 +146,9 @@ struct sfh_mag_data {
|
|||||||
struct sfh_als_data {
|
struct sfh_als_data {
|
||||||
struct sfh_common_data commondata;
|
struct sfh_common_data commondata;
|
||||||
u32 lux;
|
u32 lux;
|
||||||
|
u32 light_color_temp;
|
||||||
|
u32 chromaticity_x;
|
||||||
|
u32 chromaticity_y;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hpd_status {
|
struct hpd_status {
|
||||||
|
@ -418,8 +418,9 @@ config IIO_KX022A_SPI
|
|||||||
select IIO_KX022A
|
select IIO_KX022A
|
||||||
select REGMAP_SPI
|
select REGMAP_SPI
|
||||||
help
|
help
|
||||||
Enable support for the Kionix KX022A digital tri-axis
|
Enable support for the Kionix digital tri-axis accelerometers
|
||||||
accelerometer connected to I2C interface.
|
connected to SPI interface. Supported devices are:
|
||||||
|
KX022A, KX132-1211, KX132ACR-LBZ
|
||||||
|
|
||||||
config IIO_KX022A_I2C
|
config IIO_KX022A_I2C
|
||||||
tristate "Kionix KX022A tri-axis digital accelerometer I2C interface"
|
tristate "Kionix KX022A tri-axis digital accelerometer I2C interface"
|
||||||
@ -427,8 +428,9 @@ config IIO_KX022A_I2C
|
|||||||
select IIO_KX022A
|
select IIO_KX022A
|
||||||
select REGMAP_I2C
|
select REGMAP_I2C
|
||||||
help
|
help
|
||||||
Enable support for the Kionix KX022A digital tri-axis
|
Enable support for the Kionix digital tri-axis accelerometers
|
||||||
accelerometer connected to I2C interface.
|
connected to I2C interface. Supported devices are:
|
||||||
|
KX022A, KX132-1211, KX132ACR-LBZ
|
||||||
|
|
||||||
config KXSD9
|
config KXSD9
|
||||||
tristate "Kionix KXSD9 Accelerometer Driver"
|
tristate "Kionix KXSD9 Accelerometer Driver"
|
||||||
|
@ -8,9 +8,24 @@
|
|||||||
#ifndef _ADXL345_H_
|
#ifndef _ADXL345_H_
|
||||||
#define _ADXL345_H_
|
#define _ADXL345_H_
|
||||||
|
|
||||||
enum adxl345_device_type {
|
/*
|
||||||
ADXL345 = 1,
|
* In full-resolution mode, scale factor is maintained at ~4 mg/LSB
|
||||||
ADXL375 = 2,
|
* 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);
|
int adxl345_core_probe(struct device *dev, struct regmap *regmap);
|
||||||
|
@ -45,25 +45,10 @@
|
|||||||
|
|
||||||
#define ADXL345_DEVID 0xE5
|
#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 {
|
struct adxl345_data {
|
||||||
|
const struct adxl345_chip_info *info;
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
u8 data_range;
|
u8 data_range;
|
||||||
enum adxl345_device_type type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ADXL345_CHANNEL(index, axis) { \
|
#define ADXL345_CHANNEL(index, axis) { \
|
||||||
@ -110,15 +95,7 @@ static int adxl345_read_raw(struct iio_dev *indio_dev,
|
|||||||
return IIO_VAL_INT;
|
return IIO_VAL_INT;
|
||||||
case IIO_CHAN_INFO_SCALE:
|
case IIO_CHAN_INFO_SCALE:
|
||||||
*val = 0;
|
*val = 0;
|
||||||
switch (data->type) {
|
*val2 = data->info->uscale;
|
||||||
case ADXL345:
|
|
||||||
*val2 = adxl345_uscale;
|
|
||||||
break;
|
|
||||||
case ADXL375:
|
|
||||||
*val2 = adxl375_uscale;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return IIO_VAL_INT_PLUS_MICRO;
|
return IIO_VAL_INT_PLUS_MICRO;
|
||||||
case IIO_CHAN_INFO_CALIBBIAS:
|
case IIO_CHAN_INFO_CALIBBIAS:
|
||||||
ret = regmap_read(data->regmap,
|
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)
|
int adxl345_core_probe(struct device *dev, struct regmap *regmap)
|
||||||
{
|
{
|
||||||
enum adxl345_device_type type;
|
|
||||||
struct adxl345_data *data;
|
struct adxl345_data *data;
|
||||||
struct iio_dev *indio_dev;
|
struct iio_dev *indio_dev;
|
||||||
const char *name;
|
|
||||||
u32 regval;
|
u32 regval;
|
||||||
int ret;
|
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, ®val);
|
ret = regmap_read(regmap, ADXL345_REG_DEVID, ®val);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return dev_err_probe(dev, ret, "Error reading device ID\n");
|
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 = iio_priv(indio_dev);
|
||||||
data->regmap = regmap;
|
data->regmap = regmap;
|
||||||
data->type = type;
|
|
||||||
/* Enable full-resolution mode */
|
/* Enable full-resolution mode */
|
||||||
data->data_range = ADXL345_DATA_FORMAT_FULL_RES;
|
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,
|
ret = regmap_write(data->regmap, ADXL345_REG_DATA_FORMAT,
|
||||||
data->data_range);
|
data->data_range);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return dev_err_probe(dev, ret, "Failed to set data range\n");
|
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->info = &adxl345_info;
|
||||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||||
indio_dev->channels = adxl345_channels;
|
indio_dev->channels = adxl345_channels;
|
||||||
|
@ -30,22 +30,32 @@ static int adxl345_i2c_probe(struct i2c_client *client)
|
|||||||
return adxl345_core_probe(&client->dev, regmap);
|
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[] = {
|
static const struct i2c_device_id adxl345_i2c_id[] = {
|
||||||
{ "adxl345", ADXL345 },
|
{ "adxl345", (kernel_ulong_t)&adxl345_i2c_info },
|
||||||
{ "adxl375", ADXL375 },
|
{ "adxl375", (kernel_ulong_t)&adxl375_i2c_info },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, adxl345_i2c_id);
|
MODULE_DEVICE_TABLE(i2c, adxl345_i2c_id);
|
||||||
|
|
||||||
static const struct of_device_id adxl345_of_match[] = {
|
static const struct of_device_id adxl345_of_match[] = {
|
||||||
{ .compatible = "adi,adxl345", .data = (const void *)ADXL345 },
|
{ .compatible = "adi,adxl345", .data = &adxl345_i2c_info },
|
||||||
{ .compatible = "adi,adxl375", .data = (const void *)ADXL375 },
|
{ .compatible = "adi,adxl375", .data = &adxl375_i2c_info },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, adxl345_of_match);
|
MODULE_DEVICE_TABLE(of, adxl345_of_match);
|
||||||
|
|
||||||
static const struct acpi_device_id adxl345_acpi_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);
|
MODULE_DEVICE_TABLE(acpi, adxl345_acpi_match);
|
||||||
|
@ -36,22 +36,32 @@ static int adxl345_spi_probe(struct spi_device *spi)
|
|||||||
return adxl345_core_probe(&spi->dev, regmap);
|
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[] = {
|
static const struct spi_device_id adxl345_spi_id[] = {
|
||||||
{ "adxl345", ADXL345 },
|
{ "adxl345", (kernel_ulong_t)&adxl345_spi_info },
|
||||||
{ "adxl375", ADXL375 },
|
{ "adxl375", (kernel_ulong_t)&adxl375_spi_info },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(spi, adxl345_spi_id);
|
MODULE_DEVICE_TABLE(spi, adxl345_spi_id);
|
||||||
|
|
||||||
static const struct of_device_id adxl345_of_match[] = {
|
static const struct of_device_id adxl345_of_match[] = {
|
||||||
{ .compatible = "adi,adxl345", .data = (const void *)ADXL345 },
|
{ .compatible = "adi,adxl345", .data = &adxl345_spi_info },
|
||||||
{ .compatible = "adi,adxl375", .data = (const void *)ADXL375 },
|
{ .compatible = "adi,adxl375", .data = &adxl375_spi_info },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, adxl345_of_match);
|
MODULE_DEVICE_TABLE(of, adxl345_of_match);
|
||||||
|
|
||||||
static const struct acpi_device_id adxl345_acpi_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);
|
MODULE_DEVICE_TABLE(acpi, adxl345_acpi_match);
|
||||||
|
@ -926,7 +926,6 @@ static int bma180_probe(struct i2c_client *client)
|
|||||||
struct device *dev = &client->dev;
|
struct device *dev = &client->dev;
|
||||||
struct bma180_data *data;
|
struct bma180_data *data;
|
||||||
struct iio_dev *indio_dev;
|
struct iio_dev *indio_dev;
|
||||||
enum chip_ids chip;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
|
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);
|
data = iio_priv(indio_dev);
|
||||||
i2c_set_clientdata(client, indio_dev);
|
i2c_set_clientdata(client, indio_dev);
|
||||||
data->client = client;
|
data->client = client;
|
||||||
if (client->dev.of_node)
|
data->part_info = i2c_get_match_data(client);
|
||||||
chip = (uintptr_t)of_device_get_match_data(dev);
|
|
||||||
else
|
|
||||||
chip = id->driver_data;
|
|
||||||
data->part_info = &bma180_part_info[chip];
|
|
||||||
|
|
||||||
ret = iio_read_mount_matrix(dev, &data->orientation);
|
ret = iio_read_mount_matrix(dev, &data->orientation);
|
||||||
if (ret)
|
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 DEFINE_SIMPLE_DEV_PM_OPS(bma180_pm_ops, bma180_suspend, bma180_resume);
|
||||||
|
|
||||||
static const struct i2c_device_id bma180_ids[] = {
|
static const struct i2c_device_id bma180_ids[] = {
|
||||||
{ "bma023", BMA023 },
|
{ "bma023", (kernel_ulong_t)&bma180_part_info[BMA023] },
|
||||||
{ "bma150", BMA150 },
|
{ "bma150", (kernel_ulong_t)&bma180_part_info[BMA150] },
|
||||||
{ "bma180", BMA180 },
|
{ "bma180", (kernel_ulong_t)&bma180_part_info[BMA180] },
|
||||||
{ "bma250", BMA250 },
|
{ "bma250", (kernel_ulong_t)&bma180_part_info[BMA250] },
|
||||||
{ "smb380", BMA150 },
|
{ "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[] = {
|
static const struct of_device_id bma180_of_match[] = {
|
||||||
{
|
{
|
||||||
.compatible = "bosch,bma023",
|
.compatible = "bosch,bma023",
|
||||||
.data = (void *)BMA023
|
.data = &bma180_part_info[BMA023]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.compatible = "bosch,bma150",
|
.compatible = "bosch,bma150",
|
||||||
.data = (void *)BMA150
|
.data = &bma180_part_info[BMA150]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.compatible = "bosch,bma180",
|
.compatible = "bosch,bma180",
|
||||||
.data = (void *)BMA180
|
.data = &bma180_part_info[BMA180]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.compatible = "bosch,bma250",
|
.compatible = "bosch,bma250",
|
||||||
.data = (void *)BMA250
|
.data = &bma180_part_info[BMA250]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.compatible = "bosch,smb380",
|
.compatible = "bosch,smb380",
|
||||||
.data = (void *)BMA150
|
.data = &bma180_part_info[BMA150]
|
||||||
},
|
},
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
@ -14,7 +14,6 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int fxls8962af_core_probe(struct device *dev, struct regmap *regmap, int irq);
|
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 dev_pm_ops fxls8962af_pm_ops;
|
||||||
extern const struct regmap_config fxls8962af_i2c_regmap_conf;
|
extern const struct regmap_config fxls8962af_i2c_regmap_conf;
|
||||||
|
@ -422,7 +422,7 @@ error_remove_trigger:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Function to deinitialize the processing for usage id */
|
/* 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 hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
|
||||||
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
|
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);
|
sensor_hub_remove_callback(hsdev, hsdev->usage);
|
||||||
iio_device_unregister(indio_dev);
|
iio_device_unregister(indio_dev);
|
||||||
hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes);
|
hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct platform_device_id hid_accel_3d_ids[] = {
|
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,
|
.pm = &hid_sensor_pm_ops,
|
||||||
},
|
},
|
||||||
.probe = hid_accel_3d_probe,
|
.probe = hid_accel_3d_probe,
|
||||||
.remove = hid_accel_3d_remove,
|
.remove_new = hid_accel_3d_remove,
|
||||||
};
|
};
|
||||||
module_platform_driver(hid_accel_3d_platform_driver);
|
module_platform_driver(hid_accel_3d_platform_driver);
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 ROHM Semiconductors
|
* Copyright (C) 2022 ROHM Semiconductors
|
||||||
*
|
*
|
||||||
* ROHM/KIONIX KX022A accelerometer driver
|
* ROHM/KIONIX accelerometer driver
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
@ -15,6 +15,7 @@
|
|||||||
static int kx022a_i2c_probe(struct i2c_client *i2c)
|
static int kx022a_i2c_probe(struct i2c_client *i2c)
|
||||||
{
|
{
|
||||||
struct device *dev = &i2c->dev;
|
struct device *dev = &i2c->dev;
|
||||||
|
const struct kx022a_chip_info *chip_info;
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
|
|
||||||
if (!i2c->irq) {
|
if (!i2c->irq) {
|
||||||
@ -22,16 +23,30 @@ static int kx022a_i2c_probe(struct i2c_client *i2c)
|
|||||||
return -EINVAL;
|
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))
|
if (IS_ERR(regmap))
|
||||||
return dev_err_probe(dev, PTR_ERR(regmap),
|
return dev_err_probe(dev, PTR_ERR(regmap),
|
||||||
"Failed to initialize Regmap\n");
|
"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[] = {
|
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);
|
MODULE_DEVICE_TABLE(of, kx022a_of_match);
|
||||||
@ -43,6 +58,7 @@ static struct i2c_driver kx022a_i2c_driver = {
|
|||||||
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
|
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
|
||||||
},
|
},
|
||||||
.probe = kx022a_i2c_probe,
|
.probe = kx022a_i2c_probe,
|
||||||
|
.id_table = kx022a_i2c_id,
|
||||||
};
|
};
|
||||||
module_i2c_driver(kx022a_i2c_driver);
|
module_i2c_driver(kx022a_i2c_driver);
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 ROHM Semiconductors
|
* Copyright (C) 2022 ROHM Semiconductors
|
||||||
*
|
*
|
||||||
* ROHM/KIONIX KX022A accelerometer driver
|
* ROHM/KIONIX accelerometer driver
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
@ -15,6 +15,7 @@
|
|||||||
static int kx022a_spi_probe(struct spi_device *spi)
|
static int kx022a_spi_probe(struct spi_device *spi)
|
||||||
{
|
{
|
||||||
struct device *dev = &spi->dev;
|
struct device *dev = &spi->dev;
|
||||||
|
const struct kx022a_chip_info *chip_info;
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
|
|
||||||
if (!spi->irq) {
|
if (!spi->irq) {
|
||||||
@ -22,22 +23,30 @@ static int kx022a_spi_probe(struct spi_device *spi)
|
|||||||
return -EINVAL;
|
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))
|
if (IS_ERR(regmap))
|
||||||
return dev_err_probe(dev, PTR_ERR(regmap),
|
return dev_err_probe(dev, PTR_ERR(regmap),
|
||||||
"Failed to initialize Regmap\n");
|
"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[] = {
|
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);
|
MODULE_DEVICE_TABLE(spi, kx022a_id);
|
||||||
|
|
||||||
static const struct of_device_id kx022a_of_match[] = {
|
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);
|
MODULE_DEVICE_TABLE(of, kx022a_of_match);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 ROHM Semiconductors
|
* Copyright (C) 2022 ROHM Semiconductors
|
||||||
*
|
*
|
||||||
* ROHM/KIONIX KX022A accelerometer driver
|
* ROHM/KIONIX accelerometer driver
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
@ -15,7 +15,7 @@
|
|||||||
#include <linux/regmap.h>
|
#include <linux/regmap.h>
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/string_helpers.h>
|
#include <linux/string_choices.h>
|
||||||
#include <linux/units.h>
|
#include <linux/units.h>
|
||||||
|
|
||||||
#include <linux/iio/iio.h>
|
#include <linux/iio/iio.h>
|
||||||
@ -48,7 +48,7 @@ enum {
|
|||||||
KX022A_STATE_FIFO,
|
KX022A_STATE_FIFO,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Regmap configs */
|
/* kx022a Regmap configs */
|
||||||
static const struct regmap_range kx022a_volatile_ranges[] = {
|
static const struct regmap_range kx022a_volatile_ranges[] = {
|
||||||
{
|
{
|
||||||
.range_min = KX022A_REG_XHP_L,
|
.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),
|
.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,
|
.reg_bits = 8,
|
||||||
.val_bits = 8,
|
.val_bits = 8,
|
||||||
.volatile_table = &kx022a_volatile_regs,
|
.volatile_table = &kx022a_volatile_regs,
|
||||||
@ -149,10 +149,121 @@ const struct regmap_config kx022a_regmap = {
|
|||||||
.max_register = KX022A_MAX_REGISTER,
|
.max_register = KX022A_MAX_REGISTER,
|
||||||
.cache_type = REGCACHE_RBTREE,
|
.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 kx022a_data {
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
|
const struct kx022a_chip_info *chip_info;
|
||||||
struct iio_trigger *trig;
|
struct iio_trigger *trig;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct iio_mount_matrix orientation;
|
struct iio_mount_matrix orientation;
|
||||||
@ -175,6 +286,8 @@ struct kx022a_data {
|
|||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
u8 watermark;
|
u8 watermark;
|
||||||
|
|
||||||
|
__le16 *fifo_buffer;
|
||||||
|
|
||||||
/* 3 x 16bit accel data + timestamp */
|
/* 3 x 16bit accel data + timestamp */
|
||||||
__le16 buffer[8] __aligned(IIO_DMA_MINALIGN);
|
__le16 buffer[8] __aligned(IIO_DMA_MINALIGN);
|
||||||
struct {
|
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, \
|
.type = IIO_ACCEL, \
|
||||||
.modified = 1, \
|
.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_SCALE) | \
|
||||||
BIT(IIO_CHAN_INFO_SAMP_FREQ), \
|
BIT(IIO_CHAN_INFO_SAMP_FREQ), \
|
||||||
.ext_info = kx022a_ext_info, \
|
.ext_info = kx022a_ext_info, \
|
||||||
.address = KX022A_REG_##axis##OUT_L, \
|
.address = reg, \
|
||||||
.scan_index = index, \
|
.scan_index = index, \
|
||||||
.scan_type = { \
|
.scan_type = { \
|
||||||
.sign = 's', \
|
.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[] = {
|
static const struct iio_chan_spec kx022a_channels[] = {
|
||||||
KX022A_ACCEL_CHAN(X, 0),
|
KX022A_ACCEL_CHAN(X, KX022A_REG_XOUT_L, 0),
|
||||||
KX022A_ACCEL_CHAN(Y, 1),
|
KX022A_ACCEL_CHAN(Y, KX022A_REG_YOUT_L, 1),
|
||||||
KX022A_ACCEL_CHAN(Z, 2),
|
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),
|
IIO_CHAN_SOFT_TIMESTAMP(3),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -332,16 +452,15 @@ static int kx022a_turn_on_off_unlocked(struct kx022a_data *data, bool on)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (on)
|
if (on)
|
||||||
ret = regmap_set_bits(data->regmap, KX022A_REG_CNTL,
|
ret = regmap_set_bits(data->regmap, data->chip_info->cntl,
|
||||||
KX022A_MASK_PC1);
|
KX022A_MASK_PC1);
|
||||||
else
|
else
|
||||||
ret = regmap_clear_bits(data->regmap, KX022A_REG_CNTL,
|
ret = regmap_clear_bits(data->regmap, data->chip_info->cntl,
|
||||||
KX022A_MASK_PC1);
|
KX022A_MASK_PC1);
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_err(data->dev, "Turn %s fail %d\n", str_on_off(on), ret);
|
dev_err(data->dev, "Turn %s fail %d\n", str_on_off(on), ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kx022a_turn_off_lock(struct kx022a_data *data)
|
static int kx022a_turn_off_lock(struct kx022a_data *data)
|
||||||
@ -403,7 +522,7 @@ static int kx022a_write_raw(struct iio_dev *idev,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
ret = regmap_update_bits(data->regmap,
|
ret = regmap_update_bits(data->regmap,
|
||||||
KX022A_REG_ODCNTL,
|
data->chip_info->odcntl,
|
||||||
KX022A_MASK_ODR, n);
|
KX022A_MASK_ODR, n);
|
||||||
data->odr_ns = kx022a_odrs[n];
|
data->odr_ns = kx022a_odrs[n];
|
||||||
kx022a_turn_on_unlock(data);
|
kx022a_turn_on_unlock(data);
|
||||||
@ -424,7 +543,7 @@ static int kx022a_write_raw(struct iio_dev *idev,
|
|||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ret = regmap_update_bits(data->regmap, KX022A_REG_CNTL,
|
ret = regmap_update_bits(data->regmap, data->chip_info->cntl,
|
||||||
KX022A_MASK_GSEL,
|
KX022A_MASK_GSEL,
|
||||||
n << KX022A_GSEL_SHIFT);
|
n << KX022A_GSEL_SHIFT);
|
||||||
kx022a_turn_on_unlock(data);
|
kx022a_turn_on_unlock(data);
|
||||||
@ -446,7 +565,7 @@ static int kx022a_fifo_set_wmi(struct kx022a_data *data)
|
|||||||
|
|
||||||
threshold = data->watermark;
|
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);
|
KX022A_MASK_WM_TH, threshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,7 +608,7 @@ static int kx022a_read_raw(struct iio_dev *idev,
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||||
ret = regmap_read(data->regmap, KX022A_REG_ODCNTL, ®val);
|
ret = regmap_read(data->regmap, data->chip_info->odcntl, ®val);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -504,7 +623,7 @@ static int kx022a_read_raw(struct iio_dev *idev,
|
|||||||
return IIO_VAL_INT_PLUS_MICRO;
|
return IIO_VAL_INT_PLUS_MICRO;
|
||||||
|
|
||||||
case IIO_CHAN_INFO_SCALE:
|
case IIO_CHAN_INFO_SCALE:
|
||||||
ret = regmap_read(data->regmap, KX022A_REG_CNTL, ®val);
|
ret = regmap_read(data->regmap, data->chip_info->cntl, ®val);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
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);
|
struct kx022a_data *data = iio_priv(idev);
|
||||||
|
|
||||||
if (val > KX022A_FIFO_LENGTH)
|
val = min(data->chip_info->fifo_length, val);
|
||||||
val = KX022A_FIFO_LENGTH;
|
|
||||||
|
|
||||||
mutex_lock(&data->mutex);
|
mutex_lock(&data->mutex);
|
||||||
data->watermark = val;
|
data->watermark = val;
|
||||||
@ -582,30 +700,56 @@ static int kx022a_drop_fifo_contents(struct kx022a_data *data)
|
|||||||
*/
|
*/
|
||||||
data->timestamp = 0;
|
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,
|
static int __kx022a_fifo_flush(struct iio_dev *idev, unsigned int samples,
|
||||||
bool irq)
|
bool irq)
|
||||||
{
|
{
|
||||||
struct kx022a_data *data = iio_priv(idev);
|
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;
|
uint64_t sample_period;
|
||||||
int count, fifo_bytes;
|
int count, fifo_bytes;
|
||||||
bool renable = false;
|
bool renable = false;
|
||||||
int64_t tstamp;
|
int64_t tstamp;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
ret = regmap_read(data->regmap, KX022A_REG_BUF_STATUS_1, &fifo_bytes);
|
fifo_bytes = data->chip_info->get_fifo_bytes_available(data);
|
||||||
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;
|
|
||||||
|
|
||||||
if (fifo_bytes % KX022A_FIFO_SAMPLES_SIZE_BYTES)
|
if (fifo_bytes % KX022A_FIFO_SAMPLES_SIZE_BYTES)
|
||||||
dev_warn(data->dev, "Bad FIFO alignment. Data may be corrupt\n");
|
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;
|
fifo_bytes = count * KX022A_FIFO_SAMPLES_SIZE_BYTES;
|
||||||
ret = regmap_noinc_read(data->regmap, KX022A_REG_BUF_READ,
|
ret = regmap_noinc_read(data->regmap, data->chip_info->buf_read,
|
||||||
&buffer[0], fifo_bytes);
|
data->fifo_buffer, fifo_bytes);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto renable_out;
|
goto renable_out;
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
__le16 *sam = &buffer[i * 3];
|
__le16 *sam = &data->fifo_buffer[i * 3];
|
||||||
__le16 *chs;
|
__le16 *chs;
|
||||||
int bit;
|
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)
|
static int kx022a_set_drdy_irq(struct kx022a_data *data, bool en)
|
||||||
{
|
{
|
||||||
if (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);
|
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);
|
KX022A_MASK_DRDY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -760,7 +904,7 @@ static int kx022a_fifo_disable(struct kx022a_data *data)
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto unlock_out;
|
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);
|
KX022A_MASK_BUF_EN);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto unlock_out;
|
goto unlock_out;
|
||||||
@ -769,6 +913,8 @@ static int kx022a_fifo_disable(struct kx022a_data *data)
|
|||||||
|
|
||||||
kx022a_drop_fifo_contents(data);
|
kx022a_drop_fifo_contents(data);
|
||||||
|
|
||||||
|
kfree(data->fifo_buffer);
|
||||||
|
|
||||||
return kx022a_turn_on_unlock(data);
|
return kx022a_turn_on_unlock(data);
|
||||||
|
|
||||||
unlock_out:
|
unlock_out:
|
||||||
@ -791,6 +937,12 @@ static int kx022a_fifo_enable(struct kx022a_data *data)
|
|||||||
{
|
{
|
||||||
int ret;
|
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);
|
ret = kx022a_turn_off_lock(data);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@ -801,7 +953,7 @@ static int kx022a_fifo_enable(struct kx022a_data *data)
|
|||||||
goto unlock_out;
|
goto unlock_out;
|
||||||
|
|
||||||
/* Enable buffer */
|
/* 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);
|
KX022A_MASK_BUF_EN);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto unlock_out;
|
goto unlock_out;
|
||||||
@ -847,7 +999,7 @@ static irqreturn_t kx022a_trigger_handler(int irq, void *p)
|
|||||||
struct kx022a_data *data = iio_priv(idev);
|
struct kx022a_data *data = iio_priv(idev);
|
||||||
int ret;
|
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);
|
KX022A_FIFO_SAMPLES_SIZE_BYTES);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err_read;
|
goto err_read;
|
||||||
@ -895,7 +1047,7 @@ static irqreturn_t kx022a_irq_thread_handler(int irq, void *private)
|
|||||||
if (data->state & KX022A_STATE_FIFO) {
|
if (data->state & KX022A_STATE_FIFO) {
|
||||||
int ok;
|
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)
|
if (ok > 0)
|
||||||
ret = IRQ_HANDLED;
|
ret = IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
@ -948,7 +1100,7 @@ static int kx022a_chip_init(struct kx022a_data *data)
|
|||||||
int ret, val;
|
int ret, val;
|
||||||
|
|
||||||
/* Reset the senor */
|
/* 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)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -958,7 +1110,7 @@ static int kx022a_chip_init(struct kx022a_data *data)
|
|||||||
*/
|
*/
|
||||||
msleep(1);
|
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),
|
!(val & KX022A_MASK_SRST),
|
||||||
KX022A_SOFT_RESET_WAIT_TIME_US,
|
KX022A_SOFT_RESET_WAIT_TIME_US,
|
||||||
KX022A_SOFT_RESET_TOTAL_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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = regmap_reinit_cache(data->regmap, &kx022a_regmap);
|
ret = regmap_reinit_cache(data->regmap, data->chip_info->regmap_config);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(data->dev, "Failed to reinit reg cache\n");
|
dev_err(data->dev, "Failed to reinit reg cache\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set data res 16bit */
|
/* 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);
|
KX022A_MASK_BRES16);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(data->dev, "Failed to set data resolution\n");
|
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);
|
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"};
|
static const char * const regulator_names[] = {"io-vdd", "vdd"};
|
||||||
struct iio_trigger *indio_trig;
|
struct iio_trigger *indio_trig;
|
||||||
@ -1012,6 +1247,7 @@ int kx022a_probe_internal(struct device *dev)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
data = iio_priv(idev);
|
data = iio_priv(idev);
|
||||||
|
data->chip_info = chip_info;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* VDD is the analog and digital domain voltage supply and
|
* 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)
|
if (ret && ret != -ENODEV)
|
||||||
return dev_err_probe(dev, ret, "failed to enable regulator\n");
|
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)
|
if (ret)
|
||||||
return dev_err_probe(dev, ret, "Failed to access sensor\n");
|
return dev_err_probe(dev, ret, "Failed to access sensor\n");
|
||||||
|
|
||||||
if (chip_id != KX022A_ID) {
|
if (chip_id != chip_info->id)
|
||||||
dev_err(dev, "unsupported device 0x%x\n", chip_id);
|
dev_warn(dev, "unknown device 0x%x\n", chip_id);
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
irq = fwnode_irq_get_byname(fwnode, "INT1");
|
irq = fwnode_irq_get_byname(fwnode, "INT1");
|
||||||
if (irq > 0) {
|
if (irq > 0) {
|
||||||
data->inc_reg = KX022A_REG_INC1;
|
data->inc_reg = chip_info->inc1;
|
||||||
data->ien_reg = KX022A_REG_INC4;
|
data->ien_reg = chip_info->inc4;
|
||||||
} else {
|
} else {
|
||||||
irq = fwnode_irq_get_byname(fwnode, "INT2");
|
irq = fwnode_irq_get_byname(fwnode, "INT2");
|
||||||
if (irq < 0)
|
if (irq < 0)
|
||||||
return dev_err_probe(dev, irq, "No suitable IRQ\n");
|
return dev_err_probe(dev, irq, "No suitable IRQ\n");
|
||||||
|
|
||||||
data->inc_reg = KX022A_REG_INC5;
|
data->inc_reg = chip_info->inc5;
|
||||||
data->ien_reg = KX022A_REG_INC6;
|
data->ien_reg = chip_info->inc6;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->regmap = regmap;
|
data->regmap = regmap;
|
||||||
@ -1050,9 +1284,9 @@ int kx022a_probe_internal(struct device *dev)
|
|||||||
data->odr_ns = KX022A_DEFAULT_PERIOD_NS;
|
data->odr_ns = KX022A_DEFAULT_PERIOD_NS;
|
||||||
mutex_init(&data->mutex);
|
mutex_init(&data->mutex);
|
||||||
|
|
||||||
idev->channels = kx022a_channels;
|
idev->channels = chip_info->channels;
|
||||||
idev->num_channels = ARRAY_SIZE(kx022a_channels);
|
idev->num_channels = chip_info->num_channels;
|
||||||
idev->name = "kx022-accel";
|
idev->name = chip_info->name;
|
||||||
idev->info = &kx022a_info;
|
idev->info = &kx022a_info;
|
||||||
idev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
|
idev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
|
||||||
idev->available_scan_masks = kx022a_scan_masks;
|
idev->available_scan_masks = kx022a_scan_masks;
|
||||||
@ -1110,7 +1344,6 @@ int kx022a_probe_internal(struct device *dev)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return dev_err_probe(data->dev, ret, "Could not request IRQ\n");
|
return dev_err_probe(data->dev, ret, "Could not request IRQ\n");
|
||||||
|
|
||||||
|
|
||||||
ret = devm_iio_trigger_register(dev, indio_trig);
|
ret = devm_iio_trigger_register(dev, indio_trig);
|
||||||
if (ret)
|
if (ret)
|
||||||
return dev_err_probe(data->dev, ret,
|
return dev_err_probe(data->dev, ret,
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#define KX022A_REG_WHO 0x0f
|
#define KX022A_REG_WHO 0x0f
|
||||||
#define KX022A_ID 0xc8
|
#define KX022A_ID 0xc8
|
||||||
|
#define KX132ACR_LBZ_ID 0xd8
|
||||||
|
|
||||||
#define KX022A_REG_CNTL2 0x19
|
#define KX022A_REG_CNTL2 0x19
|
||||||
#define KX022A_MASK_SRST BIT(7)
|
#define KX022A_MASK_SRST BIT(7)
|
||||||
@ -74,9 +75,118 @@
|
|||||||
#define KX022A_REG_SELF_TEST 0x60
|
#define KX022A_REG_SELF_TEST 0x60
|
||||||
#define KX022A_MAX_REGISTER 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;
|
struct device;
|
||||||
|
|
||||||
int kx022a_probe_internal(struct device *dev);
|
struct kx022a_data;
|
||||||
extern const struct regmap_config kx022a_regmap;
|
|
||||||
|
/**
|
||||||
|
* 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
|
#endif
|
||||||
|
@ -1535,19 +1535,18 @@ static int mma8452_reset(struct i2c_client *client)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id mma8452_dt_ids[] = {
|
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,mma8451", .data = &mma_chip_info_table[mma8451] },
|
||||||
{ .compatible = "fsl,mma8452", .data = &mma_chip_info_table[mma8452] },
|
{ .compatible = "fsl,mma8452", .data = &mma_chip_info_table[mma8452] },
|
||||||
{ .compatible = "fsl,mma8453", .data = &mma_chip_info_table[mma8453] },
|
{ .compatible = "fsl,mma8453", .data = &mma_chip_info_table[mma8453] },
|
||||||
{ .compatible = "fsl,mma8652", .data = &mma_chip_info_table[mma8652] },
|
{ .compatible = "fsl,mma8652", .data = &mma_chip_info_table[mma8652] },
|
||||||
{ .compatible = "fsl,mma8653", .data = &mma_chip_info_table[mma8653] },
|
{ .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);
|
MODULE_DEVICE_TABLE(of, mma8452_dt_ids);
|
||||||
|
|
||||||
static int mma8452_probe(struct i2c_client *client)
|
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 mma8452_data *data;
|
||||||
struct iio_dev *indio_dev;
|
struct iio_dev *indio_dev;
|
||||||
int ret;
|
int ret;
|
||||||
@ -1560,15 +1559,10 @@ static int mma8452_probe(struct i2c_client *client)
|
|||||||
data->client = client;
|
data->client = client;
|
||||||
mutex_init(&data->lock);
|
mutex_init(&data->lock);
|
||||||
|
|
||||||
data->chip_info = device_get_match_data(&client->dev);
|
data->chip_info = i2c_get_match_data(client);
|
||||||
if (!data->chip_info) {
|
if (!data->chip_info)
|
||||||
if (id) {
|
return dev_err_probe(&client->dev, -ENODEV,
|
||||||
data->chip_info = &mma_chip_info_table[id->driver_data];
|
"unknown device model\n");
|
||||||
} else {
|
|
||||||
dev_err(&client->dev, "unknown device model\n");
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = iio_read_mount_matrix(&client->dev, &data->orientation);
|
ret = iio_read_mount_matrix(&client->dev, &data->orientation);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -1830,12 +1824,12 @@ static const struct dev_pm_ops mma8452_pm_ops = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct i2c_device_id mma8452_id[] = {
|
static const struct i2c_device_id mma8452_id[] = {
|
||||||
{ "mma8451", mma8451 },
|
{ "fxls8471", (kernel_ulong_t)&mma_chip_info_table[fxls8471] },
|
||||||
{ "mma8452", mma8452 },
|
{ "mma8451", (kernel_ulong_t)&mma_chip_info_table[mma8451] },
|
||||||
{ "mma8453", mma8453 },
|
{ "mma8452", (kernel_ulong_t)&mma_chip_info_table[mma8452] },
|
||||||
{ "mma8652", mma8652 },
|
{ "mma8453", (kernel_ulong_t)&mma_chip_info_table[mma8453] },
|
||||||
{ "mma8653", mma8653 },
|
{ "mma8652", (kernel_ulong_t)&mma_chip_info_table[mma8652] },
|
||||||
{ "fxls8471", fxls8471 },
|
{ "mma8653", (kernel_ulong_t)&mma_chip_info_table[mma8653] },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, mma8452_id);
|
MODULE_DEVICE_TABLE(i2c, mma8452_id);
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
#include <linux/pm.h>
|
#include <linux/pm.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/regmap.h>
|
#include <linux/regmap.h>
|
||||||
#include <linux/string_helpers.h>
|
#include <linux/string_choices.h>
|
||||||
#include <linux/units.h>
|
#include <linux/units.h>
|
||||||
|
|
||||||
#include <linux/iio/buffer.h>
|
#include <linux/iio/buffer.h>
|
||||||
|
@ -476,6 +476,13 @@ static const struct acpi_device_id mxc4005_acpi_match[] = {
|
|||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(acpi, 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[] = {
|
static const struct i2c_device_id mxc4005_id[] = {
|
||||||
{"mxc4005", 0},
|
{"mxc4005", 0},
|
||||||
{"mxc6655", 0},
|
{"mxc6655", 0},
|
||||||
@ -487,6 +494,7 @@ static struct i2c_driver mxc4005_driver = {
|
|||||||
.driver = {
|
.driver = {
|
||||||
.name = MXC4005_DRV_NAME,
|
.name = MXC4005_DRV_NAME,
|
||||||
.acpi_match_table = ACPI_PTR(mxc4005_acpi_match),
|
.acpi_match_table = ACPI_PTR(mxc4005_acpi_match),
|
||||||
|
.of_match_table = mxc4005_of_match,
|
||||||
},
|
},
|
||||||
.probe = mxc4005_probe,
|
.probe = mxc4005_probe,
|
||||||
.id_table = mxc4005_id,
|
.id_table = mxc4005_id,
|
||||||
|
@ -607,6 +607,16 @@ config LPC32XX_ADC
|
|||||||
activate only one via device tree selection. Provides direct access
|
activate only one via device tree selection. Provides direct access
|
||||||
via sysfs.
|
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
|
config LTC2471
|
||||||
tristate "Linear Technology LTC2471 and LTC2473 ADC driver"
|
tristate "Linear Technology LTC2471 and LTC2473 ADC driver"
|
||||||
depends on I2C
|
depends on I2C
|
||||||
@ -779,14 +789,29 @@ config MCP3422
|
|||||||
This driver can also be built as a module. If so, the module will be
|
This driver can also be built as a module. If so, the module will be
|
||||||
called mcp3422.
|
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
|
config MCP3911
|
||||||
tristate "Microchip Technology MCP3911 driver"
|
tristate "Microchip Technology MCP3911 driver"
|
||||||
depends on SPI
|
depends on SPI
|
||||||
select IIO_BUFFER
|
select IIO_BUFFER
|
||||||
select IIO_TRIGGERED_BUFFER
|
select IIO_TRIGGERED_BUFFER
|
||||||
help
|
help
|
||||||
Say yes here to build support for Microchip Technology's MCP3911
|
Say yes here to build support for one of the following
|
||||||
analog to digital converter.
|
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
|
This driver can also be built as a module. If so, the module will be
|
||||||
called mcp3911.
|
called mcp3911.
|
||||||
|
@ -56,6 +56,7 @@ obj-$(CONFIG_INTEL_MRFLD_ADC) += intel_mrfld_adc.o
|
|||||||
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
|
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
|
||||||
obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
|
obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
|
||||||
obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
|
obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
|
||||||
|
obj-$(CONFIG_LTC2309) += ltc2309.o
|
||||||
obj-$(CONFIG_LTC2471) += ltc2471.o
|
obj-$(CONFIG_LTC2471) += ltc2471.o
|
||||||
obj-$(CONFIG_LTC2485) += ltc2485.o
|
obj-$(CONFIG_LTC2485) += ltc2485.o
|
||||||
obj-$(CONFIG_LTC2496) += ltc2496.o ltc2497-core.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_MAX9611) += max9611.o
|
||||||
obj-$(CONFIG_MCP320X) += mcp320x.o
|
obj-$(CONFIG_MCP320X) += mcp320x.o
|
||||||
obj-$(CONFIG_MCP3422) += mcp3422.o
|
obj-$(CONFIG_MCP3422) += mcp3422.o
|
||||||
|
obj-$(CONFIG_MCP3564) += mcp3564.o
|
||||||
obj-$(CONFIG_MCP3911) += mcp3911.o
|
obj-$(CONFIG_MCP3911) += mcp3911.o
|
||||||
obj-$(CONFIG_MEDIATEK_MT6360_ADC) += mt6360-adc.o
|
obj-$(CONFIG_MEDIATEK_MT6360_ADC) += mt6360-adc.o
|
||||||
obj-$(CONFIG_MEDIATEK_MT6370_ADC) += mt6370-adc.o
|
obj-$(CONFIG_MEDIATEK_MT6370_ADC) += mt6370-adc.o
|
||||||
|
@ -1179,7 +1179,7 @@ out_dis_pm:
|
|||||||
return ret;
|
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 iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct ab8500_gpadc *gpadc = iio_priv(indio_dev);
|
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_put_noidle(gpadc->dev);
|
||||||
pm_runtime_disable(gpadc->dev);
|
pm_runtime_disable(gpadc->dev);
|
||||||
regulator_disable(gpadc->vddadc);
|
regulator_disable(gpadc->vddadc);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEFINE_RUNTIME_DEV_PM_OPS(ab8500_gpadc_pm_ops,
|
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 = {
|
static struct platform_driver ab8500_gpadc_driver = {
|
||||||
.probe = ab8500_gpadc_probe,
|
.probe = ab8500_gpadc_probe,
|
||||||
.remove = ab8500_gpadc_remove,
|
.remove_new = ab8500_gpadc_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "ab8500-gpadc",
|
.name = "ab8500-gpadc",
|
||||||
.pm = pm_ptr(&ab8500_gpadc_pm_ops),
|
.pm = pm_ptr(&ab8500_gpadc_pm_ops),
|
||||||
|
@ -1817,18 +1817,12 @@ static const struct clk_ops ad4130_int_clk_ops = {
|
|||||||
.unprepare = ad4130_int_clk_unprepare,
|
.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)
|
static int ad4130_setup_int_clk(struct ad4130_state *st)
|
||||||
{
|
{
|
||||||
struct device *dev = &st->spi->dev;
|
struct device *dev = &st->spi->dev;
|
||||||
struct device_node *of_node = dev_of_node(dev);
|
struct device_node *of_node = dev_of_node(dev);
|
||||||
struct clk_init_data init;
|
struct clk_init_data init;
|
||||||
const char *clk_name;
|
const char *clk_name;
|
||||||
struct clk *clk;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (st->int_pin_sel == AD4130_INT_PIN_CLK ||
|
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;
|
init.ops = &ad4130_int_clk_ops;
|
||||||
|
|
||||||
st->int_clk_hw.init = &init;
|
st->int_clk_hw.init = &init;
|
||||||
clk = devm_clk_register(dev, &st->int_clk_hw);
|
ret = devm_clk_hw_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);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return 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)
|
static int ad4130_setup(struct iio_dev *indio_dev)
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/bitfield.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
@ -43,7 +44,7 @@
|
|||||||
#define AD7192_COMM_WEN BIT(7) /* Write Enable */
|
#define AD7192_COMM_WEN BIT(7) /* Write Enable */
|
||||||
#define AD7192_COMM_WRITE 0 /* Write Operation */
|
#define AD7192_COMM_WRITE 0 /* Write Operation */
|
||||||
#define AD7192_COMM_READ BIT(6) /* Read 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 */
|
#define AD7192_COMM_CREAD BIT(2) /* Continuous Read of Data Register */
|
||||||
|
|
||||||
/* Status Register Bit Designations (AD7192_REG_STAT) */
|
/* Status Register Bit Designations (AD7192_REG_STAT) */
|
||||||
@ -56,17 +57,18 @@
|
|||||||
#define AD7192_STAT_CH1 BIT(0) /* Channel 1 */
|
#define AD7192_STAT_CH1 BIT(0) /* Channel 1 */
|
||||||
|
|
||||||
/* Mode Register Bit Designations (AD7192_REG_MODE) */
|
/* Mode Register Bit Designations (AD7192_REG_MODE) */
|
||||||
#define AD7192_MODE_SEL(x) (((x) & 0x7) << 21) /* Operation Mode Select */
|
#define AD7192_MODE_SEL_MASK GENMASK(23, 21) /* Operation Mode Select Mask */
|
||||||
#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_STA_MASK BIT(20) /* Status Register transmission 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_SINC3 BIT(15) /* SINC3 Filter Select */
|
||||||
#define AD7192_MODE_ENPAR BIT(13) /* Parity Enable */
|
#define AD7192_MODE_ENPAR BIT(13) /* Parity Enable */
|
||||||
#define AD7192_MODE_CLKDIV BIT(12) /* Clock divide by 2 (AD7190/2 only)*/
|
#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_SCYCLE BIT(11) /* Single cycle conversion */
|
||||||
#define AD7192_MODE_REJ60 BIT(10) /* 50/60Hz notch filter */
|
#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 */
|
/* Mode Register: AD7192_MODE_SEL options */
|
||||||
#define AD7192_MODE_CONT 0 /* Continuous Conversion Mode */
|
#define AD7192_MODE_CONT 0 /* Continuous Conversion Mode */
|
||||||
@ -92,13 +94,12 @@
|
|||||||
#define AD7192_CONF_CHOP BIT(23) /* CHOP enable */
|
#define AD7192_CONF_CHOP BIT(23) /* CHOP enable */
|
||||||
#define AD7192_CONF_ACX BIT(22) /* AC excitation enable(AD7195 only) */
|
#define AD7192_CONF_ACX BIT(22) /* AC excitation enable(AD7195 only) */
|
||||||
#define AD7192_CONF_REFSEL BIT(20) /* REFIN1/REFIN2 Reference Select */
|
#define AD7192_CONF_REFSEL BIT(20) /* REFIN1/REFIN2 Reference Select */
|
||||||
#define AD7192_CONF_CHAN(x) ((x) << 8) /* Channel select */
|
#define AD7192_CONF_CHAN_MASK GENMASK(18, 8) /* Channel select mask */
|
||||||
#define AD7192_CONF_CHAN_MASK (0x7FF << 8) /* Channel select mask */
|
|
||||||
#define AD7192_CONF_BURN BIT(7) /* Burnout current enable */
|
#define AD7192_CONF_BURN BIT(7) /* Burnout current enable */
|
||||||
#define AD7192_CONF_REFDET BIT(6) /* Reference detect enable */
|
#define AD7192_CONF_REFDET BIT(6) /* Reference detect enable */
|
||||||
#define AD7192_CONF_BUF BIT(4) /* Buffered Mode Enable */
|
#define AD7192_CONF_BUF BIT(4) /* Buffered Mode Enable */
|
||||||
#define AD7192_CONF_UNIPOLAR BIT(3) /* Unipolar/Bipolar 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_AIN1P_AIN2M BIT(0) /* AIN1(+) - AIN2(-) */
|
||||||
#define AD7192_CH_AIN3P_AIN4M BIT(1) /* AIN3(+) - AIN4(-) */
|
#define AD7192_CH_AIN3P_AIN4M BIT(1) /* AIN3(+) - AIN4(-) */
|
||||||
@ -130,7 +131,7 @@
|
|||||||
#define CHIPID_AD7192 0x0
|
#define CHIPID_AD7192 0x0
|
||||||
#define CHIPID_AD7193 0x2
|
#define CHIPID_AD7193 0x2
|
||||||
#define CHIPID_AD7195 0x6
|
#define CHIPID_AD7195 0x6
|
||||||
#define AD7192_ID_MASK 0x0F
|
#define AD7192_ID_MASK GENMASK(3, 0)
|
||||||
|
|
||||||
/* GPOCON Register Bit Designations (AD7192_REG_GPOCON) */
|
/* GPOCON Register Bit Designations (AD7192_REG_GPOCON) */
|
||||||
#define AD7192_GPOCON_BPDSW BIT(6) /* Bridge power-down switch enable */
|
#define AD7192_GPOCON_BPDSW BIT(6) /* Bridge power-down switch enable */
|
||||||
@ -172,6 +173,9 @@ enum {
|
|||||||
struct ad7192_chip_info {
|
struct ad7192_chip_info {
|
||||||
unsigned int chip_id;
|
unsigned int chip_id;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
const struct iio_chan_spec *channels;
|
||||||
|
u8 num_channels;
|
||||||
|
const struct iio_info *info;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ad7192_state {
|
struct ad7192_state {
|
||||||
@ -181,10 +185,10 @@ struct ad7192_state {
|
|||||||
struct clk *mclk;
|
struct clk *mclk;
|
||||||
u16 int_vref_mv;
|
u16 int_vref_mv;
|
||||||
u32 fclk;
|
u32 fclk;
|
||||||
u32 f_order;
|
|
||||||
u32 mode;
|
u32 mode;
|
||||||
u32 conf;
|
u32 conf;
|
||||||
u32 scale_avail[8][2];
|
u32 scale_avail[8][2];
|
||||||
|
u32 oversampling_ratio_avail[4];
|
||||||
u8 gpocon;
|
u8 gpocon;
|
||||||
u8 clock_sel;
|
u8 clock_sel;
|
||||||
struct mutex lock; /* protect sensor state */
|
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);
|
struct ad7192_state *st = ad_sigma_delta_to_ad7192(sd);
|
||||||
|
|
||||||
st->conf &= ~AD7192_CONF_CHAN_MASK;
|
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);
|
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);
|
struct ad7192_state *st = ad_sigma_delta_to_ad7192(sd);
|
||||||
|
|
||||||
st->mode &= ~AD7192_MODE_SEL_MASK;
|
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);
|
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;
|
int ret;
|
||||||
|
|
||||||
mode &= ~AD7192_MODE_STA_MASK;
|
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);
|
ret = ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, mode);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -400,17 +404,17 @@ static int ad7192_setup(struct iio_dev *indio_dev, struct device_node *np)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
id &= AD7192_ID_MASK;
|
id = FIELD_GET(AD7192_ID_MASK, id);
|
||||||
|
|
||||||
if (id != st->chip_info->chip_id)
|
if (id != st->chip_info->chip_id)
|
||||||
dev_warn(&st->sd.spi->dev, "device ID query failed (0x%X != 0x%X)\n",
|
dev_warn(&st->sd.spi->dev, "device ID query failed (0x%X != 0x%X)\n",
|
||||||
id, st->chip_info->chip_id);
|
id, st->chip_info->chip_id);
|
||||||
|
|
||||||
st->mode = AD7192_MODE_SEL(AD7192_MODE_IDLE) |
|
st->mode = FIELD_PREP(AD7192_MODE_SEL_MASK, AD7192_MODE_IDLE) |
|
||||||
AD7192_MODE_CLKSRC(st->clock_sel) |
|
FIELD_PREP(AD7192_MODE_CLKSRC_MASK, st->clock_sel) |
|
||||||
AD7192_MODE_RATE(480);
|
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");
|
rej60_en = of_property_read_bool(np, "adi,rejection-60-Hz-enable");
|
||||||
if (rej60_en)
|
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_REFSEL;
|
||||||
|
|
||||||
st->conf &= ~AD7192_CONF_CHOP;
|
st->conf &= ~AD7192_CONF_CHOP;
|
||||||
st->f_order = AD7192_NO_SYNC_FILTER;
|
|
||||||
|
|
||||||
buf_en = of_property_read_bool(np, "adi,buffer-enable");
|
buf_en = of_property_read_bool(np, "adi,buffer-enable");
|
||||||
if (buf_en)
|
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++) {
|
for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) {
|
||||||
scale_uv = ((u64)st->int_vref_mv * 100000000)
|
scale_uv = ((u64)st->int_vref_mv * 100000000)
|
||||||
>> (indio_dev->channels[0].scan_type.realbits -
|
>> (indio_dev->channels[0].scan_type.realbits -
|
||||||
((st->conf & AD7192_CONF_UNIPOLAR) ? 0 : 1));
|
!FIELD_GET(AD7192_CONF_UNIPOLAR, st->conf));
|
||||||
scale_uv >>= i;
|
scale_uv >>= i;
|
||||||
|
|
||||||
st->scale_avail[i][1] = do_div(scale_uv, 100000000) * 10;
|
st->scale_avail[i][1] = do_div(scale_uv, 100000000) * 10;
|
||||||
st->scale_avail[i][0] = scale_uv;
|
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;
|
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 iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||||
struct ad7192_state *st = iio_priv(indio_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,
|
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 iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||||
struct ad7192_state *st = iio_priv(indio_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,
|
static ssize_t ad7192_set(struct device *dev,
|
||||||
@ -531,22 +540,66 @@ static ssize_t ad7192_set(struct device *dev,
|
|||||||
return ret ? ret : len;
|
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,
|
static void ad7192_get_available_filter_freq(struct ad7192_state *st,
|
||||||
int *freq)
|
int *freq)
|
||||||
{
|
{
|
||||||
unsigned int fadc;
|
unsigned int fadc;
|
||||||
|
|
||||||
/* Formulas for filter at page 25 of the datasheet */
|
/* Formulas for filter at page 25 of the datasheet */
|
||||||
fadc = DIV_ROUND_CLOSEST(st->fclk,
|
fadc = ad7192_compute_f_adc(st, false, true);
|
||||||
AD7192_SYNC4_FILTER * AD7192_MODE_RATE(st->mode));
|
|
||||||
freq[0] = DIV_ROUND_CLOSEST(fadc * 240, 1024);
|
freq[0] = DIV_ROUND_CLOSEST(fadc * 240, 1024);
|
||||||
|
|
||||||
fadc = DIV_ROUND_CLOSEST(st->fclk,
|
fadc = ad7192_compute_f_adc(st, true, true);
|
||||||
AD7192_SYNC3_FILTER * AD7192_MODE_RATE(st->mode));
|
|
||||||
freq[1] = DIV_ROUND_CLOSEST(fadc * 240, 1024);
|
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);
|
freq[2] = DIV_ROUND_CLOSEST(fadc * 230, 1024);
|
||||||
|
|
||||||
|
fadc = ad7192_compute_f_adc(st, true, false);
|
||||||
freq[3] = DIV_ROUND_CLOSEST(fadc * 272, 1024);
|
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) {
|
switch (idx) {
|
||||||
case 0:
|
case 0:
|
||||||
st->f_order = AD7192_SYNC4_FILTER;
|
|
||||||
st->mode &= ~AD7192_MODE_SINC3;
|
st->mode &= ~AD7192_MODE_SINC3;
|
||||||
|
|
||||||
st->conf |= AD7192_CONF_CHOP;
|
st->conf |= AD7192_CONF_CHOP;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
st->f_order = AD7192_SYNC3_FILTER;
|
|
||||||
st->mode |= AD7192_MODE_SINC3;
|
st->mode |= AD7192_MODE_SINC3;
|
||||||
|
|
||||||
st->conf |= AD7192_CONF_CHOP;
|
st->conf |= AD7192_CONF_CHOP;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
st->f_order = AD7192_NO_SYNC_FILTER;
|
|
||||||
st->mode &= ~AD7192_MODE_SINC3;
|
st->mode &= ~AD7192_MODE_SINC3;
|
||||||
|
|
||||||
st->conf &= ~AD7192_CONF_CHOP;
|
st->conf &= ~AD7192_CONF_CHOP;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
st->f_order = AD7192_NO_SYNC_FILTER;
|
|
||||||
st->mode |= AD7192_MODE_SINC3;
|
st->mode |= AD7192_MODE_SINC3;
|
||||||
|
|
||||||
st->conf &= ~AD7192_CONF_CHOP;
|
st->conf &= ~AD7192_CONF_CHOP;
|
||||||
@ -665,12 +714,11 @@ static int ad7192_get_3db_filter_freq(struct ad7192_state *st)
|
|||||||
{
|
{
|
||||||
unsigned int fadc;
|
unsigned int fadc;
|
||||||
|
|
||||||
fadc = DIV_ROUND_CLOSEST(st->fclk,
|
fadc = ad7192_get_f_adc(st);
|
||||||
st->f_order * AD7192_MODE_RATE(st->mode));
|
|
||||||
|
|
||||||
if (st->conf & AD7192_CONF_CHOP)
|
if (FIELD_GET(AD7192_CONF_CHOP, st->conf))
|
||||||
return DIV_ROUND_CLOSEST(fadc * 240, 1024);
|
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);
|
return DIV_ROUND_CLOSEST(fadc * 272, 1024);
|
||||||
else
|
else
|
||||||
return DIV_ROUND_CLOSEST(fadc * 230, 1024);
|
return DIV_ROUND_CLOSEST(fadc * 230, 1024);
|
||||||
@ -683,7 +731,8 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,
|
|||||||
long m)
|
long m)
|
||||||
{
|
{
|
||||||
struct ad7192_state *st = iio_priv(indio_dev);
|
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) {
|
switch (m) {
|
||||||
case IIO_CHAN_INFO_RAW:
|
case IIO_CHAN_INFO_RAW:
|
||||||
@ -692,8 +741,8 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,
|
|||||||
switch (chan->type) {
|
switch (chan->type) {
|
||||||
case IIO_VOLTAGE:
|
case IIO_VOLTAGE:
|
||||||
mutex_lock(&st->lock);
|
mutex_lock(&st->lock);
|
||||||
*val = st->scale_avail[AD7192_CONF_GAIN(st->conf)][0];
|
*val = st->scale_avail[gain][0];
|
||||||
*val2 = st->scale_avail[AD7192_CONF_GAIN(st->conf)][1];
|
*val2 = st->scale_avail[gain][1];
|
||||||
mutex_unlock(&st->lock);
|
mutex_unlock(&st->lock);
|
||||||
return IIO_VAL_INT_PLUS_NANO;
|
return IIO_VAL_INT_PLUS_NANO;
|
||||||
case IIO_TEMP:
|
case IIO_TEMP:
|
||||||
@ -713,13 +762,15 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,
|
|||||||
*val -= 273 * ad7192_get_temp_scale(unipolar);
|
*val -= 273 * ad7192_get_temp_scale(unipolar);
|
||||||
return IIO_VAL_INT;
|
return IIO_VAL_INT;
|
||||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||||
*val = st->fclk /
|
*val = DIV_ROUND_CLOSEST(ad7192_get_f_adc(st), 1024);
|
||||||
(st->f_order * 1024 * AD7192_MODE_RATE(st->mode));
|
|
||||||
return IIO_VAL_INT;
|
return IIO_VAL_INT;
|
||||||
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
|
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
|
||||||
*val = ad7192_get_3db_filter_freq(st);
|
*val = ad7192_get_3db_filter_freq(st);
|
||||||
*val2 = 1000;
|
*val2 = 1000;
|
||||||
return IIO_VAL_FRACTIONAL;
|
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;
|
return -EINVAL;
|
||||||
@ -747,8 +798,8 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
|
|||||||
if (val2 == st->scale_avail[i][1]) {
|
if (val2 == st->scale_avail[i][1]) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
tmp = st->conf;
|
tmp = st->conf;
|
||||||
st->conf &= ~AD7192_CONF_GAIN(-1);
|
st->conf &= ~AD7192_CONF_GAIN_MASK;
|
||||||
st->conf |= AD7192_CONF_GAIN(i);
|
st->conf |= FIELD_PREP(AD7192_CONF_GAIN_MASK, i);
|
||||||
if (tmp == st->conf)
|
if (tmp == st->conf)
|
||||||
break;
|
break;
|
||||||
ad_sd_write_reg(&st->sd, AD7192_REG_CONF,
|
ad_sd_write_reg(&st->sd, AD7192_REG_CONF,
|
||||||
@ -764,19 +815,36 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
div = st->fclk / (val * st->f_order * 1024);
|
div = st->fclk / (val * ad7192_get_f_order(st) * 1024);
|
||||||
if (div < 1 || div > 1023) {
|
if (div < 1 || div > 1023) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
st->mode &= ~AD7192_MODE_RATE(-1);
|
st->mode &= ~AD7192_MODE_RATE_MASK;
|
||||||
st->mode |= AD7192_MODE_RATE(div);
|
st->mode |= FIELD_PREP(AD7192_MODE_RATE_MASK, div);
|
||||||
ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
|
ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
|
||||||
break;
|
break;
|
||||||
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
|
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
|
||||||
ret = ad7192_set_3db_filter_freq(st, val, val2 / 1000);
|
ret = ad7192_set_3db_filter_freq(st, val, val2 / 1000);
|
||||||
break;
|
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:
|
default:
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
}
|
}
|
||||||
@ -797,6 +865,8 @@ static int ad7192_write_raw_get_fmt(struct iio_dev *indio_dev,
|
|||||||
return IIO_VAL_INT;
|
return IIO_VAL_INT;
|
||||||
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
|
case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
|
||||||
return IIO_VAL_INT_PLUS_MICRO;
|
return IIO_VAL_INT_PLUS_MICRO;
|
||||||
|
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
|
||||||
|
return IIO_VAL_INT;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -816,6 +886,12 @@ static int ad7192_read_avail(struct iio_dev *indio_dev,
|
|||||||
/* Values are stored in a 2D matrix */
|
/* Values are stored in a 2D matrix */
|
||||||
*length = ARRAY_SIZE(st->scale_avail) * 2;
|
*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;
|
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;
|
conf &= ~AD7192_CONF_CHAN_MASK;
|
||||||
for_each_set_bit(i, scan_mask, 8)
|
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);
|
ret = ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, conf);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -862,8 +938,8 @@ static const struct iio_info ad7195_info = {
|
|||||||
.update_scan_mode = ad7192_update_scan_mode,
|
.update_scan_mode = ad7192_update_scan_mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define __AD719x_CHANNEL(_si, _channel1, _channel2, _address, _extend_name, \
|
#define __AD719x_CHANNEL(_si, _channel1, _channel2, _address, _type, \
|
||||||
_type, _mask_type_av, _ext_info) \
|
_mask_all, _mask_type_av, _mask_all_av, _ext_info) \
|
||||||
{ \
|
{ \
|
||||||
.type = (_type), \
|
.type = (_type), \
|
||||||
.differential = ((_channel2) == -1 ? 0 : 1), \
|
.differential = ((_channel2) == -1 ? 0 : 1), \
|
||||||
@ -871,13 +947,14 @@ static const struct iio_info ad7195_info = {
|
|||||||
.channel = (_channel1), \
|
.channel = (_channel1), \
|
||||||
.channel2 = (_channel2), \
|
.channel2 = (_channel2), \
|
||||||
.address = (_address), \
|
.address = (_address), \
|
||||||
.extend_name = (_extend_name), \
|
|
||||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||||
BIT(IIO_CHAN_INFO_OFFSET), \
|
BIT(IIO_CHAN_INFO_OFFSET), \
|
||||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
||||||
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
|
.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_type_available = (_mask_type_av), \
|
||||||
|
.info_mask_shared_by_all_available = (_mask_all_av), \
|
||||||
.ext_info = (_ext_info), \
|
.ext_info = (_ext_info), \
|
||||||
.scan_index = (_si), \
|
.scan_index = (_si), \
|
||||||
.scan_type = { \
|
.scan_type = { \
|
||||||
@ -889,16 +966,26 @@ static const struct iio_info ad7195_info = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define AD719x_DIFF_CHANNEL(_si, _channel1, _channel2, _address) \
|
#define AD719x_DIFF_CHANNEL(_si, _channel1, _channel2, _address) \
|
||||||
__AD719x_CHANNEL(_si, _channel1, _channel2, _address, NULL, \
|
__AD719x_CHANNEL(_si, _channel1, _channel2, _address, IIO_VOLTAGE, 0, \
|
||||||
IIO_VOLTAGE, BIT(IIO_CHAN_INFO_SCALE), \
|
BIT(IIO_CHAN_INFO_SCALE), 0, ad7192_calibsys_ext_info)
|
||||||
ad7192_calibsys_ext_info)
|
|
||||||
|
|
||||||
#define AD719x_CHANNEL(_si, _channel1, _address) \
|
#define AD719x_CHANNEL(_si, _channel1, _address) \
|
||||||
__AD719x_CHANNEL(_si, _channel1, -1, _address, NULL, IIO_VOLTAGE, \
|
__AD719x_CHANNEL(_si, _channel1, -1, _address, IIO_VOLTAGE, 0, \
|
||||||
BIT(IIO_CHAN_INFO_SCALE), ad7192_calibsys_ext_info)
|
BIT(IIO_CHAN_INFO_SCALE), 0, ad7192_calibsys_ext_info)
|
||||||
|
|
||||||
#define AD719x_TEMP_CHANNEL(_si, _address) \
|
#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[] = {
|
static const struct iio_chan_spec ad7192_channels[] = {
|
||||||
AD719x_DIFF_CHANNEL(0, 1, 2, AD7192_CH_AIN1P_AIN2M),
|
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[] = {
|
static const struct iio_chan_spec ad7193_channels[] = {
|
||||||
AD719x_DIFF_CHANNEL(0, 1, 2, AD7193_CH_AIN1P_AIN2M),
|
AD7193_DIFF_CHANNEL(0, 1, 2, AD7193_CH_AIN1P_AIN2M),
|
||||||
AD719x_DIFF_CHANNEL(1, 3, 4, AD7193_CH_AIN3P_AIN4M),
|
AD7193_DIFF_CHANNEL(1, 3, 4, AD7193_CH_AIN3P_AIN4M),
|
||||||
AD719x_DIFF_CHANNEL(2, 5, 6, AD7193_CH_AIN5P_AIN6M),
|
AD7193_DIFF_CHANNEL(2, 5, 6, AD7193_CH_AIN5P_AIN6M),
|
||||||
AD719x_DIFF_CHANNEL(3, 7, 8, AD7193_CH_AIN7P_AIN8M),
|
AD7193_DIFF_CHANNEL(3, 7, 8, AD7193_CH_AIN7P_AIN8M),
|
||||||
AD719x_TEMP_CHANNEL(4, AD7193_CH_TEMP),
|
AD719x_TEMP_CHANNEL(4, AD7193_CH_TEMP),
|
||||||
AD719x_DIFF_CHANNEL(5, 2, 2, AD7193_CH_AIN2P_AIN2M),
|
AD7193_DIFF_CHANNEL(5, 2, 2, AD7193_CH_AIN2P_AIN2M),
|
||||||
AD719x_CHANNEL(6, 1, AD7193_CH_AIN1),
|
AD7193_CHANNEL(6, 1, AD7193_CH_AIN1),
|
||||||
AD719x_CHANNEL(7, 2, AD7193_CH_AIN2),
|
AD7193_CHANNEL(7, 2, AD7193_CH_AIN2),
|
||||||
AD719x_CHANNEL(8, 3, AD7193_CH_AIN3),
|
AD7193_CHANNEL(8, 3, AD7193_CH_AIN3),
|
||||||
AD719x_CHANNEL(9, 4, AD7193_CH_AIN4),
|
AD7193_CHANNEL(9, 4, AD7193_CH_AIN4),
|
||||||
AD719x_CHANNEL(10, 5, AD7193_CH_AIN5),
|
AD7193_CHANNEL(10, 5, AD7193_CH_AIN5),
|
||||||
AD719x_CHANNEL(11, 6, AD7193_CH_AIN6),
|
AD7193_CHANNEL(11, 6, AD7193_CH_AIN6),
|
||||||
AD719x_CHANNEL(12, 7, AD7193_CH_AIN7),
|
AD7193_CHANNEL(12, 7, AD7193_CH_AIN7),
|
||||||
AD719x_CHANNEL(13, 8, AD7193_CH_AIN8),
|
AD7193_CHANNEL(13, 8, AD7193_CH_AIN8),
|
||||||
IIO_CHAN_SOFT_TIMESTAMP(14),
|
IIO_CHAN_SOFT_TIMESTAMP(14),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -934,39 +1021,33 @@ static const struct ad7192_chip_info ad7192_chip_info_tbl[] = {
|
|||||||
[ID_AD7190] = {
|
[ID_AD7190] = {
|
||||||
.chip_id = CHIPID_AD7190,
|
.chip_id = CHIPID_AD7190,
|
||||||
.name = "ad7190",
|
.name = "ad7190",
|
||||||
|
.channels = ad7192_channels,
|
||||||
|
.num_channels = ARRAY_SIZE(ad7192_channels),
|
||||||
|
.info = &ad7192_info,
|
||||||
},
|
},
|
||||||
[ID_AD7192] = {
|
[ID_AD7192] = {
|
||||||
.chip_id = CHIPID_AD7192,
|
.chip_id = CHIPID_AD7192,
|
||||||
.name = "ad7192",
|
.name = "ad7192",
|
||||||
|
.channels = ad7192_channels,
|
||||||
|
.num_channels = ARRAY_SIZE(ad7192_channels),
|
||||||
|
.info = &ad7192_info,
|
||||||
},
|
},
|
||||||
[ID_AD7193] = {
|
[ID_AD7193] = {
|
||||||
.chip_id = CHIPID_AD7193,
|
.chip_id = CHIPID_AD7193,
|
||||||
.name = "ad7193",
|
.name = "ad7193",
|
||||||
|
.channels = ad7193_channels,
|
||||||
|
.num_channels = ARRAY_SIZE(ad7193_channels),
|
||||||
|
.info = &ad7192_info,
|
||||||
},
|
},
|
||||||
[ID_AD7195] = {
|
[ID_AD7195] = {
|
||||||
.chip_id = CHIPID_AD7195,
|
.chip_id = CHIPID_AD7195,
|
||||||
.name = "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)
|
static void ad7192_reg_disable(void *reg)
|
||||||
{
|
{
|
||||||
regulator_disable(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;
|
st->chip_info = (void *)spi_get_device_id(spi)->driver_data;
|
||||||
indio_dev->name = st->chip_info->name;
|
indio_dev->name = st->chip_info->name;
|
||||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||||
|
indio_dev->channels = st->chip_info->channels;
|
||||||
ret = ad7192_channels_config(indio_dev);
|
indio_dev->num_channels = st->chip_info->num_channels;
|
||||||
if (ret < 0)
|
indio_dev->info = st->chip_info->info;
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (st->chip_info->chip_id == CHIPID_AD7195)
|
|
||||||
indio_dev->info = &ad7195_info;
|
|
||||||
else
|
|
||||||
indio_dev->info = &ad7192_info;
|
|
||||||
|
|
||||||
ret = ad_sd_init(&st->sd, indio_dev, spi, &ad7192_sigma_delta_info);
|
ret = ad_sd_init(&st->sd, indio_dev, spi, &ad7192_sigma_delta_info);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -2486,7 +2486,7 @@ reg_disable:
|
|||||||
return ret;
|
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 iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct at91_adc_state *st = iio_priv(indio_dev);
|
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->vref);
|
||||||
regulator_disable(st->reg);
|
regulator_disable(st->reg);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int at91_adc_suspend(struct device *dev)
|
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 = {
|
static struct platform_driver at91_adc_driver = {
|
||||||
.probe = at91_adc_probe,
|
.probe = at91_adc_probe,
|
||||||
.remove = at91_adc_remove,
|
.remove_new = at91_adc_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "at91-sama5d2_adc",
|
.name = "at91-sama5d2_adc",
|
||||||
.of_match_table = at91_adc_dt_match,
|
.of_match_table = at91_adc_dt_match,
|
||||||
|
@ -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");
|
st->use_external = of_property_read_bool(node, "atmel,adc-use-external-triggers");
|
||||||
|
|
||||||
if (of_property_read_u32(node, "atmel,adc-channels-used", &prop)) {
|
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 dev_err_probe(&idev->dev, -EINVAL,
|
||||||
return -EINVAL;
|
"Missing adc-channels-used property in the DT.\n");
|
||||||
}
|
|
||||||
st->channels_mask = prop;
|
st->channels_mask = prop;
|
||||||
|
|
||||||
st->sleep_mode = of_property_read_bool(node, "atmel,adc-sleep-mode");
|
st->sleep_mode = of_property_read_bool(node, "atmel,adc-sleep-mode");
|
||||||
|
|
||||||
if (of_property_read_u32(node, "atmel,adc-startup-time", &prop)) {
|
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 dev_err_probe(&idev->dev, -EINVAL,
|
||||||
return -EINVAL;
|
"Missing adc-startup-time property in the DT.\n");
|
||||||
}
|
|
||||||
st->startup_time = prop;
|
st->startup_time = prop;
|
||||||
|
|
||||||
prop = 0;
|
prop = 0;
|
||||||
of_property_read_u32(node, "atmel,adc-sample-hold-time", &prop);
|
of_property_read_u32(node, "atmel,adc-sample-hold-time", &prop);
|
||||||
st->sample_hold_time = prop;
|
st->sample_hold_time = prop;
|
||||||
|
|
||||||
if (of_property_read_u32(node, "atmel,adc-vref", &prop)) {
|
if (of_property_read_u32(node, "atmel,adc-vref", &prop))
|
||||||
dev_err(&idev->dev, "Missing adc-vref property in the DT.\n");
|
return dev_err_probe(&idev->dev, -EINVAL,
|
||||||
return -EINVAL;
|
"Missing adc-vref property in the DT.\n");
|
||||||
}
|
|
||||||
st->vref_mv = prop;
|
st->vref_mv = prop;
|
||||||
|
|
||||||
st->res = st->caps->high_res_bits;
|
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))
|
if (IS_ERR(st->reg_base))
|
||||||
return PTR_ERR(st->reg_base);
|
return PTR_ERR(st->reg_base);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disable all IRQs before setting up the handler
|
* 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);
|
at91_adc_writel(st, AT91_ADC_IDR, 0xFFFFFFFF);
|
||||||
|
|
||||||
if (st->caps->has_tsmr)
|
if (st->caps->has_tsmr)
|
||||||
ret = request_irq(st->irq, at91_adc_9x5_interrupt, 0,
|
ret = devm_request_irq(&pdev->dev, st->irq,
|
||||||
pdev->dev.driver->name, idev);
|
at91_adc_9x5_interrupt, 0,
|
||||||
|
pdev->dev.driver->name, idev);
|
||||||
else
|
else
|
||||||
ret = request_irq(st->irq, at91_adc_rl_interrupt, 0,
|
ret = devm_request_irq(&pdev->dev, st->irq,
|
||||||
pdev->dev.driver->name, idev);
|
at91_adc_rl_interrupt, 0,
|
||||||
if (ret) {
|
pdev->dev.driver->name, idev);
|
||||||
dev_err(&pdev->dev, "Failed to allocate IRQ.\n");
|
if (ret)
|
||||||
return ret;
|
return dev_err_probe(&pdev->dev, ret,
|
||||||
}
|
"Failed to allocate IRQ.\n");
|
||||||
|
|
||||||
st->clk = devm_clk_get(&pdev->dev, "adc_clk");
|
st->clk = devm_clk_get_enabled(&pdev->dev, "adc_clk");
|
||||||
if (IS_ERR(st->clk)) {
|
if (IS_ERR(st->clk))
|
||||||
dev_err(&pdev->dev, "Failed to get the clock.\n");
|
return dev_err_probe(&pdev->dev, PTR_ERR(st->clk),
|
||||||
ret = PTR_ERR(st->clk);
|
"Could not prepare or enable the clock.\n");
|
||||||
goto error_free_irq;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = clk_prepare_enable(st->clk);
|
st->adc_clk = devm_clk_get_enabled(&pdev->dev, "adc_op_clk");
|
||||||
if (ret) {
|
if (IS_ERR(st->adc_clk))
|
||||||
dev_err(&pdev->dev,
|
return dev_err_probe(&pdev->dev, PTR_ERR(st->adc_clk),
|
||||||
"Could not prepare or enable the clock.\n");
|
"Could not prepare or enable the ADC 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prescaler rate computation using the formula from the Atmel's
|
* 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;
|
prsc = (mstrclk / (2 * adc_clk)) - 1;
|
||||||
|
|
||||||
if (!st->startup_time) {
|
if (!st->startup_time)
|
||||||
dev_err(&pdev->dev, "No startup time available.\n");
|
return dev_err_probe(&pdev->dev, -EINVAL,
|
||||||
ret = -EINVAL;
|
"No startup time available.\n");
|
||||||
goto error_disable_adc_clk;
|
|
||||||
}
|
|
||||||
ticks = (*st->caps->calc_startup_ticks)(st->startup_time, adc_clk_khz);
|
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 */
|
/* Setup the ADC channels available on the board */
|
||||||
ret = at91_adc_channel_init(idev);
|
ret = at91_adc_channel_init(idev);
|
||||||
if (ret < 0) {
|
if (ret < 0)
|
||||||
dev_err(&pdev->dev, "Couldn't initialize the channels.\n");
|
return dev_err_probe(&pdev->dev, ret,
|
||||||
goto error_disable_adc_clk;
|
"Couldn't initialize the channels.\n");
|
||||||
}
|
|
||||||
|
|
||||||
init_waitqueue_head(&st->wq_data_avail);
|
init_waitqueue_head(&st->wq_data_avail);
|
||||||
mutex_init(&st->lock);
|
mutex_init(&st->lock);
|
||||||
@ -1173,21 +1149,20 @@ static int at91_adc_probe(struct platform_device *pdev)
|
|||||||
*/
|
*/
|
||||||
if (!st->touchscreen_type) {
|
if (!st->touchscreen_type) {
|
||||||
ret = at91_adc_buffer_init(idev);
|
ret = at91_adc_buffer_init(idev);
|
||||||
if (ret < 0) {
|
if (ret < 0)
|
||||||
dev_err(&pdev->dev, "Couldn't initialize the buffer.\n");
|
return dev_err_probe(&pdev->dev, ret,
|
||||||
goto error_disable_adc_clk;
|
"Couldn't initialize the buffer.\n");
|
||||||
}
|
|
||||||
|
|
||||||
ret = at91_adc_trigger_init(idev);
|
ret = at91_adc_trigger_init(idev);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(&pdev->dev, "Couldn't setup the triggers.\n");
|
dev_err(&pdev->dev, "Couldn't setup the triggers.\n");
|
||||||
at91_adc_buffer_remove(idev);
|
at91_adc_buffer_remove(idev);
|
||||||
goto error_disable_adc_clk;
|
return ret;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ret = at91_ts_register(idev, pdev);
|
ret = at91_ts_register(idev, pdev);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error_disable_adc_clk;
|
return ret;
|
||||||
|
|
||||||
at91_ts_hw_init(idev, adc_clk_khz);
|
at91_ts_hw_init(idev, adc_clk_khz);
|
||||||
}
|
}
|
||||||
@ -1207,16 +1182,10 @@ error_iio_device_register:
|
|||||||
} else {
|
} else {
|
||||||
at91_ts_unregister(st);
|
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;
|
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 iio_dev *idev = platform_get_drvdata(pdev);
|
||||||
struct at91_adc_state *st = iio_priv(idev);
|
struct at91_adc_state *st = iio_priv(idev);
|
||||||
@ -1228,11 +1197,6 @@ static int at91_adc_remove(struct platform_device *pdev)
|
|||||||
} else {
|
} else {
|
||||||
at91_ts_unregister(st);
|
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)
|
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 = {
|
static struct platform_driver at91_adc_driver = {
|
||||||
.probe = at91_adc_probe,
|
.probe = at91_adc_probe,
|
||||||
.remove = at91_adc_remove,
|
.remove_new = at91_adc_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = DRIVER_NAME,
|
.name = DRIVER_NAME,
|
||||||
.of_match_table = at91_adc_dt_ids,
|
.of_match_table = at91_adc_dt_ids,
|
||||||
|
@ -745,7 +745,7 @@ fail_map:
|
|||||||
return ret;
|
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 iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct axp20x_adc_iio *info = iio_priv(indio_dev);
|
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)
|
if (info->data->adc_en2_mask)
|
||||||
regmap_write(info->regmap, AXP20X_ADC_EN2, 0);
|
regmap_write(info->regmap, AXP20X_ADC_EN2, 0);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct platform_driver axp20x_adc_driver = {
|
static struct platform_driver axp20x_adc_driver = {
|
||||||
@ -768,7 +766,7 @@ static struct platform_driver axp20x_adc_driver = {
|
|||||||
},
|
},
|
||||||
.id_table = axp20x_adc_id_match,
|
.id_table = axp20x_adc_id_match,
|
||||||
.probe = axp20x_probe,
|
.probe = axp20x_probe,
|
||||||
.remove = axp20x_remove,
|
.remove_new = axp20x_remove,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_platform_driver(axp20x_adc_driver);
|
module_platform_driver(axp20x_adc_driver);
|
||||||
|
@ -594,7 +594,7 @@ err_adc_enable:
|
|||||||
return ret;
|
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 iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct iproc_adc_priv *adc_priv = iio_priv(indio_dev);
|
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);
|
iio_device_unregister(indio_dev);
|
||||||
iproc_adc_disable(indio_dev);
|
iproc_adc_disable(indio_dev);
|
||||||
clk_disable_unprepare(adc_priv->adc_clk);
|
clk_disable_unprepare(adc_priv->adc_clk);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id iproc_adc_of_match[] = {
|
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 = {
|
static struct platform_driver iproc_adc_driver = {
|
||||||
.probe = iproc_adc_probe,
|
.probe = iproc_adc_probe,
|
||||||
.remove = iproc_adc_remove,
|
.remove_new = iproc_adc_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "iproc-static-adc",
|
.name = "iproc-static-adc",
|
||||||
.of_match_table = iproc_adc_of_match,
|
.of_match_table = iproc_adc_of_match,
|
||||||
|
@ -691,19 +691,18 @@ unregister_event:
|
|||||||
return ret;
|
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);
|
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
iio_device_unregister(indio_dev);
|
iio_device_unregister(indio_dev);
|
||||||
dln2_unregister_event_cb(pdev, DLN2_ADC_CONDITION_MET_EV);
|
dln2_unregister_event_cb(pdev, DLN2_ADC_CONDITION_MET_EV);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct platform_driver dln2_adc_driver = {
|
static struct platform_driver dln2_adc_driver = {
|
||||||
.driver.name = DLN2_ADC_MOD_NAME,
|
.driver.name = DLN2_ADC_MOD_NAME,
|
||||||
.probe = dln2_adc_probe,
|
.probe = dln2_adc_probe,
|
||||||
.remove = dln2_adc_remove,
|
.remove_new = dln2_adc_remove,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_platform_driver(dln2_adc_driver);
|
module_platform_driver(dln2_adc_driver);
|
||||||
|
@ -217,15 +217,13 @@ static int ep93xx_adc_probe(struct platform_device *pdev)
|
|||||||
return ret;
|
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 iio_dev *iiodev = platform_get_drvdata(pdev);
|
||||||
struct ep93xx_adc_priv *priv = iio_priv(iiodev);
|
struct ep93xx_adc_priv *priv = iio_priv(iiodev);
|
||||||
|
|
||||||
iio_device_unregister(iiodev);
|
iio_device_unregister(iiodev);
|
||||||
clk_disable_unprepare(priv->clk);
|
clk_disable_unprepare(priv->clk);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id ep93xx_adc_of_ids[] = {
|
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,
|
.of_match_table = ep93xx_adc_of_ids,
|
||||||
},
|
},
|
||||||
.probe = ep93xx_adc_probe,
|
.probe = ep93xx_adc_probe,
|
||||||
.remove = ep93xx_adc_remove,
|
.remove_new = ep93xx_adc_remove,
|
||||||
};
|
};
|
||||||
module_platform_driver(ep93xx_adc_driver);
|
module_platform_driver(ep93xx_adc_driver);
|
||||||
|
|
||||||
|
@ -946,7 +946,7 @@ err_disable_reg:
|
|||||||
return ret;
|
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 iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct exynos_adc *info = iio_priv(indio_dev);
|
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_disable_clk(info);
|
||||||
exynos_adc_unprepare_clk(info);
|
exynos_adc_unprepare_clk(info);
|
||||||
regulator_disable(info->vdd);
|
regulator_disable(info->vdd);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int exynos_adc_suspend(struct device *dev)
|
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 = {
|
static struct platform_driver exynos_adc_driver = {
|
||||||
.probe = exynos_adc_probe,
|
.probe = exynos_adc_probe,
|
||||||
.remove = exynos_adc_remove,
|
.remove_new = exynos_adc_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "exynos-adc",
|
.name = "exynos-adc",
|
||||||
.of_match_table = exynos_adc_match,
|
.of_match_table = exynos_adc_match,
|
||||||
|
@ -384,7 +384,7 @@ err_regulator_disable:
|
|||||||
return ret;
|
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 iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct mx25_gcq_priv *priv = iio_priv(indio_dev);
|
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])
|
if (priv->vref[i])
|
||||||
regulator_disable(priv->vref[i]);
|
regulator_disable(priv->vref[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id mx25_gcq_ids[] = {
|
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,
|
.of_match_table = mx25_gcq_ids,
|
||||||
},
|
},
|
||||||
.probe = mx25_gcq_probe,
|
.probe = mx25_gcq_probe,
|
||||||
.remove = mx25_gcq_remove,
|
.remove_new = mx25_gcq_remove,
|
||||||
};
|
};
|
||||||
module_platform_driver(mx25_gcq_driver);
|
module_platform_driver(mx25_gcq_driver);
|
||||||
|
|
||||||
|
@ -580,7 +580,7 @@ error_regulator:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hx711_remove(struct platform_device *pdev)
|
static void hx711_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct hx711_data *hx711_data;
|
struct hx711_data *hx711_data;
|
||||||
struct iio_dev *indio_dev;
|
struct iio_dev *indio_dev;
|
||||||
@ -593,8 +593,6 @@ static int hx711_remove(struct platform_device *pdev)
|
|||||||
iio_triggered_buffer_cleanup(indio_dev);
|
iio_triggered_buffer_cleanup(indio_dev);
|
||||||
|
|
||||||
regulator_disable(hx711_data->reg_avdd);
|
regulator_disable(hx711_data->reg_avdd);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id of_hx711_match[] = {
|
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 = {
|
static struct platform_driver hx711_driver = {
|
||||||
.probe = hx711_probe,
|
.probe = hx711_probe,
|
||||||
.remove = hx711_remove,
|
.remove_new = hx711_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "hx711-gpio",
|
.name = "hx711-gpio",
|
||||||
.of_match_table = of_hx711_match,
|
.of_match_table = of_hx711_match,
|
||||||
|
@ -404,7 +404,7 @@ error_regulator_disable:
|
|||||||
return ret;
|
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 iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct imx8qxp_adc *adc = iio_priv(indio_dev);
|
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_disable(dev);
|
||||||
pm_runtime_put_noidle(dev);
|
pm_runtime_put_noidle(dev);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int imx8qxp_adc_runtime_suspend(struct device *dev)
|
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 = {
|
static struct platform_driver imx8qxp_adc_driver = {
|
||||||
.probe = imx8qxp_adc_probe,
|
.probe = imx8qxp_adc_probe,
|
||||||
.remove = imx8qxp_adc_remove,
|
.remove_new = imx8qxp_adc_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = ADC_DRIVER_NAME,
|
.name = ADC_DRIVER_NAME,
|
||||||
.of_match_table = imx8qxp_adc_match,
|
.of_match_table = imx8qxp_adc_match,
|
||||||
|
@ -392,7 +392,7 @@ error_regulator_disable:
|
|||||||
return ret;
|
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 iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct imx93_adc *adc = iio_priv(indio_dev);
|
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);
|
free_irq(adc->irq, adc);
|
||||||
clk_disable_unprepare(adc->ipg_clk);
|
clk_disable_unprepare(adc->ipg_clk);
|
||||||
regulator_disable(adc->vref);
|
regulator_disable(adc->vref);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int imx93_adc_runtime_suspend(struct device *dev)
|
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 = {
|
static struct platform_driver imx93_adc_driver = {
|
||||||
.probe = imx93_adc_probe,
|
.probe = imx93_adc_probe,
|
||||||
.remove = imx93_adc_remove,
|
.remove_new = imx93_adc_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = IMX93_ADC_DRIVER_NAME,
|
.name = IMX93_ADC_DRIVER_NAME,
|
||||||
.of_match_table = imx93_adc_match,
|
.of_match_table = imx93_adc_match,
|
||||||
|
246
drivers/iio/adc/ltc2309.c
Normal file
246
drivers/iio/adc/ltc2309.c
Normal 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(<c2309->lock);
|
||||||
|
ret = ltc2309_read_raw_channel(ltc2309, chan->address, val);
|
||||||
|
mutex_unlock(<c2309->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 = <c2309_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(<c2309->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");
|
@ -95,7 +95,6 @@ static int ltc2497_result_and_measure(struct ltc2497core_driverdata *ddata,
|
|||||||
|
|
||||||
static int ltc2497_probe(struct i2c_client *client)
|
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;
|
const struct ltc2497_chip_info *chip_info;
|
||||||
struct iio_dev *indio_dev;
|
struct iio_dev *indio_dev;
|
||||||
struct ltc2497_driverdata *st;
|
struct ltc2497_driverdata *st;
|
||||||
@ -115,9 +114,7 @@ static int ltc2497_probe(struct i2c_client *client)
|
|||||||
st->client = client;
|
st->client = client;
|
||||||
st->common_ddata.result_and_measure = ltc2497_result_and_measure;
|
st->common_ddata.result_and_measure = ltc2497_result_and_measure;
|
||||||
|
|
||||||
chip_info = device_get_match_data(dev);
|
chip_info = i2c_get_match_data(client);
|
||||||
if (!chip_info)
|
|
||||||
chip_info = (const struct ltc2497_chip_info *)id->driver_data;
|
|
||||||
st->common_ddata.chip_info = chip_info;
|
st->common_ddata.chip_info = chip_info;
|
||||||
|
|
||||||
resolution = chip_info->resolution;
|
resolution = chip_info->resolution;
|
||||||
|
@ -1599,9 +1599,7 @@ static int max1363_probe(struct i2c_client *client)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
st->chip_info = device_get_match_data(&client->dev);
|
st->chip_info = i2c_get_match_data(client);
|
||||||
if (!st->chip_info)
|
|
||||||
st->chip_info = &max1363_chip_info_tbl[id->driver_data];
|
|
||||||
st->client = client;
|
st->client = client;
|
||||||
|
|
||||||
st->vref_uv = st->chip_info->int_vref_mv * 1000;
|
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);
|
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[] = {
|
static const struct i2c_device_id max1363_id[] = {
|
||||||
{ "max1361", max1361 },
|
MAX1363_ID_TABLE("max1361", max1361),
|
||||||
{ "max1362", max1362 },
|
MAX1363_ID_TABLE("max1362", max1362),
|
||||||
{ "max1363", max1363 },
|
MAX1363_ID_TABLE("max1363", max1363),
|
||||||
{ "max1364", max1364 },
|
MAX1363_ID_TABLE("max1364", max1364),
|
||||||
{ "max1036", max1036 },
|
MAX1363_ID_TABLE("max1036", max1036),
|
||||||
{ "max1037", max1037 },
|
MAX1363_ID_TABLE("max1037", max1037),
|
||||||
{ "max1038", max1038 },
|
MAX1363_ID_TABLE("max1038", max1038),
|
||||||
{ "max1039", max1039 },
|
MAX1363_ID_TABLE("max1039", max1039),
|
||||||
{ "max1136", max1136 },
|
MAX1363_ID_TABLE("max1136", max1136),
|
||||||
{ "max1137", max1137 },
|
MAX1363_ID_TABLE("max1137", max1137),
|
||||||
{ "max1138", max1138 },
|
MAX1363_ID_TABLE("max1138", max1138),
|
||||||
{ "max1139", max1139 },
|
MAX1363_ID_TABLE("max1139", max1139),
|
||||||
{ "max1236", max1236 },
|
MAX1363_ID_TABLE("max1236", max1236),
|
||||||
{ "max1237", max1237 },
|
MAX1363_ID_TABLE("max1237", max1237),
|
||||||
{ "max1238", max1238 },
|
MAX1363_ID_TABLE("max1238", max1238),
|
||||||
{ "max1239", max1239 },
|
MAX1363_ID_TABLE("max1239", max1239),
|
||||||
{ "max11600", max11600 },
|
MAX1363_ID_TABLE("max11600", max11600),
|
||||||
{ "max11601", max11601 },
|
MAX1363_ID_TABLE("max11601", max11601),
|
||||||
{ "max11602", max11602 },
|
MAX1363_ID_TABLE("max11602", max11602),
|
||||||
{ "max11603", max11603 },
|
MAX1363_ID_TABLE("max11603", max11603),
|
||||||
{ "max11604", max11604 },
|
MAX1363_ID_TABLE("max11604", max11604),
|
||||||
{ "max11605", max11605 },
|
MAX1363_ID_TABLE("max11605", max11605),
|
||||||
{ "max11606", max11606 },
|
MAX1363_ID_TABLE("max11606", max11606),
|
||||||
{ "max11607", max11607 },
|
MAX1363_ID_TABLE("max11607", max11607),
|
||||||
{ "max11608", max11608 },
|
MAX1363_ID_TABLE("max11608", max11608),
|
||||||
{ "max11609", max11609 },
|
MAX1363_ID_TABLE("max11609", max11609),
|
||||||
{ "max11610", max11610 },
|
MAX1363_ID_TABLE("max11610", max11610),
|
||||||
{ "max11611", max11611 },
|
MAX1363_ID_TABLE("max11611", max11611),
|
||||||
{ "max11612", max11612 },
|
MAX1363_ID_TABLE("max11612", max11612),
|
||||||
{ "max11613", max11613 },
|
MAX1363_ID_TABLE("max11613", max11613),
|
||||||
{ "max11614", max11614 },
|
MAX1363_ID_TABLE("max11614", max11614),
|
||||||
{ "max11615", max11615 },
|
MAX1363_ID_TABLE("max11615", max11615),
|
||||||
{ "max11616", max11616 },
|
MAX1363_ID_TABLE("max11616", max11616),
|
||||||
{ "max11617", max11617 },
|
MAX1363_ID_TABLE("max11617", max11617),
|
||||||
{ "max11644", max11644 },
|
MAX1363_ID_TABLE("max11644", max11644),
|
||||||
{ "max11645", max11645 },
|
MAX1363_ID_TABLE("max11645", max11645),
|
||||||
{ "max11646", max11646 },
|
MAX1363_ID_TABLE("max11646", max11646),
|
||||||
{ "max11647", max11647 },
|
MAX1363_ID_TABLE("max11647", max11647),
|
||||||
{}
|
{ /* sentinel */ }
|
||||||
};
|
};
|
||||||
|
|
||||||
MODULE_DEVICE_TABLE(i2c, max1363_id);
|
MODULE_DEVICE_TABLE(i2c, max1363_id);
|
||||||
|
1513
drivers/iio/adc/mcp3564.c
Normal file
1513
drivers/iio/adc/mcp3564.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -29,11 +29,11 @@
|
|||||||
#define MCP3911_REG_MOD 0x06
|
#define MCP3911_REG_MOD 0x06
|
||||||
#define MCP3911_REG_PHASE 0x07
|
#define MCP3911_REG_PHASE 0x07
|
||||||
#define MCP3911_REG_GAIN 0x09
|
#define MCP3911_REG_GAIN 0x09
|
||||||
#define MCP3911_GAIN_MASK(ch) (GENMASK(2, 0) << 3 * 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_GAIN_VAL(ch, val) ((val << 3 * (ch)) & MCP3911_GAIN_MASK(ch))
|
||||||
|
|
||||||
#define MCP3911_REG_STATUSCOM 0x0a
|
#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_READ GENMASK(7, 6)
|
||||||
#define MCP3911_STATUSCOM_CH1_24WIDTH BIT(4)
|
#define MCP3911_STATUSCOM_CH1_24WIDTH BIT(4)
|
||||||
#define MCP3911_STATUSCOM_CH0_24WIDTH BIT(3)
|
#define MCP3911_STATUSCOM_CH0_24WIDTH BIT(3)
|
||||||
@ -51,8 +51,8 @@
|
|||||||
#define MCP3911_REG_GAINCAL_CH1 0x17
|
#define MCP3911_REG_GAINCAL_CH1 0x17
|
||||||
#define MCP3911_REG_VREFCAL 0x1a
|
#define MCP3911_REG_VREFCAL 0x1a
|
||||||
|
|
||||||
#define MCP3911_CHANNEL(x) (MCP3911_REG_CHANNEL0 + x * 3)
|
#define MCP3911_CHANNEL(ch) (MCP3911_REG_CHANNEL0 + (ch) * 3)
|
||||||
#define MCP3911_OFFCAL(x) (MCP3911_REG_OFFCAL_CH0 + x * 6)
|
#define MCP3911_OFFCAL(ch) (MCP3911_REG_OFFCAL_CH0 + (ch) * 6)
|
||||||
|
|
||||||
/* Internal voltage reference in mV */
|
/* Internal voltage reference in mV */
|
||||||
#define MCP3911_INT_VREF_MV 1200
|
#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_WRITE(reg, id) ((((reg) << 1) | ((id) << 6) | (0 << 0)) & 0xff)
|
||||||
#define MCP3911_REG_MASK GENMASK(4, 1)
|
#define MCP3911_REG_MASK GENMASK(4, 1)
|
||||||
|
|
||||||
#define MCP3911_NUM_CHANNELS 2
|
|
||||||
#define MCP3911_NUM_SCALES 6
|
#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 const int mcp3911_osr_table[] = { 32, 64, 128, 256, 512, 1024, 2048, 4096 };
|
||||||
static u32 mcp3911_scale_table[MCP3911_NUM_SCALES][2];
|
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 mcp3911 {
|
||||||
struct spi_device *spi;
|
struct spi_device *spi;
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
@ -74,14 +118,15 @@ struct mcp3911 {
|
|||||||
struct clk *clki;
|
struct clk *clki;
|
||||||
u32 dev_addr;
|
u32 dev_addr;
|
||||||
struct iio_trigger *trig;
|
struct iio_trigger *trig;
|
||||||
u32 gain[MCP3911_NUM_CHANNELS];
|
u32 gain[MCP39XX_MAX_NUM_CHANNELS];
|
||||||
|
const struct mcp3911_chip_info *chip;
|
||||||
struct {
|
struct {
|
||||||
u32 channels[MCP3911_NUM_CHANNELS];
|
u32 channels[MCP39XX_MAX_NUM_CHANNELS];
|
||||||
s64 ts __aligned(8);
|
s64 ts __aligned(8);
|
||||||
} scan;
|
} scan;
|
||||||
|
|
||||||
u8 tx_buf __aligned(IIO_DMA_MINALIGN);
|
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)
|
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);
|
return spi_write(adc->spi, &val, len + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mcp3911_update(struct mcp3911 *adc, u8 reg, u32 mask,
|
static int mcp3911_update(struct mcp3911 *adc, u8 reg, u32 mask, u32 val, u8 len)
|
||||||
u32 val, u8 len)
|
|
||||||
{
|
{
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
int ret;
|
int ret;
|
||||||
@ -126,9 +170,115 @@ static int mcp3911_update(struct mcp3911 *adc, u8 reg, u32 mask,
|
|||||||
return mcp3911_write(adc, reg, val, len);
|
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,
|
static int mcp3911_write_raw_get_fmt(struct iio_dev *indio_dev,
|
||||||
struct iio_chan_spec const *chan,
|
struct iio_chan_spec const *chan,
|
||||||
long mask)
|
long mask)
|
||||||
{
|
{
|
||||||
switch (mask) {
|
switch (mask) {
|
||||||
case IIO_CHAN_INFO_SCALE:
|
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,
|
static int mcp3911_read_avail(struct iio_dev *indio_dev,
|
||||||
struct iio_chan_spec const *chan,
|
struct iio_chan_spec const *chan,
|
||||||
const int **vals, int *type, int *length,
|
const int **vals, int *type, int *length,
|
||||||
long info)
|
long info)
|
||||||
{
|
{
|
||||||
switch (info) {
|
switch (info) {
|
||||||
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
|
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
|
||||||
@ -182,20 +332,18 @@ static int mcp3911_read_raw(struct iio_dev *indio_dev,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case IIO_CHAN_INFO_OFFSET:
|
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)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = IIO_VAL_INT;
|
ret = IIO_VAL_INT;
|
||||||
break;
|
break;
|
||||||
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
|
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
|
||||||
ret = mcp3911_read(adc, MCP3911_REG_CONFIG, val, 2);
|
ret = adc->chip->get_osr(adc, val);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
*val = FIELD_GET(MCP3911_CONFIG_OSR, *val);
|
|
||||||
*val = 32 << *val;
|
|
||||||
ret = IIO_VAL_INT;
|
ret = IIO_VAL_INT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -212,8 +360,8 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int mcp3911_write_raw(struct iio_dev *indio_dev,
|
static int mcp3911_write_raw(struct iio_dev *indio_dev,
|
||||||
struct iio_chan_spec const *channel, int val,
|
struct iio_chan_spec const *channel, int val,
|
||||||
int val2, long mask)
|
int val2, long mask)
|
||||||
{
|
{
|
||||||
struct mcp3911 *adc = iio_priv(indio_dev);
|
struct mcp3911 *adc = iio_priv(indio_dev);
|
||||||
int ret = -EINVAL;
|
int ret = -EINVAL;
|
||||||
@ -223,12 +371,10 @@ static int mcp3911_write_raw(struct iio_dev *indio_dev,
|
|||||||
case IIO_CHAN_INFO_SCALE:
|
case IIO_CHAN_INFO_SCALE:
|
||||||
for (int i = 0; i < MCP3911_NUM_SCALES; i++) {
|
for (int i = 0; i < MCP3911_NUM_SCALES; i++) {
|
||||||
if (val == mcp3911_scale_table[i][0] &&
|
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);
|
adc->gain[channel->channel] = BIT(i);
|
||||||
ret = mcp3911_update(adc, MCP3911_REG_GAIN,
|
ret = adc->chip->set_scale(adc, channel->channel, i);
|
||||||
MCP3911_GAIN_MASK(channel->channel),
|
|
||||||
MCP3911_GAIN_VAL(channel->channel, i), 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -238,24 +384,13 @@ static int mcp3911_write_raw(struct iio_dev *indio_dev,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write offset */
|
ret = adc->chip->set_offset(adc, channel->channel, val);
|
||||||
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);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
|
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
|
||||||
for (int i = 0; i < ARRAY_SIZE(mcp3911_osr_table); i++) {
|
for (int i = 0; i < ARRAY_SIZE(mcp3911_osr_table); i++) {
|
||||||
if (val == mcp3911_osr_table[i]) {
|
if (val == mcp3911_osr_table[i]) {
|
||||||
val = FIELD_PREP(MCP3911_CONFIG_OSR, i);
|
ret = adc->chip->set_osr(adc, i);
|
||||||
ret = mcp3911_update(adc, MCP3911_REG_CONFIG, MCP3911_CONFIG_OSR,
|
|
||||||
val, 2);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -269,6 +404,7 @@ out:
|
|||||||
|
|
||||||
static int mcp3911_calc_scale_table(struct mcp3911 *adc)
|
static int mcp3911_calc_scale_table(struct mcp3911 *adc)
|
||||||
{
|
{
|
||||||
|
struct device *dev = &adc->spi->dev;
|
||||||
u32 ref = MCP3911_INT_VREF_MV;
|
u32 ref = MCP3911_INT_VREF_MV;
|
||||||
u32 div;
|
u32 div;
|
||||||
int ret;
|
int ret;
|
||||||
@ -277,10 +413,7 @@ static int mcp3911_calc_scale_table(struct mcp3911 *adc)
|
|||||||
if (adc->vref) {
|
if (adc->vref) {
|
||||||
ret = regulator_get_voltage(adc->vref);
|
ret = regulator_get_voltage(adc->vref);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(&adc->spi->dev,
|
return dev_err_probe(dev, ret, "failed to get vref voltage\n");
|
||||||
"failed to get vref voltage: %d\n",
|
|
||||||
ret);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ref = ret / 1000;
|
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[] = {
|
static const struct iio_chan_spec mcp3911_channels[] = {
|
||||||
MCP3911_CHAN(0),
|
MCP3911_CHAN(0),
|
||||||
MCP3911_CHAN(1),
|
MCP3911_CHAN(1),
|
||||||
IIO_CHAN_SOFT_TIMESTAMP(2),
|
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)
|
static irqreturn_t mcp3911_trigger_handler(int irq, void *p)
|
||||||
{
|
{
|
||||||
struct iio_poll_func *pf = p;
|
struct iio_poll_func *pf = p;
|
||||||
struct iio_dev *indio_dev = pf->indio_dev;
|
struct iio_dev *indio_dev = pf->indio_dev;
|
||||||
struct mcp3911 *adc = iio_priv(indio_dev);
|
struct mcp3911 *adc = iio_priv(indio_dev);
|
||||||
|
struct device *dev = &adc->spi->dev;
|
||||||
struct spi_transfer xfer[] = {
|
struct spi_transfer xfer[] = {
|
||||||
{
|
{
|
||||||
.tx_buf = &adc->tx_buf,
|
.tx_buf = &adc->tx_buf,
|
||||||
.len = 1,
|
.len = 1,
|
||||||
}, {
|
}, {
|
||||||
.rx_buf = adc->rx_buf,
|
.rx_buf = adc->rx_buf,
|
||||||
.len = sizeof(adc->rx_buf),
|
.len = (adc->chip->num_channels - 1) * 3,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
int scan_index;
|
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);
|
adc->tx_buf = MCP3911_REG_READ(MCP3911_CHANNEL(0), adc->dev_addr);
|
||||||
ret = spi_sync_transfer(adc->spi, xfer, ARRAY_SIZE(xfer));
|
ret = spi_sync_transfer(adc->spi, xfer, ARRAY_SIZE(xfer));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_warn(&adc->spi->dev,
|
dev_warn(dev, "failed to get conversion data\n");
|
||||||
"failed to get conversion data\n");
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,43 +568,25 @@ static int mcp3911_config(struct mcp3911 *adc)
|
|||||||
u32 regval;
|
u32 regval;
|
||||||
int ret;
|
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, ®val, 2);
|
ret = mcp3911_read(adc, MCP3911_REG_CONFIG, ®val, 2);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
regval &= ~MCP3911_CONFIG_VREFEXT;
|
regval &= ~MCP3911_CONFIG_VREFEXT;
|
||||||
if (adc->vref) {
|
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);
|
regval |= FIELD_PREP(MCP3911_CONFIG_VREFEXT, 1);
|
||||||
} else {
|
} else {
|
||||||
dev_dbg(&adc->spi->dev,
|
dev_dbg(dev, "use internal voltage reference (1.2V)\n");
|
||||||
"use internal voltage reference (1.2V)\n");
|
|
||||||
regval |= FIELD_PREP(MCP3911_CONFIG_VREFEXT, 0);
|
regval |= FIELD_PREP(MCP3911_CONFIG_VREFEXT, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
regval &= ~MCP3911_CONFIG_CLKEXT;
|
regval &= ~MCP3911_CONFIG_CLKEXT;
|
||||||
if (adc->clki) {
|
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);
|
regval |= FIELD_PREP(MCP3911_CONFIG_CLKEXT, 1);
|
||||||
} else {
|
} else {
|
||||||
dev_dbg(&adc->spi->dev,
|
dev_dbg(dev, "use crystal oscillator as clocksource\n");
|
||||||
"use crystal oscillator as clocksource\n");
|
|
||||||
regval |= FIELD_PREP(MCP3911_CONFIG_CLKEXT, 0);
|
regval |= FIELD_PREP(MCP3911_CONFIG_CLKEXT, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,7 +602,97 @@ static int mcp3911_config(struct mcp3911 *adc)
|
|||||||
regval &= ~MCP3911_STATUSCOM_READ;
|
regval &= ~MCP3911_STATUSCOM_READ;
|
||||||
regval |= FIELD_PREP(MCP3911_STATUSCOM_READ, 0x02);
|
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, ®val, 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, ®val, 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, ®val, 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, ®val, 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)
|
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)
|
static int mcp3911_probe(struct spi_device *spi)
|
||||||
{
|
{
|
||||||
|
struct device *dev = &spi->dev;
|
||||||
struct iio_dev *indio_dev;
|
struct iio_dev *indio_dev;
|
||||||
struct mcp3911 *adc;
|
struct mcp3911 *adc;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc));
|
indio_dev = devm_iio_device_alloc(dev, sizeof(*adc));
|
||||||
if (!indio_dev)
|
if (!indio_dev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
adc = iio_priv(indio_dev);
|
adc = iio_priv(indio_dev);
|
||||||
adc->spi = spi;
|
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 (IS_ERR(adc->vref)) {
|
||||||
if (PTR_ERR(adc->vref) == -ENODEV) {
|
if (PTR_ERR(adc->vref) == -ENODEV) {
|
||||||
adc->vref = NULL;
|
adc->vref = NULL;
|
||||||
} else {
|
} else {
|
||||||
dev_err(&adc->spi->dev,
|
return dev_err_probe(dev, PTR_ERR(adc->vref), "failed to get regulator\n");
|
||||||
"failed to get regulator (%ld)\n",
|
|
||||||
PTR_ERR(adc->vref));
|
|
||||||
return PTR_ERR(adc->vref);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -493,34 +745,35 @@ static int mcp3911_probe(struct spi_device *spi)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = devm_add_action_or_reset(&spi->dev,
|
ret = devm_add_action_or_reset(dev, mcp3911_cleanup_regulator, adc->vref);
|
||||||
mcp3911_cleanup_regulator, adc->vref);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return 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 (IS_ERR(adc->clki)) {
|
||||||
if (PTR_ERR(adc->clki) == -ENOENT) {
|
if (PTR_ERR(adc->clki) == -ENOENT) {
|
||||||
adc->clki = NULL;
|
adc->clki = NULL;
|
||||||
} else {
|
} else {
|
||||||
dev_err(&adc->spi->dev,
|
return dev_err_probe(dev, PTR_ERR(adc->clki), "failed to get adc clk\n");
|
||||||
"failed to get adc clk (%ld)\n",
|
|
||||||
PTR_ERR(adc->clki));
|
|
||||||
return PTR_ERR(adc->clki);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
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 = adc->chip->config(adc);
|
||||||
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);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -528,12 +781,12 @@ static int mcp3911_probe(struct spi_device *spi)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Set gain to 1 for all channels */
|
/* Set gain to 1 for all channels */
|
||||||
for (int i = 0; i < MCP3911_NUM_CHANNELS; i++) {
|
for (int i = 0; i < adc->chip->num_channels - 1; i++) {
|
||||||
adc->gain[i] = 1;
|
adc->gain[i] = 1;
|
||||||
ret = mcp3911_update(adc, MCP3911_REG_GAIN,
|
ret = mcp3911_update(adc, MCP3911_REG_GAIN,
|
||||||
MCP3911_GAIN_MASK(i),
|
MCP3911_GAIN_MASK(i),
|
||||||
MCP3911_GAIN_VAL(i, 0), 1);
|
MCP3911_GAIN_VAL(i, 0), 1);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -543,21 +796,20 @@ static int mcp3911_probe(struct spi_device *spi)
|
|||||||
indio_dev->info = &mcp3911_info;
|
indio_dev->info = &mcp3911_info;
|
||||||
spi_set_drvdata(spi, indio_dev);
|
spi_set_drvdata(spi, indio_dev);
|
||||||
|
|
||||||
indio_dev->channels = mcp3911_channels;
|
indio_dev->channels = adc->chip->channels;
|
||||||
indio_dev->num_channels = ARRAY_SIZE(mcp3911_channels);
|
indio_dev->num_channels = adc->chip->num_channels;
|
||||||
|
|
||||||
mutex_init(&adc->lock);
|
mutex_init(&adc->lock);
|
||||||
|
|
||||||
if (spi->irq > 0) {
|
if (spi->irq > 0) {
|
||||||
adc->trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d",
|
adc->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name,
|
||||||
indio_dev->name,
|
iio_device_id(indio_dev));
|
||||||
iio_device_id(indio_dev));
|
|
||||||
if (!adc->trig)
|
if (!adc->trig)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
adc->trig->ops = &mcp3911_trigger_ops;
|
adc->trig->ops = &mcp3911_trigger_ops;
|
||||||
iio_trigger_set_drvdata(adc->trig, adc);
|
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)
|
if (ret)
|
||||||
return 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
|
* Some platforms might not allow the option to power it down so
|
||||||
* don't enable the interrupt to avoid extra load on the system.
|
* don't enable the interrupt to avoid extra load on the system.
|
||||||
*/
|
*/
|
||||||
ret = devm_request_irq(&spi->dev, spi->irq,
|
ret = devm_request_irq(dev, spi->irq, &iio_trigger_generic_data_rdy_poll,
|
||||||
&iio_trigger_generic_data_rdy_poll, IRQF_NO_AUTOEN | IRQF_ONESHOT,
|
IRQF_NO_AUTOEN | IRQF_ONESHOT,
|
||||||
indio_dev->name, adc->trig);
|
indio_dev->name, adc->trig);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
|
ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
|
||||||
NULL,
|
mcp3911_trigger_handler, NULL);
|
||||||
mcp3911_trigger_handler, NULL);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return 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[] = {
|
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);
|
MODULE_DEVICE_TABLE(of, mcp3911_dt_ids);
|
||||||
|
|
||||||
static const struct spi_device_id mcp3911_id[] = {
|
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);
|
MODULE_DEVICE_TABLE(spi, mcp3911_id);
|
||||||
|
@ -1045,8 +1045,10 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
|
|||||||
u32 regval;
|
u32 regval;
|
||||||
|
|
||||||
ret = meson_sar_adc_lock(indio_dev);
|
ret = meson_sar_adc_lock(indio_dev);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
dev_err(dev, "failed to lock adc\n");
|
||||||
goto err_lock;
|
goto err_lock;
|
||||||
|
}
|
||||||
|
|
||||||
ret = regulator_enable(priv->vref);
|
ret = regulator_enable(priv->vref);
|
||||||
if (ret < 0) {
|
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);
|
priv->regmap = devm_regmap_init_mmio(dev, base, priv->param->regmap_config);
|
||||||
if (IS_ERR(priv->regmap))
|
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);
|
irq = irq_of_parse_and_map(dev->of_node, 0);
|
||||||
if (!irq)
|
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);
|
ret = devm_request_irq(dev, irq, meson_sar_adc_irq, IRQF_SHARED, dev_name(dev), indio_dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return dev_err_probe(dev, ret, "failed to request irq\n");
|
||||||
|
|
||||||
priv->clkin = devm_clk_get(dev, "clkin");
|
priv->clkin = devm_clk_get(dev, "clkin");
|
||||||
if (IS_ERR(priv->clkin))
|
if (IS_ERR(priv->clkin))
|
||||||
@ -1384,7 +1386,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
|
|||||||
if (!priv->adc_clk) {
|
if (!priv->adc_clk) {
|
||||||
ret = meson_sar_adc_clk_init(indio_dev, base);
|
ret = meson_sar_adc_clk_init(indio_dev, base);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return dev_err_probe(dev, ret, "failed to init internal clk\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->vref = devm_regulator_get(dev, "vref");
|
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);
|
platform_set_drvdata(pdev, indio_dev);
|
||||||
|
|
||||||
ret = iio_device_register(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;
|
goto err_hw;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -1437,15 +1441,13 @@ err:
|
|||||||
return ret;
|
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);
|
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
iio_device_unregister(indio_dev);
|
iio_device_unregister(indio_dev);
|
||||||
|
|
||||||
meson_sar_adc_hw_disable(indio_dev);
|
meson_sar_adc_hw_disable(indio_dev);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int meson_sar_adc_suspend(struct device *dev)
|
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 = {
|
static struct platform_driver meson_sar_adc_driver = {
|
||||||
.probe = meson_sar_adc_probe,
|
.probe = meson_sar_adc_probe,
|
||||||
.remove = meson_sar_adc_remove,
|
.remove_new = meson_sar_adc_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "meson-saradc",
|
.name = "meson-saradc",
|
||||||
.of_match_table = meson_sar_adc_of_match,
|
.of_match_table = meson_sar_adc_of_match,
|
||||||
|
@ -171,7 +171,7 @@ fail_disable:
|
|||||||
return ret;
|
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 iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct mp2629_adc *info = iio_priv(indio_dev);
|
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);
|
MP2629_ADC_CONTINUOUS, 0);
|
||||||
regmap_update_bits(info->regmap, MP2629_REG_ADC_CTRL,
|
regmap_update_bits(info->regmap, MP2629_REG_ADC_CTRL,
|
||||||
MP2629_ADC_START, 0);
|
MP2629_ADC_START, 0);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id mp2629_adc_of_match[] = {
|
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,
|
.of_match_table = mp2629_adc_of_match,
|
||||||
},
|
},
|
||||||
.probe = mp2629_adc_probe,
|
.probe = mp2629_adc_probe,
|
||||||
.remove = mp2629_adc_remove,
|
.remove_new = mp2629_adc_remove,
|
||||||
};
|
};
|
||||||
module_platform_driver(mp2629_adc_driver);
|
module_platform_driver(mp2629_adc_driver);
|
||||||
|
|
||||||
|
@ -246,6 +246,14 @@ static int mt6577_auxadc_suspend(struct device *dev)
|
|||||||
return 0;
|
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)
|
static int mt6577_auxadc_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct mt6577_auxadc_device *adc_dev;
|
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);
|
indio_dev->num_channels = ARRAY_SIZE(mt6577_auxadc_iio_channels);
|
||||||
|
|
||||||
adc_dev->reg_base = devm_platform_ioremap_resource(pdev, 0);
|
adc_dev->reg_base = devm_platform_ioremap_resource(pdev, 0);
|
||||||
if (IS_ERR(adc_dev->reg_base)) {
|
if (IS_ERR(adc_dev->reg_base))
|
||||||
dev_err(&pdev->dev, "failed to get auxadc base address\n");
|
return dev_err_probe(&pdev->dev, PTR_ERR(adc_dev->reg_base),
|
||||||
return PTR_ERR(adc_dev->reg_base);
|
"failed to get auxadc base address\n");
|
||||||
}
|
|
||||||
|
|
||||||
adc_dev->adc_clk = devm_clk_get(&pdev->dev, "main");
|
adc_dev->adc_clk = devm_clk_get_enabled(&pdev->dev, "main");
|
||||||
if (IS_ERR(adc_dev->adc_clk)) {
|
if (IS_ERR(adc_dev->adc_clk))
|
||||||
dev_err(&pdev->dev, "failed to get auxadc clock\n");
|
return dev_err_probe(&pdev->dev, PTR_ERR(adc_dev->adc_clk),
|
||||||
return PTR_ERR(adc_dev->adc_clk);
|
"failed to enable auxadc clock\n");
|
||||||
}
|
|
||||||
|
|
||||||
ret = clk_prepare_enable(adc_dev->adc_clk);
|
|
||||||
if (ret) {
|
|
||||||
dev_err(&pdev->dev, "failed to enable auxadc clock\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
adc_clk_rate = clk_get_rate(adc_dev->adc_clk);
|
adc_clk_rate = clk_get_rate(adc_dev->adc_clk);
|
||||||
if (!adc_clk_rate) {
|
if (!adc_clk_rate)
|
||||||
ret = -EINVAL;
|
return dev_err_probe(&pdev->dev, -EINVAL, "null clock rate\n");
|
||||||
dev_err(&pdev->dev, "null clock rate\n");
|
|
||||||
goto err_disable_clk;
|
|
||||||
}
|
|
||||||
|
|
||||||
adc_dev->dev_comp = device_get_match_data(&pdev->dev);
|
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_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
|
||||||
MT6577_AUXADC_PDN_EN, 0);
|
MT6577_AUXADC_PDN_EN, 0);
|
||||||
mdelay(MT6577_AUXADC_POWER_READY_MS);
|
mdelay(MT6577_AUXADC_POWER_READY_MS);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, indio_dev);
|
platform_set_drvdata(pdev, indio_dev);
|
||||||
|
|
||||||
ret = iio_device_register(indio_dev);
|
ret = devm_add_action_or_reset(&pdev->dev, mt6577_power_off, adc_dev);
|
||||||
if (ret < 0) {
|
if (ret)
|
||||||
dev_err(&pdev->dev, "failed to register iio device\n");
|
return dev_err_probe(&pdev->dev, ret,
|
||||||
goto err_power_off;
|
"Failed to add action to managed power off\n");
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
ret = devm_iio_device_register(&pdev->dev, indio_dev);
|
||||||
|
if (ret < 0)
|
||||||
err_power_off:
|
return dev_err_probe(&pdev->dev, ret, "failed to register iio device\n");
|
||||||
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);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -352,7 +329,6 @@ static struct platform_driver mt6577_auxadc_driver = {
|
|||||||
.pm = pm_sleep_ptr(&mt6577_auxadc_pm_ops),
|
.pm = pm_sleep_ptr(&mt6577_auxadc_pm_ops),
|
||||||
},
|
},
|
||||||
.probe = mt6577_auxadc_probe,
|
.probe = mt6577_auxadc_probe,
|
||||||
.remove = mt6577_auxadc_remove,
|
|
||||||
};
|
};
|
||||||
module_platform_driver(mt6577_auxadc_driver);
|
module_platform_driver(mt6577_auxadc_driver);
|
||||||
|
|
||||||
|
@ -807,7 +807,7 @@ err_trig:
|
|||||||
return ret;
|
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 iio_dev *iio = platform_get_drvdata(pdev);
|
||||||
struct mxs_lradc_adc *adc = iio_priv(iio);
|
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);
|
mxs_lradc_adc_hw_stop(adc);
|
||||||
iio_triggered_buffer_cleanup(iio);
|
iio_triggered_buffer_cleanup(iio);
|
||||||
mxs_lradc_adc_trigger_remove(iio);
|
mxs_lradc_adc_trigger_remove(iio);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct platform_driver mxs_lradc_adc_driver = {
|
static struct platform_driver mxs_lradc_adc_driver = {
|
||||||
@ -825,7 +823,7 @@ static struct platform_driver mxs_lradc_adc_driver = {
|
|||||||
.name = "mxs-lradc-adc",
|
.name = "mxs-lradc-adc",
|
||||||
},
|
},
|
||||||
.probe = mxs_lradc_adc_probe,
|
.probe = mxs_lradc_adc_probe,
|
||||||
.remove = mxs_lradc_adc_remove,
|
.remove_new = mxs_lradc_adc_remove,
|
||||||
};
|
};
|
||||||
module_platform_driver(mxs_lradc_adc_driver);
|
module_platform_driver(mxs_lradc_adc_driver);
|
||||||
|
|
||||||
|
@ -320,7 +320,7 @@ err_disable_clk:
|
|||||||
return ret;
|
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 iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct npcm_adc *info = iio_priv(indio_dev);
|
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))
|
if (!IS_ERR(info->vref))
|
||||||
regulator_disable(info->vref);
|
regulator_disable(info->vref);
|
||||||
clk_disable_unprepare(info->adc_clk);
|
clk_disable_unprepare(info->adc_clk);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct platform_driver npcm_adc_driver = {
|
static struct platform_driver npcm_adc_driver = {
|
||||||
.probe = npcm_adc_probe,
|
.probe = npcm_adc_probe,
|
||||||
.remove = npcm_adc_remove,
|
.remove_new = npcm_adc_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "npcm_adc",
|
.name = "npcm_adc",
|
||||||
.of_match_table = npcm_adc_match,
|
.of_match_table = npcm_adc_match,
|
||||||
|
@ -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 include both gain error, as specified in the datasheet, and
|
||||||
* the gain error drift. These paramenters vary depending on device and whether
|
* 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,
|
static int palmas_gpadc_threshold_with_tolerance(int val, const int INL,
|
||||||
const int gain_error,
|
const int gain_error,
|
||||||
|
@ -957,7 +957,7 @@ out_disable_vref:
|
|||||||
return ret;
|
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 iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct pm8xxx_xoadc *adc = iio_priv(indio_dev);
|
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);
|
iio_device_unregister(indio_dev);
|
||||||
|
|
||||||
regulator_disable(adc->vref);
|
regulator_disable(adc->vref);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct xoadc_variant pm8018_variant = {
|
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,
|
.of_match_table = pm8xxx_xoadc_id_table,
|
||||||
},
|
},
|
||||||
.probe = pm8xxx_xoadc_probe,
|
.probe = pm8xxx_xoadc_probe,
|
||||||
.remove = pm8xxx_xoadc_remove,
|
.remove_new = pm8xxx_xoadc_remove,
|
||||||
};
|
};
|
||||||
module_platform_driver(pm8xxx_xoadc_driver);
|
module_platform_driver(pm8xxx_xoadc_driver);
|
||||||
|
|
||||||
|
@ -559,7 +559,7 @@ err_clk_if_enable:
|
|||||||
return ret;
|
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 iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct rcar_gyroadc *priv = iio_priv(indio_dev);
|
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);
|
pm_runtime_set_suspended(dev);
|
||||||
clk_disable_unprepare(priv->clk);
|
clk_disable_unprepare(priv->clk);
|
||||||
rcar_gyroadc_deinit_supplies(indio_dev);
|
rcar_gyroadc_deinit_supplies(indio_dev);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rcar_gyroadc_suspend(struct device *dev)
|
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 = {
|
static struct platform_driver rcar_gyroadc_driver = {
|
||||||
.probe = rcar_gyroadc_probe,
|
.probe = rcar_gyroadc_probe,
|
||||||
.remove = rcar_gyroadc_remove,
|
.remove_new = rcar_gyroadc_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = DRIVER_NAME,
|
.name = DRIVER_NAME,
|
||||||
.of_match_table = rcar_gyroadc_match,
|
.of_match_table = rcar_gyroadc_match,
|
||||||
|
@ -274,10 +274,9 @@ static int spear_adc_probe(struct platform_device *pdev)
|
|||||||
int irq;
|
int irq;
|
||||||
|
|
||||||
indio_dev = devm_iio_device_alloc(dev, sizeof(struct spear_adc_state));
|
indio_dev = devm_iio_device_alloc(dev, sizeof(struct spear_adc_state));
|
||||||
if (!indio_dev) {
|
if (!indio_dev)
|
||||||
dev_err(dev, "failed allocating iio device\n");
|
return dev_err_probe(dev, -ENOMEM,
|
||||||
return -ENOMEM;
|
"failed allocating iio device\n");
|
||||||
}
|
|
||||||
|
|
||||||
st = iio_priv(indio_dev);
|
st = iio_priv(indio_dev);
|
||||||
|
|
||||||
@ -297,37 +296,24 @@ static int spear_adc_probe(struct platform_device *pdev)
|
|||||||
st->adc_base_spear3xx =
|
st->adc_base_spear3xx =
|
||||||
(struct adc_regs_spear3xx __iomem *)st->adc_base_spear6xx;
|
(struct adc_regs_spear3xx __iomem *)st->adc_base_spear6xx;
|
||||||
|
|
||||||
st->clk = devm_clk_get(dev, NULL);
|
st->clk = devm_clk_get_enabled(dev, NULL);
|
||||||
if (IS_ERR(st->clk)) {
|
if (IS_ERR(st->clk))
|
||||||
dev_err(dev, "failed getting clock\n");
|
return dev_err_probe(dev, PTR_ERR(st->clk),
|
||||||
return PTR_ERR(st->clk);
|
"failed enabling clock\n");
|
||||||
}
|
|
||||||
|
|
||||||
ret = clk_prepare_enable(st->clk);
|
|
||||||
if (ret) {
|
|
||||||
dev_err(dev, "failed enabling clock\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (irq < 0) {
|
if (irq < 0)
|
||||||
ret = irq;
|
return irq;
|
||||||
goto errout2;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = devm_request_irq(dev, irq, spear_adc_isr, 0, SPEAR_ADC_MOD_NAME,
|
ret = devm_request_irq(dev, irq, spear_adc_isr, 0, SPEAR_ADC_MOD_NAME,
|
||||||
st);
|
st);
|
||||||
if (ret < 0) {
|
if (ret < 0)
|
||||||
dev_err(dev, "failed requesting interrupt\n");
|
return dev_err_probe(dev, ret, "failed requesting interrupt\n");
|
||||||
goto errout2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (of_property_read_u32(np, "sampling-frequency",
|
if (of_property_read_u32(np, "sampling-frequency",
|
||||||
&st->sampling_freq)) {
|
&st->sampling_freq))
|
||||||
dev_err(dev, "sampling-frequency missing in DT\n");
|
return dev_err_probe(dev, -EINVAL,
|
||||||
ret = -EINVAL;
|
"sampling-frequency missing in DT\n");
|
||||||
goto errout2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Optional avg_samples defaults to 0, resulting in single data
|
* 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);
|
spear_adc_configure(st);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, indio_dev);
|
|
||||||
|
|
||||||
init_completion(&st->completion);
|
init_completion(&st->completion);
|
||||||
|
|
||||||
indio_dev->name = SPEAR_ADC_MOD_NAME;
|
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->channels = spear_adc_iio_channels;
|
||||||
indio_dev->num_channels = ARRAY_SIZE(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)
|
if (ret)
|
||||||
goto errout2;
|
return ret;
|
||||||
|
|
||||||
dev_info(dev, "SPEAR ADC driver loaded, IRQ %d\n", irq);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,7 +356,6 @@ MODULE_DEVICE_TABLE(of, spear_adc_dt_ids);
|
|||||||
|
|
||||||
static struct platform_driver spear_adc_driver = {
|
static struct platform_driver spear_adc_driver = {
|
||||||
.probe = spear_adc_probe,
|
.probe = spear_adc_probe,
|
||||||
.remove = spear_adc_remove,
|
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = SPEAR_ADC_MOD_NAME,
|
.name = SPEAR_ADC_MOD_NAME,
|
||||||
.of_match_table = of_match_ptr(spear_adc_dt_ids),
|
.of_match_table = of_match_ptr(spear_adc_dt_ids),
|
||||||
|
@ -17,10 +17,11 @@
|
|||||||
#include <linux/irqdomain.h>
|
#include <linux/irqdomain.h>
|
||||||
#include <linux/mfd/syscon.h>
|
#include <linux/mfd/syscon.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/property.h>
|
||||||
#include <linux/regmap.h>
|
#include <linux/regmap.h>
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
@ -720,8 +721,7 @@ static int stm32_adc_probe(struct platform_device *pdev)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
platform_set_drvdata(pdev, &priv->common);
|
platform_set_drvdata(pdev, &priv->common);
|
||||||
|
|
||||||
priv->cfg = (const struct stm32_adc_priv_cfg *)
|
priv->cfg = device_get_match_data(dev);
|
||||||
of_match_device(dev->driver->of_match_table, dev)->data;
|
|
||||||
priv->nb_adc_max = priv->cfg->num_adcs;
|
priv->nb_adc_max = priv->cfg->num_adcs;
|
||||||
spin_lock_init(&priv->common.lock);
|
spin_lock_init(&priv->common.lock);
|
||||||
|
|
||||||
@ -814,7 +814,7 @@ err_pm_stop:
|
|||||||
return ret;
|
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_common *common = platform_get_drvdata(pdev);
|
||||||
struct stm32_adc_priv *priv = to_stm32_adc_priv(common);
|
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_disable(&pdev->dev);
|
||||||
pm_runtime_set_suspended(&pdev->dev);
|
pm_runtime_set_suspended(&pdev->dev);
|
||||||
pm_runtime_put_noidle(&pdev->dev);
|
pm_runtime_put_noidle(&pdev->dev);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stm32_adc_core_runtime_suspend(struct device *dev)
|
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 = {
|
static struct platform_driver stm32_adc_driver = {
|
||||||
.probe = stm32_adc_probe,
|
.probe = stm32_adc_probe,
|
||||||
.remove = stm32_adc_remove,
|
.remove_new = stm32_adc_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "stm32-adc-core",
|
.name = "stm32-adc-core",
|
||||||
.of_match_table = stm32_adc_of_match,
|
.of_match_table = stm32_adc_of_match,
|
||||||
|
@ -2209,7 +2209,7 @@ static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev,
|
|||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto err;
|
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);
|
ret = stm32_adc_populate_int_ch(indio_dev, name, val);
|
||||||
if (ret == -ENOENT)
|
if (ret == -ENOENT)
|
||||||
continue;
|
continue;
|
||||||
@ -2513,7 +2513,7 @@ err_dma_disable:
|
|||||||
return ret;
|
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 iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct stm32_adc *adc = iio_priv(indio_dev);
|
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);
|
adc->rx_buf, adc->rx_dma_buf);
|
||||||
dma_release_channel(adc->dma_chan);
|
dma_release_channel(adc->dma_chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stm32_adc_suspend(struct device *dev)
|
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 = {
|
static struct platform_driver stm32_adc_driver = {
|
||||||
.probe = stm32_adc_probe,
|
.probe = stm32_adc_probe,
|
||||||
.remove = stm32_adc_remove,
|
.remove_new = stm32_adc_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "stm32-adc",
|
.name = "stm32-adc",
|
||||||
.of_match_table = stm32_adc_of_match,
|
.of_match_table = stm32_adc_of_match,
|
||||||
|
@ -1620,7 +1620,7 @@ err_cleanup:
|
|||||||
return ret;
|
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 iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
|
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);
|
of_platform_depopulate(&pdev->dev);
|
||||||
iio_device_unregister(indio_dev);
|
iio_device_unregister(indio_dev);
|
||||||
stm32_dfsdm_dma_release(indio_dev);
|
stm32_dfsdm_dma_release(indio_dev);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stm32_dfsdm_adc_suspend(struct device *dev)
|
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),
|
.pm = pm_sleep_ptr(&stm32_dfsdm_adc_pm_ops),
|
||||||
},
|
},
|
||||||
.probe = stm32_dfsdm_adc_probe,
|
.probe = stm32_dfsdm_adc_probe,
|
||||||
.remove = stm32_dfsdm_adc_remove,
|
.remove_new = stm32_dfsdm_adc_remove,
|
||||||
};
|
};
|
||||||
module_platform_driver(stm32_dfsdm_adc_driver);
|
module_platform_driver(stm32_dfsdm_adc_driver);
|
||||||
|
|
||||||
|
@ -436,7 +436,7 @@ pm_put:
|
|||||||
return ret;
|
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);
|
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_set_suspended(&pdev->dev);
|
||||||
pm_runtime_put_noidle(&pdev->dev);
|
pm_runtime_put_noidle(&pdev->dev);
|
||||||
stm32_dfsdm_clk_disable_unprepare(dfsdm);
|
stm32_dfsdm_clk_disable_unprepare(dfsdm);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stm32_dfsdm_core_suspend(struct device *dev)
|
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 = {
|
static struct platform_driver stm32_dfsdm_driver = {
|
||||||
.probe = stm32_dfsdm_probe,
|
.probe = stm32_dfsdm_probe,
|
||||||
.remove = stm32_dfsdm_core_remove,
|
.remove_new = stm32_dfsdm_core_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "stm32-dfsdm",
|
.name = "stm32-dfsdm",
|
||||||
.of_match_table = stm32_dfsdm_of_match,
|
.of_match_table = stm32_dfsdm_of_match,
|
||||||
|
@ -669,7 +669,7 @@ err_map:
|
|||||||
return ret;
|
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 iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
|
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);
|
pm_runtime_disable(&pdev->dev);
|
||||||
|
|
||||||
if (!IS_ENABLED(CONFIG_THERMAL_OF))
|
if (!IS_ENABLED(CONFIG_THERMAL_OF))
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
if (!info->no_irq)
|
if (!info->no_irq)
|
||||||
iio_map_array_unregister(indio_dev);
|
iio_map_array_unregister(indio_dev);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct platform_device_id sun4i_gpadc_id[] = {
|
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,
|
.id_table = sun4i_gpadc_id,
|
||||||
.probe = sun4i_gpadc_probe,
|
.probe = sun4i_gpadc_probe,
|
||||||
.remove = sun4i_gpadc_remove,
|
.remove_new = sun4i_gpadc_remove,
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, sun4i_gpadc_of_id);
|
MODULE_DEVICE_TABLE(of, sun4i_gpadc_of_id);
|
||||||
|
|
||||||
|
@ -154,7 +154,6 @@ static void adc081c_reg_disable(void *reg)
|
|||||||
|
|
||||||
static int adc081c_probe(struct i2c_client *client)
|
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 iio_dev *iio;
|
||||||
struct adc081c *adc;
|
struct adc081c *adc;
|
||||||
const struct adcxx1c_model *model;
|
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))
|
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (dev_fwnode(&client->dev))
|
model = i2c_get_match_data(client);
|
||||||
model = device_get_match_data(&client->dev);
|
|
||||||
else
|
|
||||||
model = &adcxx1c_models[id->driver_data];
|
|
||||||
|
|
||||||
iio = devm_iio_device_alloc(&client->dev, sizeof(*adc));
|
iio = devm_iio_device_alloc(&client->dev, sizeof(*adc));
|
||||||
if (!iio)
|
if (!iio)
|
||||||
@ -207,9 +203,9 @@ static int adc081c_probe(struct i2c_client *client)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct i2c_device_id adc081c_id[] = {
|
static const struct i2c_device_id adc081c_id[] = {
|
||||||
{ "adc081c", ADC081C },
|
{ "adc081c", (kernel_ulong_t)&adcxx1c_models[ADC081C] },
|
||||||
{ "adc101c", ADC101C },
|
{ "adc101c", (kernel_ulong_t)&adcxx1c_models[ADC101C] },
|
||||||
{ "adc121c", ADC121C },
|
{ "adc121c", (kernel_ulong_t)&adcxx1c_models[ADC121C] },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, adc081c_id);
|
MODULE_DEVICE_TABLE(i2c, adc081c_id);
|
||||||
|
@ -976,16 +976,13 @@ static int ads1015_set_conv_mode(struct ads1015_data *data, int mode)
|
|||||||
|
|
||||||
static int ads1015_probe(struct i2c_client *client)
|
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;
|
const struct ads1015_chip_data *chip;
|
||||||
struct iio_dev *indio_dev;
|
struct iio_dev *indio_dev;
|
||||||
struct ads1015_data *data;
|
struct ads1015_data *data;
|
||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
chip = device_get_match_data(&client->dev);
|
chip = i2c_get_match_data(client);
|
||||||
if (!chip)
|
|
||||||
chip = (const struct ads1015_chip_data *)id->driver_data;
|
|
||||||
if (!chip)
|
if (!chip)
|
||||||
return dev_err_probe(&client->dev, -EINVAL, "Unknown chip\n");
|
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;
|
1 << ADS1015_CFG_COMP_LAT_SHIFT;
|
||||||
|
|
||||||
switch (irq_trig) {
|
switch (irq_trig) {
|
||||||
|
case IRQF_TRIGGER_FALLING:
|
||||||
case IRQF_TRIGGER_LOW:
|
case IRQF_TRIGGER_LOW:
|
||||||
cfg_comp |= ADS1015_CFG_COMP_POL_LOW <<
|
cfg_comp |= ADS1015_CFG_COMP_POL_LOW <<
|
||||||
ADS1015_CFG_COMP_POL_SHIFT;
|
ADS1015_CFG_COMP_POL_SHIFT;
|
||||||
break;
|
break;
|
||||||
case IRQF_TRIGGER_HIGH:
|
case IRQF_TRIGGER_HIGH:
|
||||||
|
case IRQF_TRIGGER_RISING:
|
||||||
cfg_comp |= ADS1015_CFG_COMP_POL_HIGH <<
|
cfg_comp |= ADS1015_CFG_COMP_POL_HIGH <<
|
||||||
ADS1015_CFG_COMP_POL_SHIFT;
|
ADS1015_CFG_COMP_POL_SHIFT;
|
||||||
break;
|
break;
|
||||||
|
@ -681,7 +681,7 @@ err_dma:
|
|||||||
return err;
|
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 iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct tiadc_device *adc_dev = iio_priv(indio_dev);
|
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);
|
step_en = get_adc_step_mask(adc_dev);
|
||||||
am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
|
am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tiadc_suspend(struct device *dev)
|
static int tiadc_suspend(struct device *dev)
|
||||||
@ -747,7 +745,7 @@ static struct platform_driver tiadc_driver = {
|
|||||||
.of_match_table = ti_adc_dt_ids,
|
.of_match_table = ti_adc_dt_ids,
|
||||||
},
|
},
|
||||||
.probe = tiadc_probe,
|
.probe = tiadc_probe,
|
||||||
.remove = tiadc_remove,
|
.remove_new = tiadc_remove,
|
||||||
};
|
};
|
||||||
module_platform_driver(tiadc_driver);
|
module_platform_driver(tiadc_driver);
|
||||||
|
|
||||||
|
@ -892,7 +892,7 @@ err_current_generator:
|
|||||||
return ret;
|
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 iio_dev *iio_dev = platform_get_drvdata(pdev);
|
||||||
struct twl4030_madc_data *madc = iio_priv(iio_dev);
|
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);
|
twl4030_madc_set_power(madc, 0);
|
||||||
|
|
||||||
regulator_disable(madc->usb3v1);
|
regulator_disable(madc->usb3v1);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_OF
|
#ifdef CONFIG_OF
|
||||||
@ -917,7 +915,7 @@ MODULE_DEVICE_TABLE(of, twl_madc_of_match);
|
|||||||
|
|
||||||
static struct platform_driver twl4030_madc_driver = {
|
static struct platform_driver twl4030_madc_driver = {
|
||||||
.probe = twl4030_madc_probe,
|
.probe = twl4030_madc_probe,
|
||||||
.remove = twl4030_madc_remove,
|
.remove_new = twl4030_madc_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "twl4030_madc",
|
.name = "twl4030_madc",
|
||||||
.of_match_table = of_match_ptr(twl_madc_of_match),
|
.of_match_table = of_match_ptr(twl_madc_of_match),
|
||||||
|
@ -16,9 +16,10 @@
|
|||||||
*/
|
*/
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/mod_devicetable.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/property.h>
|
||||||
#include <linux/mfd/twl.h>
|
#include <linux/mfd/twl.h>
|
||||||
#include <linux/iio/iio.h>
|
#include <linux/iio/iio.h>
|
||||||
#include <linux/iio/sysfs.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 device *dev = &pdev->dev;
|
||||||
struct twl6030_gpadc_data *gpadc;
|
struct twl6030_gpadc_data *gpadc;
|
||||||
const struct twl6030_gpadc_platform_data *pdata;
|
const struct twl6030_gpadc_platform_data *pdata;
|
||||||
const struct of_device_id *match;
|
|
||||||
struct iio_dev *indio_dev;
|
struct iio_dev *indio_dev;
|
||||||
int irq;
|
int irq;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
match = of_match_device(of_twl6030_match_tbl, dev);
|
pdata = device_get_match_data(&pdev->dev);
|
||||||
if (!match)
|
if (!pdata)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
pdata = match->data;
|
|
||||||
|
|
||||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*gpadc));
|
indio_dev = devm_iio_device_alloc(dev, sizeof(*gpadc));
|
||||||
if (!indio_dev)
|
if (!indio_dev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -968,14 +966,12 @@ static int twl6030_gpadc_probe(struct platform_device *pdev)
|
|||||||
return iio_device_register(indio_dev);
|
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);
|
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
twl6030_gpadc_disable_irq(TWL6030_GPADC_RT_SW1_EOC_MASK);
|
twl6030_gpadc_disable_irq(TWL6030_GPADC_RT_SW1_EOC_MASK);
|
||||||
iio_device_unregister(indio_dev);
|
iio_device_unregister(indio_dev);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int twl6030_gpadc_suspend(struct device *pdev)
|
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 = {
|
static struct platform_driver twl6030_gpadc_driver = {
|
||||||
.probe = twl6030_gpadc_probe,
|
.probe = twl6030_gpadc_probe,
|
||||||
.remove = twl6030_gpadc_remove,
|
.remove_new = twl6030_gpadc_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = DRIVER_NAME,
|
.name = DRIVER_NAME,
|
||||||
.pm = pm_sleep_ptr(&twl6030_gpadc_pm_ops),
|
.pm = pm_sleep_ptr(&twl6030_gpadc_pm_ops),
|
||||||
|
@ -916,7 +916,7 @@ error_adc_clk_enable:
|
|||||||
return ret;
|
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 iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct vf610_adc *info = iio_priv(indio_dev);
|
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);
|
iio_triggered_buffer_cleanup(indio_dev);
|
||||||
regulator_disable(info->vref);
|
regulator_disable(info->vref);
|
||||||
clk_disable_unprepare(info->clk);
|
clk_disable_unprepare(info->clk);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vf610_adc_suspend(struct device *dev)
|
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 = {
|
static struct platform_driver vf610_adc_driver = {
|
||||||
.probe = vf610_adc_probe,
|
.probe = vf610_adc_probe,
|
||||||
.remove = vf610_adc_remove,
|
.remove_new = vf610_adc_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = DRIVER_NAME,
|
.name = DRIVER_NAME,
|
||||||
.of_match_table = vf610_adc_match,
|
.of_match_table = vf610_adc_match,
|
||||||
|
@ -40,6 +40,7 @@ config STX104
|
|||||||
select REGMAP_MMIO
|
select REGMAP_MMIO
|
||||||
select GPIOLIB
|
select GPIOLIB
|
||||||
select GPIO_REGMAP
|
select GPIO_REGMAP
|
||||||
|
select I8254
|
||||||
help
|
help
|
||||||
Say yes here to build support for the Apex Embedded Systems STX104
|
Say yes here to build support for the Apex Embedded Systems STX104
|
||||||
integrated analog PC/104 card.
|
integrated analog PC/104 card.
|
||||||
|
@ -441,12 +441,30 @@ static int ad74413r_set_channel_function(struct ad74413r_state *st,
|
|||||||
{
|
{
|
||||||
int ret;
|
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,
|
ret = regmap_update_bits(st->regmap,
|
||||||
AD74413R_REG_CH_FUNC_SETUP_X(channel),
|
AD74413R_REG_CH_FUNC_SETUP_X(channel),
|
||||||
AD74413R_CH_FUNC_SETUP_MASK, func);
|
AD74413R_CH_FUNC_SETUP_MASK, func);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/* Delay required before updating the new DAC code */
|
||||||
|
usleep_range(150, 170);
|
||||||
|
|
||||||
if (func == CH_FUNC_CURRENT_INPUT_LOOP_POWER)
|
if (func == CH_FUNC_CURRENT_INPUT_LOOP_POWER)
|
||||||
ret = regmap_set_bits(st->regmap,
|
ret = regmap_set_bits(st->regmap,
|
||||||
AD74413R_REG_ADC_CONFIG_X(channel),
|
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;
|
return IIO_VAL_FRACTIONAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ad74413_get_input_current_offset(struct ad74413r_state *st,
|
static int ad74413r_get_input_current_offset(struct ad74413r_state *st,
|
||||||
unsigned int channel, int *val)
|
unsigned int channel, int *val)
|
||||||
{
|
{
|
||||||
unsigned int range;
|
unsigned int range;
|
||||||
int voltage_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,
|
return ad74413r_get_input_voltage_offset(st,
|
||||||
chan->channel, val);
|
chan->channel, val);
|
||||||
case IIO_CURRENT:
|
case IIO_CURRENT:
|
||||||
return ad74413_get_input_current_offset(st,
|
return ad74413r_get_input_current_offset(st,
|
||||||
chan->channel, val);
|
chan->channel, val);
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/gpio/regmap.h>
|
#include <linux/gpio/regmap.h>
|
||||||
|
#include <linux/i8254.h>
|
||||||
#include <linux/iio/iio.h>
|
#include <linux/iio/iio.h>
|
||||||
#include <linux/iio/types.h>
|
#include <linux/iio/types.h>
|
||||||
#include <linux/isa.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_STATUS (STX104_AIO_BASE + 0x8)
|
||||||
#define STX104_ADC_CONTROL (STX104_AIO_BASE + 0x9)
|
#define STX104_ADC_CONTROL (STX104_AIO_BASE + 0x9)
|
||||||
#define STX104_ADC_CONFIGURATION (STX104_AIO_BASE + 0x11)
|
#define STX104_ADC_CONFIGURATION (STX104_AIO_BASE + 0x11)
|
||||||
|
#define STX104_I8254_BASE (STX104_AIO_BASE + 0x12)
|
||||||
|
|
||||||
#define STX104_AIO_DATA_STRIDE 2
|
#define STX104_AIO_DATA_STRIDE 2
|
||||||
#define STX104_DAC_OFFSET(_channel) (STX104_DAC_BASE + STX104_AIO_DATA_STRIDE * (_channel))
|
#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 */
|
/* ADC Configuration */
|
||||||
#define STX104_GAIN GENMASK(1, 0)
|
#define STX104_GAIN GENMASK(1, 0)
|
||||||
#define STX104_ADBU BIT(2)
|
#define STX104_ADBU BIT(2)
|
||||||
|
#define STX104_RBK GENMASK(7, 4)
|
||||||
#define STX104_BIPOLAR 0
|
#define STX104_BIPOLAR 0
|
||||||
#define STX104_GAIN_X1 0
|
#define STX104_GAIN_X1 0
|
||||||
#define STX104_GAIN_X2 1
|
#define STX104_GAIN_X2 1
|
||||||
@ -168,6 +171,32 @@ static const struct regmap_config dio_regmap_config = {
|
|||||||
.io_port = true,
|
.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,
|
static int stx104_read_raw(struct iio_dev *indio_dev,
|
||||||
struct iio_chan_spec const *chan, int *val, int *val2, long mask)
|
struct iio_chan_spec const *chan, int *val, int *val2, long mask)
|
||||||
{
|
{
|
||||||
@ -339,6 +368,21 @@ static const char *stx104_names[STX104_NGPIO] = {
|
|||||||
"DIN0", "DIN1", "DIN2", "DIN3", "DOUT0", "DOUT1", "DOUT2", "DOUT3"
|
"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)
|
static int stx104_init_hw(struct stx104_iio *const priv)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
@ -361,7 +405,7 @@ static int stx104_init_hw(struct stx104_iio *const priv)
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
return 0;
|
return bank_select_i8254(priv->aio_ctl_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stx104_probe(struct device *dev, unsigned int id)
|
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 iio_dev *indio_dev;
|
||||||
struct stx104_iio *priv;
|
struct stx104_iio *priv;
|
||||||
struct gpio_regmap_config gpio_config;
|
struct gpio_regmap_config gpio_config;
|
||||||
|
struct i8254_regmap_config pit_config;
|
||||||
void __iomem *stx104_base;
|
void __iomem *stx104_base;
|
||||||
struct regmap *aio_ctl_map;
|
struct regmap *aio_ctl_map;
|
||||||
struct regmap *aio_data_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),
|
return dev_err_probe(dev, PTR_ERR(dio_map),
|
||||||
"Unable to initialize dio register map\n");
|
"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 = iio_priv(indio_dev);
|
||||||
priv->aio_ctl_map = aio_ctl_map;
|
priv->aio_ctl_map = aio_ctl_map;
|
||||||
priv->aio_data_map = aio_data_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,
|
.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 = {
|
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_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
|
||||||
MODULE_DESCRIPTION("Apex Embedded Systems STX104 IIO driver");
|
MODULE_DESCRIPTION("Apex Embedded Systems STX104 IIO driver");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
MODULE_IMPORT_NS(I8254);
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
enum hmc425a_type {
|
enum hmc425a_type {
|
||||||
ID_HMC425A,
|
ID_HMC425A,
|
||||||
|
ID_HMC540S,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hmc425a_chip_info {
|
struct hmc425a_chip_info {
|
||||||
@ -70,6 +71,9 @@ static int hmc425a_read_raw(struct iio_dev *indio_dev,
|
|||||||
case ID_HMC425A:
|
case ID_HMC425A:
|
||||||
gain = ~code * -500;
|
gain = ~code * -500;
|
||||||
break;
|
break;
|
||||||
|
case ID_HMC540S:
|
||||||
|
gain = ~code * -1000;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*val = gain / 1000;
|
*val = gain / 1000;
|
||||||
@ -106,6 +110,9 @@ static int hmc425a_write_raw(struct iio_dev *indio_dev,
|
|||||||
case ID_HMC425A:
|
case ID_HMC425A:
|
||||||
code = ~((abs(gain) / 500) & 0x3F);
|
code = ~((abs(gain) / 500) & 0x3F);
|
||||||
break;
|
break;
|
||||||
|
case ID_HMC540S:
|
||||||
|
code = ~((abs(gain) / 1000) & 0xF);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&st->lock);
|
mutex_lock(&st->lock);
|
||||||
@ -157,6 +164,7 @@ static const struct iio_chan_spec hmc425a_channels[] = {
|
|||||||
/* Match table for of_platform binding */
|
/* Match table for of_platform binding */
|
||||||
static const struct of_device_id hmc425a_of_match[] = {
|
static const struct of_device_id hmc425a_of_match[] = {
|
||||||
{ .compatible = "adi,hmc425a", .data = (void *)ID_HMC425A },
|
{ .compatible = "adi,hmc425a", .data = (void *)ID_HMC425A },
|
||||||
|
{ .compatible = "adi,hmc540s", .data = (void *)ID_HMC540S },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, hmc425a_of_match);
|
MODULE_DEVICE_TABLE(of, hmc425a_of_match);
|
||||||
@ -171,6 +179,15 @@ static struct hmc425a_chip_info hmc425a_chip_info_tbl[] = {
|
|||||||
.gain_max = 0,
|
.gain_max = 0,
|
||||||
.default_gain = -0x40, /* set default gain -31.5db*/
|
.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)
|
static int hmc425a_probe(struct platform_device *pdev)
|
||||||
|
@ -203,7 +203,6 @@ MODULE_DEVICE_TABLE(of, atlas_ezo_dt_ids);
|
|||||||
|
|
||||||
static int atlas_ezo_probe(struct i2c_client *client)
|
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;
|
const struct atlas_ezo_device *chip;
|
||||||
struct atlas_ezo_data *data;
|
struct atlas_ezo_data *data;
|
||||||
struct iio_dev *indio_dev;
|
struct iio_dev *indio_dev;
|
||||||
@ -212,10 +211,7 @@ static int atlas_ezo_probe(struct i2c_client *client)
|
|||||||
if (!indio_dev)
|
if (!indio_dev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (dev_fwnode(&client->dev))
|
chip = i2c_get_match_data(client);
|
||||||
chip = device_get_match_data(&client->dev);
|
|
||||||
else
|
|
||||||
chip = (const struct atlas_ezo_device *)id->driver_data;
|
|
||||||
if (!chip)
|
if (!chip)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ enum {
|
|||||||
struct atlas_data {
|
struct atlas_data {
|
||||||
struct i2c_client *client;
|
struct i2c_client *client;
|
||||||
struct iio_trigger *trig;
|
struct iio_trigger *trig;
|
||||||
struct atlas_device *chip;
|
const struct atlas_device *chip;
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
struct irq_work work;
|
struct irq_work work;
|
||||||
unsigned int interrupt_enabled;
|
unsigned int interrupt_enabled;
|
||||||
@ -353,7 +353,7 @@ struct atlas_device {
|
|||||||
int delay;
|
int delay;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct atlas_device atlas_devices[] = {
|
static const struct atlas_device atlas_devices[] = {
|
||||||
[ATLAS_PH_SM] = {
|
[ATLAS_PH_SM] = {
|
||||||
.channels = atlas_ph_channels,
|
.channels = atlas_ph_channels,
|
||||||
.num_channels = 3,
|
.num_channels = 3,
|
||||||
@ -589,30 +589,29 @@ static const struct iio_info atlas_info = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct i2c_device_id atlas_id[] = {
|
static const struct i2c_device_id atlas_id[] = {
|
||||||
{ "atlas-ph-sm", ATLAS_PH_SM },
|
{ "atlas-ph-sm", (kernel_ulong_t)&atlas_devices[ATLAS_PH_SM] },
|
||||||
{ "atlas-ec-sm", ATLAS_EC_SM },
|
{ "atlas-ec-sm", (kernel_ulong_t)&atlas_devices[ATLAS_EC_SM] },
|
||||||
{ "atlas-orp-sm", ATLAS_ORP_SM },
|
{ "atlas-orp-sm", (kernel_ulong_t)&atlas_devices[ATLAS_ORP_SM] },
|
||||||
{ "atlas-do-sm", ATLAS_DO_SM },
|
{ "atlas-do-sm", (kernel_ulong_t)&atlas_devices[ATLAS_DO_SM] },
|
||||||
{ "atlas-rtd-sm", ATLAS_RTD_SM },
|
{ "atlas-rtd-sm", (kernel_ulong_t)&atlas_devices[ATLAS_RTD_SM] },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, atlas_id);
|
MODULE_DEVICE_TABLE(i2c, atlas_id);
|
||||||
|
|
||||||
static const struct of_device_id atlas_dt_ids[] = {
|
static const struct of_device_id atlas_dt_ids[] = {
|
||||||
{ .compatible = "atlas,ph-sm", .data = (void *)ATLAS_PH_SM, },
|
{ .compatible = "atlas,ph-sm", .data = &atlas_devices[ATLAS_PH_SM] },
|
||||||
{ .compatible = "atlas,ec-sm", .data = (void *)ATLAS_EC_SM, },
|
{ .compatible = "atlas,ec-sm", .data = &atlas_devices[ATLAS_EC_SM] },
|
||||||
{ .compatible = "atlas,orp-sm", .data = (void *)ATLAS_ORP_SM, },
|
{ .compatible = "atlas,orp-sm", .data = &atlas_devices[ATLAS_ORP_SM] },
|
||||||
{ .compatible = "atlas,do-sm", .data = (void *)ATLAS_DO_SM, },
|
{ .compatible = "atlas,do-sm", .data = &atlas_devices[ATLAS_DO_SM] },
|
||||||
{ .compatible = "atlas,rtd-sm", .data = (void *)ATLAS_RTD_SM, },
|
{ .compatible = "atlas,rtd-sm", .data = &atlas_devices[ATLAS_RTD_SM] },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, atlas_dt_ids);
|
MODULE_DEVICE_TABLE(of, atlas_dt_ids);
|
||||||
|
|
||||||
static int atlas_probe(struct i2c_client *client)
|
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_data *data;
|
||||||
struct atlas_device *chip;
|
const struct atlas_device *chip;
|
||||||
struct iio_trigger *trig;
|
struct iio_trigger *trig;
|
||||||
struct iio_dev *indio_dev;
|
struct iio_dev *indio_dev;
|
||||||
int ret;
|
int ret;
|
||||||
@ -621,10 +620,7 @@ static int atlas_probe(struct i2c_client *client)
|
|||||||
if (!indio_dev)
|
if (!indio_dev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (!dev_fwnode(&client->dev))
|
chip = i2c_get_match_data(client);
|
||||||
chip = &atlas_devices[id->driver_data];
|
|
||||||
else
|
|
||||||
chip = &atlas_devices[(unsigned long)device_get_match_data(&client->dev)];
|
|
||||||
|
|
||||||
indio_dev->info = &atlas_info;
|
indio_dev->info = &atlas_info;
|
||||||
indio_dev->name = ATLAS_DRV_NAME;
|
indio_dev->name = ATLAS_DRV_NAME;
|
||||||
|
@ -114,6 +114,7 @@ struct sgp_data {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct sgp_device {
|
struct sgp_device {
|
||||||
|
unsigned long product_id;
|
||||||
const struct iio_chan_spec *channels;
|
const struct iio_chan_spec *channels;
|
||||||
int num_channels;
|
int num_channels;
|
||||||
};
|
};
|
||||||
@ -182,10 +183,12 @@ static const struct iio_chan_spec sgpc3_channels[] = {
|
|||||||
|
|
||||||
static const struct sgp_device sgp_devices[] = {
|
static const struct sgp_device sgp_devices[] = {
|
||||||
[SGP30] = {
|
[SGP30] = {
|
||||||
|
.product_id = SGP30,
|
||||||
.channels = sgp30_channels,
|
.channels = sgp30_channels,
|
||||||
.num_channels = ARRAY_SIZE(sgp30_channels),
|
.num_channels = ARRAY_SIZE(sgp30_channels),
|
||||||
},
|
},
|
||||||
[SGPC3] = {
|
[SGPC3] = {
|
||||||
|
.product_id = SGPC3,
|
||||||
.channels = sgpc3_channels,
|
.channels = sgpc3_channels,
|
||||||
.num_channels = ARRAY_SIZE(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[] = {
|
static const struct of_device_id sgp_dt_ids[] = {
|
||||||
{ .compatible = "sensirion,sgp30", .data = (void *)SGP30 },
|
{ .compatible = "sensirion,sgp30", .data = &sgp_devices[SGP30] },
|
||||||
{ .compatible = "sensirion,sgpc3", .data = (void *)SGPC3 },
|
{ .compatible = "sensirion,sgpc3", .data = &sgp_devices[SGPC3] },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
static int sgp_probe(struct i2c_client *client)
|
static int sgp_probe(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
const struct i2c_device_id *id = i2c_client_get_device_id(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 device *dev = &client->dev;
|
||||||
struct iio_dev *indio_dev;
|
struct iio_dev *indio_dev;
|
||||||
struct sgp_data *data;
|
struct sgp_data *data;
|
||||||
unsigned long product_id;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
|
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
|
||||||
if (!indio_dev)
|
if (!indio_dev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (dev_fwnode(dev))
|
match_data = i2c_get_match_data(client);
|
||||||
product_id = (unsigned long)device_get_match_data(dev);
|
|
||||||
else
|
|
||||||
product_id = id->driver_data;
|
|
||||||
|
|
||||||
data = iio_priv(indio_dev);
|
data = iio_priv(indio_dev);
|
||||||
i2c_set_clientdata(client, 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);
|
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)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
indio_dev->info = &sgp_info;
|
indio_dev->info = &sgp_info;
|
||||||
indio_dev->name = id->name;
|
indio_dev->name = id->name;
|
||||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||||
indio_dev->channels = sgp_devices[product_id].channels;
|
indio_dev->channels = match_data->channels;
|
||||||
indio_dev->num_channels = sgp_devices[product_id].num_channels;
|
indio_dev->num_channels = match_data->num_channels;
|
||||||
|
|
||||||
sgp_init(data);
|
sgp_init(data);
|
||||||
|
|
||||||
@ -562,8 +562,8 @@ static void sgp_remove(struct i2c_client *client)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct i2c_device_id sgp_id[] = {
|
static const struct i2c_device_id sgp_id[] = {
|
||||||
{ "sgp30", SGP30 },
|
{ "sgp30", (kernel_ulong_t)&sgp_devices[SGP30] },
|
||||||
{ "sgpc3", SGPC3 },
|
{ "sgpc3", (kernel_ulong_t)&sgp_devices[SGPC3] },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -342,19 +342,17 @@ static const struct vz89x_chip_data vz89x_chips[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct of_device_id vz89x_dt_ids[] = {
|
static const struct of_device_id vz89x_dt_ids[] = {
|
||||||
{ .compatible = "sgx,vz89x", .data = (void *) VZ89X },
|
{ .compatible = "sgx,vz89x", .data = &vz89x_chips[VZ89X] },
|
||||||
{ .compatible = "sgx,vz89te", .data = (void *) VZ89TE },
|
{ .compatible = "sgx,vz89te", .data = &vz89x_chips[VZ89TE] },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, vz89x_dt_ids);
|
MODULE_DEVICE_TABLE(of, vz89x_dt_ids);
|
||||||
|
|
||||||
static int vz89x_probe(struct i2c_client *client)
|
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 device *dev = &client->dev;
|
||||||
struct iio_dev *indio_dev;
|
struct iio_dev *indio_dev;
|
||||||
struct vz89x_data *data;
|
struct vz89x_data *data;
|
||||||
int chip_id;
|
|
||||||
|
|
||||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
|
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
|
||||||
if (!indio_dev)
|
if (!indio_dev)
|
||||||
@ -369,14 +367,10 @@ static int vz89x_probe(struct i2c_client *client)
|
|||||||
else
|
else
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (!dev_fwnode(dev))
|
data->chip = i2c_get_match_data(client);
|
||||||
chip_id = id->driver_data;
|
|
||||||
else
|
|
||||||
chip_id = (unsigned long)device_get_match_data(dev);
|
|
||||||
|
|
||||||
i2c_set_clientdata(client, indio_dev);
|
i2c_set_clientdata(client, indio_dev);
|
||||||
data->client = client;
|
data->client = client;
|
||||||
data->chip = &vz89x_chips[chip_id];
|
|
||||||
data->last_update = jiffies - HZ;
|
data->last_update = jiffies - HZ;
|
||||||
mutex_init(&data->lock);
|
mutex_init(&data->lock);
|
||||||
|
|
||||||
@ -391,8 +385,8 @@ static int vz89x_probe(struct i2c_client *client)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct i2c_device_id vz89x_id[] = {
|
static const struct i2c_device_id vz89x_id[] = {
|
||||||
{ "vz89x", VZ89X },
|
{ "vz89x", (kernel_ulong_t)&vz89x_chips[VZ89X] },
|
||||||
{ "vz89te", VZ89TE },
|
{ "vz89te", (kernel_ulong_t)&vz89x_chips[VZ89TE] },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, vz89x_id);
|
MODULE_DEVICE_TABLE(i2c, vz89x_id);
|
||||||
|
@ -226,15 +226,13 @@ disable_reg:
|
|||||||
return ret;
|
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 iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct dpot_dac *dac = iio_priv(indio_dev);
|
struct dpot_dac *dac = iio_priv(indio_dev);
|
||||||
|
|
||||||
iio_device_unregister(indio_dev);
|
iio_device_unregister(indio_dev);
|
||||||
regulator_disable(dac->vref);
|
regulator_disable(dac->vref);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id dpot_dac_match[] = {
|
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 = {
|
static struct platform_driver dpot_dac_driver = {
|
||||||
.probe = dpot_dac_probe,
|
.probe = dpot_dac_probe,
|
||||||
.remove = dpot_dac_remove,
|
.remove_new = dpot_dac_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "iio-dpot-dac",
|
.name = "iio-dpot-dac",
|
||||||
.of_match_table = dpot_dac_match,
|
.of_match_table = dpot_dac_match,
|
||||||
|
@ -165,7 +165,7 @@ dis_reg:
|
|||||||
return ret;
|
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 iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct lpc18xx_dac *dac = iio_priv(indio_dev);
|
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);
|
writel(0, dac->base + LPC18XX_DAC_CTRL);
|
||||||
clk_disable_unprepare(dac->clk);
|
clk_disable_unprepare(dac->clk);
|
||||||
regulator_disable(dac->vref);
|
regulator_disable(dac->vref);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id lpc18xx_dac_match[] = {
|
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 = {
|
static struct platform_driver lpc18xx_dac_driver = {
|
||||||
.probe = lpc18xx_dac_probe,
|
.probe = lpc18xx_dac_probe,
|
||||||
.remove = lpc18xx_dac_remove,
|
.remove_new = lpc18xx_dac_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "lpc18xx-dac",
|
.name = "lpc18xx-dac",
|
||||||
.of_match_table = lpc18xx_dac_match,
|
.of_match_table = lpc18xx_dac_match,
|
||||||
|
@ -30,9 +30,14 @@
|
|||||||
#define MCP472X_REF_VREF_UNBUFFERED 0x02
|
#define MCP472X_REF_VREF_UNBUFFERED 0x02
|
||||||
#define MCP472X_REF_VREF_BUFFERED 0x03
|
#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 mcp4725_data {
|
||||||
struct i2c_client *client;
|
struct i2c_client *client;
|
||||||
int id;
|
|
||||||
unsigned ref_mode;
|
unsigned ref_mode;
|
||||||
bool vref_buffered;
|
bool vref_buffered;
|
||||||
u16 dac_value;
|
u16 dac_value;
|
||||||
@ -384,6 +389,7 @@ static int mcp4725_probe_dt(struct device *dev,
|
|||||||
static int mcp4725_probe(struct i2c_client *client)
|
static int mcp4725_probe(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||||
|
const struct mcp4725_chip_info *info;
|
||||||
struct mcp4725_data *data;
|
struct mcp4725_data *data;
|
||||||
struct iio_dev *indio_dev;
|
struct iio_dev *indio_dev;
|
||||||
struct mcp4725_platform_data *pdata, pdata_dt;
|
struct mcp4725_platform_data *pdata, pdata_dt;
|
||||||
@ -398,10 +404,7 @@ static int mcp4725_probe(struct i2c_client *client)
|
|||||||
data = iio_priv(indio_dev);
|
data = iio_priv(indio_dev);
|
||||||
i2c_set_clientdata(client, indio_dev);
|
i2c_set_clientdata(client, indio_dev);
|
||||||
data->client = client;
|
data->client = client;
|
||||||
if (dev_fwnode(&client->dev))
|
info = i2c_get_match_data(client);
|
||||||
data->id = (uintptr_t)device_get_match_data(&client->dev);
|
|
||||||
else
|
|
||||||
data->id = id->driver_data;
|
|
||||||
pdata = dev_get_platdata(&client->dev);
|
pdata = dev_get_platdata(&client->dev);
|
||||||
|
|
||||||
if (!pdata) {
|
if (!pdata) {
|
||||||
@ -414,7 +417,7 @@ static int mcp4725_probe(struct i2c_client *client)
|
|||||||
pdata = &pdata_dt;
|
pdata = &pdata_dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->id == MCP4725 && pdata->use_vref) {
|
if (info->use_ext_ref_voltage && pdata->use_vref) {
|
||||||
dev_err(&client->dev,
|
dev_err(&client->dev,
|
||||||
"external reference is unavailable on MCP4725");
|
"external reference is unavailable on MCP4725");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -455,12 +458,12 @@ static int mcp4725_probe(struct i2c_client *client)
|
|||||||
|
|
||||||
indio_dev->name = id->name;
|
indio_dev->name = id->name;
|
||||||
indio_dev->info = &mcp4725_info;
|
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->num_channels = 1;
|
||||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||||
|
|
||||||
/* read current DAC value and settings */
|
/* 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) {
|
if (err < 0) {
|
||||||
dev_err(&client->dev, "failed to read DAC value");
|
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 = pd > 0;
|
||||||
data->powerdown_mode = pd ? pd - 1 : 2; /* largest resistor to gnd */
|
data->powerdown_mode = pd ? pd - 1 : 2; /* largest resistor to gnd */
|
||||||
data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);
|
data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);
|
||||||
if (data->id == MCP4726)
|
if (!info->use_ext_ref_voltage)
|
||||||
ref = (inbuf[3] >> 3) & 0x3;
|
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,
|
dev_info(&client->dev,
|
||||||
"voltage reference mode differs (conf: %u, eeprom: %u), setting %u",
|
"voltage reference mode differs (conf: %u, eeprom: %u), setting %u",
|
||||||
data->ref_mode, ref, data->ref_mode);
|
data->ref_mode, ref, data->ref_mode);
|
||||||
@ -510,9 +513,20 @@ static void mcp4725_remove(struct i2c_client *client)
|
|||||||
regulator_disable(data->vdd_reg);
|
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[] = {
|
static const struct i2c_device_id mcp4725_id[] = {
|
||||||
{ "mcp4725", MCP4725 },
|
{ "mcp4725", (kernel_ulong_t)&mcp4725 },
|
||||||
{ "mcp4726", MCP4726 },
|
{ "mcp4726", (kernel_ulong_t)&mcp4726 },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, mcp4725_id);
|
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[] = {
|
static const struct of_device_id mcp4725_of_match[] = {
|
||||||
{
|
{
|
||||||
.compatible = "microchip,mcp4725",
|
.compatible = "microchip,mcp4725",
|
||||||
.data = (void *)MCP4725
|
.data = &mcp4725
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.compatible = "microchip,mcp4726",
|
.compatible = "microchip,mcp4726",
|
||||||
.data = (void *)MCP4726
|
.data = &mcp4726
|
||||||
},
|
},
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
@ -9,9 +9,12 @@
|
|||||||
|
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
#include <linux/mod_devicetable.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/property.h>
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
#include <linux/reset.h>
|
#include <linux/reset.h>
|
||||||
|
|
||||||
@ -94,16 +97,12 @@ static int stm32_dac_probe(struct platform_device *pdev)
|
|||||||
struct reset_control *rst;
|
struct reset_control *rst;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!dev->of_node)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||||
if (!priv)
|
if (!priv)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
platform_set_drvdata(pdev, &priv->common);
|
platform_set_drvdata(pdev, &priv->common);
|
||||||
|
|
||||||
cfg = (const struct stm32_dac_cfg *)
|
cfg = device_get_match_data(dev);
|
||||||
of_match_device(dev->driver->of_match_table, dev)->data;
|
|
||||||
|
|
||||||
mmio = devm_platform_ioremap_resource(pdev, 0);
|
mmio = devm_platform_ioremap_resource(pdev, 0);
|
||||||
if (IS_ERR(mmio))
|
if (IS_ERR(mmio))
|
||||||
@ -183,7 +182,7 @@ err_pm_stop:
|
|||||||
return ret;
|
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);
|
pm_runtime_get_sync(&pdev->dev);
|
||||||
of_platform_depopulate(&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_disable(&pdev->dev);
|
||||||
pm_runtime_set_suspended(&pdev->dev);
|
pm_runtime_set_suspended(&pdev->dev);
|
||||||
pm_runtime_put_noidle(&pdev->dev);
|
pm_runtime_put_noidle(&pdev->dev);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stm32_dac_core_resume(struct device *dev)
|
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 = {
|
static struct platform_driver stm32_dac_driver = {
|
||||||
.probe = stm32_dac_probe,
|
.probe = stm32_dac_probe,
|
||||||
.remove = stm32_dac_remove,
|
.remove_new = stm32_dac_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "stm32-dac-core",
|
.name = "stm32-dac-core",
|
||||||
.of_match_table = stm32_dac_of_match,
|
.of_match_table = stm32_dac_of_match,
|
||||||
|
@ -11,12 +11,13 @@
|
|||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/iio/iio.h>
|
#include <linux/iio/iio.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/kstrtox.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mod_devicetable.h>
|
#include <linux/mod_devicetable.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/string_helpers.h>
|
#include <linux/string_choices.h>
|
||||||
|
|
||||||
#include "stm32-dac-core.h"
|
#include "stm32-dac-core.h"
|
||||||
|
|
||||||
@ -361,7 +362,7 @@ err_pm_put:
|
|||||||
return ret;
|
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);
|
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_disable(&pdev->dev);
|
||||||
pm_runtime_set_suspended(&pdev->dev);
|
pm_runtime_set_suspended(&pdev->dev);
|
||||||
pm_runtime_put_noidle(&pdev->dev);
|
pm_runtime_put_noidle(&pdev->dev);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stm32_dac_suspend(struct device *dev)
|
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 = {
|
static struct platform_driver stm32_dac_driver = {
|
||||||
.probe = stm32_dac_probe,
|
.probe = stm32_dac_probe,
|
||||||
.remove = stm32_dac_remove,
|
.remove_new = stm32_dac_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "stm32-dac",
|
.name = "stm32-dac",
|
||||||
.of_match_table = stm32_dac_of_match,
|
.of_match_table = stm32_dac_of_match,
|
||||||
|
@ -313,7 +313,6 @@ static int dac5571_probe(struct i2c_client *client)
|
|||||||
const struct dac5571_spec *spec;
|
const struct dac5571_spec *spec;
|
||||||
struct dac5571_data *data;
|
struct dac5571_data *data;
|
||||||
struct iio_dev *indio_dev;
|
struct iio_dev *indio_dev;
|
||||||
enum chip_id chip_id;
|
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
|
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->modes = INDIO_DIRECT_MODE;
|
||||||
indio_dev->channels = dac5571_channels;
|
indio_dev->channels = dac5571_channels;
|
||||||
|
|
||||||
if (dev_fwnode(dev))
|
spec = i2c_get_match_data(client);
|
||||||
chip_id = (uintptr_t)device_get_match_data(dev);
|
|
||||||
else
|
|
||||||
chip_id = id->driver_data;
|
|
||||||
|
|
||||||
spec = &dac5571_spec[chip_id];
|
|
||||||
|
|
||||||
indio_dev->num_channels = spec->num_channels;
|
indio_dev->num_channels = spec->num_channels;
|
||||||
data->spec = spec;
|
data->spec = spec;
|
||||||
@ -392,31 +386,31 @@ static void dac5571_remove(struct i2c_client *i2c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id dac5571_of_id[] = {
|
static const struct of_device_id dac5571_of_id[] = {
|
||||||
{.compatible = "ti,dac5571", .data = (void *)single_8bit},
|
{.compatible = "ti,dac121c081", .data = &dac5571_spec[single_12bit] },
|
||||||
{.compatible = "ti,dac6571", .data = (void *)single_10bit},
|
{.compatible = "ti,dac5571", .data = &dac5571_spec[single_8bit] },
|
||||||
{.compatible = "ti,dac7571", .data = (void *)single_12bit},
|
{.compatible = "ti,dac6571", .data = &dac5571_spec[single_10bit] },
|
||||||
{.compatible = "ti,dac5574", .data = (void *)quad_8bit},
|
{.compatible = "ti,dac7571", .data = &dac5571_spec[single_12bit] },
|
||||||
{.compatible = "ti,dac6574", .data = (void *)quad_10bit},
|
{.compatible = "ti,dac5574", .data = &dac5571_spec[quad_8bit] },
|
||||||
{.compatible = "ti,dac7574", .data = (void *)quad_12bit},
|
{.compatible = "ti,dac6574", .data = &dac5571_spec[quad_10bit] },
|
||||||
{.compatible = "ti,dac5573", .data = (void *)quad_8bit},
|
{.compatible = "ti,dac7574", .data = &dac5571_spec[quad_12bit] },
|
||||||
{.compatible = "ti,dac6573", .data = (void *)quad_10bit},
|
{.compatible = "ti,dac5573", .data = &dac5571_spec[quad_8bit] },
|
||||||
{.compatible = "ti,dac7573", .data = (void *)quad_12bit},
|
{.compatible = "ti,dac6573", .data = &dac5571_spec[quad_10bit] },
|
||||||
{.compatible = "ti,dac121c081", .data = (void *)single_12bit},
|
{.compatible = "ti,dac7573", .data = &dac5571_spec[quad_12bit] },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, dac5571_of_id);
|
MODULE_DEVICE_TABLE(of, dac5571_of_id);
|
||||||
|
|
||||||
static const struct i2c_device_id dac5571_id[] = {
|
static const struct i2c_device_id dac5571_id[] = {
|
||||||
{"dac5571", single_8bit},
|
{"dac121c081", (kernel_ulong_t)&dac5571_spec[single_12bit] },
|
||||||
{"dac6571", single_10bit},
|
{"dac5571", (kernel_ulong_t)&dac5571_spec[single_8bit] },
|
||||||
{"dac7571", single_12bit},
|
{"dac6571", (kernel_ulong_t)&dac5571_spec[single_10bit] },
|
||||||
{"dac5574", quad_8bit},
|
{"dac7571", (kernel_ulong_t)&dac5571_spec[single_12bit] },
|
||||||
{"dac6574", quad_10bit},
|
{"dac5574", (kernel_ulong_t)&dac5571_spec[quad_8bit] },
|
||||||
{"dac7574", quad_12bit},
|
{"dac6574", (kernel_ulong_t)&dac5571_spec[quad_10bit] },
|
||||||
{"dac5573", quad_8bit},
|
{"dac7574", (kernel_ulong_t)&dac5571_spec[quad_12bit] },
|
||||||
{"dac6573", quad_10bit},
|
{"dac5573", (kernel_ulong_t)&dac5571_spec[quad_8bit] },
|
||||||
{"dac7573", quad_12bit},
|
{"dac6573", (kernel_ulong_t)&dac5571_spec[quad_10bit] },
|
||||||
{"dac121c081", single_12bit},
|
{"dac7573", (kernel_ulong_t)&dac5571_spec[quad_12bit] },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, dac5571_id);
|
MODULE_DEVICE_TABLE(i2c, dac5571_id);
|
||||||
|
@ -231,7 +231,7 @@ error_iio_device_register:
|
|||||||
return ret;
|
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 iio_dev *indio_dev = platform_get_drvdata(pdev);
|
||||||
struct vf610_dac *info = iio_priv(indio_dev);
|
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);
|
iio_device_unregister(indio_dev);
|
||||||
vf610_dac_exit(info);
|
vf610_dac_exit(info);
|
||||||
clk_disable_unprepare(info->clk);
|
clk_disable_unprepare(info->clk);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vf610_dac_suspend(struct device *dev)
|
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 = {
|
static struct platform_driver vf610_dac_driver = {
|
||||||
.probe = vf610_dac_probe,
|
.probe = vf610_dac_probe,
|
||||||
.remove = vf610_dac_remove,
|
.remove_new = vf610_dac_remove,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "vf610-dac",
|
.name = "vf610-dac",
|
||||||
.of_match_table = vf610_dac_match,
|
.of_match_table = vf610_dac_match,
|
||||||
|
@ -33,7 +33,6 @@ enum {
|
|||||||
|
|
||||||
struct adf4350_state {
|
struct adf4350_state {
|
||||||
struct spi_device *spi;
|
struct spi_device *spi;
|
||||||
struct regulator *reg;
|
|
||||||
struct gpio_desc *lock_detect_gpiod;
|
struct gpio_desc *lock_detect_gpiod;
|
||||||
struct adf4350_platform_data *pdata;
|
struct adf4350_platform_data *pdata;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
@ -469,6 +468,15 @@ static struct adf4350_platform_data *adf4350_parse_dt(struct device *dev)
|
|||||||
return pdata;
|
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)
|
static int adf4350_probe(struct spi_device *spi)
|
||||||
{
|
{
|
||||||
struct adf4350_platform_data *pdata;
|
struct adf4350_platform_data *pdata;
|
||||||
@ -491,31 +499,21 @@ static int adf4350_probe(struct spi_device *spi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!pdata->clkin) {
|
if (!pdata->clkin) {
|
||||||
clk = devm_clk_get(&spi->dev, "clkin");
|
clk = devm_clk_get_enabled(&spi->dev, "clkin");
|
||||||
if (IS_ERR(clk))
|
if (IS_ERR(clk))
|
||||||
return -EPROBE_DEFER;
|
return PTR_ERR(clk);
|
||||||
|
|
||||||
ret = clk_prepare_enable(clk);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
|
||||||
if (indio_dev == NULL) {
|
if (indio_dev == NULL)
|
||||||
ret = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto error_disable_clk;
|
|
||||||
}
|
|
||||||
|
|
||||||
st = iio_priv(indio_dev);
|
st = iio_priv(indio_dev);
|
||||||
|
|
||||||
st->reg = devm_regulator_get(&spi->dev, "vcc");
|
ret = devm_regulator_get_enable(&spi->dev, "vcc");
|
||||||
if (!IS_ERR(st->reg)) {
|
if (ret)
|
||||||
ret = regulator_enable(st->reg);
|
return ret;
|
||||||
if (ret)
|
|
||||||
goto error_disable_clk;
|
|
||||||
}
|
|
||||||
|
|
||||||
spi_set_drvdata(spi, indio_dev);
|
|
||||||
st->spi = spi;
|
st->spi = spi;
|
||||||
st->pdata = pdata;
|
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,
|
st->lock_detect_gpiod = devm_gpiod_get_optional(&spi->dev, NULL,
|
||||||
GPIOD_IN);
|
GPIOD_IN);
|
||||||
if (IS_ERR(st->lock_detect_gpiod)) {
|
if (IS_ERR(st->lock_detect_gpiod))
|
||||||
ret = PTR_ERR(st->lock_detect_gpiod);
|
return PTR_ERR(st->lock_detect_gpiod);
|
||||||
goto error_disable_reg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pdata->power_up_frequency) {
|
if (pdata->power_up_frequency) {
|
||||||
ret = adf4350_set_freq(st, pdata->power_up_frequency);
|
ret = adf4350_set_freq(st, pdata->power_up_frequency);
|
||||||
if (ret)
|
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)
|
if (ret)
|
||||||
goto error_disable_reg;
|
return dev_err_probe(&spi->dev, ret,
|
||||||
|
"Failed to add action to managed power down\n");
|
||||||
|
|
||||||
return 0;
|
return devm_iio_device_register(&spi->dev, indio_dev);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id adf4350_of_match[] = {
|
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,
|
.of_match_table = adf4350_of_match,
|
||||||
},
|
},
|
||||||
.probe = adf4350_probe,
|
.probe = adf4350_probe,
|
||||||
.remove = adf4350_remove,
|
|
||||||
.id_table = adf4350_id,
|
.id_table = adf4350_id,
|
||||||
};
|
};
|
||||||
module_spi_driver(adf4350_driver);
|
module_spi_driver(adf4350_driver);
|
||||||
|
@ -359,7 +359,7 @@ error_remove_trigger:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Function to deinitialize the processing for usage id */
|
/* 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 hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
|
||||||
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
|
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);
|
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_GYRO_3D);
|
||||||
iio_device_unregister(indio_dev);
|
iio_device_unregister(indio_dev);
|
||||||
hid_sensor_remove_trigger(indio_dev, &gyro_state->common_attributes);
|
hid_sensor_remove_trigger(indio_dev, &gyro_state->common_attributes);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct platform_device_id hid_gyro_3d_ids[] = {
|
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,
|
.pm = &hid_sensor_pm_ops,
|
||||||
},
|
},
|
||||||
.probe = hid_gyro_3d_probe,
|
.probe = hid_gyro_3d_probe,
|
||||||
.remove = hid_gyro_3d_remove,
|
.remove_new = hid_gyro_3d_remove,
|
||||||
};
|
};
|
||||||
module_platform_driver(hid_gyro_3d_platform_driver);
|
module_platform_driver(hid_gyro_3d_platform_driver);
|
||||||
|
|
||||||
|
@ -260,7 +260,7 @@ error_remove_trigger:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Function to deinitialize the processing for usage id */
|
/* 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 hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
|
||||||
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
|
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);
|
iio_device_unregister(indio_dev);
|
||||||
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_HUMIDITY);
|
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_HUMIDITY);
|
||||||
hid_sensor_remove_trigger(indio_dev, &humid_st->common_attributes);
|
hid_sensor_remove_trigger(indio_dev, &humid_st->common_attributes);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct platform_device_id hid_humidity_ids[] = {
|
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,
|
.pm = &hid_sensor_pm_ops,
|
||||||
},
|
},
|
||||||
.probe = hid_humidity_probe,
|
.probe = hid_humidity_probe,
|
||||||
.remove = hid_humidity_remove,
|
.remove_new = hid_humidity_remove,
|
||||||
};
|
};
|
||||||
module_platform_driver(hid_humidity_platform_driver);
|
module_platform_driver(hid_humidity_platform_driver);
|
||||||
|
|
||||||
|
@ -169,9 +169,16 @@ static const struct i2c_device_id si7005_id[] = {
|
|||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, 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 = {
|
static struct i2c_driver si7005_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "si7005",
|
.name = "si7005",
|
||||||
|
.of_match_table = si7005_dt_ids,
|
||||||
},
|
},
|
||||||
.probe = si7005_probe,
|
.probe = si7005_probe,
|
||||||
.id_table = si7005_id,
|
.id_table = si7005_id,
|
||||||
|
@ -30,9 +30,6 @@ struct iio_ioctl_handler {
|
|||||||
unsigned int cmd, unsigned long arg);
|
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,
|
void iio_device_ioctl_handler_register(struct iio_dev *indio_dev,
|
||||||
struct iio_ioctl_handler *h);
|
struct iio_ioctl_handler *h);
|
||||||
void iio_device_ioctl_handler_unregister(struct iio_ioctl_handler *h);
|
void iio_device_ioctl_handler_unregister(struct iio_ioctl_handler *h);
|
||||||
|
@ -31,6 +31,12 @@
|
|||||||
#define ADIS16475_REG_Y_ACCEL_L 0x14
|
#define ADIS16475_REG_Y_ACCEL_L 0x14
|
||||||
#define ADIS16475_REG_Z_ACCEL_L 0x18
|
#define ADIS16475_REG_Z_ACCEL_L 0x18
|
||||||
#define ADIS16475_REG_TEMP_OUT 0x1c
|
#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_X_GYRO_BIAS_L 0x40
|
||||||
#define ADIS16475_REG_Y_GYRO_BIAS_L 0x44
|
#define ADIS16475_REG_Y_GYRO_BIAS_L 0x44
|
||||||
#define ADIS16475_REG_Z_GYRO_BIAS_L 0x48
|
#define ADIS16475_REG_Z_GYRO_BIAS_L 0x48
|
||||||
@ -55,6 +61,7 @@
|
|||||||
#define ADIS16475_REG_PROD_ID 0x72
|
#define ADIS16475_REG_PROD_ID 0x72
|
||||||
#define ADIS16475_REG_SERIAL_NUM 0x74
|
#define ADIS16475_REG_SERIAL_NUM 0x74
|
||||||
#define ADIS16475_REG_FLASH_CNT 0x7c
|
#define ADIS16475_REG_FLASH_CNT 0x7c
|
||||||
|
#define ADIS16500_BURST_DATA_SEL_MASK BIT(8)
|
||||||
#define ADIS16500_BURST32_MASK BIT(9)
|
#define ADIS16500_BURST32_MASK BIT(9)
|
||||||
#define ADIS16500_BURST32(x) FIELD_PREP(ADIS16500_BURST32_MASK, x)
|
#define ADIS16500_BURST32(x) FIELD_PREP(ADIS16500_BURST32_MASK, x)
|
||||||
/* number of data elements in burst mode */
|
/* number of data elements in burst mode */
|
||||||
@ -65,6 +72,8 @@
|
|||||||
#define ADIS16475_BURST_MAX_SPEED 1000000
|
#define ADIS16475_BURST_MAX_SPEED 1000000
|
||||||
#define ADIS16475_LSB_DEC_MASK BIT(0)
|
#define ADIS16475_LSB_DEC_MASK BIT(0)
|
||||||
#define ADIS16475_LSB_FIR_MASK BIT(1)
|
#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 {
|
enum {
|
||||||
ADIS16475_SYNC_DIRECT = 1,
|
ADIS16475_SYNC_DIRECT = 1,
|
||||||
@ -84,16 +93,20 @@ struct adis16475_chip_info {
|
|||||||
const struct adis16475_sync *sync;
|
const struct adis16475_sync *sync;
|
||||||
const struct adis_data adis_data;
|
const struct adis_data adis_data;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
#define ADIS16475_HAS_BURST32 BIT(0)
|
||||||
|
#define ADIS16475_HAS_BURST_DELTA_DATA BIT(1)
|
||||||
|
const long flags;
|
||||||
u32 num_channels;
|
u32 num_channels;
|
||||||
u32 gyro_max_val;
|
u32 gyro_max_val;
|
||||||
u32 gyro_max_scale;
|
u32 gyro_max_scale;
|
||||||
u32 accel_max_val;
|
u32 accel_max_val;
|
||||||
u32 accel_max_scale;
|
u32 accel_max_scale;
|
||||||
u32 temp_scale;
|
u32 temp_scale;
|
||||||
|
u32 deltang_max_val;
|
||||||
|
u32 deltvel_max_val;
|
||||||
u32 int_clk;
|
u32 int_clk;
|
||||||
u16 max_dec;
|
u16 max_dec;
|
||||||
u8 num_sync;
|
u8 num_sync;
|
||||||
bool has_burst32;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct adis16475 {
|
struct adis16475 {
|
||||||
@ -115,6 +128,12 @@ enum {
|
|||||||
ADIS16475_SCAN_ACCEL_Y,
|
ADIS16475_SCAN_ACCEL_Y,
|
||||||
ADIS16475_SCAN_ACCEL_Z,
|
ADIS16475_SCAN_ACCEL_Z,
|
||||||
ADIS16475_SCAN_TEMP,
|
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;
|
static bool low_rate_allow;
|
||||||
@ -451,6 +470,14 @@ static int adis16475_read_raw(struct iio_dev *indio_dev,
|
|||||||
case IIO_TEMP:
|
case IIO_TEMP:
|
||||||
*val = st->info->temp_scale;
|
*val = st->info->temp_scale;
|
||||||
return IIO_VAL_INT;
|
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:
|
default:
|
||||||
return -EINVAL;
|
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[] = {
|
static const struct iio_chan_spec adis16475_channels[] = {
|
||||||
ADIS16475_GYRO_CHANNEL(X),
|
ADIS16475_GYRO_CHANNEL(X),
|
||||||
ADIS16475_GYRO_CHANNEL(Y),
|
ADIS16475_GYRO_CHANNEL(Y),
|
||||||
@ -559,6 +637,12 @@ static const struct iio_chan_spec adis16475_channels[] = {
|
|||||||
ADIS16475_ACCEL_CHANNEL(Y),
|
ADIS16475_ACCEL_CHANNEL(Y),
|
||||||
ADIS16475_ACCEL_CHANNEL(Z),
|
ADIS16475_ACCEL_CHANNEL(Z),
|
||||||
ADIS16475_TEMP_CHANNEL(),
|
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)
|
IIO_CHAN_SOFT_TIMESTAMP(7)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -662,6 +746,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
|
|||||||
.accel_max_val = 1,
|
.accel_max_val = 1,
|
||||||
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
|
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
|
||||||
.temp_scale = 100,
|
.temp_scale = 100,
|
||||||
|
.deltang_max_val = IIO_DEGREE_TO_RAD(2160),
|
||||||
|
.deltvel_max_val = 400,
|
||||||
.int_clk = 2000,
|
.int_clk = 2000,
|
||||||
.max_dec = 1999,
|
.max_dec = 1999,
|
||||||
.sync = adis16475_sync_mode,
|
.sync = adis16475_sync_mode,
|
||||||
@ -677,6 +763,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
|
|||||||
.accel_max_val = 1,
|
.accel_max_val = 1,
|
||||||
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
|
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
|
||||||
.temp_scale = 100,
|
.temp_scale = 100,
|
||||||
|
.deltang_max_val = IIO_DEGREE_TO_RAD(360),
|
||||||
|
.deltvel_max_val = 100,
|
||||||
.int_clk = 2000,
|
.int_clk = 2000,
|
||||||
.max_dec = 1999,
|
.max_dec = 1999,
|
||||||
.sync = adis16475_sync_mode,
|
.sync = adis16475_sync_mode,
|
||||||
@ -692,6 +780,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
|
|||||||
.accel_max_val = 1,
|
.accel_max_val = 1,
|
||||||
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
|
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
|
||||||
.temp_scale = 100,
|
.temp_scale = 100,
|
||||||
|
.deltang_max_val = IIO_DEGREE_TO_RAD(720),
|
||||||
|
.deltvel_max_val = 100,
|
||||||
.int_clk = 2000,
|
.int_clk = 2000,
|
||||||
.max_dec = 1999,
|
.max_dec = 1999,
|
||||||
.sync = adis16475_sync_mode,
|
.sync = adis16475_sync_mode,
|
||||||
@ -707,6 +797,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
|
|||||||
.accel_max_val = 1,
|
.accel_max_val = 1,
|
||||||
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
|
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
|
||||||
.temp_scale = 100,
|
.temp_scale = 100,
|
||||||
|
.deltang_max_val = IIO_DEGREE_TO_RAD(2160),
|
||||||
|
.deltvel_max_val = 100,
|
||||||
.int_clk = 2000,
|
.int_clk = 2000,
|
||||||
.max_dec = 1999,
|
.max_dec = 1999,
|
||||||
.sync = adis16475_sync_mode,
|
.sync = adis16475_sync_mode,
|
||||||
@ -715,50 +807,56 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
|
|||||||
},
|
},
|
||||||
[ADIS16477_1] = {
|
[ADIS16477_1] = {
|
||||||
.name = "adis16477-1",
|
.name = "adis16477-1",
|
||||||
.num_channels = ARRAY_SIZE(adis16475_channels),
|
.num_channels = ARRAY_SIZE(adis16477_channels),
|
||||||
.channels = adis16475_channels,
|
.channels = adis16477_channels,
|
||||||
.gyro_max_val = 1,
|
.gyro_max_val = 1,
|
||||||
.gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
|
.gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
|
||||||
.accel_max_val = 1,
|
.accel_max_val = 1,
|
||||||
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
|
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
|
||||||
.temp_scale = 100,
|
.temp_scale = 100,
|
||||||
|
.deltang_max_val = IIO_DEGREE_TO_RAD(360),
|
||||||
|
.deltvel_max_val = 400,
|
||||||
.int_clk = 2000,
|
.int_clk = 2000,
|
||||||
.max_dec = 1999,
|
.max_dec = 1999,
|
||||||
.sync = adis16475_sync_mode,
|
.sync = adis16475_sync_mode,
|
||||||
.num_sync = ARRAY_SIZE(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),
|
.adis_data = ADIS16475_DATA(16477, &adis16475_timeouts),
|
||||||
},
|
},
|
||||||
[ADIS16477_2] = {
|
[ADIS16477_2] = {
|
||||||
.name = "adis16477-2",
|
.name = "adis16477-2",
|
||||||
.num_channels = ARRAY_SIZE(adis16475_channels),
|
.num_channels = ARRAY_SIZE(adis16477_channels),
|
||||||
.channels = adis16475_channels,
|
.channels = adis16477_channels,
|
||||||
.gyro_max_val = 1,
|
.gyro_max_val = 1,
|
||||||
.gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
|
.gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
|
||||||
.accel_max_val = 1,
|
.accel_max_val = 1,
|
||||||
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
|
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
|
||||||
.temp_scale = 100,
|
.temp_scale = 100,
|
||||||
|
.deltang_max_val = IIO_DEGREE_TO_RAD(720),
|
||||||
|
.deltvel_max_val = 400,
|
||||||
.int_clk = 2000,
|
.int_clk = 2000,
|
||||||
.max_dec = 1999,
|
.max_dec = 1999,
|
||||||
.sync = adis16475_sync_mode,
|
.sync = adis16475_sync_mode,
|
||||||
.num_sync = ARRAY_SIZE(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),
|
.adis_data = ADIS16475_DATA(16477, &adis16475_timeouts),
|
||||||
},
|
},
|
||||||
[ADIS16477_3] = {
|
[ADIS16477_3] = {
|
||||||
.name = "adis16477-3",
|
.name = "adis16477-3",
|
||||||
.num_channels = ARRAY_SIZE(adis16475_channels),
|
.num_channels = ARRAY_SIZE(adis16477_channels),
|
||||||
.channels = adis16475_channels,
|
.channels = adis16477_channels,
|
||||||
.gyro_max_val = 1,
|
.gyro_max_val = 1,
|
||||||
.gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
|
.gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
|
||||||
.accel_max_val = 1,
|
.accel_max_val = 1,
|
||||||
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
|
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
|
||||||
.temp_scale = 100,
|
.temp_scale = 100,
|
||||||
|
.deltang_max_val = IIO_DEGREE_TO_RAD(2160),
|
||||||
|
.deltvel_max_val = 400,
|
||||||
.int_clk = 2000,
|
.int_clk = 2000,
|
||||||
.max_dec = 1999,
|
.max_dec = 1999,
|
||||||
.sync = adis16475_sync_mode,
|
.sync = adis16475_sync_mode,
|
||||||
.num_sync = ARRAY_SIZE(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),
|
.adis_data = ADIS16475_DATA(16477, &adis16475_timeouts),
|
||||||
},
|
},
|
||||||
[ADIS16465_1] = {
|
[ADIS16465_1] = {
|
||||||
@ -770,6 +868,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
|
|||||||
.accel_max_val = 1,
|
.accel_max_val = 1,
|
||||||
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
|
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
|
||||||
.temp_scale = 100,
|
.temp_scale = 100,
|
||||||
|
.deltang_max_val = IIO_DEGREE_TO_RAD(360),
|
||||||
|
.deltvel_max_val = 100,
|
||||||
.int_clk = 2000,
|
.int_clk = 2000,
|
||||||
.max_dec = 1999,
|
.max_dec = 1999,
|
||||||
.sync = adis16475_sync_mode,
|
.sync = adis16475_sync_mode,
|
||||||
@ -785,6 +885,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
|
|||||||
.accel_max_val = 1,
|
.accel_max_val = 1,
|
||||||
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
|
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
|
||||||
.temp_scale = 100,
|
.temp_scale = 100,
|
||||||
|
.deltang_max_val = IIO_DEGREE_TO_RAD(720),
|
||||||
|
.deltvel_max_val = 100,
|
||||||
.int_clk = 2000,
|
.int_clk = 2000,
|
||||||
.max_dec = 1999,
|
.max_dec = 1999,
|
||||||
.sync = adis16475_sync_mode,
|
.sync = adis16475_sync_mode,
|
||||||
@ -800,6 +902,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
|
|||||||
.accel_max_val = 1,
|
.accel_max_val = 1,
|
||||||
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
|
.accel_max_scale = IIO_M_S_2_TO_G(4000 << 16),
|
||||||
.temp_scale = 100,
|
.temp_scale = 100,
|
||||||
|
.deltang_max_val = IIO_DEGREE_TO_RAD(2160),
|
||||||
|
.deltvel_max_val = 100,
|
||||||
.int_clk = 2000,
|
.int_clk = 2000,
|
||||||
.max_dec = 1999,
|
.max_dec = 1999,
|
||||||
.sync = adis16475_sync_mode,
|
.sync = adis16475_sync_mode,
|
||||||
@ -815,6 +919,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
|
|||||||
.accel_max_val = 1,
|
.accel_max_val = 1,
|
||||||
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
|
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
|
||||||
.temp_scale = 100,
|
.temp_scale = 100,
|
||||||
|
.deltang_max_val = IIO_DEGREE_TO_RAD(360),
|
||||||
|
.deltvel_max_val = 400,
|
||||||
.int_clk = 2000,
|
.int_clk = 2000,
|
||||||
.max_dec = 1999,
|
.max_dec = 1999,
|
||||||
.sync = adis16475_sync_mode,
|
.sync = adis16475_sync_mode,
|
||||||
@ -830,6 +936,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
|
|||||||
.accel_max_val = 1,
|
.accel_max_val = 1,
|
||||||
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
|
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
|
||||||
.temp_scale = 100,
|
.temp_scale = 100,
|
||||||
|
.deltang_max_val = IIO_DEGREE_TO_RAD(720),
|
||||||
|
.deltvel_max_val = 400,
|
||||||
.int_clk = 2000,
|
.int_clk = 2000,
|
||||||
.max_dec = 1999,
|
.max_dec = 1999,
|
||||||
.sync = adis16475_sync_mode,
|
.sync = adis16475_sync_mode,
|
||||||
@ -845,6 +953,8 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
|
|||||||
.accel_max_val = 1,
|
.accel_max_val = 1,
|
||||||
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
|
.accel_max_scale = IIO_M_S_2_TO_G(800 << 16),
|
||||||
.temp_scale = 100,
|
.temp_scale = 100,
|
||||||
|
.deltang_max_val = IIO_DEGREE_TO_RAD(2160),
|
||||||
|
.deltvel_max_val = 400,
|
||||||
.int_clk = 2000,
|
.int_clk = 2000,
|
||||||
.max_dec = 1999,
|
.max_dec = 1999,
|
||||||
.sync = adis16475_sync_mode,
|
.sync = adis16475_sync_mode,
|
||||||
@ -853,129 +963,168 @@ static const struct adis16475_chip_info adis16475_chip_info[] = {
|
|||||||
},
|
},
|
||||||
[ADIS16500] = {
|
[ADIS16500] = {
|
||||||
.name = "adis16500",
|
.name = "adis16500",
|
||||||
.num_channels = ARRAY_SIZE(adis16475_channels),
|
.num_channels = ARRAY_SIZE(adis16477_channels),
|
||||||
.channels = adis16475_channels,
|
.channels = adis16477_channels,
|
||||||
.gyro_max_val = 1,
|
.gyro_max_val = 1,
|
||||||
.gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
|
.gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
|
||||||
.accel_max_val = 392,
|
.accel_max_val = 392,
|
||||||
.accel_max_scale = 32000 << 16,
|
.accel_max_scale = 32000 << 16,
|
||||||
.temp_scale = 100,
|
.temp_scale = 100,
|
||||||
|
.deltang_max_val = IIO_DEGREE_TO_RAD(2160),
|
||||||
|
.deltvel_max_val = 400,
|
||||||
.int_clk = 2000,
|
.int_clk = 2000,
|
||||||
.max_dec = 1999,
|
.max_dec = 1999,
|
||||||
.sync = adis16475_sync_mode,
|
.sync = adis16475_sync_mode,
|
||||||
/* pulse sync not supported */
|
/* pulse sync not supported */
|
||||||
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
|
.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),
|
.adis_data = ADIS16475_DATA(16500, &adis1650x_timeouts),
|
||||||
},
|
},
|
||||||
[ADIS16505_1] = {
|
[ADIS16505_1] = {
|
||||||
.name = "adis16505-1",
|
.name = "adis16505-1",
|
||||||
.num_channels = ARRAY_SIZE(adis16475_channels),
|
.num_channels = ARRAY_SIZE(adis16477_channels),
|
||||||
.channels = adis16475_channels,
|
.channels = adis16477_channels,
|
||||||
.gyro_max_val = 1,
|
.gyro_max_val = 1,
|
||||||
.gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
|
.gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
|
||||||
.accel_max_val = 78,
|
.accel_max_val = 78,
|
||||||
.accel_max_scale = 32000 << 16,
|
.accel_max_scale = 32000 << 16,
|
||||||
.temp_scale = 100,
|
.temp_scale = 100,
|
||||||
|
.deltang_max_val = IIO_DEGREE_TO_RAD(360),
|
||||||
|
.deltvel_max_val = 100,
|
||||||
.int_clk = 2000,
|
.int_clk = 2000,
|
||||||
.max_dec = 1999,
|
.max_dec = 1999,
|
||||||
.sync = adis16475_sync_mode,
|
.sync = adis16475_sync_mode,
|
||||||
/* pulse sync not supported */
|
/* pulse sync not supported */
|
||||||
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
|
.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),
|
.adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts),
|
||||||
},
|
},
|
||||||
[ADIS16505_2] = {
|
[ADIS16505_2] = {
|
||||||
.name = "adis16505-2",
|
.name = "adis16505-2",
|
||||||
.num_channels = ARRAY_SIZE(adis16475_channels),
|
.num_channels = ARRAY_SIZE(adis16477_channels),
|
||||||
.channels = adis16475_channels,
|
.channels = adis16477_channels,
|
||||||
.gyro_max_val = 1,
|
.gyro_max_val = 1,
|
||||||
.gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
|
.gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
|
||||||
.accel_max_val = 78,
|
.accel_max_val = 78,
|
||||||
.accel_max_scale = 32000 << 16,
|
.accel_max_scale = 32000 << 16,
|
||||||
.temp_scale = 100,
|
.temp_scale = 100,
|
||||||
|
.deltang_max_val = IIO_DEGREE_TO_RAD(720),
|
||||||
|
.deltvel_max_val = 100,
|
||||||
.int_clk = 2000,
|
.int_clk = 2000,
|
||||||
.max_dec = 1999,
|
.max_dec = 1999,
|
||||||
.sync = adis16475_sync_mode,
|
.sync = adis16475_sync_mode,
|
||||||
/* pulse sync not supported */
|
/* pulse sync not supported */
|
||||||
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
|
.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),
|
.adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts),
|
||||||
},
|
},
|
||||||
[ADIS16505_3] = {
|
[ADIS16505_3] = {
|
||||||
.name = "adis16505-3",
|
.name = "adis16505-3",
|
||||||
.num_channels = ARRAY_SIZE(adis16475_channels),
|
.num_channels = ARRAY_SIZE(adis16477_channels),
|
||||||
.channels = adis16475_channels,
|
.channels = adis16477_channels,
|
||||||
.gyro_max_val = 1,
|
.gyro_max_val = 1,
|
||||||
.gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
|
.gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
|
||||||
.accel_max_val = 78,
|
.accel_max_val = 78,
|
||||||
.accel_max_scale = 32000 << 16,
|
.accel_max_scale = 32000 << 16,
|
||||||
.temp_scale = 100,
|
.temp_scale = 100,
|
||||||
|
.deltang_max_val = IIO_DEGREE_TO_RAD(2160),
|
||||||
|
.deltvel_max_val = 100,
|
||||||
.int_clk = 2000,
|
.int_clk = 2000,
|
||||||
.max_dec = 1999,
|
.max_dec = 1999,
|
||||||
.sync = adis16475_sync_mode,
|
.sync = adis16475_sync_mode,
|
||||||
/* pulse sync not supported */
|
/* pulse sync not supported */
|
||||||
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
|
.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),
|
.adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts),
|
||||||
},
|
},
|
||||||
[ADIS16507_1] = {
|
[ADIS16507_1] = {
|
||||||
.name = "adis16507-1",
|
.name = "adis16507-1",
|
||||||
.num_channels = ARRAY_SIZE(adis16475_channels),
|
.num_channels = ARRAY_SIZE(adis16477_channels),
|
||||||
.channels = adis16475_channels,
|
.channels = adis16477_channels,
|
||||||
.gyro_max_val = 1,
|
.gyro_max_val = 1,
|
||||||
.gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
|
.gyro_max_scale = IIO_RAD_TO_DEGREE(160 << 16),
|
||||||
.accel_max_val = 392,
|
.accel_max_val = 392,
|
||||||
.accel_max_scale = 32000 << 16,
|
.accel_max_scale = 32000 << 16,
|
||||||
.temp_scale = 100,
|
.temp_scale = 100,
|
||||||
|
.deltang_max_val = IIO_DEGREE_TO_RAD(360),
|
||||||
|
.deltvel_max_val = 400,
|
||||||
.int_clk = 2000,
|
.int_clk = 2000,
|
||||||
.max_dec = 1999,
|
.max_dec = 1999,
|
||||||
.sync = adis16475_sync_mode,
|
.sync = adis16475_sync_mode,
|
||||||
/* pulse sync not supported */
|
/* pulse sync not supported */
|
||||||
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
|
.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),
|
.adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts),
|
||||||
},
|
},
|
||||||
[ADIS16507_2] = {
|
[ADIS16507_2] = {
|
||||||
.name = "adis16507-2",
|
.name = "adis16507-2",
|
||||||
.num_channels = ARRAY_SIZE(adis16475_channels),
|
.num_channels = ARRAY_SIZE(adis16477_channels),
|
||||||
.channels = adis16475_channels,
|
.channels = adis16477_channels,
|
||||||
.gyro_max_val = 1,
|
.gyro_max_val = 1,
|
||||||
.gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
|
.gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
|
||||||
.accel_max_val = 392,
|
.accel_max_val = 392,
|
||||||
.accel_max_scale = 32000 << 16,
|
.accel_max_scale = 32000 << 16,
|
||||||
.temp_scale = 100,
|
.temp_scale = 100,
|
||||||
|
.deltang_max_val = IIO_DEGREE_TO_RAD(720),
|
||||||
|
.deltvel_max_val = 400,
|
||||||
.int_clk = 2000,
|
.int_clk = 2000,
|
||||||
.max_dec = 1999,
|
.max_dec = 1999,
|
||||||
.sync = adis16475_sync_mode,
|
.sync = adis16475_sync_mode,
|
||||||
/* pulse sync not supported */
|
/* pulse sync not supported */
|
||||||
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
|
.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),
|
.adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts),
|
||||||
},
|
},
|
||||||
[ADIS16507_3] = {
|
[ADIS16507_3] = {
|
||||||
.name = "adis16507-3",
|
.name = "adis16507-3",
|
||||||
.num_channels = ARRAY_SIZE(adis16475_channels),
|
.num_channels = ARRAY_SIZE(adis16477_channels),
|
||||||
.channels = adis16475_channels,
|
.channels = adis16477_channels,
|
||||||
.gyro_max_val = 1,
|
.gyro_max_val = 1,
|
||||||
.gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
|
.gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
|
||||||
.accel_max_val = 392,
|
.accel_max_val = 392,
|
||||||
.accel_max_scale = 32000 << 16,
|
.accel_max_scale = 32000 << 16,
|
||||||
.temp_scale = 100,
|
.temp_scale = 100,
|
||||||
|
.deltang_max_val = IIO_DEGREE_TO_RAD(2160),
|
||||||
|
.deltvel_max_val = 400,
|
||||||
.int_clk = 2000,
|
.int_clk = 2000,
|
||||||
.max_dec = 1999,
|
.max_dec = 1999,
|
||||||
.sync = adis16475_sync_mode,
|
.sync = adis16475_sync_mode,
|
||||||
/* pulse sync not supported */
|
/* pulse sync not supported */
|
||||||
.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
|
.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),
|
.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 = {
|
static const struct iio_info adis16475_info = {
|
||||||
.read_raw = &adis16475_read_raw,
|
.read_raw = &adis16475_read_raw,
|
||||||
.write_raw = &adis16475_write_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,
|
.debugfs_reg_access = adis_debugfs_reg_access,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -998,7 +1147,7 @@ static void adis16475_burst32_check(struct adis16475 *st)
|
|||||||
int ret;
|
int ret;
|
||||||
struct adis *adis = &st->adis;
|
struct adis *adis = &st->adis;
|
||||||
|
|
||||||
if (!st->info->has_burst32)
|
if (!(st->info->flags & ADIS16475_HAS_BURST32))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (st->lsb_flag && !st->burst32) {
|
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 iio_dev *indio_dev = pf->indio_dev;
|
||||||
struct adis16475 *st = iio_priv(indio_dev);
|
struct adis16475 *st = iio_priv(indio_dev);
|
||||||
struct adis *adis = &st->adis;
|
struct adis *adis = &st->adis;
|
||||||
int ret, bit, i = 0;
|
int ret, bit, buff_offset = 0, i = 0;
|
||||||
__be16 *buffer;
|
__be16 *buffer;
|
||||||
u16 crc;
|
u16 crc;
|
||||||
bool valid;
|
bool valid;
|
||||||
@ -1073,7 +1222,20 @@ static irqreturn_t adis16475_trigger_handler(int irq, void *p)
|
|||||||
switch (bit) {
|
switch (bit) {
|
||||||
case ADIS16475_SCAN_TEMP:
|
case ADIS16475_SCAN_TEMP:
|
||||||
st->data[i++] = buffer[offset];
|
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;
|
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:
|
case ADIS16475_SCAN_GYRO_X ... ADIS16475_SCAN_ACCEL_Z:
|
||||||
/*
|
/*
|
||||||
* The first 2 bytes on the received data are the
|
* 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) {
|
if (st->burst32) {
|
||||||
/* upper 16 */
|
/* upper 16 */
|
||||||
st->data[i++] = buffer[bit * 2 + 2];
|
st->data[i++] = buffer[(bit - buff_offset) * 2 + 2];
|
||||||
/* lower 16 */
|
/* lower 16 */
|
||||||
st->data[i++] = buffer[bit * 2 + 1];
|
st->data[i++] = buffer[(bit - buff_offset) * 2 + 1];
|
||||||
} else {
|
} 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
|
* Don't bother in doing the manual read if the
|
||||||
* device supports burst32. burst32 will be
|
* device supports burst32. burst32 will be
|
||||||
* enabled in the next call to
|
* enabled in the next call to
|
||||||
* adis16475_burst32_check()...
|
* adis16475_burst32_check()...
|
||||||
*/
|
*/
|
||||||
if (st->lsb_flag && !st->info->has_burst32) {
|
if (st->lsb_flag && !(st->info->flags & ADIS16475_HAS_BURST32)) {
|
||||||
u16 val = 0;
|
u16 val = 0;
|
||||||
const u32 reg = ADIS16475_REG_X_GYRO_L +
|
const u32 reg = ADIS16475_REG_X_GYRO_L +
|
||||||
bit * 4;
|
bit * 4;
|
||||||
|
@ -71,6 +71,19 @@ int inv_mpu_aux_init(const struct inv_mpu6050_state *st)
|
|||||||
unsigned int val;
|
unsigned int val;
|
||||||
int ret;
|
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 */
|
/* configure i2c master */
|
||||||
val = INV_MPU6050_BITS_I2C_MST_CLK_400KHZ |
|
val = INV_MPU6050_BITS_I2C_MST_CLK_400KHZ |
|
||||||
INV_MPU6050_BIT_WAIT_FOR_ES;
|
INV_MPU6050_BIT_WAIT_FOR_ES;
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
#include <linux/pm.h>
|
#include <linux/pm.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/property.h>
|
||||||
|
|
||||||
#include <linux/iio/common/inv_sensors_timestamp.h>
|
#include <linux/iio/common/inv_sensors_timestamp.h>
|
||||||
#include <linux/iio/iio.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->irq = irq;
|
||||||
st->map = regmap;
|
st->map = regmap;
|
||||||
|
|
||||||
|
st->level_shifter = device_property_read_bool(dev,
|
||||||
|
"invensense,level-shifter");
|
||||||
pdata = dev_get_platdata(dev);
|
pdata = dev_get_platdata(dev);
|
||||||
if (!pdata) {
|
if (!pdata) {
|
||||||
result = iio_read_mount_matrix(dev, &st->orientation);
|
result = iio_read_mount_matrix(dev, &st->orientation);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user