mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-06 19:07:52 +00:00
2nd set of IIO features, cleanups etc for 5.13
Trying again as a wrong fixes tag managed to beat the checking script I was running. A few of these are fixes for major rework earlier in cycle. Bulk of patches are the ad7150 pre graduation cleanup, some link fixes in maintainers and set using the new IRQF_NO_AUTOEN flag. Note includes a merge of a tag from tip to get the IRQF_NO_AUTOEN support (one patch only from Barry Song) Staging graduation * adi,ad7150 CDC - A lot of precursor patches cleaning it up first. - Includes core support for timeout event ABI where after a time a adaptive threshold jumps to fix slow tracking problems. Cleanups and minor / late breaking fixes * core - Use sysfs_emit() and sysfs_emit_at() as appropriate - Fix a bug introduced in this cycle for iio_read_channel_processed_scale() - Fix handling of getfd ioctl as IIO_IOCTL_UNHANDLED is a valid ioctl number - Tidy up some pointless type conversion in string formatting and odd indentation. * dac - Use sysfs_emit() for powerdown attribute show() functions. * docs - Fix dead links due to txt to yaml binding conversions. * treewide - Use IRQF_NO_AUTOEN * various - Typo fixes in comments. * triggers/hr-timer-trigger - Fix an overflow handing issue. * ad,ad7923 - Device managed functions in probe() * ad,ad9467 - Fix kconfig dependency issue * adi,adis16201 - Fix a wrong axis assignment that stops the driver loading. * invensense,mpu6050 - Allow use as a standalone trigger (no channels enabled) - Drop unnecessary manual assignment of indio_dev->modes - Make device function in a basic way if no interrupt wired. - Sanity check scale writes. * semtech,sx9310 - Fix access to a variable length array in DT binding. - Sanity check input before writing debounce register. * st,stm32-dfsdm - Drop __func__ from dev_dbg() and pr_debug(). * yamaha,yas530 - Include asm/unaligned.h instead of be_byteshift.h - Fix an issue with return value on an error path. -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEEbilms4eEBlKRJoGxVIU0mcT0FogFAmBtYfIRHGppYzIzQGtl cm5lbC5vcmcACgkQVIU0mcT0FogXCQ//T6eQjWzgM3y3mR2Op0koyTYHBBQSq+/a SfgfcKmDJbAqebg/f4RfyU6Q+5l2aRZOsznRDPXHQUtIvocmp8D+LKMLJQpdDcKC P0kbge0UXW2zP+l/+cd1qy14+aka+l2lsMV1pdCsJXbBrOpW3rhRkJiK0BRchXLm 5XyFXcrnBcuH/unLBYTvsUZ4QLHMav1FWN6CMsjmZzOgPU3SzJCPz4qpd1ZugULU BvRs8GCQYhA23FVlStr7OTo1N0NHHDt0M8oCwEO2fdg+MXBVOarAtHxZuVq+dfPv 7EXlE8J/v2g6kXLiMT2dvXIKSOhpUgZI+gaVfX+drZyayfrTi+ik+EVdr/yGHEkv 1lFab0/svaAeZGjlOuB9qNUoee45Qkpf6ef/jY5DT88Gy5/C5fYCVmPx0f7GP8iy N3qCOtA70peAd1W7B9FBZzUaaB3rhNkCqzvTHkZiLOmkz2hG5zXfY7PAdyn0jf72 9n7PAuiEfV6vH9ZrtLjL4ReodpNzTFqgNsoMf90ff+LDqlZNgtNY/UHc4a8T+k1T 9F6dMECrEmnL9qYMmn7wF2oFvOkMoFcb7avugl5zeZFjV3gE/udAdwOeHGXCtATV LX0ro8HejHOd6WxW7cKDG47TuNyBMvai7TNyGMkZNQWwVHbNdqQFsOi+aYI9Sm92 JkQSzbogpMA= =7i4R -----END PGP SIGNATURE----- Merge tag 'iio-for-5.13b-take2' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next Jonathan writes: 2nd set of IIO features, cleanups etc for 5.13 Trying again as a wrong fixes tag managed to beat the checking script I was running. A few of these are fixes for major rework earlier in cycle. Bulk of patches are the ad7150 pre graduation cleanup, some link fixes in maintainers and set using the new IRQF_NO_AUTOEN flag. Note includes a merge of a tag from tip to get the IRQF_NO_AUTOEN support (one patch only from Barry Song) Staging graduation * adi,ad7150 CDC - A lot of precursor patches cleaning it up first. - Includes core support for timeout event ABI where after a time a adaptive threshold jumps to fix slow tracking problems. Cleanups and minor / late breaking fixes * core - Use sysfs_emit() and sysfs_emit_at() as appropriate - Fix a bug introduced in this cycle for iio_read_channel_processed_scale() - Fix handling of getfd ioctl as IIO_IOCTL_UNHANDLED is a valid ioctl number - Tidy up some pointless type conversion in string formatting and odd indentation. * dac - Use sysfs_emit() for powerdown attribute show() functions. * docs - Fix dead links due to txt to yaml binding conversions. * treewide - Use IRQF_NO_AUTOEN * various - Typo fixes in comments. * triggers/hr-timer-trigger - Fix an overflow handing issue. * ad,ad7923 - Device managed functions in probe() * ad,ad9467 - Fix kconfig dependency issue * adi,adis16201 - Fix a wrong axis assignment that stops the driver loading. * invensense,mpu6050 - Allow use as a standalone trigger (no channels enabled) - Drop unnecessary manual assignment of indio_dev->modes - Make device function in a basic way if no interrupt wired. - Sanity check scale writes. * semtech,sx9310 - Fix access to a variable length array in DT binding. - Sanity check input before writing debounce register. * st,stm32-dfsdm - Drop __func__ from dev_dbg() and pr_debug(). * yamaha,yas530 - Include asm/unaligned.h instead of be_byteshift.h - Fix an issue with return value on an error path. * tag 'iio-for-5.13b-take2' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio: (76 commits) iio: inv_mpu6050: Fully validate gyro and accel scale writes iio: sx9310: Fix write_.._debounce() iio: sx9310: Fix access to variable DT array iio: adc: Kconfig: make AD9467 depend on ADI_AXI_ADC symbol iio: magnetometer: yas530: Include right header iio: magnetometer: yas530: Fix return value on error path iio:cdc:ad7150: Fix use of uninitialized ret iio: hrtimer-trigger: Fix potential integer overflow in iio_hrtimer_store_sampling_frequency iio:adc: Fix trivial typo iio:adc:ad7476: Fix remove handling iio:adc:ad_sigma_delta: Use IRQF_NO_AUTOEN rather than request and disable iio:imu:adis: Use IRQF_NO_AUTOEN instead of irq request then disable iio:chemical:scd30: Use IRQF_NO_AUTOEN to avoid irq request then disable iio:adc:sun4i-gpadc: Use new IRQF_NO_AUTOEN flag instead of request then disable iio:adc:nau7802: Use IRQF_NO_AUTOEN instead of request then disable iio:adc:exynos-adc: Use new IRQF_NO_AUTOEN flag rather than separate irq_disable() iio:adc:ad7766: Use new IRQF_NO_AUTOEN to reduce boilerplate iio: buffer: use sysfs_attr_init() on allocated attrs iio: trigger: Fix strange (ladder-type) indentation iio: trigger: Replace explicit casting and wrong specifier with proper one ...
This commit is contained in:
commit
6470a8206a
63 changed files with 1078 additions and 927 deletions
|
@ -371,6 +371,7 @@ What: /sys/bus/iio/devices/iio:deviceX/in_humidityrelative_offset
|
|||
What: /sys/bus/iio/devices/iio:deviceX/in_magn_offset
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_rot_offset
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_angl_offset
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_capacitanceX_offset
|
||||
KernelVersion: 2.6.35
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
|
@ -702,6 +703,8 @@ What: /sys/.../iio:deviceX/events/in_voltageY_thresh_falling_en
|
|||
What: /sys/.../iio:deviceX/events/in_voltageY_thresh_either_en
|
||||
What: /sys/.../iio:deviceX/events/in_tempY_thresh_rising_en
|
||||
What: /sys/.../iio:deviceX/events/in_tempY_thresh_falling_en
|
||||
What: /sys/.../iio:deviceX/events/in_capacitanceY_thresh_rising_en
|
||||
What: /sys/.../iio:deviceX/events/in_capacitanceY_thresh_falling_en
|
||||
KernelVersion: 2.6.37
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
|
@ -779,6 +782,32 @@ Description:
|
|||
a given event type is enabled a future point (and not those for
|
||||
whatever event was previously enabled).
|
||||
|
||||
What: /sys/.../events/in_capacitanceY_adaptive_thresh_rising_en
|
||||
What: /sys/.../events/in_capacitanceY_adaptive_thresh_falling_en
|
||||
KernelVersion: 5.13
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Descrption:
|
||||
Adaptive thresholds are similar to normal fixed thresholds
|
||||
but the value is expressed as an offset from a value which
|
||||
provides a low frequency approximation of the channel itself.
|
||||
Thus these detect if a rapid change occurs in the specified
|
||||
direction which crosses tracking value + offset.
|
||||
Tracking value calculation is devices specific.
|
||||
|
||||
What: /sys/.../in_capacitanceY_adaptive_thresh_rising_timeout
|
||||
What: /sys/.../in_capacitanceY_adaptive_thresh_falling_timeout
|
||||
KernelVersion: 5.11
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Descrption:
|
||||
When adaptive thresholds are used, the tracking signal
|
||||
may adjust too slowly to step changes in the raw signal.
|
||||
*_timeout (in seconds) specifies a time for which the
|
||||
difference between the slow tracking signal and the raw
|
||||
signal is allowed to remain out-of-range before a reset
|
||||
event occurs in which the tracking signal is made equal
|
||||
to the raw signal, allowing slow tracking to resume and the
|
||||
adaptive threshold event detection to function as expected.
|
||||
|
||||
What: /sys/.../events/in_accel_thresh_rising_value
|
||||
What: /sys/.../events/in_accel_thresh_falling_value
|
||||
What: /sys/.../events/in_accel_x_raw_thresh_rising_value
|
||||
|
@ -819,6 +848,10 @@ What: /sys/.../events/in_proximity0_thresh_falling_value
|
|||
What: /sys/.../events/in_proximity0_thresh_rising_value
|
||||
What: /sys/.../events/in_illuminance_thresh_rising_value
|
||||
What: /sys/.../events/in_illuminance_thresh_falling_value
|
||||
What: /sys/.../events/in_capacitanceY_thresh_rising_value
|
||||
What: /sys/.../events/in_capacitanceY_thresh_falling_value
|
||||
What: /sys/.../events/in_capacitanceY_thresh_adaptive_rising_value
|
||||
What: /sys/.../events/in_capacitanceY_thresh_falling_rising_value
|
||||
KernelVersion: 2.6.37
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
|
|
69
Documentation/devicetree/bindings/iio/cdc/adi,ad7150.yaml
Normal file
69
Documentation/devicetree/bindings/iio/cdc/adi,ad7150.yaml
Normal file
|
@ -0,0 +1,69 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/cdc/adi,ad7150.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog device AD7150 and similar capacitance to digital convertors.
|
||||
|
||||
maintainers:
|
||||
- Jonathan Cameron <jic23@kernel.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,ad7150
|
||||
- adi,ad7151
|
||||
- adi,ad7156
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
interrupts: true
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- adi,ad7150
|
||||
- adi,ad7156
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: adi,ad7151
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
minItems: 1
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cdc@48 {
|
||||
compatible = "adi,ad7150";
|
||||
reg = <0x48>;
|
||||
interrupts = <25 2>, <26 2>;
|
||||
interrupt-parent = <&gpio>;
|
||||
};
|
||||
};
|
||||
...
|
26
MAINTAINERS
26
MAINTAINERS
|
@ -1141,7 +1141,7 @@ W: http://ez.analog.com/community/linux-device-drivers
|
|||
F: Documentation/ABI/testing/sysfs-bus-iio-frequency-ad9523
|
||||
F: Documentation/ABI/testing/sysfs-bus-iio-frequency-adf4350
|
||||
F: Documentation/devicetree/bindings/iio/*/adi,*
|
||||
F: Documentation/devicetree/bindings/iio/dac/ad5758.txt
|
||||
F: Documentation/devicetree/bindings/iio/dac/adi,ad5758.yaml
|
||||
F: drivers/iio/*/ad*
|
||||
F: drivers/iio/adc/ltc249*
|
||||
F: drivers/iio/amplifiers/hmc425a.c
|
||||
|
@ -8198,7 +8198,7 @@ M: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
|
|||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
W: http://www.st.com/
|
||||
F: Documentation/devicetree/bindings/iio/humidity/hts221.txt
|
||||
F: Documentation/devicetree/bindings/iio/humidity/st,hts221.yaml
|
||||
F: drivers/iio/humidity/hts221*
|
||||
|
||||
HUAWEI ETHERNET DRIVER
|
||||
|
@ -8664,7 +8664,7 @@ M: Peter Rosin <peda@axentia.se>
|
|||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/ABI/testing/sysfs-bus-iio-dac-dpot-dac
|
||||
F: Documentation/devicetree/bindings/iio/dac/dpot-dac.txt
|
||||
F: Documentation/devicetree/bindings/iio/dac/dpot-dac.yaml
|
||||
F: drivers/iio/dac/dpot-dac.c
|
||||
|
||||
IIO ENVELOPE DETECTOR
|
||||
|
@ -8672,7 +8672,7 @@ M: Peter Rosin <peda@axentia.se>
|
|||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/ABI/testing/sysfs-bus-iio-adc-envelope-detector
|
||||
F: Documentation/devicetree/bindings/iio/adc/envelope-detector.txt
|
||||
F: Documentation/devicetree/bindings/iio/adc/envelope-detector.yaml
|
||||
F: drivers/iio/adc/envelope-detector.c
|
||||
|
||||
IIO MULTIPLEXER
|
||||
|
@ -8706,9 +8706,9 @@ IIO UNIT CONVERTER
|
|||
M: Peter Rosin <peda@axentia.se>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/afe/current-sense-amplifier.txt
|
||||
F: Documentation/devicetree/bindings/iio/afe/current-sense-shunt.txt
|
||||
F: Documentation/devicetree/bindings/iio/afe/voltage-divider.txt
|
||||
F: Documentation/devicetree/bindings/iio/afe/current-sense-amplifier.yaml
|
||||
F: Documentation/devicetree/bindings/iio/afe/current-sense-shunt.yaml
|
||||
F: Documentation/devicetree/bindings/iio/afe/voltage-divider.yaml
|
||||
F: drivers/iio/afe/iio-rescale.c
|
||||
|
||||
IKANOS/ADI EAGLE ADSL USB DRIVER
|
||||
|
@ -11798,7 +11798,7 @@ MICROCHIP SAMA5D2-COMPATIBLE ADC DRIVER
|
|||
M: Eugen Hristev <eugen.hristev@microchip.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt
|
||||
F: Documentation/devicetree/bindings/iio/adc/atmel,sama5d2-adc.yaml
|
||||
F: drivers/iio/adc/at91-sama5d2_adc.c
|
||||
F: include/dt-bindings/iio/adc/at91-sama5d2_adc.h
|
||||
|
||||
|
@ -14280,7 +14280,7 @@ PNI RM3100 IIO DRIVER
|
|||
M: Song Qiang <songqiang1304521@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/magnetometer/pni,rm3100.txt
|
||||
F: Documentation/devicetree/bindings/iio/magnetometer/pni,rm3100.yaml
|
||||
F: drivers/iio/magnetometer/rm3100*
|
||||
|
||||
PNP SUPPORT
|
||||
|
@ -15252,7 +15252,7 @@ RENESAS R-CAR GYROADC DRIVER
|
|||
M: Marek Vasut <marek.vasut@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/iio/adc/renesas,gyroadc.txt
|
||||
F: Documentation/devicetree/bindings/iio/adc/renesas,rcar-gyroadc.yaml
|
||||
F: drivers/iio/adc/rcar-gyroadc.c
|
||||
|
||||
RENESAS R-CAR I2C DRIVERS
|
||||
|
@ -16930,7 +16930,7 @@ M: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
|
|||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
W: http://www.st.com/
|
||||
F: Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt
|
||||
F: Documentation/devicetree/bindings/iio/imu/st,lsm6dsx.yaml
|
||||
F: drivers/iio/imu/st_lsm6dsx/
|
||||
|
||||
ST MIPID02 CSI-2 TO PARALLEL BRIDGE DRIVER
|
||||
|
@ -16952,7 +16952,7 @@ ST VL53L0X ToF RANGER(I2C) IIO DRIVER
|
|||
M: Song Qiang <songqiang1304521@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/proximity/vl53l0x.txt
|
||||
F: Documentation/devicetree/bindings/iio/proximity/st,vl53l0x.yaml
|
||||
F: drivers/iio/proximity/vl53l0x-i2c.c
|
||||
|
||||
STABLE BRANCH
|
||||
|
@ -17688,7 +17688,7 @@ TEXAS INSTRUMENTS' DAC7612 DAC DRIVER
|
|||
M: Ricardo Ribalda <ribalda@kernel.org>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/iio/dac/ti,dac7612.txt
|
||||
F: Documentation/devicetree/bindings/iio/dac/ti,dac7612.yaml
|
||||
F: drivers/iio/dac/ti-dac7612.c
|
||||
|
||||
TEXAS INSTRUMENTS DMA DRIVERS
|
||||
|
|
|
@ -72,6 +72,7 @@ source "drivers/iio/accel/Kconfig"
|
|||
source "drivers/iio/adc/Kconfig"
|
||||
source "drivers/iio/afe/Kconfig"
|
||||
source "drivers/iio/amplifiers/Kconfig"
|
||||
source "drivers/iio/cdc/Kconfig"
|
||||
source "drivers/iio/chemical/Kconfig"
|
||||
source "drivers/iio/common/Kconfig"
|
||||
source "drivers/iio/dac/Kconfig"
|
||||
|
|
|
@ -18,6 +18,7 @@ obj-y += adc/
|
|||
obj-y += afe/
|
||||
obj-y += amplifiers/
|
||||
obj-y += buffer/
|
||||
obj-y += cdc/
|
||||
obj-y += chemical/
|
||||
obj-y += common/
|
||||
obj-y += dac/
|
||||
|
|
|
@ -215,7 +215,7 @@ static const struct iio_chan_spec adis16201_channels[] = {
|
|||
ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC_REG, ADIS16201_SCAN_AUX_ADC, 0, 12),
|
||||
ADIS_INCLI_CHAN(X, ADIS16201_XINCL_OUT_REG, ADIS16201_SCAN_INCLI_X,
|
||||
BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
|
||||
ADIS_INCLI_CHAN(X, ADIS16201_YINCL_OUT_REG, ADIS16201_SCAN_INCLI_Y,
|
||||
ADIS_INCLI_CHAN(Y, ADIS16201_YINCL_OUT_REG, ADIS16201_SCAN_INCLI_Y,
|
||||
BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
|
||||
IIO_CHAN_SOFT_TIMESTAMP(7)
|
||||
};
|
||||
|
|
|
@ -97,7 +97,7 @@ config AD7298
|
|||
module will be called ad7298.
|
||||
|
||||
config AD7476
|
||||
tristate "Analog Devices AD7476 1-channel ADCs driver and other similar devices from AD an TI"
|
||||
tristate "Analog Devices AD7476 1-channel ADCs driver and other similar devices from AD and TI"
|
||||
depends on SPI
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
|
@ -249,7 +249,7 @@ config AD799X
|
|||
config AD9467
|
||||
tristate "Analog Devices AD9467 High Speed ADC driver"
|
||||
depends on SPI
|
||||
select ADI_AXI_ADC
|
||||
depends on ADI_AXI_ADC
|
||||
help
|
||||
Say yes here to build support for Analog Devices:
|
||||
* AD9467 16-Bit, 200 MSPS/250 MSPS Analog-to-Digital Converter
|
||||
|
|
|
@ -142,12 +142,6 @@ static int ad7298_update_scan_mode(struct iio_dev *indio_dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ad7298_trigger_handler() bh of trigger launched polling to ring buffer
|
||||
*
|
||||
* Currently there is no option in this driver to disable the saving of
|
||||
* timestamps within the ring.
|
||||
*/
|
||||
static irqreturn_t ad7298_trigger_handler(int irq, void *p)
|
||||
{
|
||||
struct iio_poll_func *pf = p;
|
||||
|
|
|
@ -321,25 +321,15 @@ static int ad7476_probe(struct spi_device *spi)
|
|||
spi_message_init(&st->msg);
|
||||
spi_message_add_tail(&st->xfer, &st->msg);
|
||||
|
||||
ret = iio_triggered_buffer_setup(indio_dev, NULL,
|
||||
&ad7476_trigger_handler, NULL);
|
||||
ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL,
|
||||
&ad7476_trigger_handler, NULL);
|
||||
if (ret)
|
||||
goto error_disable_reg;
|
||||
return ret;
|
||||
|
||||
if (st->chip_info->reset)
|
||||
st->chip_info->reset(st);
|
||||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret)
|
||||
goto error_ring_unregister;
|
||||
return 0;
|
||||
|
||||
error_ring_unregister:
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
error_disable_reg:
|
||||
regulator_disable(st->reg);
|
||||
|
||||
return ret;
|
||||
return devm_iio_device_register(&spi->dev, indio_dev);
|
||||
}
|
||||
|
||||
static const struct spi_device_id ad7476_id[] = {
|
||||
|
|
|
@ -255,18 +255,17 @@ static int ad7766_probe(struct spi_device *spi)
|
|||
ad7766->trig->ops = &ad7766_trigger_ops;
|
||||
iio_trigger_set_drvdata(ad7766->trig, ad7766);
|
||||
|
||||
ret = devm_request_irq(&spi->dev, spi->irq, ad7766_irq,
|
||||
IRQF_TRIGGER_FALLING, dev_name(&spi->dev),
|
||||
ad7766->trig);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* The device generates interrupts as long as it is powered up.
|
||||
* Some platforms might not allow the option to power it down so
|
||||
* disable the interrupt to avoid extra load on the system
|
||||
* don't enable the interrupt to avoid extra load on the system
|
||||
*/
|
||||
disable_irq(spi->irq);
|
||||
ret = devm_request_irq(&spi->dev, spi->irq, ad7766_irq,
|
||||
IRQF_TRIGGER_FALLING | IRQF_NO_AUTOEN,
|
||||
dev_name(&spi->dev),
|
||||
ad7766->trig);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = devm_iio_trigger_register(&spi->dev, ad7766->trig);
|
||||
if (ret)
|
||||
|
|
|
@ -109,12 +109,6 @@ static int ad7887_ring_postdisable(struct iio_dev *indio_dev)
|
|||
return spi_sync(st->spi, &st->msg[AD7887_CH0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* ad7887_trigger_handler() bh of trigger launched polling to ring buffer
|
||||
*
|
||||
* Currently there is no option in this driver to disable the saving of
|
||||
* timestamps within the ring.
|
||||
**/
|
||||
static irqreturn_t ad7887_trigger_handler(int irq, void *p)
|
||||
{
|
||||
struct iio_poll_func *pf = p;
|
||||
|
|
|
@ -192,12 +192,6 @@ static int ad7923_update_scan_mode(struct iio_dev *indio_dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ad7923_trigger_handler() bh of trigger launched polling to ring buffer
|
||||
*
|
||||
* Currently there is no option in this driver to disable the saving of
|
||||
* timestamps within the ring.
|
||||
*/
|
||||
static irqreturn_t ad7923_trigger_handler(int irq, void *p)
|
||||
{
|
||||
struct iio_poll_func *pf = p;
|
||||
|
@ -293,6 +287,13 @@ static const struct iio_info ad7923_info = {
|
|||
.update_scan_mode = ad7923_update_scan_mode,
|
||||
};
|
||||
|
||||
static void ad7923_regulator_disable(void *data)
|
||||
{
|
||||
struct ad7923_state *st = data;
|
||||
|
||||
regulator_disable(st->reg);
|
||||
}
|
||||
|
||||
static int ad7923_probe(struct spi_device *spi)
|
||||
{
|
||||
struct ad7923_state *st;
|
||||
|
@ -306,8 +307,6 @@ static int ad7923_probe(struct spi_device *spi)
|
|||
|
||||
st = iio_priv(indio_dev);
|
||||
|
||||
spi_set_drvdata(spi, indio_dev);
|
||||
|
||||
st->spi = spi;
|
||||
st->settings = AD7923_CODING | AD7923_RANGE |
|
||||
AD7923_PM_MODE_WRITE(AD7923_PM_MODE_OPS);
|
||||
|
@ -340,35 +339,16 @@ static int ad7923_probe(struct spi_device *spi)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iio_triggered_buffer_setup(indio_dev, NULL,
|
||||
&ad7923_trigger_handler, NULL);
|
||||
ret = devm_add_action_or_reset(&spi->dev, ad7923_regulator_disable, st);
|
||||
if (ret)
|
||||
goto error_disable_reg;
|
||||
return ret;
|
||||
|
||||
ret = iio_device_register(indio_dev);
|
||||
ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL,
|
||||
&ad7923_trigger_handler, NULL);
|
||||
if (ret)
|
||||
goto error_cleanup_ring;
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
|
||||
error_cleanup_ring:
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
error_disable_reg:
|
||||
regulator_disable(st->reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ad7923_remove(struct spi_device *spi)
|
||||
{
|
||||
struct iio_dev *indio_dev = spi_get_drvdata(spi);
|
||||
struct ad7923_state *st = iio_priv(indio_dev);
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
iio_triggered_buffer_cleanup(indio_dev);
|
||||
regulator_disable(st->reg);
|
||||
|
||||
return 0;
|
||||
return devm_iio_device_register(&spi->dev, indio_dev);
|
||||
}
|
||||
|
||||
static const struct spi_device_id ad7923_id[] = {
|
||||
|
@ -401,7 +381,6 @@ static struct spi_driver ad7923_driver = {
|
|||
.of_match_table = ad7923_of_match,
|
||||
},
|
||||
.probe = ad7923_probe,
|
||||
.remove = ad7923_remove,
|
||||
.id_table = ad7923_id,
|
||||
};
|
||||
module_spi_driver(ad7923_driver);
|
||||
|
|
|
@ -182,12 +182,6 @@ static int ad799x_update_config(struct ad799x_state *st, u16 config)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ad799x_trigger_handler() bh of trigger launched polling to ring buffer
|
||||
*
|
||||
* Currently there is no option in this driver to disable the saving of
|
||||
* timestamps within the ring.
|
||||
**/
|
||||
static irqreturn_t ad799x_trigger_handler(int irq, void *p)
|
||||
{
|
||||
struct iio_poll_func *pf = p;
|
||||
|
|
|
@ -485,18 +485,15 @@ static int ad_sd_probe_trigger(struct iio_dev *indio_dev)
|
|||
sigma_delta->trig->ops = &ad_sd_trigger_ops;
|
||||
init_completion(&sigma_delta->completion);
|
||||
|
||||
sigma_delta->irq_dis = true;
|
||||
ret = request_irq(sigma_delta->spi->irq,
|
||||
ad_sd_data_rdy_trig_poll,
|
||||
sigma_delta->info->irq_flags,
|
||||
sigma_delta->info->irq_flags | IRQF_NO_AUTOEN,
|
||||
indio_dev->name,
|
||||
sigma_delta);
|
||||
if (ret)
|
||||
goto error_free_trig;
|
||||
|
||||
if (!sigma_delta->irq_dis) {
|
||||
sigma_delta->irq_dis = true;
|
||||
disable_irq_nosync(sigma_delta->spi->irq);
|
||||
}
|
||||
iio_trigger_set_drvdata(sigma_delta->trig, sigma_delta);
|
||||
|
||||
ret = iio_trigger_register(sigma_delta->trig);
|
||||
|
|
|
@ -778,9 +778,9 @@ static int exynos_adc_ts_init(struct exynos_adc *info)
|
|||
return ret;
|
||||
}
|
||||
|
||||
disable_irq(info->tsirq);
|
||||
ret = request_threaded_irq(info->tsirq, NULL, exynos_ts_isr,
|
||||
IRQF_ONESHOT, "touchscreen", info);
|
||||
IRQF_ONESHOT | IRQF_NO_AUTOEN,
|
||||
"touchscreen", info);
|
||||
if (ret)
|
||||
input_unregister_device(info->input);
|
||||
|
||||
|
|
|
@ -498,7 +498,8 @@ static int nau7802_probe(struct i2c_client *client,
|
|||
ret = request_threaded_irq(client->irq,
|
||||
NULL,
|
||||
nau7802_eoc_trigger,
|
||||
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
|
||||
IRQF_TRIGGER_HIGH | IRQF_ONESHOT |
|
||||
IRQF_NO_AUTOEN,
|
||||
client->dev.driver->name,
|
||||
indio_dev);
|
||||
if (ret) {
|
||||
|
@ -513,8 +514,7 @@ static int nau7802_probe(struct i2c_client *client,
|
|||
dev_info(&client->dev,
|
||||
"Failed to allocate IRQ, using polling mode\n");
|
||||
client->irq = 0;
|
||||
} else
|
||||
disable_irq(client->irq);
|
||||
}
|
||||
}
|
||||
|
||||
if (!client->irq) {
|
||||
|
|
|
@ -198,7 +198,7 @@ static int stm32_dfsdm_compute_osrs(struct stm32_dfsdm_filter *fl,
|
|||
unsigned int p = fl->ford; /* filter order (ford) */
|
||||
struct stm32_dfsdm_filter_osr *flo = &fl->flo[fast];
|
||||
|
||||
pr_debug("%s: Requested oversampling: %d\n", __func__, oversamp);
|
||||
pr_debug("Requested oversampling: %d\n", oversamp);
|
||||
/*
|
||||
* This function tries to compute filter oversampling and integrator
|
||||
* oversampling, base on oversampling ratio requested by user.
|
||||
|
@ -295,8 +295,8 @@ static int stm32_dfsdm_compute_osrs(struct stm32_dfsdm_filter *fl,
|
|||
flo->max = (s32)max;
|
||||
flo->bits = bits;
|
||||
|
||||
pr_debug("%s: fast %d, fosr %d, iosr %d, res 0x%llx/%d bits, rshift %d, lshift %d\n",
|
||||
__func__, fast, flo->fosr, flo->iosr,
|
||||
pr_debug("fast %d, fosr %d, iosr %d, res 0x%llx/%d bits, rshift %d, lshift %d\n",
|
||||
fast, flo->fosr, flo->iosr,
|
||||
flo->res, bits, flo->rshift,
|
||||
flo->lshift);
|
||||
}
|
||||
|
@ -864,7 +864,7 @@ static void stm32_dfsdm_dma_buffer_done(void *data)
|
|||
* support in IIO.
|
||||
*/
|
||||
|
||||
dev_dbg(&indio_dev->dev, "%s: pos = %d, available = %d\n", __func__,
|
||||
dev_dbg(&indio_dev->dev, "pos = %d, available = %d\n",
|
||||
adc->bufi, available);
|
||||
old_pos = adc->bufi;
|
||||
|
||||
|
@ -918,7 +918,7 @@ static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev)
|
|||
if (!adc->dma_chan)
|
||||
return -EINVAL;
|
||||
|
||||
dev_dbg(&indio_dev->dev, "%s size=%d watermark=%d\n", __func__,
|
||||
dev_dbg(&indio_dev->dev, "size=%d watermark=%d\n",
|
||||
adc->buf_sz, adc->buf_sz / 2);
|
||||
|
||||
if (adc->nconv == 1 && !indio_dev->trig)
|
||||
|
|
|
@ -470,7 +470,8 @@ static int sun4i_irq_init(struct platform_device *pdev, const char *name,
|
|||
}
|
||||
|
||||
*irq = ret;
|
||||
ret = devm_request_any_context_irq(&pdev->dev, *irq, handler, 0,
|
||||
ret = devm_request_any_context_irq(&pdev->dev, *irq, handler,
|
||||
IRQF_NO_AUTOEN,
|
||||
devname, info);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "could not request %s interrupt: %d\n",
|
||||
|
@ -478,7 +479,6 @@ static int sun4i_irq_init(struct platform_device *pdev, const char *name,
|
|||
return ret;
|
||||
}
|
||||
|
||||
disable_irq(*irq);
|
||||
atomic_set(atomic, 0);
|
||||
|
||||
return 0;
|
||||
|
|
17
drivers/iio/cdc/Kconfig
Normal file
17
drivers/iio/cdc/Kconfig
Normal file
|
@ -0,0 +1,17 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# CDC drivers
|
||||
#
|
||||
menu "Capacitance to digital converters"
|
||||
|
||||
config AD7150
|
||||
tristate "Analog Devices ad7150/1/6 capacitive sensor driver"
|
||||
depends on I2C
|
||||
help
|
||||
Say yes here to build support for Analog Devices capacitive sensors.
|
||||
(ad7150, ad7151, ad7156) Provides direct access via sysfs.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ad7150.
|
||||
|
||||
endmenu
|
6
drivers/iio/cdc/Makefile
Normal file
6
drivers/iio/cdc/Makefile
Normal file
|
@ -0,0 +1,6 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Makefile for industrial I/O capacitance to digital converter (CDC) drivers
|
||||
#
|
||||
|
||||
obj-$(CONFIG_AD7150) += ad7150.o
|
673
drivers/iio/cdc/ad7150.c
Normal file
673
drivers/iio/cdc/ad7150.c
Normal file
|
@ -0,0 +1,673 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* AD7150 capacitive sensor driver supporting AD7150/1/6
|
||||
*
|
||||
* Copyright 2010-2011 Analog Devices Inc.
|
||||
* Copyright 2021 Jonathan Cameron <Jonathan.Cameron@huawei.com>
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/events.h>
|
||||
|
||||
#define AD7150_STATUS_REG 0
|
||||
#define AD7150_STATUS_OUT1 BIT(3)
|
||||
#define AD7150_STATUS_OUT2 BIT(5)
|
||||
#define AD7150_CH1_DATA_HIGH_REG 1
|
||||
#define AD7150_CH2_DATA_HIGH_REG 3
|
||||
#define AD7150_CH1_AVG_HIGH_REG 5
|
||||
#define AD7150_CH2_AVG_HIGH_REG 7
|
||||
#define AD7150_CH1_SENSITIVITY_REG 9
|
||||
#define AD7150_CH1_THR_HOLD_H_REG 9
|
||||
#define AD7150_CH1_TIMEOUT_REG 10
|
||||
#define AD7150_CH_TIMEOUT_RECEDING GENMASK(3, 0)
|
||||
#define AD7150_CH_TIMEOUT_APPROACHING GENMASK(7, 4)
|
||||
#define AD7150_CH1_SETUP_REG 11
|
||||
#define AD7150_CH2_SENSITIVITY_REG 12
|
||||
#define AD7150_CH2_THR_HOLD_H_REG 12
|
||||
#define AD7150_CH2_TIMEOUT_REG 13
|
||||
#define AD7150_CH2_SETUP_REG 14
|
||||
#define AD7150_CFG_REG 15
|
||||
#define AD7150_CFG_FIX BIT(7)
|
||||
#define AD7150_CFG_THRESHTYPE_MSK GENMASK(6, 5)
|
||||
#define AD7150_CFG_TT_NEG 0x0
|
||||
#define AD7150_CFG_TT_POS 0x1
|
||||
#define AD7150_CFG_TT_IN_WINDOW 0x2
|
||||
#define AD7150_CFG_TT_OUT_WINDOW 0x3
|
||||
#define AD7150_PD_TIMER_REG 16
|
||||
#define AD7150_CH1_CAPDAC_REG 17
|
||||
#define AD7150_CH2_CAPDAC_REG 18
|
||||
#define AD7150_SN3_REG 19
|
||||
#define AD7150_SN2_REG 20
|
||||
#define AD7150_SN1_REG 21
|
||||
#define AD7150_SN0_REG 22
|
||||
#define AD7150_ID_REG 23
|
||||
|
||||
enum {
|
||||
AD7150,
|
||||
AD7151,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ad7150_chip_info - instance specific chip data
|
||||
* @client: i2c client for this device
|
||||
* @threshold: thresholds for simple capacitance value events
|
||||
* @thresh_sensitivity: threshold for simple capacitance offset
|
||||
* from 'average' value.
|
||||
* @thresh_timeout: a timeout, in samples from the moment an
|
||||
* adaptive threshold event occurs to when the average
|
||||
* value jumps to current value. Note made up of two fields,
|
||||
* 3:0 are for timeout receding - applies if below lower threshold
|
||||
* 7:4 are for timeout approaching - applies if above upper threshold
|
||||
* @state_lock: ensure consistent state of this structure wrt the
|
||||
* hardware.
|
||||
* @interrupts: one or two interrupt numbers depending on device type.
|
||||
* @int_enabled: is a given interrupt currently enabled.
|
||||
* @type: threshold type
|
||||
* @dir: threshold direction
|
||||
*/
|
||||
struct ad7150_chip_info {
|
||||
struct i2c_client *client;
|
||||
u16 threshold[2][2];
|
||||
u8 thresh_sensitivity[2][2];
|
||||
u8 thresh_timeout[2][2];
|
||||
struct mutex state_lock;
|
||||
int interrupts[2];
|
||||
bool int_enabled[2];
|
||||
enum iio_event_type type;
|
||||
enum iio_event_direction dir;
|
||||
};
|
||||
|
||||
static const u8 ad7150_addresses[][6] = {
|
||||
{ AD7150_CH1_DATA_HIGH_REG, AD7150_CH1_AVG_HIGH_REG,
|
||||
AD7150_CH1_SETUP_REG, AD7150_CH1_THR_HOLD_H_REG,
|
||||
AD7150_CH1_SENSITIVITY_REG, AD7150_CH1_TIMEOUT_REG },
|
||||
{ AD7150_CH2_DATA_HIGH_REG, AD7150_CH2_AVG_HIGH_REG,
|
||||
AD7150_CH2_SETUP_REG, AD7150_CH2_THR_HOLD_H_REG,
|
||||
AD7150_CH2_SENSITIVITY_REG, AD7150_CH2_TIMEOUT_REG },
|
||||
};
|
||||
|
||||
static int ad7150_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val,
|
||||
int *val2,
|
||||
long mask)
|
||||
{
|
||||
struct ad7150_chip_info *chip = iio_priv(indio_dev);
|
||||
int channel = chan->channel;
|
||||
int ret;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
ret = i2c_smbus_read_word_swapped(chip->client,
|
||||
ad7150_addresses[channel][0]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*val = ret >> 4;
|
||||
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_AVERAGE_RAW:
|
||||
ret = i2c_smbus_read_word_swapped(chip->client,
|
||||
ad7150_addresses[channel][1]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*val = ret;
|
||||
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
/*
|
||||
* Base units for capacitance are nano farads and the value
|
||||
* calculated from the datasheet formula is in picofarad
|
||||
* so multiply by 1000
|
||||
*/
|
||||
*val = 1000;
|
||||
*val2 = 40944 >> 4; /* To match shift in _RAW */
|
||||
return IIO_VAL_FRACTIONAL;
|
||||
case IIO_CHAN_INFO_OFFSET:
|
||||
*val = -(12288 >> 4); /* To match shift in _RAW */
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SAMP_FREQ:
|
||||
/* Strangely same for both 1 and 2 chan parts */
|
||||
*val = 100;
|
||||
return IIO_VAL_INT;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int ad7150_read_event_config(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir)
|
||||
{
|
||||
struct ad7150_chip_info *chip = iio_priv(indio_dev);
|
||||
u8 threshtype;
|
||||
bool thrfixed;
|
||||
int ret;
|
||||
|
||||
ret = i2c_smbus_read_byte_data(chip->client, AD7150_CFG_REG);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
threshtype = FIELD_GET(AD7150_CFG_THRESHTYPE_MSK, ret);
|
||||
|
||||
/*check if threshold mode is fixed or adaptive*/
|
||||
thrfixed = FIELD_GET(AD7150_CFG_FIX, ret);
|
||||
|
||||
switch (type) {
|
||||
case IIO_EV_TYPE_THRESH_ADAPTIVE:
|
||||
if (dir == IIO_EV_DIR_RISING)
|
||||
return !thrfixed && (threshtype == AD7150_CFG_TT_POS);
|
||||
return !thrfixed && (threshtype == AD7150_CFG_TT_NEG);
|
||||
case IIO_EV_TYPE_THRESH:
|
||||
if (dir == IIO_EV_DIR_RISING)
|
||||
return thrfixed && (threshtype == AD7150_CFG_TT_POS);
|
||||
return thrfixed && (threshtype == AD7150_CFG_TT_NEG);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* state_lock should be held to ensure consistent state */
|
||||
static int ad7150_write_event_params(struct iio_dev *indio_dev,
|
||||
unsigned int chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir)
|
||||
{
|
||||
struct ad7150_chip_info *chip = iio_priv(indio_dev);
|
||||
int rising = (dir == IIO_EV_DIR_RISING);
|
||||
|
||||
/* Only update value live, if parameter is in use */
|
||||
if ((type != chip->type) || (dir != chip->dir))
|
||||
return 0;
|
||||
|
||||
switch (type) {
|
||||
/* Note completely different from the adaptive versions */
|
||||
case IIO_EV_TYPE_THRESH: {
|
||||
u16 value = chip->threshold[rising][chan];
|
||||
return i2c_smbus_write_word_swapped(chip->client,
|
||||
ad7150_addresses[chan][3],
|
||||
value);
|
||||
}
|
||||
case IIO_EV_TYPE_THRESH_ADAPTIVE: {
|
||||
int ret;
|
||||
u8 sens, timeout;
|
||||
|
||||
sens = chip->thresh_sensitivity[rising][chan];
|
||||
ret = i2c_smbus_write_byte_data(chip->client,
|
||||
ad7150_addresses[chan][4],
|
||||
sens);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Single timeout register contains timeouts for both
|
||||
* directions.
|
||||
*/
|
||||
timeout = FIELD_PREP(AD7150_CH_TIMEOUT_APPROACHING,
|
||||
chip->thresh_timeout[1][chan]);
|
||||
timeout |= FIELD_PREP(AD7150_CH_TIMEOUT_RECEDING,
|
||||
chip->thresh_timeout[0][chan]);
|
||||
return i2c_smbus_write_byte_data(chip->client,
|
||||
ad7150_addresses[chan][5],
|
||||
timeout);
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int ad7150_write_event_config(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir, int state)
|
||||
{
|
||||
struct ad7150_chip_info *chip = iio_priv(indio_dev);
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* There is only a single shared control and no on chip
|
||||
* interrupt disables for the two interrupt lines.
|
||||
* So, enabling will switch the events configured to enable
|
||||
* whatever was most recently requested and if necessary enable_irq()
|
||||
* the interrupt and any disable will disable_irq() for that
|
||||
* channels interrupt.
|
||||
*/
|
||||
if (!state) {
|
||||
if ((chip->int_enabled[chan->channel]) &&
|
||||
(type == chip->type) && (dir == chip->dir)) {
|
||||
disable_irq(chip->interrupts[chan->channel]);
|
||||
chip->int_enabled[chan->channel] = false;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
mutex_lock(&chip->state_lock);
|
||||
if ((type != chip->type) || (dir != chip->dir)) {
|
||||
int rising = (dir == IIO_EV_DIR_RISING);
|
||||
u8 thresh_type, cfg, fixed;
|
||||
|
||||
/*
|
||||
* Need to temporarily disable both interrupts if
|
||||
* enabled - this is to avoid races around changing
|
||||
* config and thresholds.
|
||||
* Note enable/disable_irq() are reference counted so
|
||||
* no need to check if already enabled.
|
||||
*/
|
||||
disable_irq(chip->interrupts[0]);
|
||||
disable_irq(chip->interrupts[1]);
|
||||
|
||||
ret = i2c_smbus_read_byte_data(chip->client, AD7150_CFG_REG);
|
||||
if (ret < 0)
|
||||
goto error_ret;
|
||||
|
||||
cfg = ret & ~(AD7150_CFG_THRESHTYPE_MSK | AD7150_CFG_FIX);
|
||||
|
||||
if (type == IIO_EV_TYPE_THRESH_ADAPTIVE)
|
||||
fixed = 0;
|
||||
else
|
||||
fixed = 1;
|
||||
|
||||
if (rising)
|
||||
thresh_type = AD7150_CFG_TT_POS;
|
||||
else
|
||||
thresh_type = AD7150_CFG_TT_NEG;
|
||||
|
||||
cfg |= FIELD_PREP(AD7150_CFG_FIX, fixed) |
|
||||
FIELD_PREP(AD7150_CFG_THRESHTYPE_MSK, thresh_type);
|
||||
|
||||
ret = i2c_smbus_write_byte_data(chip->client, AD7150_CFG_REG,
|
||||
cfg);
|
||||
if (ret < 0)
|
||||
goto error_ret;
|
||||
|
||||
/*
|
||||
* There is a potential race condition here, but not easy
|
||||
* to close given we can't disable the interrupt at the
|
||||
* chip side of things. Rely on the status bit.
|
||||
*/
|
||||
chip->type = type;
|
||||
chip->dir = dir;
|
||||
|
||||
/* update control attributes */
|
||||
ret = ad7150_write_event_params(indio_dev, chan->channel, type,
|
||||
dir);
|
||||
if (ret)
|
||||
goto error_ret;
|
||||
/* reenable any irq's we disabled whilst changing mode */
|
||||
enable_irq(chip->interrupts[0]);
|
||||
enable_irq(chip->interrupts[1]);
|
||||
}
|
||||
if (!chip->int_enabled[chan->channel]) {
|
||||
enable_irq(chip->interrupts[chan->channel]);
|
||||
chip->int_enabled[chan->channel] = true;
|
||||
}
|
||||
|
||||
error_ret:
|
||||
mutex_unlock(&chip->state_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ad7150_read_event_value(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir,
|
||||
enum iio_event_info info,
|
||||
int *val, int *val2)
|
||||
{
|
||||
struct ad7150_chip_info *chip = iio_priv(indio_dev);
|
||||
int rising = (dir == IIO_EV_DIR_RISING);
|
||||
|
||||
/* Complex register sharing going on here */
|
||||
switch (info) {
|
||||
case IIO_EV_INFO_VALUE:
|
||||
switch (type) {
|
||||
case IIO_EV_TYPE_THRESH_ADAPTIVE:
|
||||
*val = chip->thresh_sensitivity[rising][chan->channel];
|
||||
return IIO_VAL_INT;
|
||||
case IIO_EV_TYPE_THRESH:
|
||||
*val = chip->threshold[rising][chan->channel];
|
||||
return IIO_VAL_INT;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
case IIO_EV_INFO_TIMEOUT:
|
||||
*val = 0;
|
||||
*val2 = chip->thresh_timeout[rising][chan->channel] * 10000;
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int ad7150_write_event_value(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir,
|
||||
enum iio_event_info info,
|
||||
int val, int val2)
|
||||
{
|
||||
int ret;
|
||||
struct ad7150_chip_info *chip = iio_priv(indio_dev);
|
||||
int rising = (dir == IIO_EV_DIR_RISING);
|
||||
|
||||
mutex_lock(&chip->state_lock);
|
||||
switch (info) {
|
||||
case IIO_EV_INFO_VALUE:
|
||||
switch (type) {
|
||||
case IIO_EV_TYPE_THRESH_ADAPTIVE:
|
||||
chip->thresh_sensitivity[rising][chan->channel] = val;
|
||||
break;
|
||||
case IIO_EV_TYPE_THRESH:
|
||||
chip->threshold[rising][chan->channel] = val;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto error_ret;
|
||||
}
|
||||
break;
|
||||
case IIO_EV_INFO_TIMEOUT: {
|
||||
/*
|
||||
* Raw timeout is in cycles of 10 msecs as long as both
|
||||
* channels are enabled.
|
||||
* In terms of INT_PLUS_MICRO, that is in units of 10,000
|
||||
*/
|
||||
int timeout = val2 / 10000;
|
||||
|
||||
if (val != 0 || timeout < 0 || timeout > 15 || val2 % 10000) {
|
||||
ret = -EINVAL;
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
chip->thresh_timeout[rising][chan->channel] = timeout;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
/* write back if active */
|
||||
ret = ad7150_write_event_params(indio_dev, chan->channel, type, dir);
|
||||
|
||||
error_ret:
|
||||
mutex_unlock(&chip->state_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct iio_event_spec ad7150_events[] = {
|
||||
{
|
||||
.type = IIO_EV_TYPE_THRESH,
|
||||
.dir = IIO_EV_DIR_RISING,
|
||||
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
|
||||
BIT(IIO_EV_INFO_ENABLE),
|
||||
}, {
|
||||
.type = IIO_EV_TYPE_THRESH,
|
||||
.dir = IIO_EV_DIR_FALLING,
|
||||
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
|
||||
BIT(IIO_EV_INFO_ENABLE),
|
||||
}, {
|
||||
.type = IIO_EV_TYPE_THRESH_ADAPTIVE,
|
||||
.dir = IIO_EV_DIR_RISING,
|
||||
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
|
||||
BIT(IIO_EV_INFO_ENABLE) |
|
||||
BIT(IIO_EV_INFO_TIMEOUT),
|
||||
}, {
|
||||
.type = IIO_EV_TYPE_THRESH_ADAPTIVE,
|
||||
.dir = IIO_EV_DIR_FALLING,
|
||||
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
|
||||
BIT(IIO_EV_INFO_ENABLE) |
|
||||
BIT(IIO_EV_INFO_TIMEOUT),
|
||||
},
|
||||
};
|
||||
|
||||
#define AD7150_CAPACITANCE_CHAN(_chan) { \
|
||||
.type = IIO_CAPACITANCE, \
|
||||
.indexed = 1, \
|
||||
.channel = _chan, \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||
BIT(IIO_CHAN_INFO_AVERAGE_RAW), \
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
|
||||
BIT(IIO_CHAN_INFO_OFFSET), \
|
||||
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
|
||||
.event_spec = ad7150_events, \
|
||||
.num_event_specs = ARRAY_SIZE(ad7150_events), \
|
||||
}
|
||||
|
||||
#define AD7150_CAPACITANCE_CHAN_NO_IRQ(_chan) { \
|
||||
.type = IIO_CAPACITANCE, \
|
||||
.indexed = 1, \
|
||||
.channel = _chan, \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||
BIT(IIO_CHAN_INFO_AVERAGE_RAW), \
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
|
||||
BIT(IIO_CHAN_INFO_OFFSET), \
|
||||
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
|
||||
}
|
||||
|
||||
static const struct iio_chan_spec ad7150_channels[] = {
|
||||
AD7150_CAPACITANCE_CHAN(0),
|
||||
AD7150_CAPACITANCE_CHAN(1),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec ad7150_channels_no_irq[] = {
|
||||
AD7150_CAPACITANCE_CHAN_NO_IRQ(0),
|
||||
AD7150_CAPACITANCE_CHAN_NO_IRQ(1),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec ad7151_channels[] = {
|
||||
AD7150_CAPACITANCE_CHAN(0),
|
||||
};
|
||||
|
||||
static const struct iio_chan_spec ad7151_channels_no_irq[] = {
|
||||
AD7150_CAPACITANCE_CHAN_NO_IRQ(0),
|
||||
};
|
||||
|
||||
static irqreturn_t __ad7150_event_handler(void *private, u8 status_mask,
|
||||
int channel)
|
||||
{
|
||||
struct iio_dev *indio_dev = private;
|
||||
struct ad7150_chip_info *chip = iio_priv(indio_dev);
|
||||
s64 timestamp = iio_get_time_ns(indio_dev);
|
||||
int int_status;
|
||||
|
||||
int_status = i2c_smbus_read_byte_data(chip->client, AD7150_STATUS_REG);
|
||||
if (int_status < 0)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if (!(int_status & status_mask))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
iio_push_event(indio_dev,
|
||||
IIO_UNMOD_EVENT_CODE(IIO_CAPACITANCE, channel,
|
||||
chip->type, chip->dir),
|
||||
timestamp);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t ad7150_event_handler_ch1(int irq, void *private)
|
||||
{
|
||||
return __ad7150_event_handler(private, AD7150_STATUS_OUT1, 0);
|
||||
}
|
||||
|
||||
static irqreturn_t ad7150_event_handler_ch2(int irq, void *private)
|
||||
{
|
||||
return __ad7150_event_handler(private, AD7150_STATUS_OUT2, 1);
|
||||
}
|
||||
|
||||
static IIO_CONST_ATTR(in_capacitance_thresh_adaptive_timeout_available,
|
||||
"[0 0.01 0.15]");
|
||||
|
||||
static struct attribute *ad7150_event_attributes[] = {
|
||||
&iio_const_attr_in_capacitance_thresh_adaptive_timeout_available
|
||||
.dev_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group ad7150_event_attribute_group = {
|
||||
.attrs = ad7150_event_attributes,
|
||||
.name = "events",
|
||||
};
|
||||
|
||||
static const struct iio_info ad7150_info = {
|
||||
.event_attrs = &ad7150_event_attribute_group,
|
||||
.read_raw = &ad7150_read_raw,
|
||||
.read_event_config = &ad7150_read_event_config,
|
||||
.write_event_config = &ad7150_write_event_config,
|
||||
.read_event_value = &ad7150_read_event_value,
|
||||
.write_event_value = &ad7150_write_event_value,
|
||||
};
|
||||
|
||||
static const struct iio_info ad7150_info_no_irq = {
|
||||
.read_raw = &ad7150_read_raw,
|
||||
};
|
||||
|
||||
static void ad7150_reg_disable(void *data)
|
||||
{
|
||||
struct regulator *reg = data;
|
||||
|
||||
regulator_disable(reg);
|
||||
}
|
||||
|
||||
static int ad7150_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct ad7150_chip_info *chip;
|
||||
struct iio_dev *indio_dev;
|
||||
struct regulator *reg;
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
chip = iio_priv(indio_dev);
|
||||
mutex_init(&chip->state_lock);
|
||||
chip->client = client;
|
||||
|
||||
indio_dev->name = id->name;
|
||||
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
reg = devm_regulator_get(&client->dev, "vdd");
|
||||
if (IS_ERR(reg))
|
||||
return PTR_ERR(reg);
|
||||
|
||||
ret = regulator_enable(reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(&client->dev, ad7150_reg_disable, reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
chip->interrupts[0] = fwnode_irq_get(dev_fwnode(&client->dev), 0);
|
||||
if (chip->interrupts[0] < 0)
|
||||
return chip->interrupts[0];
|
||||
if (id->driver_data == AD7150) {
|
||||
chip->interrupts[1] = fwnode_irq_get(dev_fwnode(&client->dev), 1);
|
||||
if (chip->interrupts[1] < 0)
|
||||
return chip->interrupts[1];
|
||||
}
|
||||
if (chip->interrupts[0] &&
|
||||
(id->driver_data == AD7151 || chip->interrupts[1])) {
|
||||
irq_set_status_flags(chip->interrupts[0], IRQ_NOAUTOEN);
|
||||
ret = devm_request_threaded_irq(&client->dev,
|
||||
chip->interrupts[0],
|
||||
NULL,
|
||||
&ad7150_event_handler_ch1,
|
||||
IRQF_TRIGGER_RISING |
|
||||
IRQF_ONESHOT,
|
||||
"ad7150_irq1",
|
||||
indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
indio_dev->info = &ad7150_info;
|
||||
switch (id->driver_data) {
|
||||
case AD7150:
|
||||
indio_dev->channels = ad7150_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(ad7150_channels);
|
||||
irq_set_status_flags(chip->interrupts[1], IRQ_NOAUTOEN);
|
||||
ret = devm_request_threaded_irq(&client->dev,
|
||||
chip->interrupts[1],
|
||||
NULL,
|
||||
&ad7150_event_handler_ch2,
|
||||
IRQF_TRIGGER_RISING |
|
||||
IRQF_ONESHOT,
|
||||
"ad7150_irq2",
|
||||
indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case AD7151:
|
||||
indio_dev->channels = ad7151_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(ad7151_channels);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
} else {
|
||||
indio_dev->info = &ad7150_info_no_irq;
|
||||
switch (id->driver_data) {
|
||||
case AD7150:
|
||||
indio_dev->channels = ad7150_channels_no_irq;
|
||||
indio_dev->num_channels =
|
||||
ARRAY_SIZE(ad7150_channels_no_irq);
|
||||
break;
|
||||
case AD7151:
|
||||
indio_dev->channels = ad7151_channels_no_irq;
|
||||
indio_dev->num_channels =
|
||||
ARRAY_SIZE(ad7151_channels_no_irq);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return devm_iio_device_register(indio_dev->dev.parent, indio_dev);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id ad7150_id[] = {
|
||||
{ "ad7150", AD7150 },
|
||||
{ "ad7151", AD7151 },
|
||||
{ "ad7156", AD7150 },
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, ad7150_id);
|
||||
|
||||
static const struct of_device_id ad7150_of_match[] = {
|
||||
{ "adi,ad7150" },
|
||||
{ "adi,ad7151" },
|
||||
{ "adi,ad7156" },
|
||||
{}
|
||||
};
|
||||
static struct i2c_driver ad7150_driver = {
|
||||
.driver = {
|
||||
.name = "ad7150",
|
||||
.of_match_table = ad7150_of_match,
|
||||
},
|
||||
.probe = ad7150_probe,
|
||||
.id_table = ad7150_id,
|
||||
};
|
||||
module_i2c_driver(ad7150_driver);
|
||||
|
||||
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
|
||||
MODULE_DESCRIPTION("Analog Devices AD7150/1/6 capacitive sensor driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -655,19 +655,19 @@ static int scd30_setup_trigger(struct iio_dev *indio_dev)
|
|||
|
||||
indio_dev->trig = iio_trigger_get(trig);
|
||||
|
||||
/*
|
||||
* Interrupt is enabled just before taking a fresh measurement
|
||||
* and disabled afterwards. This means we need to ensure it is not
|
||||
* enabled here to keep calls to enable/disable balanced.
|
||||
*/
|
||||
ret = devm_request_threaded_irq(dev, state->irq, scd30_irq_handler,
|
||||
scd30_irq_thread_handler, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
|
||||
scd30_irq_thread_handler,
|
||||
IRQF_TRIGGER_HIGH | IRQF_ONESHOT |
|
||||
IRQF_NO_AUTOEN,
|
||||
indio_dev->name, indio_dev);
|
||||
if (ret)
|
||||
dev_err(dev, "failed to request irq\n");
|
||||
|
||||
/*
|
||||
* Interrupt is enabled just before taking a fresh measurement
|
||||
* and disabled afterwards. This means we need to disable it here
|
||||
* to keep calls to enable/disable balanced.
|
||||
*/
|
||||
disable_irq(state->irq);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -277,7 +277,7 @@ static ssize_t ad5064_read_dac_powerdown(struct iio_dev *indio_dev,
|
|||
{
|
||||
struct ad5064_state *st = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%d\n", st->pwr_down[chan->channel]);
|
||||
return sysfs_emit(buf, "%d\n", st->pwr_down[chan->channel]);
|
||||
}
|
||||
|
||||
static ssize_t ad5064_write_dac_powerdown(struct iio_dev *indio_dev,
|
||||
|
|
|
@ -255,7 +255,7 @@ static ssize_t ad5360_read_dac_powerdown(struct device *dev,
|
|||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct ad5360_state *st = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%d\n", (bool)(st->ctrl & AD5360_SF_CTRL_PWR_DOWN));
|
||||
return sysfs_emit(buf, "%d\n", (bool)(st->ctrl & AD5360_SF_CTRL_PWR_DOWN));
|
||||
}
|
||||
|
||||
static int ad5360_update_ctrl(struct iio_dev *indio_dev, unsigned int set,
|
||||
|
|
|
@ -85,7 +85,7 @@ static ssize_t ad5380_read_dac_powerdown(struct iio_dev *indio_dev,
|
|||
{
|
||||
struct ad5380_state *st = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%d\n", st->pwr_down);
|
||||
return sysfs_emit(buf, "%d\n", st->pwr_down);
|
||||
}
|
||||
|
||||
static ssize_t ad5380_write_dac_powerdown(struct iio_dev *indio_dev,
|
||||
|
|
|
@ -100,7 +100,7 @@ static ssize_t ad5446_read_dac_powerdown(struct iio_dev *indio_dev,
|
|||
{
|
||||
struct ad5446_state *st = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%d\n", st->pwr_down);
|
||||
return sysfs_emit(buf, "%d\n", st->pwr_down);
|
||||
}
|
||||
|
||||
static ssize_t ad5446_write_dac_powerdown(struct iio_dev *indio_dev,
|
||||
|
|
|
@ -170,8 +170,8 @@ static ssize_t ad5504_read_dac_powerdown(struct iio_dev *indio_dev,
|
|||
{
|
||||
struct ad5504_state *st = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%d\n",
|
||||
!(st->pwr_down_mask & (1 << chan->channel)));
|
||||
return sysfs_emit(buf, "%d\n",
|
||||
!(st->pwr_down_mask & (1 << chan->channel)));
|
||||
}
|
||||
|
||||
static ssize_t ad5504_write_dac_powerdown(struct iio_dev *indio_dev,
|
||||
|
|
|
@ -117,8 +117,8 @@ static ssize_t ad5624r_read_dac_powerdown(struct iio_dev *indio_dev,
|
|||
{
|
||||
struct ad5624r_state *st = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%d\n",
|
||||
!!(st->pwr_down_mask & (1 << chan->channel)));
|
||||
return sysfs_emit(buf, "%d\n",
|
||||
!!(st->pwr_down_mask & (1 << chan->channel)));
|
||||
}
|
||||
|
||||
static ssize_t ad5624r_write_dac_powerdown(struct iio_dev *indio_dev,
|
||||
|
|
|
@ -57,7 +57,7 @@ static ssize_t ad5686_read_dac_powerdown(struct iio_dev *indio_dev,
|
|||
{
|
||||
struct ad5686_state *st = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%d\n", !!(st->pwr_down_mask &
|
||||
return sysfs_emit(buf, "%d\n", !!(st->pwr_down_mask &
|
||||
(0x3 << (chan->channel * 2))));
|
||||
}
|
||||
|
||||
|
|
|
@ -399,8 +399,8 @@ static ssize_t ad5755_read_powerdown(struct iio_dev *indio_dev, uintptr_t priv,
|
|||
{
|
||||
struct ad5755_state *st = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%d\n",
|
||||
(bool)(st->pwr_down & (1 << chan->channel)));
|
||||
return sysfs_emit(buf, "%d\n",
|
||||
(bool)(st->pwr_down & (1 << chan->channel)));
|
||||
}
|
||||
|
||||
static ssize_t ad5755_write_powerdown(struct iio_dev *indio_dev, uintptr_t priv,
|
||||
|
|
|
@ -574,7 +574,7 @@ static ssize_t ad5758_read_powerdown(struct iio_dev *indio_dev,
|
|||
{
|
||||
struct ad5758_state *st = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%d\n", st->pwr_down);
|
||||
return sysfs_emit(buf, "%d\n", st->pwr_down);
|
||||
}
|
||||
|
||||
static ssize_t ad5758_write_powerdown(struct iio_dev *indio_dev,
|
||||
|
|
|
@ -89,7 +89,7 @@ static const char * const ad5766_dither_scales[] = {
|
|||
/**
|
||||
* struct ad5766_state - driver instance specific data
|
||||
* @spi: SPI device
|
||||
* @lock: Lock used to restrict concurent access to SPI device
|
||||
* @lock: Lock used to restrict concurrent access to SPI device
|
||||
* @chip_info: Chip model specific constants
|
||||
* @gpio_reset: Reset GPIO, used to reset the device
|
||||
* @crt_range: Current selected output range
|
||||
|
|
|
@ -433,7 +433,7 @@ static ssize_t ad5770r_read_dac_powerdown(struct iio_dev *indio_dev,
|
|||
{
|
||||
struct ad5770r_state *st = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%d\n", st->ch_pwr_down[chan->channel]);
|
||||
return sysfs_emit(buf, "%d\n", st->ch_pwr_down[chan->channel]);
|
||||
}
|
||||
|
||||
static ssize_t ad5770r_write_dac_powerdown(struct iio_dev *indio_dev,
|
||||
|
|
|
@ -177,7 +177,7 @@ static ssize_t ad5791_read_dac_powerdown(struct iio_dev *indio_dev,
|
|||
{
|
||||
struct ad5791_state *st = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%d\n", st->pwr_down);
|
||||
return sysfs_emit(buf, "%d\n", st->pwr_down);
|
||||
}
|
||||
|
||||
static ssize_t ad5791_write_dac_powerdown(struct iio_dev *indio_dev,
|
||||
|
|
|
@ -65,7 +65,7 @@ static ssize_t ad7303_read_dac_powerdown(struct iio_dev *indio_dev,
|
|||
{
|
||||
struct ad7303_state *st = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%d\n", (bool)(st->config &
|
||||
return sysfs_emit(buf, "%d\n", (bool)(st->config &
|
||||
AD7303_CFG_POWER_DOWN(chan->channel)));
|
||||
}
|
||||
|
||||
|
|
|
@ -135,8 +135,8 @@ static ssize_t ltc2632_read_dac_powerdown(struct iio_dev *indio_dev,
|
|||
{
|
||||
struct ltc2632_state *st = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%d\n",
|
||||
!!(st->powerdown_cache_mask & (1 << chan->channel)));
|
||||
return sysfs_emit(buf, "%d\n",
|
||||
!!(st->powerdown_cache_mask & (1 << chan->channel)));
|
||||
}
|
||||
|
||||
static ssize_t ltc2632_write_dac_powerdown(struct iio_dev *indio_dev,
|
||||
|
|
|
@ -84,7 +84,7 @@ static ssize_t max5821_read_dac_powerdown(struct iio_dev *indio_dev,
|
|||
{
|
||||
struct max5821_data *st = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%d\n", st->powerdown[chan->channel]);
|
||||
return sysfs_emit(buf, "%d\n", st->powerdown[chan->channel]);
|
||||
}
|
||||
|
||||
static int max5821_sync_powerdown_mode(struct max5821_data *data,
|
||||
|
|
|
@ -167,7 +167,7 @@ static ssize_t mcp4725_read_powerdown(struct iio_dev *indio_dev,
|
|||
{
|
||||
struct mcp4725_data *data = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%d\n", data->powerdown);
|
||||
return sysfs_emit(buf, "%d\n", data->powerdown);
|
||||
}
|
||||
|
||||
static ssize_t mcp4725_write_powerdown(struct iio_dev *indio_dev,
|
||||
|
|
|
@ -210,7 +210,7 @@ static ssize_t stm32_dac_read_powerdown(struct iio_dev *indio_dev,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%d\n", ret ? 0 : 1);
|
||||
return sysfs_emit(buf, "%d\n", ret ? 0 : 1);
|
||||
}
|
||||
|
||||
static ssize_t stm32_dac_write_powerdown(struct iio_dev *indio_dev,
|
||||
|
|
|
@ -121,7 +121,7 @@ static ssize_t ti_dac_read_powerdown(struct iio_dev *indio_dev,
|
|||
{
|
||||
struct ti_dac_chip *ti_dac = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%d\n", ti_dac->powerdown);
|
||||
return sysfs_emit(buf, "%d\n", ti_dac->powerdown);
|
||||
}
|
||||
|
||||
static ssize_t ti_dac_write_powerdown(struct iio_dev *indio_dev,
|
||||
|
|
|
@ -166,7 +166,7 @@ static ssize_t dac5571_read_powerdown(struct iio_dev *indio_dev,
|
|||
{
|
||||
struct dac5571_data *data = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%d\n", data->powerdown[chan->channel]);
|
||||
return sysfs_emit(buf, "%d\n", data->powerdown[chan->channel]);
|
||||
}
|
||||
|
||||
static ssize_t dac5571_write_powerdown(struct iio_dev *indio_dev,
|
||||
|
|
|
@ -110,7 +110,7 @@ static ssize_t ti_dac_read_powerdown(struct iio_dev *indio_dev,
|
|||
{
|
||||
struct ti_dac_chip *ti_dac = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%d\n", ti_dac->powerdown);
|
||||
return sysfs_emit(buf, "%d\n", ti_dac->powerdown);
|
||||
}
|
||||
|
||||
static ssize_t ti_dac_write_powerdown(struct iio_dev *indio_dev,
|
||||
|
|
|
@ -403,12 +403,12 @@ static int adis16460_probe(struct spi_device *spi)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* We cannot mask the interrupt, so ensure it isn't auto enabled */
|
||||
st->adis.irq_flag |= IRQF_NO_AUTOEN;
|
||||
ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
adis16460_enable_irq(&st->adis, 0);
|
||||
|
||||
ret = __adis_initial_startup(&st->adis);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
|
@ -1258,6 +1258,9 @@ static int adis16475_config_irq_pin(struct adis16475 *st)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* We cannot mask the interrupt so ensure it's not enabled at request */
|
||||
st->adis.irq_flag |= IRQF_NO_AUTOEN;
|
||||
|
||||
val = ADIS16475_MSG_CTRL_DR_POL(polarity);
|
||||
ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
|
||||
ADIS16475_MSG_CTRL_DR_POL_MASK, val);
|
||||
|
@ -1362,8 +1365,6 @@ static int adis16475_probe(struct spi_device *spi)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
adis16475_enable_irq(&st->adis, false);
|
||||
|
||||
ret = devm_iio_device_register(&spi->dev, indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
|
@ -29,18 +29,19 @@ static const struct iio_trigger_ops adis_trigger_ops = {
|
|||
|
||||
static int adis_validate_irq_flag(struct adis *adis)
|
||||
{
|
||||
unsigned long direction = adis->irq_flag & IRQF_TRIGGER_MASK;
|
||||
/*
|
||||
* Typically this devices have data ready either on the rising edge or
|
||||
* on the falling edge of the data ready pin. This checks enforces that
|
||||
* one of those is set in the drivers... It defaults to
|
||||
* IRQF_TRIGGER_RISING for backward compatibility wiht devices that
|
||||
* IRQF_TRIGGER_RISING for backward compatibility with devices that
|
||||
* don't support changing the pin polarity.
|
||||
*/
|
||||
if (!adis->irq_flag) {
|
||||
adis->irq_flag = IRQF_TRIGGER_RISING;
|
||||
if (direction == IRQF_TRIGGER_NONE) {
|
||||
adis->irq_flag |= IRQF_TRIGGER_RISING;
|
||||
return 0;
|
||||
} else if (adis->irq_flag != IRQF_TRIGGER_RISING &&
|
||||
adis->irq_flag != IRQF_TRIGGER_FALLING) {
|
||||
} else if (direction != IRQF_TRIGGER_RISING &&
|
||||
direction != IRQF_TRIGGER_FALLING) {
|
||||
dev_err(&adis->spi->dev, "Invalid IRQ mask: %08lx\n",
|
||||
adis->irq_flag);
|
||||
return -EINVAL;
|
||||
|
|
|
@ -731,12 +731,16 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
|
|||
}
|
||||
}
|
||||
|
||||
static int inv_mpu6050_write_gyro_scale(struct inv_mpu6050_state *st, int val)
|
||||
static int inv_mpu6050_write_gyro_scale(struct inv_mpu6050_state *st, int val,
|
||||
int val2)
|
||||
{
|
||||
int result, i;
|
||||
|
||||
if (val != 0)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(gyro_scale_6050); ++i) {
|
||||
if (gyro_scale_6050[i] == val) {
|
||||
if (gyro_scale_6050[i] == val2) {
|
||||
result = inv_mpu6050_set_gyro_fsr(st, i);
|
||||
if (result)
|
||||
return result;
|
||||
|
@ -767,13 +771,17 @@ static int inv_write_raw_get_fmt(struct iio_dev *indio_dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int inv_mpu6050_write_accel_scale(struct inv_mpu6050_state *st, int val)
|
||||
static int inv_mpu6050_write_accel_scale(struct inv_mpu6050_state *st, int val,
|
||||
int val2)
|
||||
{
|
||||
int result, i;
|
||||
u8 d;
|
||||
|
||||
if (val != 0)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(accel_scale); ++i) {
|
||||
if (accel_scale[i] == val) {
|
||||
if (accel_scale[i] == val2) {
|
||||
d = (i << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT);
|
||||
result = regmap_write(st->map, st->reg->accl_config, d);
|
||||
if (result)
|
||||
|
@ -814,10 +822,10 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
|
|||
case IIO_CHAN_INFO_SCALE:
|
||||
switch (chan->type) {
|
||||
case IIO_ANGL_VEL:
|
||||
result = inv_mpu6050_write_gyro_scale(st, val2);
|
||||
result = inv_mpu6050_write_gyro_scale(st, val, val2);
|
||||
break;
|
||||
case IIO_ACCEL:
|
||||
result = inv_mpu6050_write_accel_scale(st, val2);
|
||||
result = inv_mpu6050_write_accel_scale(st, val, val2);
|
||||
break;
|
||||
default:
|
||||
result = -EINVAL;
|
||||
|
@ -1458,15 +1466,21 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
|
|||
st->plat_data = *pdata;
|
||||
}
|
||||
|
||||
desc = irq_get_irq_data(irq);
|
||||
if (!desc) {
|
||||
dev_err(dev, "Could not find IRQ %d\n", irq);
|
||||
return -EINVAL;
|
||||
if (irq > 0) {
|
||||
desc = irq_get_irq_data(irq);
|
||||
if (!desc) {
|
||||
dev_err(dev, "Could not find IRQ %d\n", irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
irq_type = irqd_get_trigger_type(desc);
|
||||
if (!irq_type)
|
||||
irq_type = IRQF_TRIGGER_RISING;
|
||||
} else {
|
||||
/* Doesn't really matter, use the default */
|
||||
irq_type = IRQF_TRIGGER_RISING;
|
||||
}
|
||||
|
||||
irq_type = irqd_get_trigger_type(desc);
|
||||
if (!irq_type)
|
||||
irq_type = IRQF_TRIGGER_RISING;
|
||||
if (irq_type & IRQF_TRIGGER_RISING) // rising or both-edge
|
||||
st->irq_mask = INV_MPU6050_ACTIVE_HIGH;
|
||||
else if (irq_type == IRQF_TRIGGER_FALLING)
|
||||
|
@ -1591,20 +1605,26 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
|
|||
}
|
||||
|
||||
indio_dev->info = &mpu_info;
|
||||
indio_dev->modes = INDIO_BUFFER_TRIGGERED;
|
||||
|
||||
result = devm_iio_triggered_buffer_setup(dev, indio_dev,
|
||||
iio_pollfunc_store_time,
|
||||
inv_mpu6050_read_fifo,
|
||||
NULL);
|
||||
if (result) {
|
||||
dev_err(dev, "configure buffer fail %d\n", result);
|
||||
return result;
|
||||
}
|
||||
result = inv_mpu6050_probe_trigger(indio_dev, irq_type);
|
||||
if (result) {
|
||||
dev_err(dev, "trigger probe fail %d\n", result);
|
||||
return result;
|
||||
if (irq > 0) {
|
||||
/*
|
||||
* The driver currently only supports buffered capture with its
|
||||
* own trigger. So no IRQ, no trigger, no buffer
|
||||
*/
|
||||
result = devm_iio_triggered_buffer_setup(dev, indio_dev,
|
||||
iio_pollfunc_store_time,
|
||||
inv_mpu6050_read_fifo,
|
||||
NULL);
|
||||
if (result) {
|
||||
dev_err(dev, "configure buffer fail %d\n", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = inv_mpu6050_probe_trigger(indio_dev, irq_type);
|
||||
if (result) {
|
||||
dev_err(dev, "trigger probe fail %d\n", result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
result = devm_iio_device_register(dev, indio_dev);
|
||||
|
|
|
@ -11,6 +11,16 @@ static unsigned int inv_scan_query_mpu6050(struct iio_dev *indio_dev)
|
|||
struct inv_mpu6050_state *st = iio_priv(indio_dev);
|
||||
unsigned int mask;
|
||||
|
||||
/*
|
||||
* If the MPU6050 is just used as a trigger, then the scan mask
|
||||
* is not allocated so we simply enable the temperature channel
|
||||
* as a dummy and bail out.
|
||||
*/
|
||||
if (!indio_dev->active_scan_mask) {
|
||||
st->chip_config.temp_fifo_enable = true;
|
||||
return INV_MPU6050_SENSOR_TEMP;
|
||||
}
|
||||
|
||||
st->chip_config.gyro_fifo_enable =
|
||||
test_bit(INV_MPU6050_SCAN_GYRO_X,
|
||||
indio_dev->active_scan_mask) ||
|
||||
|
|
|
@ -260,7 +260,7 @@ static ssize_t iio_show_scan_index(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%u\n", to_iio_dev_attr(attr)->c->scan_index);
|
||||
return sysfs_emit(buf, "%u\n", to_iio_dev_attr(attr)->c->scan_index);
|
||||
}
|
||||
|
||||
static ssize_t iio_show_fixed_type(struct device *dev,
|
||||
|
@ -278,15 +278,15 @@ static ssize_t iio_show_fixed_type(struct device *dev,
|
|||
#endif
|
||||
}
|
||||
if (this_attr->c->scan_type.repeat > 1)
|
||||
return sprintf(buf, "%s:%c%d/%dX%d>>%u\n",
|
||||
return sysfs_emit(buf, "%s:%c%d/%dX%d>>%u\n",
|
||||
iio_endian_prefix[type],
|
||||
this_attr->c->scan_type.sign,
|
||||
this_attr->c->scan_type.realbits,
|
||||
this_attr->c->scan_type.storagebits,
|
||||
this_attr->c->scan_type.repeat,
|
||||
this_attr->c->scan_type.shift);
|
||||
else
|
||||
return sprintf(buf, "%s:%c%d/%d>>%u\n",
|
||||
else
|
||||
return sysfs_emit(buf, "%s:%c%d/%d>>%u\n",
|
||||
iio_endian_prefix[type],
|
||||
this_attr->c->scan_type.sign,
|
||||
this_attr->c->scan_type.realbits,
|
||||
|
@ -305,7 +305,7 @@ static ssize_t iio_scan_el_show(struct device *dev,
|
|||
ret = !!test_bit(to_iio_dev_attr(attr)->address,
|
||||
buffer->scan_mask);
|
||||
|
||||
return sprintf(buf, "%d\n", ret);
|
||||
return sysfs_emit(buf, "%d\n", ret);
|
||||
}
|
||||
|
||||
/* Note NULL used as error indicator as it doesn't make sense. */
|
||||
|
@ -449,7 +449,7 @@ static ssize_t iio_scan_el_ts_show(struct device *dev,
|
|||
{
|
||||
struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
|
||||
|
||||
return sprintf(buf, "%d\n", buffer->scan_timestamp);
|
||||
return sysfs_emit(buf, "%d\n", buffer->scan_timestamp);
|
||||
}
|
||||
|
||||
static ssize_t iio_scan_el_ts_store(struct device *dev,
|
||||
|
@ -541,7 +541,7 @@ static ssize_t iio_buffer_read_length(struct device *dev,
|
|||
{
|
||||
struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
|
||||
|
||||
return sprintf(buf, "%d\n", buffer->length);
|
||||
return sysfs_emit(buf, "%d\n", buffer->length);
|
||||
}
|
||||
|
||||
static ssize_t iio_buffer_write_length(struct device *dev,
|
||||
|
@ -583,7 +583,7 @@ static ssize_t iio_buffer_show_enable(struct device *dev,
|
|||
{
|
||||
struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
|
||||
|
||||
return sprintf(buf, "%d\n", iio_buffer_is_active(buffer));
|
||||
return sysfs_emit(buf, "%d\n", iio_buffer_is_active(buffer));
|
||||
}
|
||||
|
||||
static unsigned int iio_storage_bytes_for_si(struct iio_dev *indio_dev,
|
||||
|
@ -1227,7 +1227,7 @@ static ssize_t iio_buffer_show_watermark(struct device *dev,
|
|||
{
|
||||
struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
|
||||
|
||||
return sprintf(buf, "%u\n", buffer->watermark);
|
||||
return sysfs_emit(buf, "%u\n", buffer->watermark);
|
||||
}
|
||||
|
||||
static ssize_t iio_buffer_store_watermark(struct device *dev,
|
||||
|
@ -1271,7 +1271,7 @@ static ssize_t iio_dma_show_data_available(struct device *dev,
|
|||
{
|
||||
struct iio_buffer *buffer = to_iio_dev_attr(attr)->buffer;
|
||||
|
||||
return sprintf(buf, "%zu\n", iio_buffer_data_available(buffer));
|
||||
return sysfs_emit(buf, "%zu\n", iio_buffer_data_available(buffer));
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(length, S_IRUGO | S_IWUSR, iio_buffer_read_length,
|
||||
|
@ -1309,6 +1309,7 @@ static struct attribute *iio_buffer_wrap_attr(struct iio_buffer *buffer,
|
|||
iio_attr->buffer = buffer;
|
||||
memcpy(&iio_attr->dev_attr, dattr, sizeof(iio_attr->dev_attr));
|
||||
iio_attr->dev_attr.attr.name = kstrdup_const(attr->name, GFP_KERNEL);
|
||||
sysfs_attr_init(&iio_attr->dev_attr.attr);
|
||||
|
||||
list_add(&iio_attr->l, &buffer->buffer_attr_list);
|
||||
|
||||
|
@ -1442,7 +1443,7 @@ static long iio_device_buffer_getfd(struct iio_dev *indio_dev, unsigned long arg
|
|||
goto error_free_ib;
|
||||
}
|
||||
|
||||
return fd;
|
||||
return 0;
|
||||
|
||||
error_free_ib:
|
||||
kfree(ib);
|
||||
|
|
|
@ -234,7 +234,7 @@ ssize_t iio_read_const_attr(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%s\n", to_iio_const_attr(attr)->string);
|
||||
return sysfs_emit(buf, "%s\n", to_iio_const_attr(attr)->string);
|
||||
}
|
||||
EXPORT_SYMBOL(iio_read_const_attr);
|
||||
|
||||
|
@ -504,7 +504,7 @@ ssize_t iio_enum_available_read(struct iio_dev *indio_dev,
|
|||
for (i = 0; i < e->num_items; ++i) {
|
||||
if (!e->items[i])
|
||||
continue;
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len, "%s ", e->items[i]);
|
||||
len += sysfs_emit_at(buf, len, "%s ", e->items[i]);
|
||||
}
|
||||
|
||||
/* replace last space with a newline */
|
||||
|
@ -529,7 +529,7 @@ ssize_t iio_enum_read(struct iio_dev *indio_dev,
|
|||
else if (i >= e->num_items || !e->items[i])
|
||||
return -EINVAL;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", e->items[i]);
|
||||
return sysfs_emit(buf, "%s\n", e->items[i]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iio_enum_read);
|
||||
|
||||
|
@ -580,10 +580,10 @@ ssize_t iio_show_mount_matrix(struct iio_dev *indio_dev, uintptr_t priv,
|
|||
if (!mtx)
|
||||
mtx = &iio_mount_idmatrix;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s, %s, %s; %s, %s, %s; %s, %s, %s\n",
|
||||
mtx->rotation[0], mtx->rotation[1], mtx->rotation[2],
|
||||
mtx->rotation[3], mtx->rotation[4], mtx->rotation[5],
|
||||
mtx->rotation[6], mtx->rotation[7], mtx->rotation[8]);
|
||||
return sysfs_emit(buf, "%s, %s, %s; %s, %s, %s; %s, %s, %s\n",
|
||||
mtx->rotation[0], mtx->rotation[1], mtx->rotation[2],
|
||||
mtx->rotation[3], mtx->rotation[4], mtx->rotation[5],
|
||||
mtx->rotation[6], mtx->rotation[7], mtx->rotation[8]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iio_show_mount_matrix);
|
||||
|
||||
|
@ -623,7 +623,7 @@ int iio_read_mount_matrix(struct device *dev, const char *propname,
|
|||
}
|
||||
EXPORT_SYMBOL(iio_read_mount_matrix);
|
||||
|
||||
static ssize_t __iio_format_value(char *buf, size_t len, unsigned int type,
|
||||
static ssize_t __iio_format_value(char *buf, size_t offset, unsigned int type,
|
||||
int size, const int *vals)
|
||||
{
|
||||
int tmp0, tmp1;
|
||||
|
@ -632,52 +632,53 @@ static ssize_t __iio_format_value(char *buf, size_t len, unsigned int type,
|
|||
|
||||
switch (type) {
|
||||
case IIO_VAL_INT:
|
||||
return scnprintf(buf, len, "%d", vals[0]);
|
||||
return sysfs_emit_at(buf, offset, "%d", vals[0]);
|
||||
case IIO_VAL_INT_PLUS_MICRO_DB:
|
||||
scale_db = true;
|
||||
fallthrough;
|
||||
case IIO_VAL_INT_PLUS_MICRO:
|
||||
if (vals[1] < 0)
|
||||
return scnprintf(buf, len, "-%d.%06u%s", abs(vals[0]),
|
||||
-vals[1], scale_db ? " dB" : "");
|
||||
return sysfs_emit_at(buf, offset, "-%d.%06u%s",
|
||||
abs(vals[0]), -vals[1],
|
||||
scale_db ? " dB" : "");
|
||||
else
|
||||
return scnprintf(buf, len, "%d.%06u%s", vals[0], vals[1],
|
||||
scale_db ? " dB" : "");
|
||||
return sysfs_emit_at(buf, offset, "%d.%06u%s", vals[0],
|
||||
vals[1], scale_db ? " dB" : "");
|
||||
case IIO_VAL_INT_PLUS_NANO:
|
||||
if (vals[1] < 0)
|
||||
return scnprintf(buf, len, "-%d.%09u", abs(vals[0]),
|
||||
-vals[1]);
|
||||
return sysfs_emit_at(buf, offset, "-%d.%09u",
|
||||
abs(vals[0]), -vals[1]);
|
||||
else
|
||||
return scnprintf(buf, len, "%d.%09u", vals[0], vals[1]);
|
||||
return sysfs_emit_at(buf, offset, "%d.%09u", vals[0],
|
||||
vals[1]);
|
||||
case IIO_VAL_FRACTIONAL:
|
||||
tmp2 = div_s64((s64)vals[0] * 1000000000LL, vals[1]);
|
||||
tmp1 = vals[1];
|
||||
tmp0 = (int)div_s64_rem(tmp2, 1000000000, &tmp1);
|
||||
if ((tmp2 < 0) && (tmp0 == 0))
|
||||
return snprintf(buf, len, "-0.%09u", abs(tmp1));
|
||||
return sysfs_emit_at(buf, offset, "-0.%09u", abs(tmp1));
|
||||
else
|
||||
return snprintf(buf, len, "%d.%09u", tmp0, abs(tmp1));
|
||||
return sysfs_emit_at(buf, offset, "%d.%09u", tmp0,
|
||||
abs(tmp1));
|
||||
case IIO_VAL_FRACTIONAL_LOG2:
|
||||
tmp2 = shift_right((s64)vals[0] * 1000000000LL, vals[1]);
|
||||
tmp0 = (int)div_s64_rem(tmp2, 1000000000LL, &tmp1);
|
||||
if (tmp0 == 0 && tmp2 < 0)
|
||||
return snprintf(buf, len, "-0.%09u", abs(tmp1));
|
||||
return sysfs_emit_at(buf, offset, "-0.%09u", abs(tmp1));
|
||||
else
|
||||
return scnprintf(buf, len, "%d.%09u", tmp0, abs(tmp1));
|
||||
return sysfs_emit_at(buf, offset, "%d.%09u", tmp0,
|
||||
abs(tmp1));
|
||||
case IIO_VAL_INT_MULTIPLE:
|
||||
{
|
||||
int i;
|
||||
int l = 0;
|
||||
|
||||
for (i = 0; i < size; ++i) {
|
||||
l += scnprintf(&buf[l], len - l, "%d ", vals[i]);
|
||||
if (l >= len)
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < size; ++i)
|
||||
l += sysfs_emit_at(buf, offset + l, "%d ", vals[i]);
|
||||
return l;
|
||||
}
|
||||
case IIO_VAL_CHAR:
|
||||
return scnprintf(buf, len, "%c", (char)vals[0]);
|
||||
return sysfs_emit_at(buf, offset, "%c", (char)vals[0]);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -701,11 +702,11 @@ ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals)
|
|||
{
|
||||
ssize_t len;
|
||||
|
||||
len = __iio_format_value(buf, PAGE_SIZE, type, size, vals);
|
||||
len = __iio_format_value(buf, 0, type, size, vals);
|
||||
if (len >= PAGE_SIZE - 1)
|
||||
return -EFBIG;
|
||||
|
||||
return len + sprintf(buf + len, "\n");
|
||||
return len + sysfs_emit_at(buf, len, "\n");
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iio_format_value);
|
||||
|
||||
|
@ -763,22 +764,21 @@ static ssize_t iio_format_list(char *buf, const int *vals, int type, int length,
|
|||
break;
|
||||
}
|
||||
|
||||
len = scnprintf(buf, PAGE_SIZE, prefix);
|
||||
len = sysfs_emit(buf, prefix);
|
||||
|
||||
for (i = 0; i <= length - stride; i += stride) {
|
||||
if (i != 0) {
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len, " ");
|
||||
len += sysfs_emit_at(buf, len, " ");
|
||||
if (len >= PAGE_SIZE)
|
||||
return -EFBIG;
|
||||
}
|
||||
|
||||
len += __iio_format_value(buf + len, PAGE_SIZE - len, type,
|
||||
stride, &vals[i]);
|
||||
len += __iio_format_value(buf, len, type, stride, &vals[i]);
|
||||
if (len >= PAGE_SIZE)
|
||||
return -EFBIG;
|
||||
}
|
||||
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len, "%s\n", suffix);
|
||||
len += sysfs_emit_at(buf, len, "%s\n", suffix);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
@ -1369,7 +1369,7 @@ static ssize_t iio_show_dev_name(struct device *dev,
|
|||
char *buf)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", indio_dev->name);
|
||||
return sysfs_emit(buf, "%s\n", indio_dev->name);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL);
|
||||
|
@ -1379,7 +1379,7 @@ static ssize_t iio_show_dev_label(struct device *dev,
|
|||
char *buf)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", indio_dev->label);
|
||||
return sysfs_emit(buf, "%s\n", indio_dev->label);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(label, S_IRUGO, iio_show_dev_label, NULL);
|
||||
|
|
|
@ -245,6 +245,7 @@ static const char * const iio_ev_info_text[] = {
|
|||
[IIO_EV_INFO_PERIOD] = "period",
|
||||
[IIO_EV_INFO_HIGH_PASS_FILTER_3DB] = "high_pass_filter_3db",
|
||||
[IIO_EV_INFO_LOW_PASS_FILTER_3DB] = "low_pass_filter_3db",
|
||||
[IIO_EV_INFO_TIMEOUT] = "timeout",
|
||||
};
|
||||
|
||||
static enum iio_event_direction iio_ev_attr_dir(struct iio_dev_attr *attr)
|
||||
|
@ -297,7 +298,7 @@ static ssize_t iio_ev_state_show(struct device *dev,
|
|||
if (val < 0)
|
||||
return val;
|
||||
else
|
||||
return sprintf(buf, "%d\n", val);
|
||||
return sysfs_emit(buf, "%d\n", val);
|
||||
}
|
||||
|
||||
static ssize_t iio_ev_value_show(struct device *dev,
|
||||
|
|
|
@ -50,7 +50,7 @@ static ssize_t iio_trigger_read_name(struct device *dev,
|
|||
char *buf)
|
||||
{
|
||||
struct iio_trigger *trig = to_iio_trigger(dev);
|
||||
return sprintf(buf, "%s\n", trig->name);
|
||||
return sysfs_emit(buf, "%s\n", trig->name);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL);
|
||||
|
@ -75,8 +75,7 @@ int __iio_trigger_register(struct iio_trigger *trig_info,
|
|||
return trig_info->id;
|
||||
|
||||
/* Set the name used for the sysfs directory etc */
|
||||
dev_set_name(&trig_info->dev, "trigger%ld",
|
||||
(unsigned long) trig_info->id);
|
||||
dev_set_name(&trig_info->dev, "trigger%d", trig_info->id);
|
||||
|
||||
ret = device_add(&trig_info->dev);
|
||||
if (ret)
|
||||
|
@ -212,6 +211,7 @@ EXPORT_SYMBOL(iio_trigger_notify_done);
|
|||
static int iio_trigger_get_irq(struct iio_trigger *trig)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&trig->pool_lock);
|
||||
ret = bitmap_find_free_region(trig->pool,
|
||||
CONFIG_IIO_CONSUMERS_PER_TRIGGER,
|
||||
|
@ -240,9 +240,9 @@ static void iio_trigger_put_irq(struct iio_trigger *trig, int irq)
|
|||
int iio_trigger_attach_poll_func(struct iio_trigger *trig,
|
||||
struct iio_poll_func *pf)
|
||||
{
|
||||
bool notinuse =
|
||||
bitmap_empty(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER);
|
||||
int ret = 0;
|
||||
bool notinuse
|
||||
= bitmap_empty(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER);
|
||||
|
||||
/* Prevent the module from being removed whilst attached to a trigger */
|
||||
__module_get(pf->indio_dev->driver_module);
|
||||
|
@ -291,11 +291,10 @@ int iio_trigger_attach_poll_func(struct iio_trigger *trig,
|
|||
int iio_trigger_detach_poll_func(struct iio_trigger *trig,
|
||||
struct iio_poll_func *pf)
|
||||
{
|
||||
bool no_other_users =
|
||||
bitmap_weight(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER) == 1;
|
||||
int ret = 0;
|
||||
bool no_other_users
|
||||
= (bitmap_weight(trig->pool,
|
||||
CONFIG_IIO_CONSUMERS_PER_TRIGGER)
|
||||
== 1);
|
||||
|
||||
if (trig->ops && trig->ops->set_trigger_state && no_other_users) {
|
||||
ret = trig->ops->set_trigger_state(trig, false);
|
||||
if (ret)
|
||||
|
@ -313,6 +312,7 @@ int iio_trigger_detach_poll_func(struct iio_trigger *trig,
|
|||
irqreturn_t iio_pollfunc_store_time(int irq, void *p)
|
||||
{
|
||||
struct iio_poll_func *pf = p;
|
||||
|
||||
pf->timestamp = iio_get_time_ns(pf->indio_dev);
|
||||
return IRQ_WAKE_THREAD;
|
||||
}
|
||||
|
@ -375,7 +375,7 @@ static ssize_t iio_trigger_read_current(struct device *dev,
|
|||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
|
||||
if (indio_dev->trig)
|
||||
return sprintf(buf, "%s\n", indio_dev->trig->name);
|
||||
return sysfs_emit(buf, "%s\n", indio_dev->trig->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -499,18 +499,16 @@ static const struct device_type iio_trig_type = {
|
|||
static void iio_trig_subirqmask(struct irq_data *d)
|
||||
{
|
||||
struct irq_chip *chip = irq_data_get_irq_chip(d);
|
||||
struct iio_trigger *trig
|
||||
= container_of(chip,
|
||||
struct iio_trigger, subirq_chip);
|
||||
struct iio_trigger *trig = container_of(chip, struct iio_trigger, subirq_chip);
|
||||
|
||||
trig->subirqs[d->irq - trig->subirq_base].enabled = false;
|
||||
}
|
||||
|
||||
static void iio_trig_subirqunmask(struct irq_data *d)
|
||||
{
|
||||
struct irq_chip *chip = irq_data_get_irq_chip(d);
|
||||
struct iio_trigger *trig
|
||||
= container_of(chip,
|
||||
struct iio_trigger, subirq_chip);
|
||||
struct iio_trigger *trig = container_of(chip, struct iio_trigger, subirq_chip);
|
||||
|
||||
trig->subirqs[d->irq - trig->subirq_base].enabled = true;
|
||||
}
|
||||
|
||||
|
@ -696,7 +694,7 @@ EXPORT_SYMBOL(iio_trigger_using_own);
|
|||
* device, -EINVAL otherwise.
|
||||
*/
|
||||
int iio_trigger_validate_own_device(struct iio_trigger *trig,
|
||||
struct iio_dev *indio_dev)
|
||||
struct iio_dev *indio_dev)
|
||||
{
|
||||
if (indio_dev->dev.parent != trig->dev.parent)
|
||||
return -EINVAL;
|
||||
|
|
|
@ -702,7 +702,7 @@ int iio_read_channel_processed_scale(struct iio_channel *chan, int *val,
|
|||
if (iio_channel_has_info(chan->channel, IIO_CHAN_INFO_PROCESSED)) {
|
||||
ret = iio_channel_read(chan, val, NULL,
|
||||
IIO_CHAN_INFO_PROCESSED);
|
||||
if (ret)
|
||||
if (ret < 0)
|
||||
goto err_unlock;
|
||||
*val *= scale;
|
||||
} else {
|
||||
|
|
|
@ -32,13 +32,14 @@
|
|||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/unaligned/be_byteshift.h>
|
||||
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/iio/triggered_buffer.h>
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
/* This register map covers YAS530 and YAS532 but differs in YAS 537 and YAS539 */
|
||||
#define YAS5XX_DEVICE_ID 0x80
|
||||
#define YAS5XX_ACTUATE_INIT_COIL 0x81
|
||||
|
@ -887,6 +888,7 @@ static int yas5xx_probe(struct i2c_client *i2c,
|
|||
strncpy(yas5xx->name, "yas532", sizeof(yas5xx->name));
|
||||
break;
|
||||
default:
|
||||
ret = -ENODEV;
|
||||
dev_err(dev, "unhandled device ID %02x\n", yas5xx->devid);
|
||||
goto assert_reset;
|
||||
}
|
||||
|
|
|
@ -763,7 +763,11 @@ static int sx9310_write_far_debounce(struct sx9310_data *data, int val)
|
|||
int ret;
|
||||
unsigned int regval;
|
||||
|
||||
val = ilog2(val);
|
||||
if (val > 0)
|
||||
val = ilog2(val);
|
||||
if (!FIELD_FIT(SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_MASK, val))
|
||||
return -EINVAL;
|
||||
|
||||
regval = FIELD_PREP(SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_MASK, val);
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
|
@ -780,7 +784,11 @@ static int sx9310_write_close_debounce(struct sx9310_data *data, int val)
|
|||
int ret;
|
||||
unsigned int regval;
|
||||
|
||||
val = ilog2(val);
|
||||
if (val > 0)
|
||||
val = ilog2(val);
|
||||
if (!FIELD_FIT(SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_MASK, val))
|
||||
return -EINVAL;
|
||||
|
||||
regval = FIELD_PREP(SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_MASK, val);
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
|
@ -1213,17 +1221,17 @@ static int sx9310_init_compensation(struct iio_dev *indio_dev)
|
|||
}
|
||||
|
||||
static const struct sx9310_reg_default *
|
||||
sx9310_get_default_reg(struct sx9310_data *data, int i,
|
||||
sx9310_get_default_reg(struct sx9310_data *data, int idx,
|
||||
struct sx9310_reg_default *reg_def)
|
||||
{
|
||||
int ret;
|
||||
const struct device_node *np = data->client->dev.of_node;
|
||||
u32 combined[SX9310_NUM_CHANNELS] = { 4, 4, 4, 4 };
|
||||
unsigned long comb_mask = 0;
|
||||
const char *res;
|
||||
u32 combined[SX9310_NUM_CHANNELS];
|
||||
u32 start = 0, raw = 0, pos = 0;
|
||||
unsigned long comb_mask = 0;
|
||||
int ret, i, count;
|
||||
const char *res;
|
||||
|
||||
memcpy(reg_def, &sx9310_default_regs[i], sizeof(*reg_def));
|
||||
memcpy(reg_def, &sx9310_default_regs[idx], sizeof(*reg_def));
|
||||
if (!np)
|
||||
return reg_def;
|
||||
|
||||
|
@ -1234,15 +1242,31 @@ sx9310_get_default_reg(struct sx9310_data *data, int i,
|
|||
reg_def->def |= SX9310_REG_PROX_CTRL2_SHIELDEN_GROUND;
|
||||
}
|
||||
|
||||
reg_def->def &= ~SX9310_REG_PROX_CTRL2_COMBMODE_MASK;
|
||||
of_property_read_u32_array(np, "semtech,combined-sensors",
|
||||
combined, ARRAY_SIZE(combined));
|
||||
for (i = 0; i < ARRAY_SIZE(combined); i++) {
|
||||
if (combined[i] <= SX9310_NUM_CHANNELS)
|
||||
comb_mask |= BIT(combined[i]);
|
||||
count = of_property_count_elems_of_size(np, "semtech,combined-sensors",
|
||||
sizeof(u32));
|
||||
if (count > 0 && count <= ARRAY_SIZE(combined)) {
|
||||
ret = of_property_read_u32_array(np, "semtech,combined-sensors",
|
||||
combined, count);
|
||||
if (ret)
|
||||
break;
|
||||
} else {
|
||||
/*
|
||||
* Either the property does not exist in the DT or the
|
||||
* number of entries is incorrect.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < count; i++) {
|
||||
if (combined[i] >= SX9310_NUM_CHANNELS) {
|
||||
/* Invalid sensor (invalid DT). */
|
||||
break;
|
||||
}
|
||||
comb_mask |= BIT(combined[i]);
|
||||
}
|
||||
if (i < count)
|
||||
break;
|
||||
|
||||
comb_mask &= 0xf;
|
||||
reg_def->def &= ~SX9310_REG_PROX_CTRL2_COMBMODE_MASK;
|
||||
if (comb_mask == (BIT(3) | BIT(2) | BIT(1) | BIT(0)))
|
||||
reg_def->def |= SX9310_REG_PROX_CTRL2_COMBMODE_CS0_CS1_CS2_CS3;
|
||||
else if (comb_mask == (BIT(1) | BIT(2)))
|
||||
|
|
|
@ -63,7 +63,7 @@ ssize_t iio_hrtimer_store_sampling_frequency(struct device *dev,
|
|||
if (integer < 0 || fract < 0)
|
||||
return -ERANGE;
|
||||
|
||||
val = fract + 1000 * integer; /* mHz */
|
||||
val = fract + 1000ULL * integer; /* mHz */
|
||||
|
||||
if (!val || val > UINT_MAX)
|
||||
return -EINVAL;
|
||||
|
|
|
@ -4,16 +4,6 @@
|
|||
#
|
||||
menu "Capacitance to digital converters"
|
||||
|
||||
config AD7150
|
||||
tristate "Analog Devices ad7150/1/6 capacitive sensor driver"
|
||||
depends on I2C
|
||||
help
|
||||
Say yes here to build support for Analog Devices capacitive sensors.
|
||||
(ad7150, ad7151, ad7156) Provides direct access via sysfs.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ad7150.
|
||||
|
||||
config AD7746
|
||||
tristate "Analog Devices AD7745, AD7746 AD7747 capacitive sensor driver"
|
||||
depends on I2C
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Makefile for industrial I/O DAC drivers
|
||||
# Makefile for industrial I/O CDC drivers
|
||||
#
|
||||
|
||||
obj-$(CONFIG_AD7150) += ad7150.o
|
||||
obj-$(CONFIG_AD7746) += ad7746.o
|
||||
|
|
|
@ -1,655 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* AD7150 capacitive sensor driver supporting AD7150/1/6
|
||||
*
|
||||
* Copyright 2010-2011 Analog Devices Inc.
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/events.h>
|
||||
/*
|
||||
* AD7150 registers definition
|
||||
*/
|
||||
|
||||
#define AD7150_STATUS 0
|
||||
#define AD7150_STATUS_OUT1 BIT(3)
|
||||
#define AD7150_STATUS_OUT2 BIT(5)
|
||||
#define AD7150_CH1_DATA_HIGH 1
|
||||
#define AD7150_CH2_DATA_HIGH 3
|
||||
#define AD7150_CH1_AVG_HIGH 5
|
||||
#define AD7150_CH2_AVG_HIGH 7
|
||||
#define AD7150_CH1_SENSITIVITY 9
|
||||
#define AD7150_CH1_THR_HOLD_H 9
|
||||
#define AD7150_CH1_TIMEOUT 10
|
||||
#define AD7150_CH1_SETUP 11
|
||||
#define AD7150_CH2_SENSITIVITY 12
|
||||
#define AD7150_CH2_THR_HOLD_H 12
|
||||
#define AD7150_CH2_TIMEOUT 13
|
||||
#define AD7150_CH2_SETUP 14
|
||||
#define AD7150_CFG 15
|
||||
#define AD7150_CFG_FIX BIT(7)
|
||||
#define AD7150_PD_TIMER 16
|
||||
#define AD7150_CH1_CAPDAC 17
|
||||
#define AD7150_CH2_CAPDAC 18
|
||||
#define AD7150_SN3 19
|
||||
#define AD7150_SN2 20
|
||||
#define AD7150_SN1 21
|
||||
#define AD7150_SN0 22
|
||||
#define AD7150_ID 23
|
||||
|
||||
/* AD7150 masks */
|
||||
#define AD7150_THRESHTYPE_MSK GENMASK(6, 5)
|
||||
|
||||
/**
|
||||
* struct ad7150_chip_info - instance specific chip data
|
||||
* @client: i2c client for this device
|
||||
* @current_event: device always has one type of event enabled.
|
||||
* This element stores the event code of the current one.
|
||||
* @threshold: thresholds for simple capacitance value events
|
||||
* @thresh_sensitivity: threshold for simple capacitance offset
|
||||
* from 'average' value.
|
||||
* @mag_sensitity: threshold for magnitude of capacitance offset
|
||||
* from 'average' value.
|
||||
* @thresh_timeout: a timeout, in samples from the moment an
|
||||
* adaptive threshold event occurs to when the average
|
||||
* value jumps to current value.
|
||||
* @mag_timeout: a timeout, in sample from the moment an
|
||||
* adaptive magnitude event occurs to when the average
|
||||
* value jumps to the current value.
|
||||
* @old_state: store state from previous event, allowing confirmation
|
||||
* of new condition.
|
||||
* @conversion_mode: the current conversion mode.
|
||||
* @state_lock: ensure consistent state of this structure wrt the
|
||||
* hardware.
|
||||
*/
|
||||
struct ad7150_chip_info {
|
||||
struct i2c_client *client;
|
||||
u64 current_event;
|
||||
u16 threshold[2][2];
|
||||
u8 thresh_sensitivity[2][2];
|
||||
u8 mag_sensitivity[2][2];
|
||||
u8 thresh_timeout[2][2];
|
||||
u8 mag_timeout[2][2];
|
||||
int old_state;
|
||||
char *conversion_mode;
|
||||
struct mutex state_lock;
|
||||
};
|
||||
|
||||
/*
|
||||
* sysfs nodes
|
||||
*/
|
||||
|
||||
static const u8 ad7150_addresses[][6] = {
|
||||
{ AD7150_CH1_DATA_HIGH, AD7150_CH1_AVG_HIGH,
|
||||
AD7150_CH1_SETUP, AD7150_CH1_THR_HOLD_H,
|
||||
AD7150_CH1_SENSITIVITY, AD7150_CH1_TIMEOUT },
|
||||
{ AD7150_CH2_DATA_HIGH, AD7150_CH2_AVG_HIGH,
|
||||
AD7150_CH2_SETUP, AD7150_CH2_THR_HOLD_H,
|
||||
AD7150_CH2_SENSITIVITY, AD7150_CH2_TIMEOUT },
|
||||
};
|
||||
|
||||
static int ad7150_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val,
|
||||
int *val2,
|
||||
long mask)
|
||||
{
|
||||
int ret;
|
||||
struct ad7150_chip_info *chip = iio_priv(indio_dev);
|
||||
int channel = chan->channel;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
ret = i2c_smbus_read_word_data(chip->client,
|
||||
ad7150_addresses[channel][0]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*val = swab16(ret);
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_AVERAGE_RAW:
|
||||
ret = i2c_smbus_read_word_data(chip->client,
|
||||
ad7150_addresses[channel][1]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*val = swab16(ret);
|
||||
return IIO_VAL_INT;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int ad7150_read_event_config(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir)
|
||||
{
|
||||
int ret;
|
||||
u8 threshtype;
|
||||
bool thrfixed;
|
||||
struct ad7150_chip_info *chip = iio_priv(indio_dev);
|
||||
|
||||
ret = i2c_smbus_read_byte_data(chip->client, AD7150_CFG);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
threshtype = FIELD_GET(AD7150_THRESHTYPE_MSK, ret);
|
||||
|
||||
/*check if threshold mode is fixed or adaptive*/
|
||||
thrfixed = FIELD_GET(AD7150_CFG_FIX, ret);
|
||||
|
||||
switch (type) {
|
||||
case IIO_EV_TYPE_MAG_ADAPTIVE:
|
||||
if (dir == IIO_EV_DIR_RISING)
|
||||
return !thrfixed && (threshtype == 0x1);
|
||||
return !thrfixed && (threshtype == 0x0);
|
||||
case IIO_EV_TYPE_THRESH_ADAPTIVE:
|
||||
if (dir == IIO_EV_DIR_RISING)
|
||||
return !thrfixed && (threshtype == 0x3);
|
||||
return !thrfixed && (threshtype == 0x2);
|
||||
case IIO_EV_TYPE_THRESH:
|
||||
if (dir == IIO_EV_DIR_RISING)
|
||||
return thrfixed && (threshtype == 0x1);
|
||||
return thrfixed && (threshtype == 0x0);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* state_lock should be held to ensure consistent state*/
|
||||
|
||||
static int ad7150_write_event_params(struct iio_dev *indio_dev,
|
||||
unsigned int chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir)
|
||||
{
|
||||
int ret;
|
||||
u16 value;
|
||||
u8 sens, timeout;
|
||||
struct ad7150_chip_info *chip = iio_priv(indio_dev);
|
||||
int rising = (dir == IIO_EV_DIR_RISING);
|
||||
u64 event_code;
|
||||
|
||||
event_code = IIO_UNMOD_EVENT_CODE(IIO_CAPACITANCE, chan, type, dir);
|
||||
|
||||
if (event_code != chip->current_event)
|
||||
return 0;
|
||||
|
||||
switch (type) {
|
||||
/* Note completely different from the adaptive versions */
|
||||
case IIO_EV_TYPE_THRESH:
|
||||
value = chip->threshold[rising][chan];
|
||||
return i2c_smbus_write_word_data(chip->client,
|
||||
ad7150_addresses[chan][3],
|
||||
swab16(value));
|
||||
case IIO_EV_TYPE_MAG_ADAPTIVE:
|
||||
sens = chip->mag_sensitivity[rising][chan];
|
||||
timeout = chip->mag_timeout[rising][chan];
|
||||
break;
|
||||
case IIO_EV_TYPE_THRESH_ADAPTIVE:
|
||||
sens = chip->thresh_sensitivity[rising][chan];
|
||||
timeout = chip->thresh_timeout[rising][chan];
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = i2c_smbus_write_byte_data(chip->client,
|
||||
ad7150_addresses[chan][4],
|
||||
sens);
|
||||
if (ret)
|
||||
return ret;
|
||||
return i2c_smbus_write_byte_data(chip->client,
|
||||
ad7150_addresses[chan][5],
|
||||
timeout);
|
||||
}
|
||||
|
||||
static int ad7150_write_event_config(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir, int state)
|
||||
{
|
||||
u8 thresh_type, cfg, adaptive;
|
||||
int ret;
|
||||
struct ad7150_chip_info *chip = iio_priv(indio_dev);
|
||||
int rising = (dir == IIO_EV_DIR_RISING);
|
||||
u64 event_code;
|
||||
|
||||
/* Something must always be turned on */
|
||||
if (!state)
|
||||
return -EINVAL;
|
||||
|
||||
event_code = IIO_UNMOD_EVENT_CODE(chan->type, chan->channel, type, dir);
|
||||
if (event_code == chip->current_event)
|
||||
return 0;
|
||||
mutex_lock(&chip->state_lock);
|
||||
ret = i2c_smbus_read_byte_data(chip->client, AD7150_CFG);
|
||||
if (ret < 0)
|
||||
goto error_ret;
|
||||
|
||||
cfg = ret & ~((0x03 << 5) | BIT(7));
|
||||
|
||||
switch (type) {
|
||||
case IIO_EV_TYPE_MAG_ADAPTIVE:
|
||||
adaptive = 1;
|
||||
if (rising)
|
||||
thresh_type = 0x1;
|
||||
else
|
||||
thresh_type = 0x0;
|
||||
break;
|
||||
case IIO_EV_TYPE_THRESH_ADAPTIVE:
|
||||
adaptive = 1;
|
||||
if (rising)
|
||||
thresh_type = 0x3;
|
||||
else
|
||||
thresh_type = 0x2;
|
||||
break;
|
||||
case IIO_EV_TYPE_THRESH:
|
||||
adaptive = 0;
|
||||
if (rising)
|
||||
thresh_type = 0x1;
|
||||
else
|
||||
thresh_type = 0x0;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
cfg |= (!adaptive << 7) | (thresh_type << 5);
|
||||
|
||||
ret = i2c_smbus_write_byte_data(chip->client, AD7150_CFG, cfg);
|
||||
if (ret < 0)
|
||||
goto error_ret;
|
||||
|
||||
chip->current_event = event_code;
|
||||
|
||||
/* update control attributes */
|
||||
ret = ad7150_write_event_params(indio_dev, chan->channel, type, dir);
|
||||
error_ret:
|
||||
mutex_unlock(&chip->state_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ad7150_read_event_value(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir,
|
||||
enum iio_event_info info,
|
||||
int *val, int *val2)
|
||||
{
|
||||
struct ad7150_chip_info *chip = iio_priv(indio_dev);
|
||||
int rising = (dir == IIO_EV_DIR_RISING);
|
||||
|
||||
/* Complex register sharing going on here */
|
||||
switch (type) {
|
||||
case IIO_EV_TYPE_MAG_ADAPTIVE:
|
||||
*val = chip->mag_sensitivity[rising][chan->channel];
|
||||
return IIO_VAL_INT;
|
||||
case IIO_EV_TYPE_THRESH_ADAPTIVE:
|
||||
*val = chip->thresh_sensitivity[rising][chan->channel];
|
||||
return IIO_VAL_INT;
|
||||
case IIO_EV_TYPE_THRESH:
|
||||
*val = chip->threshold[rising][chan->channel];
|
||||
return IIO_VAL_INT;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int ad7150_write_event_value(struct iio_dev *indio_dev,
|
||||
const struct iio_chan_spec *chan,
|
||||
enum iio_event_type type,
|
||||
enum iio_event_direction dir,
|
||||
enum iio_event_info info,
|
||||
int val, int val2)
|
||||
{
|
||||
int ret;
|
||||
struct ad7150_chip_info *chip = iio_priv(indio_dev);
|
||||
int rising = (dir == IIO_EV_DIR_RISING);
|
||||
|
||||
mutex_lock(&chip->state_lock);
|
||||
switch (type) {
|
||||
case IIO_EV_TYPE_MAG_ADAPTIVE:
|
||||
chip->mag_sensitivity[rising][chan->channel] = val;
|
||||
break;
|
||||
case IIO_EV_TYPE_THRESH_ADAPTIVE:
|
||||
chip->thresh_sensitivity[rising][chan->channel] = val;
|
||||
break;
|
||||
case IIO_EV_TYPE_THRESH:
|
||||
chip->threshold[rising][chan->channel] = val;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
/* write back if active */
|
||||
ret = ad7150_write_event_params(indio_dev, chan->channel, type, dir);
|
||||
|
||||
error_ret:
|
||||
mutex_unlock(&chip->state_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ad7150_show_timeout(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct ad7150_chip_info *chip = iio_priv(indio_dev);
|
||||
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
|
||||
u8 value;
|
||||
|
||||
/* use the event code for consistency reasons */
|
||||
int chan = IIO_EVENT_CODE_EXTRACT_CHAN(this_attr->address);
|
||||
int rising = (IIO_EVENT_CODE_EXTRACT_DIR(this_attr->address)
|
||||
== IIO_EV_DIR_RISING) ? 1 : 0;
|
||||
|
||||
switch (IIO_EVENT_CODE_EXTRACT_TYPE(this_attr->address)) {
|
||||
case IIO_EV_TYPE_MAG_ADAPTIVE:
|
||||
value = chip->mag_timeout[rising][chan];
|
||||
break;
|
||||
case IIO_EV_TYPE_THRESH_ADAPTIVE:
|
||||
value = chip->thresh_timeout[rising][chan];
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return sprintf(buf, "%d\n", value);
|
||||
}
|
||||
|
||||
static ssize_t ad7150_store_timeout(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct ad7150_chip_info *chip = iio_priv(indio_dev);
|
||||
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
|
||||
int chan = IIO_EVENT_CODE_EXTRACT_CHAN(this_attr->address);
|
||||
enum iio_event_direction dir;
|
||||
enum iio_event_type type;
|
||||
int rising;
|
||||
u8 data;
|
||||
int ret;
|
||||
|
||||
type = IIO_EVENT_CODE_EXTRACT_TYPE(this_attr->address);
|
||||
dir = IIO_EVENT_CODE_EXTRACT_DIR(this_attr->address);
|
||||
rising = (dir == IIO_EV_DIR_RISING);
|
||||
|
||||
ret = kstrtou8(buf, 10, &data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&chip->state_lock);
|
||||
switch (type) {
|
||||
case IIO_EV_TYPE_MAG_ADAPTIVE:
|
||||
chip->mag_timeout[rising][chan] = data;
|
||||
break;
|
||||
case IIO_EV_TYPE_THRESH_ADAPTIVE:
|
||||
chip->thresh_timeout[rising][chan] = data;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
ret = ad7150_write_event_params(indio_dev, chan, type, dir);
|
||||
error_ret:
|
||||
mutex_unlock(&chip->state_lock);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
#define AD7150_TIMEOUT(chan, type, dir, ev_type, ev_dir) \
|
||||
IIO_DEVICE_ATTR(in_capacitance##chan##_##type##_##dir##_timeout, \
|
||||
0644, \
|
||||
&ad7150_show_timeout, \
|
||||
&ad7150_store_timeout, \
|
||||
IIO_UNMOD_EVENT_CODE(IIO_CAPACITANCE, \
|
||||
chan, \
|
||||
IIO_EV_TYPE_##ev_type, \
|
||||
IIO_EV_DIR_##ev_dir))
|
||||
static AD7150_TIMEOUT(0, mag_adaptive, rising, MAG_ADAPTIVE, RISING);
|
||||
static AD7150_TIMEOUT(0, mag_adaptive, falling, MAG_ADAPTIVE, FALLING);
|
||||
static AD7150_TIMEOUT(1, mag_adaptive, rising, MAG_ADAPTIVE, RISING);
|
||||
static AD7150_TIMEOUT(1, mag_adaptive, falling, MAG_ADAPTIVE, FALLING);
|
||||
static AD7150_TIMEOUT(0, thresh_adaptive, rising, THRESH_ADAPTIVE, RISING);
|
||||
static AD7150_TIMEOUT(0, thresh_adaptive, falling, THRESH_ADAPTIVE, FALLING);
|
||||
static AD7150_TIMEOUT(1, thresh_adaptive, rising, THRESH_ADAPTIVE, RISING);
|
||||
static AD7150_TIMEOUT(1, thresh_adaptive, falling, THRESH_ADAPTIVE, FALLING);
|
||||
|
||||
static const struct iio_event_spec ad7150_events[] = {
|
||||
{
|
||||
.type = IIO_EV_TYPE_THRESH,
|
||||
.dir = IIO_EV_DIR_RISING,
|
||||
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
|
||||
BIT(IIO_EV_INFO_ENABLE),
|
||||
}, {
|
||||
.type = IIO_EV_TYPE_THRESH,
|
||||
.dir = IIO_EV_DIR_FALLING,
|
||||
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
|
||||
BIT(IIO_EV_INFO_ENABLE),
|
||||
}, {
|
||||
.type = IIO_EV_TYPE_THRESH_ADAPTIVE,
|
||||
.dir = IIO_EV_DIR_RISING,
|
||||
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
|
||||
BIT(IIO_EV_INFO_ENABLE),
|
||||
}, {
|
||||
.type = IIO_EV_TYPE_THRESH_ADAPTIVE,
|
||||
.dir = IIO_EV_DIR_FALLING,
|
||||
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
|
||||
BIT(IIO_EV_INFO_ENABLE),
|
||||
}, {
|
||||
.type = IIO_EV_TYPE_MAG_ADAPTIVE,
|
||||
.dir = IIO_EV_DIR_RISING,
|
||||
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
|
||||
BIT(IIO_EV_INFO_ENABLE),
|
||||
}, {
|
||||
.type = IIO_EV_TYPE_MAG_ADAPTIVE,
|
||||
.dir = IIO_EV_DIR_FALLING,
|
||||
.mask_separate = BIT(IIO_EV_INFO_VALUE) |
|
||||
BIT(IIO_EV_INFO_ENABLE),
|
||||
},
|
||||
};
|
||||
|
||||
#define AD7150_CAPACITANCE_CHAN(_chan) { \
|
||||
.type = IIO_CAPACITANCE, \
|
||||
.indexed = 1, \
|
||||
.channel = _chan, \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
||||
BIT(IIO_CHAN_INFO_AVERAGE_RAW), \
|
||||
.event_spec = ad7150_events, \
|
||||
.num_event_specs = ARRAY_SIZE(ad7150_events), \
|
||||
}
|
||||
|
||||
static const struct iio_chan_spec ad7150_channels[] = {
|
||||
AD7150_CAPACITANCE_CHAN(0),
|
||||
AD7150_CAPACITANCE_CHAN(1)
|
||||
};
|
||||
|
||||
static irqreturn_t ad7150_event_handler(int irq, void *private)
|
||||
{
|
||||
struct iio_dev *indio_dev = private;
|
||||
struct ad7150_chip_info *chip = iio_priv(indio_dev);
|
||||
u8 int_status;
|
||||
s64 timestamp = iio_get_time_ns(indio_dev);
|
||||
int ret;
|
||||
|
||||
ret = i2c_smbus_read_byte_data(chip->client, AD7150_STATUS);
|
||||
if (ret < 0)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
int_status = ret;
|
||||
|
||||
if ((int_status & AD7150_STATUS_OUT1) &&
|
||||
!(chip->old_state & AD7150_STATUS_OUT1))
|
||||
iio_push_event(indio_dev,
|
||||
IIO_UNMOD_EVENT_CODE(IIO_CAPACITANCE,
|
||||
0,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_RISING),
|
||||
timestamp);
|
||||
else if ((!(int_status & AD7150_STATUS_OUT1)) &&
|
||||
(chip->old_state & AD7150_STATUS_OUT1))
|
||||
iio_push_event(indio_dev,
|
||||
IIO_UNMOD_EVENT_CODE(IIO_CAPACITANCE,
|
||||
0,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_FALLING),
|
||||
timestamp);
|
||||
|
||||
if ((int_status & AD7150_STATUS_OUT2) &&
|
||||
!(chip->old_state & AD7150_STATUS_OUT2))
|
||||
iio_push_event(indio_dev,
|
||||
IIO_UNMOD_EVENT_CODE(IIO_CAPACITANCE,
|
||||
1,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_RISING),
|
||||
timestamp);
|
||||
else if ((!(int_status & AD7150_STATUS_OUT2)) &&
|
||||
(chip->old_state & AD7150_STATUS_OUT2))
|
||||
iio_push_event(indio_dev,
|
||||
IIO_UNMOD_EVENT_CODE(IIO_CAPACITANCE,
|
||||
1,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_FALLING),
|
||||
timestamp);
|
||||
/* store the status to avoid repushing same events */
|
||||
chip->old_state = int_status;
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/* Timeouts not currently handled by core */
|
||||
static struct attribute *ad7150_event_attributes[] = {
|
||||
&iio_dev_attr_in_capacitance0_mag_adaptive_rising_timeout
|
||||
.dev_attr.attr,
|
||||
&iio_dev_attr_in_capacitance0_mag_adaptive_falling_timeout
|
||||
.dev_attr.attr,
|
||||
&iio_dev_attr_in_capacitance1_mag_adaptive_rising_timeout
|
||||
.dev_attr.attr,
|
||||
&iio_dev_attr_in_capacitance1_mag_adaptive_falling_timeout
|
||||
.dev_attr.attr,
|
||||
&iio_dev_attr_in_capacitance0_thresh_adaptive_rising_timeout
|
||||
.dev_attr.attr,
|
||||
&iio_dev_attr_in_capacitance0_thresh_adaptive_falling_timeout
|
||||
.dev_attr.attr,
|
||||
&iio_dev_attr_in_capacitance1_thresh_adaptive_rising_timeout
|
||||
.dev_attr.attr,
|
||||
&iio_dev_attr_in_capacitance1_thresh_adaptive_falling_timeout
|
||||
.dev_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group ad7150_event_attribute_group = {
|
||||
.attrs = ad7150_event_attributes,
|
||||
.name = "events",
|
||||
};
|
||||
|
||||
static const struct iio_info ad7150_info = {
|
||||
.event_attrs = &ad7150_event_attribute_group,
|
||||
.read_raw = &ad7150_read_raw,
|
||||
.read_event_config = &ad7150_read_event_config,
|
||||
.write_event_config = &ad7150_write_event_config,
|
||||
.read_event_value = &ad7150_read_event_value,
|
||||
.write_event_value = &ad7150_write_event_value,
|
||||
};
|
||||
|
||||
static int ad7150_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
struct ad7150_chip_info *chip;
|
||||
struct iio_dev *indio_dev;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
chip = iio_priv(indio_dev);
|
||||
mutex_init(&chip->state_lock);
|
||||
/* this is only used for device removal purposes */
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
|
||||
chip->client = client;
|
||||
|
||||
indio_dev->name = id->name;
|
||||
indio_dev->channels = ad7150_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(ad7150_channels);
|
||||
|
||||
indio_dev->info = &ad7150_info;
|
||||
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
if (client->irq) {
|
||||
ret = devm_request_threaded_irq(&client->dev, client->irq,
|
||||
NULL,
|
||||
&ad7150_event_handler,
|
||||
IRQF_TRIGGER_RISING |
|
||||
IRQF_TRIGGER_FALLING |
|
||||
IRQF_ONESHOT,
|
||||
"ad7150_irq1",
|
||||
indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (client->dev.platform_data) {
|
||||
ret = devm_request_threaded_irq(&client->dev, *(unsigned int *)
|
||||
client->dev.platform_data,
|
||||
NULL,
|
||||
&ad7150_event_handler,
|
||||
IRQF_TRIGGER_RISING |
|
||||
IRQF_TRIGGER_FALLING |
|
||||
IRQF_ONESHOT,
|
||||
"ad7150_irq2",
|
||||
indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev_info(&client->dev, "%s capacitive sensor registered,irq: %d\n",
|
||||
id->name, client->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id ad7150_id[] = {
|
||||
{ "ad7150", 0 },
|
||||
{ "ad7151", 0 },
|
||||
{ "ad7156", 0 },
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, ad7150_id);
|
||||
|
||||
static struct i2c_driver ad7150_driver = {
|
||||
.driver = {
|
||||
.name = "ad7150",
|
||||
},
|
||||
.probe = ad7150_probe,
|
||||
.id_table = ad7150_id,
|
||||
};
|
||||
module_i2c_driver(ad7150_driver);
|
||||
|
||||
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
|
||||
MODULE_DESCRIPTION("Analog Devices AD7150/1/6 capacitive sensor driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -15,7 +15,7 @@
|
|||
* @vref_buffered: Controls buffering of the external reference voltage.
|
||||
*
|
||||
* Vref related settings are available only on MCP4756. See
|
||||
* Documentation/devicetree/bindings/iio/dac/mcp4725.txt for more information.
|
||||
* Documentation/devicetree/bindings/iio/dac/microchip,mcp4725.yaml for more information.
|
||||
*/
|
||||
struct mcp4725_platform_data {
|
||||
bool use_vref;
|
||||
|
|
|
@ -16,6 +16,7 @@ enum iio_event_info {
|
|||
IIO_EV_INFO_PERIOD,
|
||||
IIO_EV_INFO_HIGH_PASS_FILTER_3DB,
|
||||
IIO_EV_INFO_LOW_PASS_FILTER_3DB,
|
||||
IIO_EV_INFO_TIMEOUT,
|
||||
};
|
||||
|
||||
#define IIO_VAL_INT 1
|
||||
|
|
|
@ -61,6 +61,9 @@
|
|||
* interrupt handler after suspending interrupts. For system
|
||||
* wakeup devices users need to implement wakeup detection in
|
||||
* their interrupt handlers.
|
||||
* IRQF_NO_AUTOEN - Don't enable IRQ or NMI automatically when users request it.
|
||||
* Users will enable it explicitly by enable_irq() or enable_nmi()
|
||||
* later.
|
||||
*/
|
||||
#define IRQF_SHARED 0x00000080
|
||||
#define IRQF_PROBE_SHARED 0x00000100
|
||||
|
@ -74,6 +77,7 @@
|
|||
#define IRQF_NO_THREAD 0x00010000
|
||||
#define IRQF_EARLY_RESUME 0x00020000
|
||||
#define IRQF_COND_SUSPEND 0x00040000
|
||||
#define IRQF_NO_AUTOEN 0x00080000
|
||||
|
||||
#define IRQF_TIMER (__IRQF_TIMER | IRQF_NO_SUSPEND | IRQF_NO_THREAD)
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
* mounting matrix retrieved from device-tree)
|
||||
*
|
||||
* Contains platform specific information on how to configure the MPU6050 to
|
||||
* work on this platform. The orientation matricies are 3x3 rotation matricies
|
||||
* work on this platform. The orientation matrices are 3x3 rotation matrices
|
||||
* that are applied to the data to rotate from the mounting orientation to the
|
||||
* platform orientation. The values must be one of 0, 1, or -1 and each row and
|
||||
* column should have exactly 1 non-zero value.
|
||||
|
|
|
@ -1697,7 +1697,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
|
|||
irqd_set(&desc->irq_data, IRQD_NO_BALANCING);
|
||||
}
|
||||
|
||||
if (irq_settings_can_autoenable(desc)) {
|
||||
if (!(new->flags & IRQF_NO_AUTOEN) &&
|
||||
irq_settings_can_autoenable(desc)) {
|
||||
irq_startup(desc, IRQ_RESEND, IRQ_START_COND);
|
||||
} else {
|
||||
/*
|
||||
|
@ -2090,10 +2091,15 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler,
|
|||
* which interrupt is which (messes up the interrupt freeing
|
||||
* logic etc).
|
||||
*
|
||||
* Also shared interrupts do not go well with disabling auto enable.
|
||||
* The sharing interrupt might request it while it's still disabled
|
||||
* and then wait for interrupts forever.
|
||||
*
|
||||
* Also IRQF_COND_SUSPEND only makes sense for shared interrupts and
|
||||
* it cannot be set along with IRQF_NO_SUSPEND.
|
||||
*/
|
||||
if (((irqflags & IRQF_SHARED) && !dev_id) ||
|
||||
((irqflags & IRQF_SHARED) && (irqflags & IRQF_NO_AUTOEN)) ||
|
||||
(!(irqflags & IRQF_SHARED) && (irqflags & IRQF_COND_SUSPEND)) ||
|
||||
((irqflags & IRQF_NO_SUSPEND) && (irqflags & IRQF_COND_SUSPEND)))
|
||||
return -EINVAL;
|
||||
|
@ -2249,7 +2255,8 @@ int request_nmi(unsigned int irq, irq_handler_t handler,
|
|||
|
||||
desc = irq_to_desc(irq);
|
||||
|
||||
if (!desc || irq_settings_can_autoenable(desc) ||
|
||||
if (!desc || (irq_settings_can_autoenable(desc) &&
|
||||
!(irqflags & IRQF_NO_AUTOEN)) ||
|
||||
!irq_settings_can_request(desc) ||
|
||||
WARN_ON(irq_settings_is_per_cpu_devid(desc)) ||
|
||||
!irq_supports_nmi(desc))
|
||||
|
|
Loading…
Reference in a new issue