diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-09-29 21:37:48 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-09-29 21:37:48 -0400 |
commit | 9f827d8099e76a4a2fb99faa88ee7859459f2360 (patch) | |
tree | f08d4db69c53bb441d759747c59a68ae28e82825 | |
parent | 99207b80bbf602f1674485c3f9653b7c527785d9 (diff) | |
parent | 1d2f1e084b7386b4082ebc2490ce0ddc8efe5667 (diff) |
Merge tag 'iio-for-4.4a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next
Jonathan writes:
First round of new driver, new functionality and cleanups for IIO in the 4.4 cycle
New device support
* APDS9960 ALS + proximity driver
* bmg160 SPI devices.
* HDC100x humidity sensors
* Holt HI-8435 threshold detector
* mma8453Q accelerometer added to the mma8452 driver
* mma86452FC and mma8653FC accelerometers added to the mma8452 driver
* mxc4005 accelerometer
* PulsedLight LIDAR
* SensorTech VZ89x volatile organic compound sensor
* UPISEMI uS5182d ALS and proximity sensors
New core functionality
* triggered events - use triggers to check for changes in threshold type
detectors on devices with out interrupt support. First user is the holt
comparator.
* chemical concentration and resistance channel types.
New driver functionality
* vf610
- buffer support.
- followup coccinelle warning fix.
Core rework
* buffers
- break out callback buffer to own module.
- move buffer implementations to a new subdirectory
* percolate the error code form iio_event_getfd out to userspace
rather than giving a missleading error later on.
Cleanups
* adddac drivers
- use BIT macro where appropriate.
* meter drivers
- use BIT macro where appropriate.
* ad7303
- add an OF match table to line up with the binding docs.
* adc128s052
- add an OF match table to line up with the binding docs.
* adf4350
- add an OF match table to line up with the binding docs
* as3935
- add an OF match table to line up with the binding docs.
* berlin2-adc
- use GENMASK and BIT for masks
- prevent attempting to sample multiple channels at once by moving a
mutex scop
- coding style cleanups
* bmg150_magn
- kconfig sort order was wrong - fix it.
* bmg160
- use i2c regmap and drop all uses of i2c_client
- separate i2c and core driver
* cc10001_adc
- kconfig sort order was wrong - fix it.
* evgen (dummy driver helper module)
- move interrupt generation to irq_work to reduce differences between
the dummy driver and real hardware drivers.
* hmc5843
- set the name dynamically rather than to a fixed value for one of the
suported parts.
- export module alias information to allow autoprobing of module.
* lpc32xx
- on failure to get resource or irq return -ENXIO as uppose to -EBUSY
* max1027
- set .of_match_table to actually allow OF style matching.
* max5821
- add MODULE_DEVICE_TABLE for OF table.
* mma8452
- refactor to separate out chip specific data.
- add freefall / motion interrupt source for devices that do their
interrupts slightly differently.
- update copywrite notice.
- leave naming of events directory in sysfs to the core
* mcp320x
- set .of_match_table so that it can be use for OF style matching.
* mlx90614
- Implement filter configuration (note the datasheet changed as a result
of the driver reviews to include the values we needed ;)
* opt3001
- drop .owner field as assigned by platform driver core.
* si7020
- replace a bitmask on the humidity values with a more correct range
check.
* stk310
- improved error handling.
- use BIT macro where appropriate and use the resulting defines
instead of magic numbers in the code.
- fix indentation
* st-sensors
- add debugfs register read hook
* tsl4531
- fix error handling in check_id
* twl6030
- fix module autoload for OF
* iio-trig-sysfs
- document add and remove attribute
* trigger in staging
- code alignment fixes.
- braces on both branches of if statement if needed for one.
* xilinx-xadc
- push interrupts into hardirq context as there isn't much in them
any more and it avoids breaking PREEMPT_RT builds due to the use
of a spinlock between the hardirq and the thread.
Tools
* event-monitor
- report unsupported events. We keep expanding what can come from drivers
so give a helpful error if one turns up in an out of date userspace
program.
* generic-buffer
- helpful message about needing to enable a channel to start the buffer.
88 files changed, 5114 insertions, 471 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 42d360fe66a5..8ce14c85156d 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio | |||
@@ -581,6 +581,7 @@ What: /sys/.../iio:deviceX/events/in_voltageY_supply_thresh_rising_en | |||
581 | What: /sys/.../iio:deviceX/events/in_voltageY_supply_thresh_falling_en | 581 | What: /sys/.../iio:deviceX/events/in_voltageY_supply_thresh_falling_en |
582 | What: /sys/.../iio:deviceX/events/in_voltageY_thresh_rising_en | 582 | What: /sys/.../iio:deviceX/events/in_voltageY_thresh_rising_en |
583 | What: /sys/.../iio:deviceX/events/in_voltageY_thresh_falling_en | 583 | What: /sys/.../iio:deviceX/events/in_voltageY_thresh_falling_en |
584 | What: /sys/.../iio:deviceX/events/in_voltageY_thresh_either_en | ||
584 | What: /sys/.../iio:deviceX/events/in_tempY_thresh_rising_en | 585 | What: /sys/.../iio:deviceX/events/in_tempY_thresh_rising_en |
585 | What: /sys/.../iio:deviceX/events/in_tempY_thresh_falling_en | 586 | What: /sys/.../iio:deviceX/events/in_tempY_thresh_falling_en |
586 | KernelVersion: 2.6.37 | 587 | KernelVersion: 2.6.37 |
@@ -1459,3 +1460,22 @@ Description: | |||
1459 | measurements and return the average value as output data. Each | 1460 | measurements and return the average value as output data. Each |
1460 | value resulted from <type>[_name]_oversampling_ratio measurements | 1461 | value resulted from <type>[_name]_oversampling_ratio measurements |
1461 | is considered as one sample for <type>[_name]_sampling_frequency. | 1462 | is considered as one sample for <type>[_name]_sampling_frequency. |
1463 | |||
1464 | What: /sys/bus/iio/devices/iio:deviceX/in_concentration_raw | ||
1465 | What: /sys/bus/iio/devices/iio:deviceX/in_concentrationX_raw | ||
1466 | What: /sys/bus/iio/devices/iio:deviceX/in_concentration_co2_raw | ||
1467 | What: /sys/bus/iio/devices/iio:deviceX/in_concentrationX_co2_raw | ||
1468 | What: /sys/bus/iio/devices/iio:deviceX/in_concentration_voc_raw | ||
1469 | What: /sys/bus/iio/devices/iio:deviceX/in_concentrationX_voc_raw | ||
1470 | KernelVersion: 4.3 | ||
1471 | Contact: linux-iio@vger.kernel.org | ||
1472 | Description: | ||
1473 | Raw (unscaled no offset etc.) percentage reading of a substance. | ||
1474 | |||
1475 | What: /sys/bus/iio/devices/iio:deviceX/in_resistance_raw | ||
1476 | What: /sys/bus/iio/devices/iio:deviceX/in_resistanceX_raw | ||
1477 | KernelVersion: 4.3 | ||
1478 | Contact: linux-iio@vger.kernel.org | ||
1479 | Description: | ||
1480 | Raw (unscaled no offset etc.) resistance reading that can be processed | ||
1481 | into an ohm value. | ||
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-adc-hi8435 b/Documentation/ABI/testing/sysfs-bus-iio-adc-hi8435 new file mode 100644 index 000000000000..f30b4c424fb6 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-adc-hi8435 | |||
@@ -0,0 +1,43 @@ | |||
1 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_sensing_mode | ||
2 | Date: August 2015 | ||
3 | KernelVersion: 4.2.0 | ||
4 | Contact: source@cogentembedded.com | ||
5 | Description: | ||
6 | Program sensor type for threshold detector inputs. | ||
7 | Could be either "GND-Open" or "Supply-Open" mode. Y is a | ||
8 | threshold detector input channel. Channels 0..7, 8..15, 16..23 | ||
9 | and 24..31 has common sensor types. | ||
10 | |||
11 | What: /sys/bus/iio/devices/iio:deviceX/events/in_voltageY_thresh_falling_value | ||
12 | Date: August 2015 | ||
13 | KernelVersion: 4.2.0 | ||
14 | Contact: source@cogentembedded.com | ||
15 | Description: | ||
16 | Channel Y low voltage threshold. If sensor input voltage goes lower then | ||
17 | this value then the threshold falling event is pushed. | ||
18 | Depending on in_voltageY_sensing_mode the low voltage threshold | ||
19 | is separately set for "GND-Open" and "Supply-Open" modes. | ||
20 | Channels 0..31 have common low threshold values, but could have different | ||
21 | sensing_modes. | ||
22 | The low voltage threshold range is between 2..21V. | ||
23 | Hysteresis between low and high thresholds can not be lower then 2 and | ||
24 | can not be odd. | ||
25 | If falling threshold results hysteresis to odd value then rising | ||
26 | threshold is automatically subtracted by one. | ||
27 | |||
28 | What: /sys/bus/iio/devices/iio:deviceX/events/in_voltageY_thresh_rising_value | ||
29 | Date: August 2015 | ||
30 | KernelVersion: 4.2.0 | ||
31 | Contact: source@cogentembedded.com | ||
32 | Description: | ||
33 | Channel Y high voltage threshold. If sensor input voltage goes higher then | ||
34 | this value then the threshold rising event is pushed. | ||
35 | Depending on in_voltageY_sensing_mode the high voltage threshold | ||
36 | is separately set for "GND-Open" and "Supply-Open" modes. | ||
37 | Channels 0..31 have common high threshold values, but could have different | ||
38 | sensing_modes. | ||
39 | The high voltage threshold range is between 3..22V. | ||
40 | Hysteresis between low and high thresholds can not be lower then 2 and | ||
41 | can not be odd. | ||
42 | If rising threshold results hysteresis to odd value then falling | ||
43 | threshold is automatically appended by one. | ||
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-chemical-vz89x b/Documentation/ABI/testing/sysfs-bus-iio-chemical-vz89x new file mode 100644 index 000000000000..c0c1ea924535 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-chemical-vz89x | |||
@@ -0,0 +1,7 @@ | |||
1 | What: /sys/bus/iio/devices/iio:deviceX/in_concentration_VOC_short_raw | ||
2 | Date: September 2015 | ||
3 | KernelVersion: 4.3 | ||
4 | Contact: Matt Ranostay <mranostay@gmail.com> | ||
5 | Description: | ||
6 | Get the raw calibration VOC value from the sensor. | ||
7 | This value has little application outside of calibration. | ||
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-humidity-hdc100x b/Documentation/ABI/testing/sysfs-bus-iio-humidity-hdc100x new file mode 100644 index 000000000000..b72bb62552cf --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-humidity-hdc100x | |||
@@ -0,0 +1,9 @@ | |||
1 | What: /sys/bus/iio/devices/iio:deviceX/out_current_heater_raw | ||
2 | What: /sys/bus/iio/devices/iio:deviceX/out_current_heater_raw_available | ||
3 | KernelVersion: 4.3 | ||
4 | Contact: linux-iio@vger.kernel.org | ||
5 | Description: | ||
6 | Controls the heater device within the humidity sensor to get | ||
7 | rid of excess condensation. | ||
8 | |||
9 | Valid control values are 0 = OFF, and 1 = ON. | ||
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs b/Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs index bbb039237a25..04ac62305018 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs +++ b/Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs | |||
@@ -18,3 +18,25 @@ Description: | |||
18 | trigger. In order to associate the trigger with an IIO device | 18 | trigger. In order to associate the trigger with an IIO device |
19 | one should write this name string to | 19 | one should write this name string to |
20 | /sys/bus/iio/devices/iio:deviceY/trigger/current_trigger. | 20 | /sys/bus/iio/devices/iio:deviceY/trigger/current_trigger. |
21 | |||
22 | What: /sys/bus/iio/devices/iio_sysfs_trigger/add_trigger | ||
23 | KernelVersion: 2.6.39 | ||
24 | Contact: linux-iio@vger.kernel.org | ||
25 | Description: | ||
26 | This attribute is provided by the iio-trig-sysfs stand-alone | ||
27 | driver and it is used to activate the creation of a new trigger. | ||
28 | In order to achieve this, one should write a positive integer | ||
29 | into the associated file, which will serve as the id of the | ||
30 | trigger. If the trigger with the specified id is already present | ||
31 | in the system, an invalid argument message will be returned. | ||
32 | |||
33 | What: /sys/bus/iio/devices/iio_sysfs_trigger/remove_trigger | ||
34 | KernelVersion: 2.6.39 | ||
35 | Contact: linux-iio@vger.kernel.org | ||
36 | Description: | ||
37 | This attribute is used to unregister and delete a previously | ||
38 | created trigger from the list of available triggers. In order to | ||
39 | achieve this, one should write a positive integer into the | ||
40 | associated file, representing the id of the trigger that needs | ||
41 | to be removed. If the trigger can't be found, an invalid | ||
42 | argument message will be returned to the user. | ||
diff --git a/Documentation/DocBook/iio.tmpl b/Documentation/DocBook/iio.tmpl index 06bb53de5a47..98be322673da 100644 --- a/Documentation/DocBook/iio.tmpl +++ b/Documentation/DocBook/iio.tmpl | |||
@@ -578,7 +578,7 @@ | |||
578 | work together. | 578 | work together. |
579 | </para> | 579 | </para> |
580 | <sect2 id="iiotrigbufsetup"> <title> IIO triggered buffer setup</title> | 580 | <sect2 id="iiotrigbufsetup"> <title> IIO triggered buffer setup</title> |
581 | !Edrivers/iio/industrialio-triggered-buffer.c | 581 | !Edrivers/iio/buffer/industrialio-triggered-buffer.c |
582 | !Finclude/linux/iio/iio.h iio_buffer_setup_ops | 582 | !Finclude/linux/iio/iio.h iio_buffer_setup_ops |
583 | 583 | ||
584 | 584 | ||
diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt index d77d412cbc68..c50cf13c852e 100644 --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt | |||
@@ -54,7 +54,6 @@ epson,rx8581 I2C-BUS INTERFACE REAL TIME CLOCK MODULE | |||
54 | fsl,mag3110 MAG3110: Xtrinsic High Accuracy, 3D Magnetometer | 54 | fsl,mag3110 MAG3110: Xtrinsic High Accuracy, 3D Magnetometer |
55 | fsl,mc13892 MC13892: Power Management Integrated Circuit (PMIC) for i.MX35/51 | 55 | fsl,mc13892 MC13892: Power Management Integrated Circuit (PMIC) for i.MX35/51 |
56 | fsl,mma8450 MMA8450Q: Xtrinsic Low-power, 3-axis Xtrinsic Accelerometer | 56 | fsl,mma8450 MMA8450Q: Xtrinsic Low-power, 3-axis Xtrinsic Accelerometer |
57 | fsl,mma8452 MMA8452Q: 3-axis 12-bit / 8-bit Digital Accelerometer | ||
58 | fsl,mpr121 MPR121: Proximity Capacitive Touch Sensor Controller | 57 | fsl,mpr121 MPR121: Proximity Capacitive Touch Sensor Controller |
59 | fsl,sgtl5000 SGTL5000: Ultra Low-Power Audio Codec | 58 | fsl,sgtl5000 SGTL5000: Ultra Low-Power Audio Codec |
60 | gmt,g751 G751: Digital Temperature Sensor and Thermal Watchdog with Two-Wire Interface | 59 | gmt,g751 G751: Digital Temperature Sensor and Thermal Watchdog with Two-Wire Interface |
@@ -80,6 +79,7 @@ oki,ml86v7667 OKI ML86V7667 video decoder | |||
80 | ovti,ov5642 OV5642: Color CMOS QSXGA (5-megapixel) Image Sensor with OmniBSI and Embedded TrueFocus | 79 | ovti,ov5642 OV5642: Color CMOS QSXGA (5-megapixel) Image Sensor with OmniBSI and Embedded TrueFocus |
81 | pericom,pt7c4338 Real-time Clock Module | 80 | pericom,pt7c4338 Real-time Clock Module |
82 | plx,pex8648 48-Lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch | 81 | plx,pex8648 48-Lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch |
82 | pulsedlight,lidar-lite-v2 Pulsedlight LIDAR range-finding sensor | ||
83 | ramtron,24c64 i2c serial eeprom (24cxx) | 83 | ramtron,24c64 i2c serial eeprom (24cxx) |
84 | ricoh,r2025sd I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC | 84 | ricoh,r2025sd I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC |
85 | ricoh,r2221tl I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC | 85 | ricoh,r2221tl I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC |
@@ -88,6 +88,7 @@ ricoh,rs5c372b I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC | |||
88 | ricoh,rv5c386 I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC | 88 | ricoh,rv5c386 I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC |
89 | ricoh,rv5c387a I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC | 89 | ricoh,rv5c387a I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC |
90 | samsung,24ad0xd1 S524AD0XF1 (128K/256K-bit Serial EEPROM for Low Power) | 90 | samsung,24ad0xd1 S524AD0XF1 (128K/256K-bit Serial EEPROM for Low Power) |
91 | sgx,vz89x SGX Sensortech VZ89X Sensors | ||
91 | sii,s35390a 2-wire CMOS real-time clock | 92 | sii,s35390a 2-wire CMOS real-time clock |
92 | skyworks,sky81452 Skyworks SKY81452: Six-Channel White LED Driver with Touch Panel Bias Supply | 93 | skyworks,sky81452 Skyworks SKY81452: Six-Channel White LED Driver with Touch Panel Bias Supply |
93 | st-micro,24c256 i2c serial eeprom (24cxx) | 94 | st-micro,24c256 i2c serial eeprom (24cxx) |
diff --git a/Documentation/devicetree/bindings/iio/accel/mma8452.txt b/Documentation/devicetree/bindings/iio/accel/mma8452.txt new file mode 100644 index 000000000000..e3c37467d7da --- /dev/null +++ b/Documentation/devicetree/bindings/iio/accel/mma8452.txt | |||
@@ -0,0 +1,24 @@ | |||
1 | Freescale MMA8452Q, MMA8453Q, MMA8652FC or MMA8653FC triaxial accelerometer | ||
2 | |||
3 | Required properties: | ||
4 | |||
5 | - compatible: should contain one of | ||
6 | * "fsl,mma8452" | ||
7 | * "fsl,mma8453" | ||
8 | * "fsl,mma8652" | ||
9 | * "fsl,mma8653" | ||
10 | - reg: the I2C address of the chip | ||
11 | |||
12 | Optional properties: | ||
13 | |||
14 | - interrupt-parent: should be the phandle for the interrupt controller | ||
15 | - interrupts: interrupt mapping for GPIO IRQ | ||
16 | |||
17 | Example: | ||
18 | |||
19 | mma8453fc@1d { | ||
20 | compatible = "fsl,mma8453"; | ||
21 | reg = <0x1d>; | ||
22 | interrupt-parent = <&gpio1>; | ||
23 | interrupts = <5 0>; | ||
24 | }; | ||
diff --git a/Documentation/devicetree/bindings/iio/adc/hi8435.txt b/Documentation/devicetree/bindings/iio/adc/hi8435.txt new file mode 100644 index 000000000000..3b0348c5e516 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/hi8435.txt | |||
@@ -0,0 +1,21 @@ | |||
1 | Holt Integrated Circuits HI-8435 threshold detector bindings | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: should be "holt,hi8435" | ||
5 | - reg: spi chip select number for the device | ||
6 | |||
7 | Recommended properties: | ||
8 | - spi-max-frequency: definition as per | ||
9 | Documentation/devicetree/bindings/spi/spi-bus.txt | ||
10 | |||
11 | Optional properties: | ||
12 | - gpios: GPIO used for controlling the reset pin | ||
13 | |||
14 | Example: | ||
15 | sensor@0 { | ||
16 | compatible = "holt,hi8435"; | ||
17 | reg = <0>; | ||
18 | gpios = <&gpio6 1 0>; | ||
19 | |||
20 | spi-max-frequency = <1000000>; | ||
21 | }; | ||
diff --git a/Documentation/devicetree/bindings/iio/light/apds9960.txt b/Documentation/devicetree/bindings/iio/light/apds9960.txt new file mode 100644 index 000000000000..174b709f16db --- /dev/null +++ b/Documentation/devicetree/bindings/iio/light/apds9960.txt | |||
@@ -0,0 +1,22 @@ | |||
1 | * Avago APDS9960 gesture/RGB/ALS/proximity sensor | ||
2 | |||
3 | http://www.avagotech.com/docs/AV02-4191EN | ||
4 | |||
5 | Required properties: | ||
6 | |||
7 | - compatible: must be "avago,apds9960" | ||
8 | - reg: the I2c address of the sensor | ||
9 | - interrupt-parent: should be the phandle for the interrupt controller | ||
10 | - interrupts : the sole interrupt generated by the device | ||
11 | |||
12 | Refer to interrupt-controller/interrupts.txt for generic interrupt client | ||
13 | node bindings. | ||
14 | |||
15 | Example: | ||
16 | |||
17 | apds9960@39 { | ||
18 | compatible = "avago,apds9960"; | ||
19 | reg = <0x39>; | ||
20 | interrupt-parent = <&gpio1>; | ||
21 | interrupts = <16 1>; | ||
22 | }; | ||
diff --git a/Documentation/devicetree/bindings/iio/light/us5182d.txt b/Documentation/devicetree/bindings/iio/light/us5182d.txt new file mode 100644 index 000000000000..6f0a530144fd --- /dev/null +++ b/Documentation/devicetree/bindings/iio/light/us5182d.txt | |||
@@ -0,0 +1,34 @@ | |||
1 | * UPISEMI us5182d I2C ALS and Proximity sensor | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: must be "upisemi,usd5182" | ||
5 | - reg: the I2C address of the device | ||
6 | |||
7 | Optional properties: | ||
8 | - upisemi,glass-coef: glass attenuation factor - compensation factor of | ||
9 | resolution 1000 for material transmittance. | ||
10 | - upisemi,dark-ths: array of 8 elements containing 16-bit thresholds (adc | ||
11 | counts) corresponding to every scale. | ||
12 | - upisemi,upper-dark-gain: 8-bit dark gain compensation factor(4 int and 4 | ||
13 | fractional bits - Q4.4) applied when light > threshold | ||
14 | - upisemi,lower-dark-gain: 8-bit dark gain compensation factor(4 int and 4 | ||
15 | fractional bits - Q4.4) applied when light < threshold | ||
16 | |||
17 | If the optional properties are not specified these factors will default to the | ||
18 | values in the below example. | ||
19 | The glass-coef defaults to no compensation for the covering material. | ||
20 | The threshold array defaults to experimental values that work with US5182D | ||
21 | sensor on evaluation board - roughly between 12-32 lux. | ||
22 | There will be no dark-gain compensation by default when ALS > thresh | ||
23 | (0 * dark-gain), and a 1.35 compensation factor when ALS < thresh. | ||
24 | |||
25 | Example: | ||
26 | |||
27 | usd5182@39 { | ||
28 | compatible = "upisemi,usd5182"; | ||
29 | reg = <0x39>; | ||
30 | upisemi,glass-coef = < 1000 >; | ||
31 | upisemi,dark-ths = /bits/ 16 <170 200 512 512 800 2000 4000 8000>; | ||
32 | upisemi,upper-dark-gain = /bits/ 8 <0x00>; | ||
33 | upisemi,lower-dark-gain = /bits/ 8 <0x16>; | ||
34 | }; | ||
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 82d2ac97af74..13e54a0e78b9 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt | |||
@@ -101,6 +101,7 @@ himax Himax Technologies, Inc. | |||
101 | hisilicon Hisilicon Limited. | 101 | hisilicon Hisilicon Limited. |
102 | hit Hitachi Ltd. | 102 | hit Hitachi Ltd. |
103 | hitex Hitex Development Tools | 103 | hitex Hitex Development Tools |
104 | holt Holt Integrated Circuits, Inc. | ||
104 | honeywell Honeywell | 105 | honeywell Honeywell |
105 | hp Hewlett Packard | 106 | hp Hewlett Packard |
106 | i2se I2SE GmbH | 107 | i2se I2SE GmbH |
@@ -169,6 +170,7 @@ phytec PHYTEC Messtechnik GmbH | |||
169 | picochip Picochip Ltd | 170 | picochip Picochip Ltd |
170 | plathome Plat'Home Co., Ltd. | 171 | plathome Plat'Home Co., Ltd. |
171 | pixcir PIXCIR MICROELECTRONICS Co., Ltd | 172 | pixcir PIXCIR MICROELECTRONICS Co., Ltd |
173 | pulsedlight PulsedLight, Inc | ||
172 | powervr PowerVR (deprecated, use img) | 174 | powervr PowerVR (deprecated, use img) |
173 | qca Qualcomm Atheros, Inc. | 175 | qca Qualcomm Atheros, Inc. |
174 | qcom Qualcomm Technologies, Inc | 176 | qcom Qualcomm Technologies, Inc |
@@ -191,6 +193,7 @@ sbs Smart Battery System | |||
191 | schindler Schindler | 193 | schindler Schindler |
192 | seagate Seagate Technology PLC | 194 | seagate Seagate Technology PLC |
193 | semtech Semtech Corporation | 195 | semtech Semtech Corporation |
196 | sgx SGX Sensortech | ||
194 | sharp Sharp Corporation | 197 | sharp Sharp Corporation |
195 | sil Silicon Image | 198 | sil Silicon Image |
196 | silabs Silicon Laboratories | 199 | silabs Silicon Laboratories |
@@ -223,6 +226,7 @@ toshiba Toshiba Corporation | |||
223 | toumaz Toumaz | 226 | toumaz Toumaz |
224 | tplink TP-LINK Technologies Co., Ltd. | 227 | tplink TP-LINK Technologies Co., Ltd. |
225 | truly Truly Semiconductors Limited | 228 | truly Truly Semiconductors Limited |
229 | upisemi uPI Semiconductor Corp. | ||
226 | usi Universal Scientific Industrial Co., Ltd. | 230 | usi Universal Scientific Industrial Co., Ltd. |
227 | v3 V3 Semiconductor | 231 | v3 V3 Semiconductor |
228 | variscite Variscite Ltd. | 232 | variscite Variscite Ltd. |
diff --git a/MAINTAINERS b/MAINTAINERS index 7b181d561bb3..6d7af82cb09c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -6918,6 +6918,13 @@ S: Supported | |||
6918 | F: include/linux/mlx5/ | 6918 | F: include/linux/mlx5/ |
6919 | F: drivers/infiniband/hw/mlx5/ | 6919 | F: drivers/infiniband/hw/mlx5/ |
6920 | 6920 | ||
6921 | MELEXIS MLX90614 DRIVER | ||
6922 | M: Crt Mori <cmo@melexis.com> | ||
6923 | L: linux-iio@vger.kernel.org | ||
6924 | W: http://www.melexis.com | ||
6925 | S: Supported | ||
6926 | F: drivers/iio/temperature/mlx90614.c | ||
6927 | |||
6921 | MN88472 MEDIA DRIVER | 6928 | MN88472 MEDIA DRIVER |
6922 | M: Antti Palosaari <crope@iki.fi> | 6929 | M: Antti Palosaari <crope@iki.fi> |
6923 | L: linux-media@vger.kernel.org | 6930 | L: linux-media@vger.kernel.org |
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index 4011effe4c05..119c94df2b9e 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig | |||
@@ -19,27 +19,7 @@ config IIO_BUFFER | |||
19 | acquisition methods. | 19 | acquisition methods. |
20 | 20 | ||
21 | if IIO_BUFFER | 21 | if IIO_BUFFER |
22 | 22 | source "drivers/iio/buffer/Kconfig" | |
23 | config IIO_BUFFER_CB | ||
24 | bool "IIO callback buffer used for push in-kernel interfaces" | ||
25 | help | ||
26 | Should be selected by any drivers that do in-kernel push | ||
27 | usage. That is, those where the data is pushed to the consumer. | ||
28 | |||
29 | config IIO_KFIFO_BUF | ||
30 | tristate "Industrial I/O buffering based on kfifo" | ||
31 | help | ||
32 | A simple fifo based on kfifo. Note that this currently provides | ||
33 | no buffer events so it is up to userspace to work out how | ||
34 | often to read from the buffer. | ||
35 | |||
36 | config IIO_TRIGGERED_BUFFER | ||
37 | tristate | ||
38 | select IIO_TRIGGER | ||
39 | select IIO_KFIFO_BUF | ||
40 | help | ||
41 | Provides helper functions for setting up triggered buffers. | ||
42 | |||
43 | endif # IIO_BUFFER | 23 | endif # IIO_BUFFER |
44 | 24 | ||
45 | config IIO_TRIGGER | 25 | config IIO_TRIGGER |
@@ -58,9 +38,16 @@ config IIO_CONSUMERS_PER_TRIGGER | |||
58 | This value controls the maximum number of consumers that a | 38 | This value controls the maximum number of consumers that a |
59 | given trigger may handle. Default is 2. | 39 | given trigger may handle. Default is 2. |
60 | 40 | ||
41 | config IIO_TRIGGERED_EVENT | ||
42 | tristate | ||
43 | select IIO_TRIGGER | ||
44 | help | ||
45 | Provides helper functions for setting up triggered events. | ||
46 | |||
61 | source "drivers/iio/accel/Kconfig" | 47 | source "drivers/iio/accel/Kconfig" |
62 | source "drivers/iio/adc/Kconfig" | 48 | source "drivers/iio/adc/Kconfig" |
63 | source "drivers/iio/amplifiers/Kconfig" | 49 | source "drivers/iio/amplifiers/Kconfig" |
50 | source "drivers/iio/chemical/Kconfig" | ||
64 | source "drivers/iio/common/Kconfig" | 51 | source "drivers/iio/common/Kconfig" |
65 | source "drivers/iio/dac/Kconfig" | 52 | source "drivers/iio/dac/Kconfig" |
66 | source "drivers/iio/frequency/Kconfig" | 53 | source "drivers/iio/frequency/Kconfig" |
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index 698afc2d17ce..e2100554e3b4 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile | |||
@@ -6,14 +6,14 @@ obj-$(CONFIG_IIO) += industrialio.o | |||
6 | industrialio-y := industrialio-core.o industrialio-event.o inkern.o | 6 | industrialio-y := industrialio-core.o industrialio-event.o inkern.o |
7 | industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o | 7 | industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o |
8 | industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o | 8 | industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o |
9 | industrialio-$(CONFIG_IIO_BUFFER_CB) += buffer_cb.o | ||
10 | 9 | ||
11 | obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o | 10 | obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o |
12 | obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o | ||
13 | 11 | ||
14 | obj-y += accel/ | 12 | obj-y += accel/ |
15 | obj-y += adc/ | 13 | obj-y += adc/ |
16 | obj-y += amplifiers/ | 14 | obj-y += amplifiers/ |
15 | obj-y += buffer/ | ||
16 | obj-y += chemical/ | ||
17 | obj-y += common/ | 17 | obj-y += common/ |
18 | obj-y += dac/ | 18 | obj-y += dac/ |
19 | obj-y += gyro/ | 19 | obj-y += gyro/ |
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index a59047d7657e..8172ae5c3d0d 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig | |||
@@ -100,13 +100,13 @@ config KXCJK1013 | |||
100 | be called kxcjk-1013. | 100 | be called kxcjk-1013. |
101 | 101 | ||
102 | config MMA8452 | 102 | config MMA8452 |
103 | tristate "Freescale MMA8452Q Accelerometer Driver" | 103 | tristate "Freescale MMA8452Q and similar Accelerometers Driver" |
104 | depends on I2C | 104 | depends on I2C |
105 | select IIO_BUFFER | 105 | select IIO_BUFFER |
106 | select IIO_TRIGGERED_BUFFER | 106 | select IIO_TRIGGERED_BUFFER |
107 | help | 107 | help |
108 | Say yes here to build support for the Freescale MMA8452Q 3-axis | 108 | Say yes here to build support for the following Freescale 3-axis |
109 | accelerometer. | 109 | accelerometers: MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC. |
110 | 110 | ||
111 | To compile this driver as a module, choose M here: the module | 111 | To compile this driver as a module, choose M here: the module |
112 | will be called mma8452. | 112 | will be called mma8452. |
@@ -137,6 +137,19 @@ config MMA9553 | |||
137 | To compile this driver as a module, choose M here: the module | 137 | To compile this driver as a module, choose M here: the module |
138 | will be called mma9553. | 138 | will be called mma9553. |
139 | 139 | ||
140 | config MXC4005 | ||
141 | tristate "Memsic MXC4005XC 3-Axis Accelerometer Driver" | ||
142 | depends on I2C | ||
143 | select IIO_BUFFER | ||
144 | select IIO_TRIGGERED_BUFFER | ||
145 | select REGMAP_I2C | ||
146 | help | ||
147 | Say yes here to build support for the Memsic MXC4005XC 3-axis | ||
148 | accelerometer. | ||
149 | |||
150 | To compile this driver as a module, choose M. The module will be | ||
151 | called mxc4005. | ||
152 | |||
140 | config STK8312 | 153 | config STK8312 |
141 | tristate "Sensortek STK8312 3-Axis Accelerometer Driver" | 154 | tristate "Sensortek STK8312 3-Axis Accelerometer Driver" |
142 | depends on I2C | 155 | depends on I2C |
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index ebd2675b2a02..020dda0ae508 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile | |||
@@ -14,6 +14,8 @@ obj-$(CONFIG_MMA9551_CORE) += mma9551_core.o | |||
14 | obj-$(CONFIG_MMA9551) += mma9551.o | 14 | obj-$(CONFIG_MMA9551) += mma9551.o |
15 | obj-$(CONFIG_MMA9553) += mma9553.o | 15 | obj-$(CONFIG_MMA9553) += mma9553.o |
16 | 16 | ||
17 | obj-$(CONFIG_MXC4005) += mxc4005.o | ||
18 | |||
17 | obj-$(CONFIG_STK8312) += stk8312.o | 19 | obj-$(CONFIG_STK8312) += stk8312.o |
18 | obj-$(CONFIG_STK8BA50) += stk8ba50.o | 20 | obj-$(CONFIG_STK8BA50) += stk8ba50.o |
19 | 21 | ||
diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index b921d84c1be6..1eccc2dcf14c 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c | |||
@@ -1,6 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | * mma8452.c - Support for Freescale MMA8452Q 3-axis 12-bit accelerometer | 2 | * mma8452.c - Support for following Freescale 3-axis accelerometers: |
3 | * | 3 | * |
4 | * MMA8452Q (12 bit) | ||
5 | * MMA8453Q (10 bit) | ||
6 | * MMA8652FC (12 bit) | ||
7 | * MMA8653FC (10 bit) | ||
8 | * | ||
9 | * Copyright 2015 Martin Kepplinger <martin.kepplinger@theobroma-systems.com> | ||
4 | * Copyright 2014 Peter Meerwald <pmeerw@pmeerw.net> | 10 | * Copyright 2014 Peter Meerwald <pmeerw@pmeerw.net> |
5 | * | 11 | * |
6 | * This file is subject to the terms and conditions of version 2 of | 12 | * This file is subject to the terms and conditions of version 2 of |
@@ -22,10 +28,11 @@ | |||
22 | #include <linux/iio/triggered_buffer.h> | 28 | #include <linux/iio/triggered_buffer.h> |
23 | #include <linux/iio/events.h> | 29 | #include <linux/iio/events.h> |
24 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
31 | #include <linux/of_device.h> | ||
25 | 32 | ||
26 | #define MMA8452_STATUS 0x00 | 33 | #define MMA8452_STATUS 0x00 |
27 | #define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0)) | 34 | #define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0)) |
28 | #define MMA8452_OUT_X 0x01 /* MSB first, 12-bit */ | 35 | #define MMA8452_OUT_X 0x01 /* MSB first */ |
29 | #define MMA8452_OUT_Y 0x03 | 36 | #define MMA8452_OUT_Y 0x03 |
30 | #define MMA8452_OUT_Z 0x05 | 37 | #define MMA8452_OUT_Z 0x05 |
31 | #define MMA8452_INT_SRC 0x0c | 38 | #define MMA8452_INT_SRC 0x0c |
@@ -38,6 +45,16 @@ | |||
38 | #define MMA8452_DATA_CFG_HPF_MASK BIT(4) | 45 | #define MMA8452_DATA_CFG_HPF_MASK BIT(4) |
39 | #define MMA8452_HP_FILTER_CUTOFF 0x0f | 46 | #define MMA8452_HP_FILTER_CUTOFF 0x0f |
40 | #define MMA8452_HP_FILTER_CUTOFF_SEL_MASK GENMASK(1, 0) | 47 | #define MMA8452_HP_FILTER_CUTOFF_SEL_MASK GENMASK(1, 0) |
48 | #define MMA8452_FF_MT_CFG 0x15 | ||
49 | #define MMA8452_FF_MT_CFG_OAE BIT(6) | ||
50 | #define MMA8452_FF_MT_CFG_ELE BIT(7) | ||
51 | #define MMA8452_FF_MT_SRC 0x16 | ||
52 | #define MMA8452_FF_MT_SRC_XHE BIT(1) | ||
53 | #define MMA8452_FF_MT_SRC_YHE BIT(3) | ||
54 | #define MMA8452_FF_MT_SRC_ZHE BIT(5) | ||
55 | #define MMA8452_FF_MT_THS 0x17 | ||
56 | #define MMA8452_FF_MT_THS_MASK 0x7f | ||
57 | #define MMA8452_FF_MT_COUNT 0x18 | ||
41 | #define MMA8452_TRANSIENT_CFG 0x1d | 58 | #define MMA8452_TRANSIENT_CFG 0x1d |
42 | #define MMA8452_TRANSIENT_CFG_HPF_BYP BIT(0) | 59 | #define MMA8452_TRANSIENT_CFG_HPF_BYP BIT(0) |
43 | #define MMA8452_TRANSIENT_CFG_CHAN(chan) BIT(chan + 1) | 60 | #define MMA8452_TRANSIENT_CFG_CHAN(chan) BIT(chan + 1) |
@@ -65,15 +82,65 @@ | |||
65 | #define MMA8452_MAX_REG 0x31 | 82 | #define MMA8452_MAX_REG 0x31 |
66 | 83 | ||
67 | #define MMA8452_INT_DRDY BIT(0) | 84 | #define MMA8452_INT_DRDY BIT(0) |
85 | #define MMA8452_INT_FF_MT BIT(2) | ||
68 | #define MMA8452_INT_TRANS BIT(5) | 86 | #define MMA8452_INT_TRANS BIT(5) |
69 | 87 | ||
70 | #define MMA8452_DEVICE_ID 0x2a | 88 | #define MMA8452_DEVICE_ID 0x2a |
89 | #define MMA8453_DEVICE_ID 0x3a | ||
90 | #define MMA8652_DEVICE_ID 0x4a | ||
91 | #define MMA8653_DEVICE_ID 0x5a | ||
71 | 92 | ||
72 | struct mma8452_data { | 93 | struct mma8452_data { |
73 | struct i2c_client *client; | 94 | struct i2c_client *client; |
74 | struct mutex lock; | 95 | struct mutex lock; |
75 | u8 ctrl_reg1; | 96 | u8 ctrl_reg1; |
76 | u8 data_cfg; | 97 | u8 data_cfg; |
98 | const struct mma_chip_info *chip_info; | ||
99 | }; | ||
100 | |||
101 | /** | ||
102 | * struct mma_chip_info - chip specific data for Freescale's accelerometers | ||
103 | * @chip_id: WHO_AM_I register's value | ||
104 | * @channels: struct iio_chan_spec matching the device's | ||
105 | * capabilities | ||
106 | * @num_channels: number of channels | ||
107 | * @mma_scales: scale factors for converting register values | ||
108 | * to m/s^2; 3 modes: 2g, 4g, 8g; 2 integers | ||
109 | * per mode: m/s^2 and micro m/s^2 | ||
110 | * @ev_cfg: event config register address | ||
111 | * @ev_cfg_ele: latch bit in event config register | ||
112 | * @ev_cfg_chan_shift: number of the bit to enable events in X | ||
113 | * direction; in event config register | ||
114 | * @ev_src: event source register address | ||
115 | * @ev_src_xe: bit in event source register that indicates | ||
116 | * an event in X direction | ||
117 | * @ev_src_ye: bit in event source register that indicates | ||
118 | * an event in Y direction | ||
119 | * @ev_src_ze: bit in event source register that indicates | ||
120 | * an event in Z direction | ||
121 | * @ev_ths: event threshold register address | ||
122 | * @ev_ths_mask: mask for the threshold value | ||
123 | * @ev_count: event count (period) register address | ||
124 | * | ||
125 | * Since not all chips supported by the driver support comparing high pass | ||
126 | * filtered data for events (interrupts), different interrupt sources are | ||
127 | * used for different chips and the relevant registers are included here. | ||
128 | */ | ||
129 | struct mma_chip_info { | ||
130 | u8 chip_id; | ||
131 | const struct iio_chan_spec *channels; | ||
132 | int num_channels; | ||
133 | const int mma_scales[3][2]; | ||
134 | u8 ev_cfg; | ||
135 | u8 ev_cfg_ele; | ||
136 | u8 ev_cfg_chan_shift; | ||
137 | u8 ev_src; | ||
138 | u8 ev_src_xe; | ||
139 | u8 ev_src_ye; | ||
140 | u8 ev_src_ze; | ||
141 | u8 ev_ths; | ||
142 | u8 ev_ths_mask; | ||
143 | u8 ev_count; | ||
77 | }; | 144 | }; |
78 | 145 | ||
79 | static int mma8452_drdy(struct mma8452_data *data) | 146 | static int mma8452_drdy(struct mma8452_data *data) |
@@ -143,16 +210,6 @@ static const int mma8452_samp_freq[8][2] = { | |||
143 | {6, 250000}, {1, 560000} | 210 | {6, 250000}, {1, 560000} |
144 | }; | 211 | }; |
145 | 212 | ||
146 | /* | ||
147 | * Hardware has fullscale of -2G, -4G, -8G corresponding to raw value -2048 | ||
148 | * The userspace interface uses m/s^2 and we declare micro units | ||
149 | * So scale factor is given by: | ||
150 | * g * N * 1000000 / 2048 for N = 2, 4, 8 and g = 9.80665 | ||
151 | */ | ||
152 | static const int mma8452_scales[3][2] = { | ||
153 | {0, 9577}, {0, 19154}, {0, 38307} | ||
154 | }; | ||
155 | |||
156 | /* Datasheet table 35 (step time vs sample frequency) */ | 213 | /* Datasheet table 35 (step time vs sample frequency) */ |
157 | static const int mma8452_transient_time_step_us[8] = { | 214 | static const int mma8452_transient_time_step_us[8] = { |
158 | 1250, | 215 | 1250, |
@@ -189,8 +246,11 @@ static ssize_t mma8452_show_scale_avail(struct device *dev, | |||
189 | struct device_attribute *attr, | 246 | struct device_attribute *attr, |
190 | char *buf) | 247 | char *buf) |
191 | { | 248 | { |
192 | return mma8452_show_int_plus_micros(buf, mma8452_scales, | 249 | struct mma8452_data *data = iio_priv(i2c_get_clientdata( |
193 | ARRAY_SIZE(mma8452_scales)); | 250 | to_i2c_client(dev))); |
251 | |||
252 | return mma8452_show_int_plus_micros(buf, data->chip_info->mma_scales, | ||
253 | ARRAY_SIZE(data->chip_info->mma_scales)); | ||
194 | } | 254 | } |
195 | 255 | ||
196 | static ssize_t mma8452_show_hp_cutoff_avail(struct device *dev, | 256 | static ssize_t mma8452_show_hp_cutoff_avail(struct device *dev, |
@@ -221,9 +281,8 @@ static int mma8452_get_samp_freq_index(struct mma8452_data *data, | |||
221 | 281 | ||
222 | static int mma8452_get_scale_index(struct mma8452_data *data, int val, int val2) | 282 | static int mma8452_get_scale_index(struct mma8452_data *data, int val, int val2) |
223 | { | 283 | { |
224 | return mma8452_get_int_plus_micros_index(mma8452_scales, | 284 | return mma8452_get_int_plus_micros_index(data->chip_info->mma_scales, |
225 | ARRAY_SIZE(mma8452_scales), | 285 | ARRAY_SIZE(data->chip_info->mma_scales), val, val2); |
226 | val, val2); | ||
227 | } | 286 | } |
228 | 287 | ||
229 | static int mma8452_get_hp_filter_index(struct mma8452_data *data, | 288 | static int mma8452_get_hp_filter_index(struct mma8452_data *data, |
@@ -270,14 +329,15 @@ static int mma8452_read_raw(struct iio_dev *indio_dev, | |||
270 | if (ret < 0) | 329 | if (ret < 0) |
271 | return ret; | 330 | return ret; |
272 | 331 | ||
273 | *val = sign_extend32(be16_to_cpu(buffer[chan->scan_index]) >> 4, | 332 | *val = sign_extend32(be16_to_cpu( |
274 | 11); | 333 | buffer[chan->scan_index]) >> chan->scan_type.shift, |
334 | chan->scan_type.realbits - 1); | ||
275 | 335 | ||
276 | return IIO_VAL_INT; | 336 | return IIO_VAL_INT; |
277 | case IIO_CHAN_INFO_SCALE: | 337 | case IIO_CHAN_INFO_SCALE: |
278 | i = data->data_cfg & MMA8452_DATA_CFG_FS_MASK; | 338 | i = data->data_cfg & MMA8452_DATA_CFG_FS_MASK; |
279 | *val = mma8452_scales[i][0]; | 339 | *val = data->chip_info->mma_scales[i][0]; |
280 | *val2 = mma8452_scales[i][1]; | 340 | *val2 = data->chip_info->mma_scales[i][1]; |
281 | 341 | ||
282 | return IIO_VAL_INT_PLUS_MICRO; | 342 | return IIO_VAL_INT_PLUS_MICRO; |
283 | case IIO_CHAN_INFO_SAMP_FREQ: | 343 | case IIO_CHAN_INFO_SAMP_FREQ: |
@@ -439,17 +499,17 @@ static int mma8452_read_thresh(struct iio_dev *indio_dev, | |||
439 | switch (info) { | 499 | switch (info) { |
440 | case IIO_EV_INFO_VALUE: | 500 | case IIO_EV_INFO_VALUE: |
441 | ret = i2c_smbus_read_byte_data(data->client, | 501 | ret = i2c_smbus_read_byte_data(data->client, |
442 | MMA8452_TRANSIENT_THS); | 502 | data->chip_info->ev_ths); |
443 | if (ret < 0) | 503 | if (ret < 0) |
444 | return ret; | 504 | return ret; |
445 | 505 | ||
446 | *val = ret & MMA8452_TRANSIENT_THS_MASK; | 506 | *val = ret & data->chip_info->ev_ths_mask; |
447 | 507 | ||
448 | return IIO_VAL_INT; | 508 | return IIO_VAL_INT; |
449 | 509 | ||
450 | case IIO_EV_INFO_PERIOD: | 510 | case IIO_EV_INFO_PERIOD: |
451 | ret = i2c_smbus_read_byte_data(data->client, | 511 | ret = i2c_smbus_read_byte_data(data->client, |
452 | MMA8452_TRANSIENT_COUNT); | 512 | data->chip_info->ev_count); |
453 | if (ret < 0) | 513 | if (ret < 0) |
454 | return ret; | 514 | return ret; |
455 | 515 | ||
@@ -497,7 +557,8 @@ static int mma8452_write_thresh(struct iio_dev *indio_dev, | |||
497 | if (val < 0 || val > MMA8452_TRANSIENT_THS_MASK) | 557 | if (val < 0 || val > MMA8452_TRANSIENT_THS_MASK) |
498 | return -EINVAL; | 558 | return -EINVAL; |
499 | 559 | ||
500 | return mma8452_change_config(data, MMA8452_TRANSIENT_THS, val); | 560 | return mma8452_change_config(data, data->chip_info->ev_ths, |
561 | val); | ||
501 | 562 | ||
502 | case IIO_EV_INFO_PERIOD: | 563 | case IIO_EV_INFO_PERIOD: |
503 | steps = (val * USEC_PER_SEC + val2) / | 564 | steps = (val * USEC_PER_SEC + val2) / |
@@ -507,7 +568,7 @@ static int mma8452_write_thresh(struct iio_dev *indio_dev, | |||
507 | if (steps < 0 || steps > 0xff) | 568 | if (steps < 0 || steps > 0xff) |
508 | return -EINVAL; | 569 | return -EINVAL; |
509 | 570 | ||
510 | return mma8452_change_config(data, MMA8452_TRANSIENT_COUNT, | 571 | return mma8452_change_config(data, data->chip_info->ev_count, |
511 | steps); | 572 | steps); |
512 | 573 | ||
513 | case IIO_EV_INFO_HIGH_PASS_FILTER_3DB: | 574 | case IIO_EV_INFO_HIGH_PASS_FILTER_3DB: |
@@ -538,13 +599,15 @@ static int mma8452_read_event_config(struct iio_dev *indio_dev, | |||
538 | enum iio_event_direction dir) | 599 | enum iio_event_direction dir) |
539 | { | 600 | { |
540 | struct mma8452_data *data = iio_priv(indio_dev); | 601 | struct mma8452_data *data = iio_priv(indio_dev); |
602 | const struct mma_chip_info *chip = data->chip_info; | ||
541 | int ret; | 603 | int ret; |
542 | 604 | ||
543 | ret = i2c_smbus_read_byte_data(data->client, MMA8452_TRANSIENT_CFG); | 605 | ret = i2c_smbus_read_byte_data(data->client, |
606 | data->chip_info->ev_cfg); | ||
544 | if (ret < 0) | 607 | if (ret < 0) |
545 | return ret; | 608 | return ret; |
546 | 609 | ||
547 | return ret & MMA8452_TRANSIENT_CFG_CHAN(chan->scan_index) ? 1 : 0; | 610 | return !!(ret & BIT(chan->scan_index + chip->ev_cfg_chan_shift)); |
548 | } | 611 | } |
549 | 612 | ||
550 | static int mma8452_write_event_config(struct iio_dev *indio_dev, | 613 | static int mma8452_write_event_config(struct iio_dev *indio_dev, |
@@ -554,20 +617,22 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev, | |||
554 | int state) | 617 | int state) |
555 | { | 618 | { |
556 | struct mma8452_data *data = iio_priv(indio_dev); | 619 | struct mma8452_data *data = iio_priv(indio_dev); |
620 | const struct mma_chip_info *chip = data->chip_info; | ||
557 | int val; | 621 | int val; |
558 | 622 | ||
559 | val = i2c_smbus_read_byte_data(data->client, MMA8452_TRANSIENT_CFG); | 623 | val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg); |
560 | if (val < 0) | 624 | if (val < 0) |
561 | return val; | 625 | return val; |
562 | 626 | ||
563 | if (state) | 627 | if (state) |
564 | val |= MMA8452_TRANSIENT_CFG_CHAN(chan->scan_index); | 628 | val |= BIT(chan->scan_index + chip->ev_cfg_chan_shift); |
565 | else | 629 | else |
566 | val &= ~MMA8452_TRANSIENT_CFG_CHAN(chan->scan_index); | 630 | val &= ~BIT(chan->scan_index + chip->ev_cfg_chan_shift); |
567 | 631 | ||
568 | val |= MMA8452_TRANSIENT_CFG_ELE; | 632 | val |= chip->ev_cfg_ele; |
633 | val |= MMA8452_FF_MT_CFG_OAE; | ||
569 | 634 | ||
570 | return mma8452_change_config(data, MMA8452_TRANSIENT_CFG, val); | 635 | return mma8452_change_config(data, chip->ev_cfg, val); |
571 | } | 636 | } |
572 | 637 | ||
573 | static void mma8452_transient_interrupt(struct iio_dev *indio_dev) | 638 | static void mma8452_transient_interrupt(struct iio_dev *indio_dev) |
@@ -576,25 +641,25 @@ static void mma8452_transient_interrupt(struct iio_dev *indio_dev) | |||
576 | s64 ts = iio_get_time_ns(); | 641 | s64 ts = iio_get_time_ns(); |
577 | int src; | 642 | int src; |
578 | 643 | ||
579 | src = i2c_smbus_read_byte_data(data->client, MMA8452_TRANSIENT_SRC); | 644 | src = i2c_smbus_read_byte_data(data->client, data->chip_info->ev_src); |
580 | if (src < 0) | 645 | if (src < 0) |
581 | return; | 646 | return; |
582 | 647 | ||
583 | if (src & MMA8452_TRANSIENT_SRC_XTRANSE) | 648 | if (src & data->chip_info->ev_src_xe) |
584 | iio_push_event(indio_dev, | 649 | iio_push_event(indio_dev, |
585 | IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X, | 650 | IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X, |
586 | IIO_EV_TYPE_MAG, | 651 | IIO_EV_TYPE_MAG, |
587 | IIO_EV_DIR_RISING), | 652 | IIO_EV_DIR_RISING), |
588 | ts); | 653 | ts); |
589 | 654 | ||
590 | if (src & MMA8452_TRANSIENT_SRC_YTRANSE) | 655 | if (src & data->chip_info->ev_src_ye) |
591 | iio_push_event(indio_dev, | 656 | iio_push_event(indio_dev, |
592 | IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_Y, | 657 | IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_Y, |
593 | IIO_EV_TYPE_MAG, | 658 | IIO_EV_TYPE_MAG, |
594 | IIO_EV_DIR_RISING), | 659 | IIO_EV_DIR_RISING), |
595 | ts); | 660 | ts); |
596 | 661 | ||
597 | if (src & MMA8452_TRANSIENT_SRC_ZTRANSE) | 662 | if (src & data->chip_info->ev_src_ze) |
598 | iio_push_event(indio_dev, | 663 | iio_push_event(indio_dev, |
599 | IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_Z, | 664 | IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_Z, |
600 | IIO_EV_TYPE_MAG, | 665 | IIO_EV_TYPE_MAG, |
@@ -606,6 +671,7 @@ static irqreturn_t mma8452_interrupt(int irq, void *p) | |||
606 | { | 671 | { |
607 | struct iio_dev *indio_dev = p; | 672 | struct iio_dev *indio_dev = p; |
608 | struct mma8452_data *data = iio_priv(indio_dev); | 673 | struct mma8452_data *data = iio_priv(indio_dev); |
674 | const struct mma_chip_info *chip = data->chip_info; | ||
609 | int ret = IRQ_NONE; | 675 | int ret = IRQ_NONE; |
610 | int src; | 676 | int src; |
611 | 677 | ||
@@ -618,7 +684,10 @@ static irqreturn_t mma8452_interrupt(int irq, void *p) | |||
618 | ret = IRQ_HANDLED; | 684 | ret = IRQ_HANDLED; |
619 | } | 685 | } |
620 | 686 | ||
621 | if (src & MMA8452_INT_TRANS) { | 687 | if ((src & MMA8452_INT_TRANS && |
688 | chip->ev_src == MMA8452_TRANSIENT_SRC) || | ||
689 | (src & MMA8452_INT_FF_MT && | ||
690 | chip->ev_src == MMA8452_FF_MT_SRC)) { | ||
622 | mma8452_transient_interrupt(indio_dev); | 691 | mma8452_transient_interrupt(indio_dev); |
623 | ret = IRQ_HANDLED; | 692 | ret = IRQ_HANDLED; |
624 | } | 693 | } |
@@ -680,6 +749,16 @@ static const struct iio_event_spec mma8452_transient_event[] = { | |||
680 | }, | 749 | }, |
681 | }; | 750 | }; |
682 | 751 | ||
752 | static const struct iio_event_spec mma8452_motion_event[] = { | ||
753 | { | ||
754 | .type = IIO_EV_TYPE_MAG, | ||
755 | .dir = IIO_EV_DIR_RISING, | ||
756 | .mask_separate = BIT(IIO_EV_INFO_ENABLE), | ||
757 | .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | | ||
758 | BIT(IIO_EV_INFO_PERIOD) | ||
759 | }, | ||
760 | }; | ||
761 | |||
683 | /* | 762 | /* |
684 | * Threshold is configured in fixed 8G/127 steps regardless of | 763 | * Threshold is configured in fixed 8G/127 steps regardless of |
685 | * currently selected scale for measurement. | 764 | * currently selected scale for measurement. |
@@ -693,10 +772,9 @@ static struct attribute *mma8452_event_attributes[] = { | |||
693 | 772 | ||
694 | static struct attribute_group mma8452_event_attribute_group = { | 773 | static struct attribute_group mma8452_event_attribute_group = { |
695 | .attrs = mma8452_event_attributes, | 774 | .attrs = mma8452_event_attributes, |
696 | .name = "events", | ||
697 | }; | 775 | }; |
698 | 776 | ||
699 | #define MMA8452_CHANNEL(axis, idx) { \ | 777 | #define MMA8452_CHANNEL(axis, idx, bits) { \ |
700 | .type = IIO_ACCEL, \ | 778 | .type = IIO_ACCEL, \ |
701 | .modified = 1, \ | 779 | .modified = 1, \ |
702 | .channel2 = IIO_MOD_##axis, \ | 780 | .channel2 = IIO_MOD_##axis, \ |
@@ -708,22 +786,144 @@ static struct attribute_group mma8452_event_attribute_group = { | |||
708 | .scan_index = idx, \ | 786 | .scan_index = idx, \ |
709 | .scan_type = { \ | 787 | .scan_type = { \ |
710 | .sign = 's', \ | 788 | .sign = 's', \ |
711 | .realbits = 12, \ | 789 | .realbits = (bits), \ |
712 | .storagebits = 16, \ | 790 | .storagebits = 16, \ |
713 | .shift = 4, \ | 791 | .shift = 16 - (bits), \ |
714 | .endianness = IIO_BE, \ | 792 | .endianness = IIO_BE, \ |
715 | }, \ | 793 | }, \ |
716 | .event_spec = mma8452_transient_event, \ | 794 | .event_spec = mma8452_transient_event, \ |
717 | .num_event_specs = ARRAY_SIZE(mma8452_transient_event), \ | 795 | .num_event_specs = ARRAY_SIZE(mma8452_transient_event), \ |
718 | } | 796 | } |
719 | 797 | ||
798 | #define MMA8652_CHANNEL(axis, idx, bits) { \ | ||
799 | .type = IIO_ACCEL, \ | ||
800 | .modified = 1, \ | ||
801 | .channel2 = IIO_MOD_##axis, \ | ||
802 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | ||
803 | BIT(IIO_CHAN_INFO_CALIBBIAS), \ | ||
804 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ | ||
805 | BIT(IIO_CHAN_INFO_SCALE), \ | ||
806 | .scan_index = idx, \ | ||
807 | .scan_type = { \ | ||
808 | .sign = 's', \ | ||
809 | .realbits = (bits), \ | ||
810 | .storagebits = 16, \ | ||
811 | .shift = 16 - (bits), \ | ||
812 | .endianness = IIO_BE, \ | ||
813 | }, \ | ||
814 | .event_spec = mma8452_motion_event, \ | ||
815 | .num_event_specs = ARRAY_SIZE(mma8452_motion_event), \ | ||
816 | } | ||
817 | |||
720 | static const struct iio_chan_spec mma8452_channels[] = { | 818 | static const struct iio_chan_spec mma8452_channels[] = { |
721 | MMA8452_CHANNEL(X, 0), | 819 | MMA8452_CHANNEL(X, 0, 12), |
722 | MMA8452_CHANNEL(Y, 1), | 820 | MMA8452_CHANNEL(Y, 1, 12), |
723 | MMA8452_CHANNEL(Z, 2), | 821 | MMA8452_CHANNEL(Z, 2, 12), |
724 | IIO_CHAN_SOFT_TIMESTAMP(3), | 822 | IIO_CHAN_SOFT_TIMESTAMP(3), |
725 | }; | 823 | }; |
726 | 824 | ||
825 | static const struct iio_chan_spec mma8453_channels[] = { | ||
826 | MMA8452_CHANNEL(X, 0, 10), | ||
827 | MMA8452_CHANNEL(Y, 1, 10), | ||
828 | MMA8452_CHANNEL(Z, 2, 10), | ||
829 | IIO_CHAN_SOFT_TIMESTAMP(3), | ||
830 | }; | ||
831 | |||
832 | static const struct iio_chan_spec mma8652_channels[] = { | ||
833 | MMA8652_CHANNEL(X, 0, 12), | ||
834 | MMA8652_CHANNEL(Y, 1, 12), | ||
835 | MMA8652_CHANNEL(Z, 2, 12), | ||
836 | IIO_CHAN_SOFT_TIMESTAMP(3), | ||
837 | }; | ||
838 | |||
839 | static const struct iio_chan_spec mma8653_channels[] = { | ||
840 | MMA8652_CHANNEL(X, 0, 10), | ||
841 | MMA8652_CHANNEL(Y, 1, 10), | ||
842 | MMA8652_CHANNEL(Z, 2, 10), | ||
843 | IIO_CHAN_SOFT_TIMESTAMP(3), | ||
844 | }; | ||
845 | |||
846 | enum { | ||
847 | mma8452, | ||
848 | mma8453, | ||
849 | mma8652, | ||
850 | mma8653, | ||
851 | }; | ||
852 | |||
853 | static const struct mma_chip_info mma_chip_info_table[] = { | ||
854 | [mma8452] = { | ||
855 | .chip_id = MMA8452_DEVICE_ID, | ||
856 | .channels = mma8452_channels, | ||
857 | .num_channels = ARRAY_SIZE(mma8452_channels), | ||
858 | /* | ||
859 | * Hardware has fullscale of -2G, -4G, -8G corresponding to | ||
860 | * raw value -2048 for 12 bit or -512 for 10 bit. | ||
861 | * The userspace interface uses m/s^2 and we declare micro units | ||
862 | * So scale factor for 12 bit here is given by: | ||
863 | * g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665 | ||
864 | */ | ||
865 | .mma_scales = { {0, 9577}, {0, 19154}, {0, 38307} }, | ||
866 | .ev_cfg = MMA8452_TRANSIENT_CFG, | ||
867 | .ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE, | ||
868 | .ev_cfg_chan_shift = 1, | ||
869 | .ev_src = MMA8452_TRANSIENT_SRC, | ||
870 | .ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE, | ||
871 | .ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE, | ||
872 | .ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE, | ||
873 | .ev_ths = MMA8452_TRANSIENT_THS, | ||
874 | .ev_ths_mask = MMA8452_TRANSIENT_THS_MASK, | ||
875 | .ev_count = MMA8452_TRANSIENT_COUNT, | ||
876 | }, | ||
877 | [mma8453] = { | ||
878 | .chip_id = MMA8453_DEVICE_ID, | ||
879 | .channels = mma8453_channels, | ||
880 | .num_channels = ARRAY_SIZE(mma8453_channels), | ||
881 | .mma_scales = { {0, 38307}, {0, 76614}, {0, 153228} }, | ||
882 | .ev_cfg = MMA8452_TRANSIENT_CFG, | ||
883 | .ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE, | ||
884 | .ev_cfg_chan_shift = 1, | ||
885 | .ev_src = MMA8452_TRANSIENT_SRC, | ||
886 | .ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE, | ||
887 | .ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE, | ||
888 | .ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE, | ||
889 | .ev_ths = MMA8452_TRANSIENT_THS, | ||
890 | .ev_ths_mask = MMA8452_TRANSIENT_THS_MASK, | ||
891 | .ev_count = MMA8452_TRANSIENT_COUNT, | ||
892 | }, | ||
893 | [mma8652] = { | ||
894 | .chip_id = MMA8652_DEVICE_ID, | ||
895 | .channels = mma8652_channels, | ||
896 | .num_channels = ARRAY_SIZE(mma8652_channels), | ||
897 | .mma_scales = { {0, 9577}, {0, 19154}, {0, 38307} }, | ||
898 | .ev_cfg = MMA8452_FF_MT_CFG, | ||
899 | .ev_cfg_ele = MMA8452_FF_MT_CFG_ELE, | ||
900 | .ev_cfg_chan_shift = 3, | ||
901 | .ev_src = MMA8452_FF_MT_SRC, | ||
902 | .ev_src_xe = MMA8452_FF_MT_SRC_XHE, | ||
903 | .ev_src_ye = MMA8452_FF_MT_SRC_YHE, | ||
904 | .ev_src_ze = MMA8452_FF_MT_SRC_ZHE, | ||
905 | .ev_ths = MMA8452_FF_MT_THS, | ||
906 | .ev_ths_mask = MMA8452_FF_MT_THS_MASK, | ||
907 | .ev_count = MMA8452_FF_MT_COUNT, | ||
908 | }, | ||
909 | [mma8653] = { | ||
910 | .chip_id = MMA8653_DEVICE_ID, | ||
911 | .channels = mma8653_channels, | ||
912 | .num_channels = ARRAY_SIZE(mma8653_channels), | ||
913 | .mma_scales = { {0, 38307}, {0, 76614}, {0, 153228} }, | ||
914 | .ev_cfg = MMA8452_FF_MT_CFG, | ||
915 | .ev_cfg_ele = MMA8452_FF_MT_CFG_ELE, | ||
916 | .ev_cfg_chan_shift = 3, | ||
917 | .ev_src = MMA8452_FF_MT_SRC, | ||
918 | .ev_src_xe = MMA8452_FF_MT_SRC_XHE, | ||
919 | .ev_src_ye = MMA8452_FF_MT_SRC_YHE, | ||
920 | .ev_src_ze = MMA8452_FF_MT_SRC_ZHE, | ||
921 | .ev_ths = MMA8452_FF_MT_THS, | ||
922 | .ev_ths_mask = MMA8452_FF_MT_THS_MASK, | ||
923 | .ev_count = MMA8452_FF_MT_COUNT, | ||
924 | }, | ||
925 | }; | ||
926 | |||
727 | static struct attribute *mma8452_attributes[] = { | 927 | static struct attribute *mma8452_attributes[] = { |
728 | &iio_dev_attr_sampling_frequency_available.dev_attr.attr, | 928 | &iio_dev_attr_sampling_frequency_available.dev_attr.attr, |
729 | &iio_dev_attr_in_accel_scale_available.dev_attr.attr, | 929 | &iio_dev_attr_in_accel_scale_available.dev_attr.attr, |
@@ -841,18 +1041,28 @@ static int mma8452_reset(struct i2c_client *client) | |||
841 | return -ETIMEDOUT; | 1041 | return -ETIMEDOUT; |
842 | } | 1042 | } |
843 | 1043 | ||
1044 | static const struct of_device_id mma8452_dt_ids[] = { | ||
1045 | { .compatible = "fsl,mma8452", .data = &mma_chip_info_table[mma8452] }, | ||
1046 | { .compatible = "fsl,mma8453", .data = &mma_chip_info_table[mma8453] }, | ||
1047 | { .compatible = "fsl,mma8652", .data = &mma_chip_info_table[mma8652] }, | ||
1048 | { .compatible = "fsl,mma8653", .data = &mma_chip_info_table[mma8653] }, | ||
1049 | { } | ||
1050 | }; | ||
1051 | MODULE_DEVICE_TABLE(of, mma8452_dt_ids); | ||
1052 | |||
844 | static int mma8452_probe(struct i2c_client *client, | 1053 | static int mma8452_probe(struct i2c_client *client, |
845 | const struct i2c_device_id *id) | 1054 | const struct i2c_device_id *id) |
846 | { | 1055 | { |
847 | struct mma8452_data *data; | 1056 | struct mma8452_data *data; |
848 | struct iio_dev *indio_dev; | 1057 | struct iio_dev *indio_dev; |
849 | int ret; | 1058 | int ret; |
1059 | const struct of_device_id *match; | ||
850 | 1060 | ||
851 | ret = i2c_smbus_read_byte_data(client, MMA8452_WHO_AM_I); | 1061 | match = of_match_device(mma8452_dt_ids, &client->dev); |
852 | if (ret < 0) | 1062 | if (!match) { |
853 | return ret; | 1063 | dev_err(&client->dev, "unknown device model\n"); |
854 | if (ret != MMA8452_DEVICE_ID) | ||
855 | return -ENODEV; | 1064 | return -ENODEV; |
1065 | } | ||
856 | 1066 | ||
857 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | 1067 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); |
858 | if (!indio_dev) | 1068 | if (!indio_dev) |
@@ -861,14 +1071,33 @@ static int mma8452_probe(struct i2c_client *client, | |||
861 | data = iio_priv(indio_dev); | 1071 | data = iio_priv(indio_dev); |
862 | data->client = client; | 1072 | data->client = client; |
863 | mutex_init(&data->lock); | 1073 | mutex_init(&data->lock); |
1074 | data->chip_info = match->data; | ||
1075 | |||
1076 | ret = i2c_smbus_read_byte_data(client, MMA8452_WHO_AM_I); | ||
1077 | if (ret < 0) | ||
1078 | return ret; | ||
1079 | |||
1080 | switch (ret) { | ||
1081 | case MMA8452_DEVICE_ID: | ||
1082 | case MMA8453_DEVICE_ID: | ||
1083 | case MMA8652_DEVICE_ID: | ||
1084 | case MMA8653_DEVICE_ID: | ||
1085 | if (ret == data->chip_info->chip_id) | ||
1086 | break; | ||
1087 | default: | ||
1088 | return -ENODEV; | ||
1089 | } | ||
1090 | |||
1091 | dev_info(&client->dev, "registering %s accelerometer; ID 0x%x\n", | ||
1092 | match->compatible, data->chip_info->chip_id); | ||
864 | 1093 | ||
865 | i2c_set_clientdata(client, indio_dev); | 1094 | i2c_set_clientdata(client, indio_dev); |
866 | indio_dev->info = &mma8452_info; | 1095 | indio_dev->info = &mma8452_info; |
867 | indio_dev->name = id->name; | 1096 | indio_dev->name = id->name; |
868 | indio_dev->dev.parent = &client->dev; | 1097 | indio_dev->dev.parent = &client->dev; |
869 | indio_dev->modes = INDIO_DIRECT_MODE; | 1098 | indio_dev->modes = INDIO_DIRECT_MODE; |
870 | indio_dev->channels = mma8452_channels; | 1099 | indio_dev->channels = data->chip_info->channels; |
871 | indio_dev->num_channels = ARRAY_SIZE(mma8452_channels); | 1100 | indio_dev->num_channels = data->chip_info->num_channels; |
872 | indio_dev->available_scan_masks = mma8452_scan_masks; | 1101 | indio_dev->available_scan_masks = mma8452_scan_masks; |
873 | 1102 | ||
874 | ret = mma8452_reset(client); | 1103 | ret = mma8452_reset(client); |
@@ -892,13 +1121,15 @@ static int mma8452_probe(struct i2c_client *client, | |||
892 | 1121 | ||
893 | if (client->irq) { | 1122 | if (client->irq) { |
894 | /* | 1123 | /* |
895 | * Although we enable the transient interrupt source once and | 1124 | * Although we enable the interrupt sources once and for |
896 | * for all here the transient event detection itself is not | 1125 | * all here the event detection itself is not enabled until |
897 | * enabled until userspace asks for it by | 1126 | * userspace asks for it by mma8452_write_event_config() |
898 | * mma8452_write_event_config() | ||
899 | */ | 1127 | */ |
900 | int supported_interrupts = MMA8452_INT_DRDY | MMA8452_INT_TRANS; | 1128 | int supported_interrupts = MMA8452_INT_DRDY | |
901 | int enabled_interrupts = MMA8452_INT_TRANS; | 1129 | MMA8452_INT_TRANS | |
1130 | MMA8452_INT_FF_MT; | ||
1131 | int enabled_interrupts = MMA8452_INT_TRANS | | ||
1132 | MMA8452_INT_FF_MT; | ||
902 | 1133 | ||
903 | /* Assume wired to INT1 pin */ | 1134 | /* Assume wired to INT1 pin */ |
904 | ret = i2c_smbus_write_byte_data(client, | 1135 | ret = i2c_smbus_write_byte_data(client, |
@@ -987,17 +1218,14 @@ static SIMPLE_DEV_PM_OPS(mma8452_pm_ops, mma8452_suspend, mma8452_resume); | |||
987 | #endif | 1218 | #endif |
988 | 1219 | ||
989 | static const struct i2c_device_id mma8452_id[] = { | 1220 | static const struct i2c_device_id mma8452_id[] = { |
990 | { "mma8452", 0 }, | 1221 | { "mma8452", mma8452 }, |
1222 | { "mma8453", mma8453 }, | ||
1223 | { "mma8652", mma8652 }, | ||
1224 | { "mma8653", mma8653 }, | ||
991 | { } | 1225 | { } |
992 | }; | 1226 | }; |
993 | MODULE_DEVICE_TABLE(i2c, mma8452_id); | 1227 | MODULE_DEVICE_TABLE(i2c, mma8452_id); |
994 | 1228 | ||
995 | static const struct of_device_id mma8452_dt_ids[] = { | ||
996 | { .compatible = "fsl,mma8452" }, | ||
997 | { } | ||
998 | }; | ||
999 | MODULE_DEVICE_TABLE(of, mma8452_dt_ids); | ||
1000 | |||
1001 | static struct i2c_driver mma8452_driver = { | 1229 | static struct i2c_driver mma8452_driver = { |
1002 | .driver = { | 1230 | .driver = { |
1003 | .name = "mma8452", | 1231 | .name = "mma8452", |
diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c new file mode 100644 index 000000000000..e72e218c2696 --- /dev/null +++ b/drivers/iio/accel/mxc4005.c | |||
@@ -0,0 +1,567 @@ | |||
1 | /* | ||
2 | * 3-axis accelerometer driver for MXC4005XC Memsic sensor | ||
3 | * | ||
4 | * Copyright (c) 2014, Intel Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/iio/iio.h> | ||
19 | #include <linux/acpi.h> | ||
20 | #include <linux/gpio/consumer.h> | ||
21 | #include <linux/regmap.h> | ||
22 | #include <linux/iio/sysfs.h> | ||
23 | #include <linux/iio/trigger.h> | ||
24 | #include <linux/iio/buffer.h> | ||
25 | #include <linux/iio/triggered_buffer.h> | ||
26 | #include <linux/iio/trigger_consumer.h> | ||
27 | |||
28 | #define MXC4005_DRV_NAME "mxc4005" | ||
29 | #define MXC4005_IRQ_NAME "mxc4005_event" | ||
30 | #define MXC4005_REGMAP_NAME "mxc4005_regmap" | ||
31 | |||
32 | #define MXC4005_REG_XOUT_UPPER 0x03 | ||
33 | #define MXC4005_REG_XOUT_LOWER 0x04 | ||
34 | #define MXC4005_REG_YOUT_UPPER 0x05 | ||
35 | #define MXC4005_REG_YOUT_LOWER 0x06 | ||
36 | #define MXC4005_REG_ZOUT_UPPER 0x07 | ||
37 | #define MXC4005_REG_ZOUT_LOWER 0x08 | ||
38 | |||
39 | #define MXC4005_REG_INT_MASK1 0x0B | ||
40 | #define MXC4005_REG_INT_MASK1_BIT_DRDYE 0x01 | ||
41 | |||
42 | #define MXC4005_REG_INT_CLR1 0x01 | ||
43 | #define MXC4005_REG_INT_CLR1_BIT_DRDYC 0x01 | ||
44 | |||
45 | #define MXC4005_REG_CONTROL 0x0D | ||
46 | #define MXC4005_REG_CONTROL_MASK_FSR GENMASK(6, 5) | ||
47 | #define MXC4005_CONTROL_FSR_SHIFT 5 | ||
48 | |||
49 | #define MXC4005_REG_DEVICE_ID 0x0E | ||
50 | |||
51 | enum mxc4005_axis { | ||
52 | AXIS_X, | ||
53 | AXIS_Y, | ||
54 | AXIS_Z, | ||
55 | }; | ||
56 | |||
57 | enum mxc4005_range { | ||
58 | MXC4005_RANGE_2G, | ||
59 | MXC4005_RANGE_4G, | ||
60 | MXC4005_RANGE_8G, | ||
61 | }; | ||
62 | |||
63 | struct mxc4005_data { | ||
64 | struct device *dev; | ||
65 | struct mutex mutex; | ||
66 | struct regmap *regmap; | ||
67 | struct iio_trigger *dready_trig; | ||
68 | __be16 buffer[8]; | ||
69 | bool trigger_enabled; | ||
70 | }; | ||
71 | |||
72 | /* | ||
73 | * MXC4005 can operate in the following ranges: | ||
74 | * +/- 2G, 4G, 8G (the default +/-2G) | ||
75 | * | ||
76 | * (2 + 2) * 9.81 / (2^12 - 1) = 0.009582 | ||
77 | * (4 + 4) * 9.81 / (2^12 - 1) = 0.019164 | ||
78 | * (8 + 8) * 9.81 / (2^12 - 1) = 0.038329 | ||
79 | */ | ||
80 | static const struct { | ||
81 | u8 range; | ||
82 | int scale; | ||
83 | } mxc4005_scale_table[] = { | ||
84 | {MXC4005_RANGE_2G, 9582}, | ||
85 | {MXC4005_RANGE_4G, 19164}, | ||
86 | {MXC4005_RANGE_8G, 38329}, | ||
87 | }; | ||
88 | |||
89 | |||
90 | static IIO_CONST_ATTR(in_accel_scale_available, "0.009582 0.019164 0.038329"); | ||
91 | |||
92 | static struct attribute *mxc4005_attributes[] = { | ||
93 | &iio_const_attr_in_accel_scale_available.dev_attr.attr, | ||
94 | NULL, | ||
95 | }; | ||
96 | |||
97 | static const struct attribute_group mxc4005_attrs_group = { | ||
98 | .attrs = mxc4005_attributes, | ||
99 | }; | ||
100 | |||
101 | static bool mxc4005_is_readable_reg(struct device *dev, unsigned int reg) | ||
102 | { | ||
103 | switch (reg) { | ||
104 | case MXC4005_REG_XOUT_UPPER: | ||
105 | case MXC4005_REG_XOUT_LOWER: | ||
106 | case MXC4005_REG_YOUT_UPPER: | ||
107 | case MXC4005_REG_YOUT_LOWER: | ||
108 | case MXC4005_REG_ZOUT_UPPER: | ||
109 | case MXC4005_REG_ZOUT_LOWER: | ||
110 | case MXC4005_REG_DEVICE_ID: | ||
111 | case MXC4005_REG_CONTROL: | ||
112 | return true; | ||
113 | default: | ||
114 | return false; | ||
115 | } | ||
116 | } | ||
117 | |||
118 | static bool mxc4005_is_writeable_reg(struct device *dev, unsigned int reg) | ||
119 | { | ||
120 | switch (reg) { | ||
121 | case MXC4005_REG_INT_CLR1: | ||
122 | case MXC4005_REG_INT_MASK1: | ||
123 | case MXC4005_REG_CONTROL: | ||
124 | return true; | ||
125 | default: | ||
126 | return false; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | static const struct regmap_config mxc4005_regmap_config = { | ||
131 | .name = MXC4005_REGMAP_NAME, | ||
132 | |||
133 | .reg_bits = 8, | ||
134 | .val_bits = 8, | ||
135 | |||
136 | .max_register = MXC4005_REG_DEVICE_ID, | ||
137 | |||
138 | .readable_reg = mxc4005_is_readable_reg, | ||
139 | .writeable_reg = mxc4005_is_writeable_reg, | ||
140 | }; | ||
141 | |||
142 | static int mxc4005_read_xyz(struct mxc4005_data *data) | ||
143 | { | ||
144 | int ret; | ||
145 | |||
146 | ret = regmap_bulk_read(data->regmap, MXC4005_REG_XOUT_UPPER, | ||
147 | (u8 *) data->buffer, sizeof(data->buffer)); | ||
148 | if (ret < 0) { | ||
149 | dev_err(data->dev, "failed to read axes\n"); | ||
150 | return ret; | ||
151 | } | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static int mxc4005_read_axis(struct mxc4005_data *data, | ||
157 | unsigned int addr) | ||
158 | { | ||
159 | __be16 reg; | ||
160 | int ret; | ||
161 | |||
162 | ret = regmap_bulk_read(data->regmap, addr, (u8 *) ®, sizeof(reg)); | ||
163 | if (ret < 0) { | ||
164 | dev_err(data->dev, "failed to read reg %02x\n", addr); | ||
165 | return ret; | ||
166 | } | ||
167 | |||
168 | return be16_to_cpu(reg); | ||
169 | } | ||
170 | |||
171 | static int mxc4005_read_scale(struct mxc4005_data *data) | ||
172 | { | ||
173 | unsigned int reg; | ||
174 | int ret; | ||
175 | int i; | ||
176 | |||
177 | ret = regmap_read(data->regmap, MXC4005_REG_CONTROL, ®); | ||
178 | if (ret < 0) { | ||
179 | dev_err(data->dev, "failed to read reg_control\n"); | ||
180 | return ret; | ||
181 | } | ||
182 | |||
183 | i = reg >> MXC4005_CONTROL_FSR_SHIFT; | ||
184 | |||
185 | if (i < 0 || i >= ARRAY_SIZE(mxc4005_scale_table)) | ||
186 | return -EINVAL; | ||
187 | |||
188 | return mxc4005_scale_table[i].scale; | ||
189 | } | ||
190 | |||
191 | static int mxc4005_set_scale(struct mxc4005_data *data, int val) | ||
192 | { | ||
193 | unsigned int reg; | ||
194 | int i; | ||
195 | int ret; | ||
196 | |||
197 | for (i = 0; i < ARRAY_SIZE(mxc4005_scale_table); i++) { | ||
198 | if (mxc4005_scale_table[i].scale == val) { | ||
199 | reg = i << MXC4005_CONTROL_FSR_SHIFT; | ||
200 | ret = regmap_update_bits(data->regmap, | ||
201 | MXC4005_REG_CONTROL, | ||
202 | MXC4005_REG_CONTROL_MASK_FSR, | ||
203 | reg); | ||
204 | if (ret < 0) | ||
205 | dev_err(data->dev, | ||
206 | "failed to write reg_control\n"); | ||
207 | return ret; | ||
208 | } | ||
209 | } | ||
210 | |||
211 | return -EINVAL; | ||
212 | } | ||
213 | |||
214 | static int mxc4005_read_raw(struct iio_dev *indio_dev, | ||
215 | struct iio_chan_spec const *chan, | ||
216 | int *val, int *val2, long mask) | ||
217 | { | ||
218 | struct mxc4005_data *data = iio_priv(indio_dev); | ||
219 | int ret; | ||
220 | |||
221 | switch (mask) { | ||
222 | case IIO_CHAN_INFO_RAW: | ||
223 | switch (chan->type) { | ||
224 | case IIO_ACCEL: | ||
225 | if (iio_buffer_enabled(indio_dev)) | ||
226 | return -EBUSY; | ||
227 | |||
228 | ret = mxc4005_read_axis(data, chan->address); | ||
229 | if (ret < 0) | ||
230 | return ret; | ||
231 | *val = sign_extend32(ret >> chan->scan_type.shift, | ||
232 | chan->scan_type.realbits - 1); | ||
233 | return IIO_VAL_INT; | ||
234 | default: | ||
235 | return -EINVAL; | ||
236 | } | ||
237 | case IIO_CHAN_INFO_SCALE: | ||
238 | ret = mxc4005_read_scale(data); | ||
239 | if (ret < 0) | ||
240 | return ret; | ||
241 | |||
242 | *val = 0; | ||
243 | *val2 = ret; | ||
244 | return IIO_VAL_INT_PLUS_MICRO; | ||
245 | default: | ||
246 | return -EINVAL; | ||
247 | } | ||
248 | } | ||
249 | |||
250 | static int mxc4005_write_raw(struct iio_dev *indio_dev, | ||
251 | struct iio_chan_spec const *chan, | ||
252 | int val, int val2, long mask) | ||
253 | { | ||
254 | struct mxc4005_data *data = iio_priv(indio_dev); | ||
255 | |||
256 | switch (mask) { | ||
257 | case IIO_CHAN_INFO_SCALE: | ||
258 | if (val != 0) | ||
259 | return -EINVAL; | ||
260 | |||
261 | return mxc4005_set_scale(data, val2); | ||
262 | default: | ||
263 | return -EINVAL; | ||
264 | } | ||
265 | } | ||
266 | |||
267 | static const struct iio_info mxc4005_info = { | ||
268 | .driver_module = THIS_MODULE, | ||
269 | .read_raw = mxc4005_read_raw, | ||
270 | .write_raw = mxc4005_write_raw, | ||
271 | .attrs = &mxc4005_attrs_group, | ||
272 | }; | ||
273 | |||
274 | static const unsigned long mxc4005_scan_masks[] = { | ||
275 | BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z), | ||
276 | 0 | ||
277 | }; | ||
278 | |||
279 | #define MXC4005_CHANNEL(_axis, _addr) { \ | ||
280 | .type = IIO_ACCEL, \ | ||
281 | .modified = 1, \ | ||
282 | .channel2 = IIO_MOD_##_axis, \ | ||
283 | .address = _addr, \ | ||
284 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | ||
285 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ | ||
286 | .scan_index = AXIS_##_axis, \ | ||
287 | .scan_type = { \ | ||
288 | .sign = 's', \ | ||
289 | .realbits = 12, \ | ||
290 | .storagebits = 16, \ | ||
291 | .shift = 4, \ | ||
292 | .endianness = IIO_BE, \ | ||
293 | }, \ | ||
294 | } | ||
295 | |||
296 | static const struct iio_chan_spec mxc4005_channels[] = { | ||
297 | MXC4005_CHANNEL(X, MXC4005_REG_XOUT_UPPER), | ||
298 | MXC4005_CHANNEL(Y, MXC4005_REG_YOUT_UPPER), | ||
299 | MXC4005_CHANNEL(Z, MXC4005_REG_ZOUT_UPPER), | ||
300 | IIO_CHAN_SOFT_TIMESTAMP(3), | ||
301 | }; | ||
302 | |||
303 | static irqreturn_t mxc4005_trigger_handler(int irq, void *private) | ||
304 | { | ||
305 | struct iio_poll_func *pf = private; | ||
306 | struct iio_dev *indio_dev = pf->indio_dev; | ||
307 | struct mxc4005_data *data = iio_priv(indio_dev); | ||
308 | int ret; | ||
309 | |||
310 | ret = mxc4005_read_xyz(data); | ||
311 | if (ret < 0) | ||
312 | goto err; | ||
313 | |||
314 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | ||
315 | pf->timestamp); | ||
316 | |||
317 | err: | ||
318 | iio_trigger_notify_done(indio_dev->trig); | ||
319 | |||
320 | return IRQ_HANDLED; | ||
321 | } | ||
322 | |||
323 | static int mxc4005_clr_intr(struct mxc4005_data *data) | ||
324 | { | ||
325 | int ret; | ||
326 | |||
327 | /* clear interrupt */ | ||
328 | ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1, | ||
329 | MXC4005_REG_INT_CLR1_BIT_DRDYC); | ||
330 | if (ret < 0) { | ||
331 | dev_err(data->dev, "failed to write to reg_int_clr1\n"); | ||
332 | return ret; | ||
333 | } | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static int mxc4005_set_trigger_state(struct iio_trigger *trig, | ||
339 | bool state) | ||
340 | { | ||
341 | struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); | ||
342 | struct mxc4005_data *data = iio_priv(indio_dev); | ||
343 | int ret; | ||
344 | |||
345 | mutex_lock(&data->mutex); | ||
346 | if (state) { | ||
347 | ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, | ||
348 | MXC4005_REG_INT_MASK1_BIT_DRDYE); | ||
349 | } else { | ||
350 | ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, | ||
351 | ~MXC4005_REG_INT_MASK1_BIT_DRDYE); | ||
352 | } | ||
353 | |||
354 | if (ret < 0) { | ||
355 | mutex_unlock(&data->mutex); | ||
356 | dev_err(data->dev, "failed to update reg_int_mask1"); | ||
357 | return ret; | ||
358 | } | ||
359 | |||
360 | data->trigger_enabled = state; | ||
361 | mutex_unlock(&data->mutex); | ||
362 | |||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | static int mxc4005_trigger_try_reen(struct iio_trigger *trig) | ||
367 | { | ||
368 | struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); | ||
369 | struct mxc4005_data *data = iio_priv(indio_dev); | ||
370 | |||
371 | if (!data->dready_trig) | ||
372 | return 0; | ||
373 | |||
374 | return mxc4005_clr_intr(data); | ||
375 | } | ||
376 | |||
377 | static const struct iio_trigger_ops mxc4005_trigger_ops = { | ||
378 | .set_trigger_state = mxc4005_set_trigger_state, | ||
379 | .try_reenable = mxc4005_trigger_try_reen, | ||
380 | .owner = THIS_MODULE, | ||
381 | }; | ||
382 | |||
383 | static int mxc4005_gpio_probe(struct i2c_client *client, | ||
384 | struct mxc4005_data *data) | ||
385 | { | ||
386 | struct device *dev; | ||
387 | struct gpio_desc *gpio; | ||
388 | int ret; | ||
389 | |||
390 | if (!client) | ||
391 | return -EINVAL; | ||
392 | |||
393 | dev = &client->dev; | ||
394 | |||
395 | gpio = devm_gpiod_get_index(dev, "mxc4005_int", 0, GPIOD_IN); | ||
396 | if (IS_ERR(gpio)) { | ||
397 | dev_err(dev, "failed to get acpi gpio index\n"); | ||
398 | return PTR_ERR(gpio); | ||
399 | } | ||
400 | |||
401 | ret = gpiod_to_irq(gpio); | ||
402 | |||
403 | dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); | ||
404 | |||
405 | return ret; | ||
406 | } | ||
407 | |||
408 | static int mxc4005_chip_init(struct mxc4005_data *data) | ||
409 | { | ||
410 | int ret; | ||
411 | unsigned int reg; | ||
412 | |||
413 | ret = regmap_read(data->regmap, MXC4005_REG_DEVICE_ID, ®); | ||
414 | if (ret < 0) { | ||
415 | dev_err(data->dev, "failed to read chip id\n"); | ||
416 | return ret; | ||
417 | } | ||
418 | |||
419 | dev_dbg(data->dev, "MXC4005 chip id %02x\n", reg); | ||
420 | |||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | static int mxc4005_probe(struct i2c_client *client, | ||
425 | const struct i2c_device_id *id) | ||
426 | { | ||
427 | struct mxc4005_data *data; | ||
428 | struct iio_dev *indio_dev; | ||
429 | struct regmap *regmap; | ||
430 | int ret; | ||
431 | |||
432 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | ||
433 | if (!indio_dev) | ||
434 | return -ENOMEM; | ||
435 | |||
436 | regmap = devm_regmap_init_i2c(client, &mxc4005_regmap_config); | ||
437 | if (IS_ERR(regmap)) { | ||
438 | dev_err(&client->dev, "failed to initialize regmap\n"); | ||
439 | return PTR_ERR(regmap); | ||
440 | } | ||
441 | |||
442 | data = iio_priv(indio_dev); | ||
443 | i2c_set_clientdata(client, indio_dev); | ||
444 | data->dev = &client->dev; | ||
445 | data->regmap = regmap; | ||
446 | |||
447 | ret = mxc4005_chip_init(data); | ||
448 | if (ret < 0) { | ||
449 | dev_err(&client->dev, "failed to initialize chip\n"); | ||
450 | return ret; | ||
451 | } | ||
452 | |||
453 | mutex_init(&data->mutex); | ||
454 | |||
455 | indio_dev->dev.parent = &client->dev; | ||
456 | indio_dev->channels = mxc4005_channels; | ||
457 | indio_dev->num_channels = ARRAY_SIZE(mxc4005_channels); | ||
458 | indio_dev->available_scan_masks = mxc4005_scan_masks; | ||
459 | indio_dev->name = MXC4005_DRV_NAME; | ||
460 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
461 | indio_dev->info = &mxc4005_info; | ||
462 | |||
463 | ret = iio_triggered_buffer_setup(indio_dev, | ||
464 | iio_pollfunc_store_time, | ||
465 | mxc4005_trigger_handler, | ||
466 | NULL); | ||
467 | if (ret < 0) { | ||
468 | dev_err(&client->dev, | ||
469 | "failed to setup iio triggered buffer\n"); | ||
470 | return ret; | ||
471 | } | ||
472 | |||
473 | if (client->irq < 0) | ||
474 | client->irq = mxc4005_gpio_probe(client, data); | ||
475 | |||
476 | if (client->irq > 0) { | ||
477 | data->dready_trig = devm_iio_trigger_alloc(&client->dev, | ||
478 | "%s-dev%d", | ||
479 | indio_dev->name, | ||
480 | indio_dev->id); | ||
481 | if (!data->dready_trig) | ||
482 | return -ENOMEM; | ||
483 | |||
484 | ret = devm_request_threaded_irq(&client->dev, client->irq, | ||
485 | iio_trigger_generic_data_rdy_poll, | ||
486 | NULL, | ||
487 | IRQF_TRIGGER_FALLING | | ||
488 | IRQF_ONESHOT, | ||
489 | MXC4005_IRQ_NAME, | ||
490 | data->dready_trig); | ||
491 | if (ret) { | ||
492 | dev_err(&client->dev, | ||
493 | "failed to init threaded irq\n"); | ||
494 | goto err_buffer_cleanup; | ||
495 | } | ||
496 | |||
497 | data->dready_trig->dev.parent = &client->dev; | ||
498 | data->dready_trig->ops = &mxc4005_trigger_ops; | ||
499 | iio_trigger_set_drvdata(data->dready_trig, indio_dev); | ||
500 | indio_dev->trig = data->dready_trig; | ||
501 | iio_trigger_get(indio_dev->trig); | ||
502 | ret = iio_trigger_register(data->dready_trig); | ||
503 | if (ret) { | ||
504 | dev_err(&client->dev, | ||
505 | "failed to register trigger\n"); | ||
506 | goto err_trigger_unregister; | ||
507 | } | ||
508 | } | ||
509 | |||
510 | ret = iio_device_register(indio_dev); | ||
511 | if (ret < 0) { | ||
512 | dev_err(&client->dev, | ||
513 | "unable to register iio device %d\n", ret); | ||
514 | goto err_buffer_cleanup; | ||
515 | } | ||
516 | |||
517 | return 0; | ||
518 | |||
519 | err_trigger_unregister: | ||
520 | iio_trigger_unregister(data->dready_trig); | ||
521 | err_buffer_cleanup: | ||
522 | iio_triggered_buffer_cleanup(indio_dev); | ||
523 | |||
524 | return ret; | ||
525 | } | ||
526 | |||
527 | static int mxc4005_remove(struct i2c_client *client) | ||
528 | { | ||
529 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | ||
530 | struct mxc4005_data *data = iio_priv(indio_dev); | ||
531 | |||
532 | iio_device_unregister(indio_dev); | ||
533 | |||
534 | iio_triggered_buffer_cleanup(indio_dev); | ||
535 | if (data->dready_trig) | ||
536 | iio_trigger_unregister(data->dready_trig); | ||
537 | |||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | static const struct acpi_device_id mxc4005_acpi_match[] = { | ||
542 | {"MXC4005", 0}, | ||
543 | { }, | ||
544 | }; | ||
545 | MODULE_DEVICE_TABLE(acpi, mxc4005_acpi_match); | ||
546 | |||
547 | static const struct i2c_device_id mxc4005_id[] = { | ||
548 | {"mxc4005", 0}, | ||
549 | { }, | ||
550 | }; | ||
551 | MODULE_DEVICE_TABLE(i2c, mxc4005_id); | ||
552 | |||
553 | static struct i2c_driver mxc4005_driver = { | ||
554 | .driver = { | ||
555 | .name = MXC4005_DRV_NAME, | ||
556 | .acpi_match_table = ACPI_PTR(mxc4005_acpi_match), | ||
557 | }, | ||
558 | .probe = mxc4005_probe, | ||
559 | .remove = mxc4005_remove, | ||
560 | .id_table = mxc4005_id, | ||
561 | }; | ||
562 | |||
563 | module_i2c_driver(mxc4005_driver); | ||
564 | |||
565 | MODULE_AUTHOR("Teodora Baluta <teodora.baluta@intel.com>"); | ||
566 | MODULE_LICENSE("GPL v2"); | ||
567 | MODULE_DESCRIPTION("MXC4005 3-axis accelerometer driver"); | ||
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index ff30f8806880..dab8b76c1427 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c | |||
@@ -618,6 +618,7 @@ static const struct iio_info accel_info = { | |||
618 | .attrs = &st_accel_attribute_group, | 618 | .attrs = &st_accel_attribute_group, |
619 | .read_raw = &st_accel_read_raw, | 619 | .read_raw = &st_accel_read_raw, |
620 | .write_raw = &st_accel_write_raw, | 620 | .write_raw = &st_accel_write_raw, |
621 | .debugfs_reg_access = &st_sensors_debugfs_reg_access, | ||
621 | }; | 622 | }; |
622 | 623 | ||
623 | #ifdef CONFIG_IIO_TRIGGER | 624 | #ifdef CONFIG_IIO_TRIGGER |
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 50c103d75af9..7868c744fd4b 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig | |||
@@ -149,6 +149,17 @@ config BERLIN2_ADC | |||
149 | Marvell Berlin2 ADC driver. This ADC has 8 channels, with one used for | 149 | Marvell Berlin2 ADC driver. This ADC has 8 channels, with one used for |
150 | temperature measurement. | 150 | temperature measurement. |
151 | 151 | ||
152 | config CC10001_ADC | ||
153 | tristate "Cosmic Circuits 10001 ADC driver" | ||
154 | depends on HAS_IOMEM && HAVE_CLK && REGULATOR | ||
155 | select IIO_BUFFER | ||
156 | select IIO_TRIGGERED_BUFFER | ||
157 | help | ||
158 | Say yes here to build support for Cosmic Circuits 10001 ADC. | ||
159 | |||
160 | This driver can also be built as a module. If so, the module will be | ||
161 | called cc10001_adc. | ||
162 | |||
152 | config DA9150_GPADC | 163 | config DA9150_GPADC |
153 | tristate "Dialog DA9150 GPADC driver support" | 164 | tristate "Dialog DA9150 GPADC driver support" |
154 | depends on MFD_DA9150 | 165 | depends on MFD_DA9150 |
@@ -161,17 +172,6 @@ config DA9150_GPADC | |||
161 | To compile this driver as a module, choose M here: the module will be | 172 | To compile this driver as a module, choose M here: the module will be |
162 | called berlin2-adc. | 173 | called berlin2-adc. |
163 | 174 | ||
164 | config CC10001_ADC | ||
165 | tristate "Cosmic Circuits 10001 ADC driver" | ||
166 | depends on HAS_IOMEM && HAVE_CLK && REGULATOR | ||
167 | select IIO_BUFFER | ||
168 | select IIO_TRIGGERED_BUFFER | ||
169 | help | ||
170 | Say yes here to build support for Cosmic Circuits 10001 ADC. | ||
171 | |||
172 | This driver can also be built as a module. If so, the module will be | ||
173 | called cc10001_adc. | ||
174 | |||
175 | config EXYNOS_ADC | 175 | config EXYNOS_ADC |
176 | tristate "Exynos ADC driver support" | 176 | tristate "Exynos ADC driver support" |
177 | depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST) | 177 | depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST) |
@@ -183,6 +183,17 @@ config EXYNOS_ADC | |||
183 | To compile this driver as a module, choose M here: the module will be | 183 | To compile this driver as a module, choose M here: the module will be |
184 | called exynos_adc. | 184 | called exynos_adc. |
185 | 185 | ||
186 | config HI8435 | ||
187 | tristate "Holt Integrated Circuits HI-8435 threshold detector" | ||
188 | select IIO_TRIGGERED_EVENT | ||
189 | depends on SPI | ||
190 | help | ||
191 | If you say yes here you get support for Holt Integrated Circuits | ||
192 | HI-8435 chip. | ||
193 | |||
194 | This driver can also be built as a module. If so, the module will be | ||
195 | called hi8435. | ||
196 | |||
186 | config LP8788_ADC | 197 | config LP8788_ADC |
187 | tristate "LP8788 ADC driver" | 198 | tristate "LP8788 ADC driver" |
188 | depends on MFD_LP8788 | 199 | depends on MFD_LP8788 |
@@ -361,6 +372,8 @@ config TWL6030_GPADC | |||
361 | config VF610_ADC | 372 | config VF610_ADC |
362 | tristate "Freescale vf610 ADC driver" | 373 | tristate "Freescale vf610 ADC driver" |
363 | depends on OF | 374 | depends on OF |
375 | select IIO_BUFFER | ||
376 | select IIO_TRIGGERED_BUFFER | ||
364 | help | 377 | help |
365 | Say yes here to support for Vybrid board analog-to-digital converter. | 378 | Say yes here to support for Vybrid board analog-to-digital converter. |
366 | Since the IP is used for i.MX6SLX, the driver also support i.MX6SLX. | 379 | Since the IP is used for i.MX6SLX, the driver also support i.MX6SLX. |
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index a0962103e866..99b37a963a1e 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile | |||
@@ -16,9 +16,10 @@ obj-$(CONFIG_AD799X) += ad799x.o | |||
16 | obj-$(CONFIG_AT91_ADC) += at91_adc.o | 16 | obj-$(CONFIG_AT91_ADC) += at91_adc.o |
17 | obj-$(CONFIG_AXP288_ADC) += axp288_adc.o | 17 | obj-$(CONFIG_AXP288_ADC) += axp288_adc.o |
18 | obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o | 18 | obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o |
19 | obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o | ||
20 | obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o | 19 | obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o |
20 | obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o | ||
21 | obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o | 21 | obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o |
22 | obj-$(CONFIG_HI8435) += hi8435.o | ||
22 | obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o | 23 | obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o |
23 | obj-$(CONFIG_MAX1027) += max1027.o | 24 | obj-$(CONFIG_MAX1027) += max1027.o |
24 | obj-$(CONFIG_MAX1363) += max1363.o | 25 | obj-$(CONFIG_MAX1363) += max1363.o |
diff --git a/drivers/iio/adc/berlin2-adc.c b/drivers/iio/adc/berlin2-adc.c index 4946d9bf1764..71c806ecc722 100644 --- a/drivers/iio/adc/berlin2-adc.c +++ b/drivers/iio/adc/berlin2-adc.c | |||
@@ -27,13 +27,13 @@ | |||
27 | #define BERLIN2_SM_CTRL_SM_SOC_INT BIT(1) | 27 | #define BERLIN2_SM_CTRL_SM_SOC_INT BIT(1) |
28 | #define BERLIN2_SM_CTRL_SOC_SM_INT BIT(2) | 28 | #define BERLIN2_SM_CTRL_SOC_SM_INT BIT(2) |
29 | #define BERLIN2_SM_CTRL_ADC_SEL(x) ((x) << 5) /* 0-15 */ | 29 | #define BERLIN2_SM_CTRL_ADC_SEL(x) ((x) << 5) /* 0-15 */ |
30 | #define BERLIN2_SM_CTRL_ADC_SEL_MASK (0xf << 5) | 30 | #define BERLIN2_SM_CTRL_ADC_SEL_MASK GENMASK(8, 5) |
31 | #define BERLIN2_SM_CTRL_ADC_POWER BIT(9) | 31 | #define BERLIN2_SM_CTRL_ADC_POWER BIT(9) |
32 | #define BERLIN2_SM_CTRL_ADC_CLKSEL_DIV2 (0x0 << 10) | 32 | #define BERLIN2_SM_CTRL_ADC_CLKSEL_DIV2 (0x0 << 10) |
33 | #define BERLIN2_SM_CTRL_ADC_CLKSEL_DIV3 (0x1 << 10) | 33 | #define BERLIN2_SM_CTRL_ADC_CLKSEL_DIV3 (0x1 << 10) |
34 | #define BERLIN2_SM_CTRL_ADC_CLKSEL_DIV4 (0x2 << 10) | 34 | #define BERLIN2_SM_CTRL_ADC_CLKSEL_DIV4 (0x2 << 10) |
35 | #define BERLIN2_SM_CTRL_ADC_CLKSEL_DIV8 (0x3 << 10) | 35 | #define BERLIN2_SM_CTRL_ADC_CLKSEL_DIV8 (0x3 << 10) |
36 | #define BERLIN2_SM_CTRL_ADC_CLKSEL_MASK (0x3 << 10) | 36 | #define BERLIN2_SM_CTRL_ADC_CLKSEL_MASK GENMASK(11, 10) |
37 | #define BERLIN2_SM_CTRL_ADC_START BIT(12) | 37 | #define BERLIN2_SM_CTRL_ADC_START BIT(12) |
38 | #define BERLIN2_SM_CTRL_ADC_RESET BIT(13) | 38 | #define BERLIN2_SM_CTRL_ADC_RESET BIT(13) |
39 | #define BERLIN2_SM_CTRL_ADC_BANDGAP_RDY BIT(14) | 39 | #define BERLIN2_SM_CTRL_ADC_BANDGAP_RDY BIT(14) |
@@ -50,7 +50,7 @@ | |||
50 | #define BERLIN2_SM_CTRL_TSEN_MODE_10_50 (0x1 << 22) /* 10-50 C */ | 50 | #define BERLIN2_SM_CTRL_TSEN_MODE_10_50 (0x1 << 22) /* 10-50 C */ |
51 | #define BERLIN2_SM_CTRL_TSEN_RESET BIT(29) | 51 | #define BERLIN2_SM_CTRL_TSEN_RESET BIT(29) |
52 | #define BERLIN2_SM_ADC_DATA 0x20 | 52 | #define BERLIN2_SM_ADC_DATA 0x20 |
53 | #define BERLIN2_SM_ADC_MASK 0x3ff | 53 | #define BERLIN2_SM_ADC_MASK GENMASK(9, 0) |
54 | #define BERLIN2_SM_ADC_STATUS 0x1c | 54 | #define BERLIN2_SM_ADC_STATUS 0x1c |
55 | #define BERLIN2_SM_ADC_STATUS_DATA_RDY(x) BIT(x) /* 0-15 */ | 55 | #define BERLIN2_SM_ADC_STATUS_DATA_RDY(x) BIT(x) /* 0-15 */ |
56 | #define BERLIN2_SM_ADC_STATUS_DATA_RDY_MASK GENMASK(15, 0) | 56 | #define BERLIN2_SM_ADC_STATUS_DATA_RDY_MASK GENMASK(15, 0) |
@@ -65,9 +65,9 @@ | |||
65 | #define BERLIN2_SM_TSEN_CTRL_START BIT(8) | 65 | #define BERLIN2_SM_TSEN_CTRL_START BIT(8) |
66 | #define BERLIN2_SM_TSEN_CTRL_SETTLING_4 (0x0 << 21) /* 4 us */ | 66 | #define BERLIN2_SM_TSEN_CTRL_SETTLING_4 (0x0 << 21) /* 4 us */ |
67 | #define BERLIN2_SM_TSEN_CTRL_SETTLING_12 (0x1 << 21) /* 12 us */ | 67 | #define BERLIN2_SM_TSEN_CTRL_SETTLING_12 (0x1 << 21) /* 12 us */ |
68 | #define BERLIN2_SM_TSEN_CTRL_SETTLING_MASK (0x1 << 21) | 68 | #define BERLIN2_SM_TSEN_CTRL_SETTLING_MASK BIT(21) |
69 | #define BERLIN2_SM_TSEN_CTRL_TRIM(x) ((x) << 22) | 69 | #define BERLIN2_SM_TSEN_CTRL_TRIM(x) ((x) << 22) |
70 | #define BERLIN2_SM_TSEN_CTRL_TRIM_MASK (0xf << 22) | 70 | #define BERLIN2_SM_TSEN_CTRL_TRIM_MASK GENMASK(25, 22) |
71 | 71 | ||
72 | struct berlin2_adc_priv { | 72 | struct berlin2_adc_priv { |
73 | struct regmap *regmap; | 73 | struct regmap *regmap; |
@@ -78,13 +78,13 @@ struct berlin2_adc_priv { | |||
78 | }; | 78 | }; |
79 | 79 | ||
80 | #define BERLIN2_ADC_CHANNEL(n, t) \ | 80 | #define BERLIN2_ADC_CHANNEL(n, t) \ |
81 | { \ | 81 | { \ |
82 | .channel = n, \ | 82 | .channel = n, \ |
83 | .datasheet_name = "channel"#n, \ | 83 | .datasheet_name = "channel"#n, \ |
84 | .type = t, \ | 84 | .type = t, \ |
85 | .indexed = 1, \ | 85 | .indexed = 1, \ |
86 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | 86 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ |
87 | } | 87 | } |
88 | 88 | ||
89 | static const struct iio_chan_spec berlin2_adc_channels[] = { | 89 | static const struct iio_chan_spec berlin2_adc_channels[] = { |
90 | BERLIN2_ADC_CHANNEL(0, IIO_VOLTAGE), /* external input */ | 90 | BERLIN2_ADC_CHANNEL(0, IIO_VOLTAGE), /* external input */ |
@@ -111,18 +111,24 @@ static int berlin2_adc_read(struct iio_dev *indio_dev, int channel) | |||
111 | 111 | ||
112 | mutex_lock(&priv->lock); | 112 | mutex_lock(&priv->lock); |
113 | 113 | ||
114 | /* Enable the interrupts */ | ||
115 | regmap_write(priv->regmap, BERLIN2_SM_ADC_STATUS, | ||
116 | BERLIN2_SM_ADC_STATUS_INT_EN(channel)); | ||
117 | |||
114 | /* Configure the ADC */ | 118 | /* Configure the ADC */ |
115 | regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, | 119 | regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, |
116 | BERLIN2_SM_CTRL_ADC_RESET | BERLIN2_SM_CTRL_ADC_SEL_MASK | 120 | BERLIN2_SM_CTRL_ADC_RESET | |
117 | | BERLIN2_SM_CTRL_ADC_START, | 121 | BERLIN2_SM_CTRL_ADC_SEL_MASK | |
118 | BERLIN2_SM_CTRL_ADC_SEL(channel) | BERLIN2_SM_CTRL_ADC_START); | 122 | BERLIN2_SM_CTRL_ADC_START, |
123 | BERLIN2_SM_CTRL_ADC_SEL(channel) | | ||
124 | BERLIN2_SM_CTRL_ADC_START); | ||
119 | 125 | ||
120 | ret = wait_event_interruptible_timeout(priv->wq, priv->data_available, | 126 | ret = wait_event_interruptible_timeout(priv->wq, priv->data_available, |
121 | msecs_to_jiffies(1000)); | 127 | msecs_to_jiffies(1000)); |
122 | 128 | ||
123 | /* Disable the interrupts */ | 129 | /* Disable the interrupts */ |
124 | regmap_update_bits(priv->regmap, BERLIN2_SM_ADC_STATUS, | 130 | regmap_update_bits(priv->regmap, BERLIN2_SM_ADC_STATUS, |
125 | BERLIN2_SM_ADC_STATUS_INT_EN(channel), 0); | 131 | BERLIN2_SM_ADC_STATUS_INT_EN(channel), 0); |
126 | 132 | ||
127 | if (ret == 0) | 133 | if (ret == 0) |
128 | ret = -ETIMEDOUT; | 134 | ret = -ETIMEDOUT; |
@@ -132,7 +138,7 @@ static int berlin2_adc_read(struct iio_dev *indio_dev, int channel) | |||
132 | } | 138 | } |
133 | 139 | ||
134 | regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, | 140 | regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, |
135 | BERLIN2_SM_CTRL_ADC_START, 0); | 141 | BERLIN2_SM_CTRL_ADC_START, 0); |
136 | 142 | ||
137 | data = priv->data; | 143 | data = priv->data; |
138 | priv->data_available = false; | 144 | priv->data_available = false; |
@@ -149,24 +155,31 @@ static int berlin2_adc_tsen_read(struct iio_dev *indio_dev) | |||
149 | 155 | ||
150 | mutex_lock(&priv->lock); | 156 | mutex_lock(&priv->lock); |
151 | 157 | ||
158 | /* Enable interrupts */ | ||
159 | regmap_write(priv->regmap, BERLIN2_SM_TSEN_STATUS, | ||
160 | BERLIN2_SM_TSEN_STATUS_INT_EN); | ||
161 | |||
152 | /* Configure the ADC */ | 162 | /* Configure the ADC */ |
153 | regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, | 163 | regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, |
154 | BERLIN2_SM_CTRL_TSEN_RESET | BERLIN2_SM_CTRL_ADC_ROTATE, | 164 | BERLIN2_SM_CTRL_TSEN_RESET | |
155 | BERLIN2_SM_CTRL_ADC_ROTATE); | 165 | BERLIN2_SM_CTRL_ADC_ROTATE, |
166 | BERLIN2_SM_CTRL_ADC_ROTATE); | ||
156 | 167 | ||
157 | /* Configure the temperature sensor */ | 168 | /* Configure the temperature sensor */ |
158 | regmap_update_bits(priv->regmap, BERLIN2_SM_TSEN_CTRL, | 169 | regmap_update_bits(priv->regmap, BERLIN2_SM_TSEN_CTRL, |
159 | BERLIN2_SM_TSEN_CTRL_TRIM_MASK | BERLIN2_SM_TSEN_CTRL_SETTLING_MASK | 170 | BERLIN2_SM_TSEN_CTRL_TRIM_MASK | |
160 | | BERLIN2_SM_TSEN_CTRL_START, | 171 | BERLIN2_SM_TSEN_CTRL_SETTLING_MASK | |
161 | BERLIN2_SM_TSEN_CTRL_TRIM(3) | BERLIN2_SM_TSEN_CTRL_SETTLING_12 | 172 | BERLIN2_SM_TSEN_CTRL_START, |
162 | | BERLIN2_SM_TSEN_CTRL_START); | 173 | BERLIN2_SM_TSEN_CTRL_TRIM(3) | |
174 | BERLIN2_SM_TSEN_CTRL_SETTLING_12 | | ||
175 | BERLIN2_SM_TSEN_CTRL_START); | ||
163 | 176 | ||
164 | ret = wait_event_interruptible_timeout(priv->wq, priv->data_available, | 177 | ret = wait_event_interruptible_timeout(priv->wq, priv->data_available, |
165 | msecs_to_jiffies(1000)); | 178 | msecs_to_jiffies(1000)); |
166 | 179 | ||
167 | /* Disable interrupts */ | 180 | /* Disable interrupts */ |
168 | regmap_update_bits(priv->regmap, BERLIN2_SM_TSEN_STATUS, | 181 | regmap_update_bits(priv->regmap, BERLIN2_SM_TSEN_STATUS, |
169 | BERLIN2_SM_TSEN_STATUS_INT_EN, 0); | 182 | BERLIN2_SM_TSEN_STATUS_INT_EN, 0); |
170 | 183 | ||
171 | if (ret == 0) | 184 | if (ret == 0) |
172 | ret = -ETIMEDOUT; | 185 | ret = -ETIMEDOUT; |
@@ -176,7 +189,7 @@ static int berlin2_adc_tsen_read(struct iio_dev *indio_dev) | |||
176 | } | 189 | } |
177 | 190 | ||
178 | regmap_update_bits(priv->regmap, BERLIN2_SM_TSEN_CTRL, | 191 | regmap_update_bits(priv->regmap, BERLIN2_SM_TSEN_CTRL, |
179 | BERLIN2_SM_TSEN_CTRL_START, 0); | 192 | BERLIN2_SM_TSEN_CTRL_START, 0); |
180 | 193 | ||
181 | data = priv->data; | 194 | data = priv->data; |
182 | priv->data_available = false; | 195 | priv->data_available = false; |
@@ -187,10 +200,9 @@ static int berlin2_adc_tsen_read(struct iio_dev *indio_dev) | |||
187 | } | 200 | } |
188 | 201 | ||
189 | static int berlin2_adc_read_raw(struct iio_dev *indio_dev, | 202 | static int berlin2_adc_read_raw(struct iio_dev *indio_dev, |
190 | struct iio_chan_spec const *chan, int *val, int *val2, | 203 | struct iio_chan_spec const *chan, int *val, |
191 | long mask) | 204 | int *val2, long mask) |
192 | { | 205 | { |
193 | struct berlin2_adc_priv *priv = iio_priv(indio_dev); | ||
194 | int temp; | 206 | int temp; |
195 | 207 | ||
196 | switch (mask) { | 208 | switch (mask) { |
@@ -198,10 +210,6 @@ static int berlin2_adc_read_raw(struct iio_dev *indio_dev, | |||
198 | if (chan->type != IIO_VOLTAGE) | 210 | if (chan->type != IIO_VOLTAGE) |
199 | return -EINVAL; | 211 | return -EINVAL; |
200 | 212 | ||
201 | /* Enable the interrupts */ | ||
202 | regmap_write(priv->regmap, BERLIN2_SM_ADC_STATUS, | ||
203 | BERLIN2_SM_ADC_STATUS_INT_EN(chan->channel)); | ||
204 | |||
205 | *val = berlin2_adc_read(indio_dev, chan->channel); | 213 | *val = berlin2_adc_read(indio_dev, chan->channel); |
206 | if (*val < 0) | 214 | if (*val < 0) |
207 | return *val; | 215 | return *val; |
@@ -211,10 +219,6 @@ static int berlin2_adc_read_raw(struct iio_dev *indio_dev, | |||
211 | if (chan->type != IIO_TEMP) | 219 | if (chan->type != IIO_TEMP) |
212 | return -EINVAL; | 220 | return -EINVAL; |
213 | 221 | ||
214 | /* Enable interrupts */ | ||
215 | regmap_write(priv->regmap, BERLIN2_SM_TSEN_STATUS, | ||
216 | BERLIN2_SM_TSEN_STATUS_INT_EN); | ||
217 | |||
218 | temp = berlin2_adc_tsen_read(indio_dev); | 222 | temp = berlin2_adc_tsen_read(indio_dev); |
219 | if (temp < 0) | 223 | if (temp < 0) |
220 | return temp; | 224 | return temp; |
@@ -306,12 +310,12 @@ static int berlin2_adc_probe(struct platform_device *pdev) | |||
306 | return tsen_irq; | 310 | return tsen_irq; |
307 | 311 | ||
308 | ret = devm_request_irq(&pdev->dev, irq, berlin2_adc_irq, 0, | 312 | ret = devm_request_irq(&pdev->dev, irq, berlin2_adc_irq, 0, |
309 | pdev->dev.driver->name, indio_dev); | 313 | pdev->dev.driver->name, indio_dev); |
310 | if (ret) | 314 | if (ret) |
311 | return ret; | 315 | return ret; |
312 | 316 | ||
313 | ret = devm_request_irq(&pdev->dev, tsen_irq, berlin2_adc_tsen_irq, | 317 | ret = devm_request_irq(&pdev->dev, tsen_irq, berlin2_adc_tsen_irq, |
314 | 0, pdev->dev.driver->name, indio_dev); | 318 | 0, pdev->dev.driver->name, indio_dev); |
315 | if (ret) | 319 | if (ret) |
316 | return ret; | 320 | return ret; |
317 | 321 | ||
@@ -328,13 +332,14 @@ static int berlin2_adc_probe(struct platform_device *pdev) | |||
328 | 332 | ||
329 | /* Power up the ADC */ | 333 | /* Power up the ADC */ |
330 | regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, | 334 | regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, |
331 | BERLIN2_SM_CTRL_ADC_POWER, BERLIN2_SM_CTRL_ADC_POWER); | 335 | BERLIN2_SM_CTRL_ADC_POWER, |
336 | BERLIN2_SM_CTRL_ADC_POWER); | ||
332 | 337 | ||
333 | ret = iio_device_register(indio_dev); | 338 | ret = iio_device_register(indio_dev); |
334 | if (ret) { | 339 | if (ret) { |
335 | /* Power down the ADC */ | 340 | /* Power down the ADC */ |
336 | regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, | 341 | regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, |
337 | BERLIN2_SM_CTRL_ADC_POWER, 0); | 342 | BERLIN2_SM_CTRL_ADC_POWER, 0); |
338 | return ret; | 343 | return ret; |
339 | } | 344 | } |
340 | 345 | ||
@@ -350,7 +355,7 @@ static int berlin2_adc_remove(struct platform_device *pdev) | |||
350 | 355 | ||
351 | /* Power down the ADC */ | 356 | /* Power down the ADC */ |
352 | regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, | 357 | regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, |
353 | BERLIN2_SM_CTRL_ADC_POWER, 0); | 358 | BERLIN2_SM_CTRL_ADC_POWER, 0); |
354 | 359 | ||
355 | return 0; | 360 | return 0; |
356 | } | 361 | } |
diff --git a/drivers/iio/adc/hi8435.c b/drivers/iio/adc/hi8435.c new file mode 100644 index 000000000000..c73c6c62a6ac --- /dev/null +++ b/drivers/iio/adc/hi8435.c | |||
@@ -0,0 +1,534 @@ | |||
1 | /* | ||
2 | * Holt Integrated Circuits HI-8435 threshold detector driver | ||
3 | * | ||
4 | * Copyright (C) 2015 Zodiac Inflight Innovations | ||
5 | * Copyright (C) 2015 Cogent Embedded, Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/delay.h> | ||
14 | #include <linux/iio/events.h> | ||
15 | #include <linux/iio/iio.h> | ||
16 | #include <linux/iio/sysfs.h> | ||
17 | #include <linux/iio/trigger.h> | ||
18 | #include <linux/iio/trigger_consumer.h> | ||
19 | #include <linux/iio/triggered_event.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <linux/of_device.h> | ||
24 | #include <linux/of_gpio.h> | ||
25 | #include <linux/spi/spi.h> | ||
26 | #include <linux/gpio/consumer.h> | ||
27 | |||
28 | #define DRV_NAME "hi8435" | ||
29 | |||
30 | /* Register offsets for HI-8435 */ | ||
31 | #define HI8435_CTRL_REG 0x02 | ||
32 | #define HI8435_PSEN_REG 0x04 | ||
33 | #define HI8435_TMDATA_REG 0x1E | ||
34 | #define HI8435_GOCENHYS_REG 0x3A | ||
35 | #define HI8435_SOCENHYS_REG 0x3C | ||
36 | #define HI8435_SO7_0_REG 0x10 | ||
37 | #define HI8435_SO15_8_REG 0x12 | ||
38 | #define HI8435_SO23_16_REG 0x14 | ||
39 | #define HI8435_SO31_24_REG 0x16 | ||
40 | #define HI8435_SO31_0_REG 0x78 | ||
41 | |||
42 | #define HI8435_WRITE_OPCODE 0x00 | ||
43 | #define HI8435_READ_OPCODE 0x80 | ||
44 | |||
45 | /* CTRL register bits */ | ||
46 | #define HI8435_CTRL_TEST 0x01 | ||
47 | #define HI8435_CTRL_SRST 0x02 | ||
48 | |||
49 | struct hi8435_priv { | ||
50 | struct spi_device *spi; | ||
51 | struct mutex lock; | ||
52 | |||
53 | unsigned long event_scan_mask; /* soft mask/unmask channels events */ | ||
54 | unsigned int event_prev_val; | ||
55 | |||
56 | unsigned threshold_lo[2]; /* GND-Open and Supply-Open thresholds */ | ||
57 | unsigned threshold_hi[2]; /* GND-Open and Supply-Open thresholds */ | ||
58 | u8 reg_buffer[3] ____cacheline_aligned; | ||
59 | }; | ||
60 | |||
61 | static int hi8435_readb(struct hi8435_priv *priv, u8 reg, u8 *val) | ||
62 | { | ||
63 | reg |= HI8435_READ_OPCODE; | ||
64 | return spi_write_then_read(priv->spi, ®, 1, val, 1); | ||
65 | } | ||
66 | |||
67 | static int hi8435_readw(struct hi8435_priv *priv, u8 reg, u16 *val) | ||
68 | { | ||
69 | int ret; | ||
70 | __be16 be_val; | ||
71 | |||
72 | reg |= HI8435_READ_OPCODE; | ||
73 | ret = spi_write_then_read(priv->spi, ®, 1, &be_val, 2); | ||
74 | *val = be16_to_cpu(be_val); | ||
75 | |||
76 | return ret; | ||
77 | } | ||
78 | |||
79 | static int hi8435_readl(struct hi8435_priv *priv, u8 reg, u32 *val) | ||
80 | { | ||
81 | int ret; | ||
82 | __be32 be_val; | ||
83 | |||
84 | reg |= HI8435_READ_OPCODE; | ||
85 | ret = spi_write_then_read(priv->spi, ®, 1, &be_val, 4); | ||
86 | *val = be32_to_cpu(be_val); | ||
87 | |||
88 | return ret; | ||
89 | } | ||
90 | |||
91 | static int hi8435_writeb(struct hi8435_priv *priv, u8 reg, u8 val) | ||
92 | { | ||
93 | priv->reg_buffer[0] = reg | HI8435_WRITE_OPCODE; | ||
94 | priv->reg_buffer[1] = val; | ||
95 | |||
96 | return spi_write(priv->spi, priv->reg_buffer, 2); | ||
97 | } | ||
98 | |||
99 | static int hi8435_writew(struct hi8435_priv *priv, u8 reg, u16 val) | ||
100 | { | ||
101 | priv->reg_buffer[0] = reg | HI8435_WRITE_OPCODE; | ||
102 | priv->reg_buffer[1] = (val >> 8) & 0xff; | ||
103 | priv->reg_buffer[2] = val & 0xff; | ||
104 | |||
105 | return spi_write(priv->spi, priv->reg_buffer, 3); | ||
106 | } | ||
107 | |||
108 | static int hi8435_read_event_config(struct iio_dev *idev, | ||
109 | const struct iio_chan_spec *chan, | ||
110 | enum iio_event_type type, | ||
111 | enum iio_event_direction dir) | ||
112 | { | ||
113 | struct hi8435_priv *priv = iio_priv(idev); | ||
114 | |||
115 | return !!(priv->event_scan_mask & BIT(chan->channel)); | ||
116 | } | ||
117 | |||
118 | static int hi8435_write_event_config(struct iio_dev *idev, | ||
119 | const struct iio_chan_spec *chan, | ||
120 | enum iio_event_type type, | ||
121 | enum iio_event_direction dir, int state) | ||
122 | { | ||
123 | struct hi8435_priv *priv = iio_priv(idev); | ||
124 | |||
125 | priv->event_scan_mask &= ~BIT(chan->channel); | ||
126 | if (state) | ||
127 | priv->event_scan_mask |= BIT(chan->channel); | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int hi8435_read_event_value(struct iio_dev *idev, | ||
133 | const struct iio_chan_spec *chan, | ||
134 | enum iio_event_type type, | ||
135 | enum iio_event_direction dir, | ||
136 | enum iio_event_info info, | ||
137 | int *val, int *val2) | ||
138 | { | ||
139 | struct hi8435_priv *priv = iio_priv(idev); | ||
140 | int ret; | ||
141 | u8 mode, psen; | ||
142 | u16 reg; | ||
143 | |||
144 | ret = hi8435_readb(priv, HI8435_PSEN_REG, &psen); | ||
145 | if (ret < 0) | ||
146 | return ret; | ||
147 | |||
148 | /* Supply-Open or GND-Open sensing mode */ | ||
149 | mode = !!(psen & BIT(chan->channel / 8)); | ||
150 | |||
151 | ret = hi8435_readw(priv, mode ? HI8435_SOCENHYS_REG : | ||
152 | HI8435_GOCENHYS_REG, ®); | ||
153 | if (ret < 0) | ||
154 | return ret; | ||
155 | |||
156 | if (dir == IIO_EV_DIR_FALLING) | ||
157 | *val = ((reg & 0xff) - (reg >> 8)) / 2; | ||
158 | else if (dir == IIO_EV_DIR_RISING) | ||
159 | *val = ((reg & 0xff) + (reg >> 8)) / 2; | ||
160 | |||
161 | return IIO_VAL_INT; | ||
162 | } | ||
163 | |||
164 | static int hi8435_write_event_value(struct iio_dev *idev, | ||
165 | const struct iio_chan_spec *chan, | ||
166 | enum iio_event_type type, | ||
167 | enum iio_event_direction dir, | ||
168 | enum iio_event_info info, | ||
169 | int val, int val2) | ||
170 | { | ||
171 | struct hi8435_priv *priv = iio_priv(idev); | ||
172 | int ret; | ||
173 | u8 mode, psen; | ||
174 | u16 reg; | ||
175 | |||
176 | ret = hi8435_readb(priv, HI8435_PSEN_REG, &psen); | ||
177 | if (ret < 0) | ||
178 | return ret; | ||
179 | |||
180 | /* Supply-Open or GND-Open sensing mode */ | ||
181 | mode = !!(psen & BIT(chan->channel / 8)); | ||
182 | |||
183 | ret = hi8435_readw(priv, mode ? HI8435_SOCENHYS_REG : | ||
184 | HI8435_GOCENHYS_REG, ®); | ||
185 | if (ret < 0) | ||
186 | return ret; | ||
187 | |||
188 | if (dir == IIO_EV_DIR_FALLING) { | ||
189 | /* falling threshold range 2..21V, hysteresis minimum 2V */ | ||
190 | if (val < 2 || val > 21 || (val + 2) > priv->threshold_hi[mode]) | ||
191 | return -EINVAL; | ||
192 | |||
193 | if (val == priv->threshold_lo[mode]) | ||
194 | return 0; | ||
195 | |||
196 | priv->threshold_lo[mode] = val; | ||
197 | |||
198 | /* hysteresis must not be odd */ | ||
199 | if ((priv->threshold_hi[mode] - priv->threshold_lo[mode]) % 2) | ||
200 | priv->threshold_hi[mode]--; | ||
201 | } else if (dir == IIO_EV_DIR_RISING) { | ||
202 | /* rising threshold range 3..22V, hysteresis minimum 2V */ | ||
203 | if (val < 3 || val > 22 || val < (priv->threshold_lo[mode] + 2)) | ||
204 | return -EINVAL; | ||
205 | |||
206 | if (val == priv->threshold_hi[mode]) | ||
207 | return 0; | ||
208 | |||
209 | priv->threshold_hi[mode] = val; | ||
210 | |||
211 | /* hysteresis must not be odd */ | ||
212 | if ((priv->threshold_hi[mode] - priv->threshold_lo[mode]) % 2) | ||
213 | priv->threshold_lo[mode]++; | ||
214 | } | ||
215 | |||
216 | /* program thresholds */ | ||
217 | mutex_lock(&priv->lock); | ||
218 | |||
219 | ret = hi8435_readw(priv, mode ? HI8435_SOCENHYS_REG : | ||
220 | HI8435_GOCENHYS_REG, ®); | ||
221 | if (ret < 0) { | ||
222 | mutex_unlock(&priv->lock); | ||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | /* hysteresis */ | ||
227 | reg = priv->threshold_hi[mode] - priv->threshold_lo[mode]; | ||
228 | reg <<= 8; | ||
229 | /* threshold center */ | ||
230 | reg |= (priv->threshold_hi[mode] + priv->threshold_lo[mode]); | ||
231 | |||
232 | ret = hi8435_writew(priv, mode ? HI8435_SOCENHYS_REG : | ||
233 | HI8435_GOCENHYS_REG, reg); | ||
234 | |||
235 | mutex_unlock(&priv->lock); | ||
236 | |||
237 | return ret; | ||
238 | } | ||
239 | |||
240 | static int hi8435_debugfs_reg_access(struct iio_dev *idev, | ||
241 | unsigned reg, unsigned writeval, | ||
242 | unsigned *readval) | ||
243 | { | ||
244 | struct hi8435_priv *priv = iio_priv(idev); | ||
245 | int ret; | ||
246 | u8 val; | ||
247 | |||
248 | if (readval != NULL) { | ||
249 | ret = hi8435_readb(priv, reg, &val); | ||
250 | *readval = val; | ||
251 | } else { | ||
252 | val = (u8)writeval; | ||
253 | ret = hi8435_writeb(priv, reg, val); | ||
254 | } | ||
255 | |||
256 | return ret; | ||
257 | } | ||
258 | |||
259 | static const struct iio_event_spec hi8435_events[] = { | ||
260 | { | ||
261 | .type = IIO_EV_TYPE_THRESH, | ||
262 | .dir = IIO_EV_DIR_RISING, | ||
263 | .mask_separate = BIT(IIO_EV_INFO_VALUE), | ||
264 | }, { | ||
265 | .type = IIO_EV_TYPE_THRESH, | ||
266 | .dir = IIO_EV_DIR_FALLING, | ||
267 | .mask_separate = BIT(IIO_EV_INFO_VALUE), | ||
268 | }, { | ||
269 | .type = IIO_EV_TYPE_THRESH, | ||
270 | .dir = IIO_EV_DIR_EITHER, | ||
271 | .mask_separate = BIT(IIO_EV_INFO_ENABLE), | ||
272 | }, | ||
273 | }; | ||
274 | |||
275 | static int hi8435_get_sensing_mode(struct iio_dev *idev, | ||
276 | const struct iio_chan_spec *chan) | ||
277 | { | ||
278 | struct hi8435_priv *priv = iio_priv(idev); | ||
279 | int ret; | ||
280 | u8 reg; | ||
281 | |||
282 | ret = hi8435_readb(priv, HI8435_PSEN_REG, ®); | ||
283 | if (ret < 0) | ||
284 | return ret; | ||
285 | |||
286 | return !!(reg & BIT(chan->channel / 8)); | ||
287 | } | ||
288 | |||
289 | static int hi8435_set_sensing_mode(struct iio_dev *idev, | ||
290 | const struct iio_chan_spec *chan, | ||
291 | unsigned int mode) | ||
292 | { | ||
293 | struct hi8435_priv *priv = iio_priv(idev); | ||
294 | int ret; | ||
295 | u8 reg; | ||
296 | |||
297 | mutex_lock(&priv->lock); | ||
298 | |||
299 | ret = hi8435_readb(priv, HI8435_PSEN_REG, ®); | ||
300 | if (ret < 0) { | ||
301 | mutex_unlock(&priv->lock); | ||
302 | return ret; | ||
303 | } | ||
304 | |||
305 | reg &= ~BIT(chan->channel / 8); | ||
306 | if (mode) | ||
307 | reg |= BIT(chan->channel / 8); | ||
308 | |||
309 | ret = hi8435_writeb(priv, HI8435_PSEN_REG, reg); | ||
310 | |||
311 | mutex_unlock(&priv->lock); | ||
312 | |||
313 | return ret; | ||
314 | } | ||
315 | |||
316 | static const char * const hi8435_sensing_modes[] = { "GND-Open", | ||
317 | "Supply-Open" }; | ||
318 | |||
319 | static const struct iio_enum hi8435_sensing_mode = { | ||
320 | .items = hi8435_sensing_modes, | ||
321 | .num_items = ARRAY_SIZE(hi8435_sensing_modes), | ||
322 | .get = hi8435_get_sensing_mode, | ||
323 | .set = hi8435_set_sensing_mode, | ||
324 | }; | ||
325 | |||
326 | static const struct iio_chan_spec_ext_info hi8435_ext_info[] = { | ||
327 | IIO_ENUM("sensing_mode", IIO_SEPARATE, &hi8435_sensing_mode), | ||
328 | {}, | ||
329 | }; | ||
330 | |||
331 | #define HI8435_VOLTAGE_CHANNEL(num) \ | ||
332 | { \ | ||
333 | .type = IIO_VOLTAGE, \ | ||
334 | .indexed = 1, \ | ||
335 | .channel = num, \ | ||
336 | .event_spec = hi8435_events, \ | ||
337 | .num_event_specs = ARRAY_SIZE(hi8435_events), \ | ||
338 | .ext_info = hi8435_ext_info, \ | ||
339 | } | ||
340 | |||
341 | static const struct iio_chan_spec hi8435_channels[] = { | ||
342 | HI8435_VOLTAGE_CHANNEL(0), | ||
343 | HI8435_VOLTAGE_CHANNEL(1), | ||
344 | HI8435_VOLTAGE_CHANNEL(2), | ||
345 | HI8435_VOLTAGE_CHANNEL(3), | ||
346 | HI8435_VOLTAGE_CHANNEL(4), | ||
347 | HI8435_VOLTAGE_CHANNEL(5), | ||
348 | HI8435_VOLTAGE_CHANNEL(6), | ||
349 | HI8435_VOLTAGE_CHANNEL(7), | ||
350 | HI8435_VOLTAGE_CHANNEL(8), | ||
351 | HI8435_VOLTAGE_CHANNEL(9), | ||
352 | HI8435_VOLTAGE_CHANNEL(10), | ||
353 | HI8435_VOLTAGE_CHANNEL(11), | ||
354 | HI8435_VOLTAGE_CHANNEL(12), | ||
355 | HI8435_VOLTAGE_CHANNEL(13), | ||
356 | HI8435_VOLTAGE_CHANNEL(14), | ||
357 | HI8435_VOLTAGE_CHANNEL(15), | ||
358 | HI8435_VOLTAGE_CHANNEL(16), | ||
359 | HI8435_VOLTAGE_CHANNEL(17), | ||
360 | HI8435_VOLTAGE_CHANNEL(18), | ||
361 | HI8435_VOLTAGE_CHANNEL(19), | ||
362 | HI8435_VOLTAGE_CHANNEL(20), | ||
363 | HI8435_VOLTAGE_CHANNEL(21), | ||
364 | HI8435_VOLTAGE_CHANNEL(22), | ||
365 | HI8435_VOLTAGE_CHANNEL(23), | ||
366 | HI8435_VOLTAGE_CHANNEL(24), | ||
367 | HI8435_VOLTAGE_CHANNEL(25), | ||
368 | HI8435_VOLTAGE_CHANNEL(26), | ||
369 | HI8435_VOLTAGE_CHANNEL(27), | ||
370 | HI8435_VOLTAGE_CHANNEL(28), | ||
371 | HI8435_VOLTAGE_CHANNEL(29), | ||
372 | HI8435_VOLTAGE_CHANNEL(30), | ||
373 | HI8435_VOLTAGE_CHANNEL(31), | ||
374 | IIO_CHAN_SOFT_TIMESTAMP(32), | ||
375 | }; | ||
376 | |||
377 | static const struct iio_info hi8435_info = { | ||
378 | .driver_module = THIS_MODULE, | ||
379 | .read_event_config = &hi8435_read_event_config, | ||
380 | .write_event_config = hi8435_write_event_config, | ||
381 | .read_event_value = &hi8435_read_event_value, | ||
382 | .write_event_value = &hi8435_write_event_value, | ||
383 | .debugfs_reg_access = &hi8435_debugfs_reg_access, | ||
384 | }; | ||
385 | |||
386 | static void hi8435_iio_push_event(struct iio_dev *idev, unsigned int val) | ||
387 | { | ||
388 | struct hi8435_priv *priv = iio_priv(idev); | ||
389 | enum iio_event_direction dir; | ||
390 | unsigned int i; | ||
391 | unsigned int status = priv->event_prev_val ^ val; | ||
392 | |||
393 | if (!status) | ||
394 | return; | ||
395 | |||
396 | for_each_set_bit(i, &priv->event_scan_mask, 32) { | ||
397 | if (status & BIT(i)) { | ||
398 | dir = val & BIT(i) ? IIO_EV_DIR_RISING : | ||
399 | IIO_EV_DIR_FALLING; | ||
400 | iio_push_event(idev, | ||
401 | IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i, | ||
402 | IIO_EV_TYPE_THRESH, dir), | ||
403 | iio_get_time_ns()); | ||
404 | } | ||
405 | } | ||
406 | |||
407 | priv->event_prev_val = val; | ||
408 | } | ||
409 | |||
410 | static irqreturn_t hi8435_trigger_handler(int irq, void *private) | ||
411 | { | ||
412 | struct iio_poll_func *pf = private; | ||
413 | struct iio_dev *idev = pf->indio_dev; | ||
414 | struct hi8435_priv *priv = iio_priv(idev); | ||
415 | u32 val; | ||
416 | int ret; | ||
417 | |||
418 | ret = hi8435_readl(priv, HI8435_SO31_0_REG, &val); | ||
419 | if (ret < 0) | ||
420 | goto err_read; | ||
421 | |||
422 | hi8435_iio_push_event(idev, val); | ||
423 | |||
424 | err_read: | ||
425 | iio_trigger_notify_done(idev->trig); | ||
426 | |||
427 | return IRQ_HANDLED; | ||
428 | } | ||
429 | |||
430 | static int hi8435_probe(struct spi_device *spi) | ||
431 | { | ||
432 | struct iio_dev *idev; | ||
433 | struct hi8435_priv *priv; | ||
434 | struct gpio_desc *reset_gpio; | ||
435 | int ret; | ||
436 | |||
437 | idev = devm_iio_device_alloc(&spi->dev, sizeof(*priv)); | ||
438 | if (!idev) | ||
439 | return -ENOMEM; | ||
440 | |||
441 | priv = iio_priv(idev); | ||
442 | priv->spi = spi; | ||
443 | |||
444 | reset_gpio = devm_gpiod_get(&spi->dev, NULL, GPIOD_OUT_LOW); | ||
445 | if (IS_ERR(reset_gpio)) { | ||
446 | /* chip s/w reset if h/w reset failed */ | ||
447 | hi8435_writeb(priv, HI8435_CTRL_REG, HI8435_CTRL_SRST); | ||
448 | hi8435_writeb(priv, HI8435_CTRL_REG, 0); | ||
449 | } else { | ||
450 | udelay(5); | ||
451 | gpiod_set_value(reset_gpio, 1); | ||
452 | } | ||
453 | |||
454 | spi_set_drvdata(spi, idev); | ||
455 | mutex_init(&priv->lock); | ||
456 | |||
457 | idev->dev.parent = &spi->dev; | ||
458 | idev->name = spi_get_device_id(spi)->name; | ||
459 | idev->modes = INDIO_DIRECT_MODE; | ||
460 | idev->info = &hi8435_info; | ||
461 | idev->channels = hi8435_channels; | ||
462 | idev->num_channels = ARRAY_SIZE(hi8435_channels); | ||
463 | |||
464 | /* unmask all events */ | ||
465 | priv->event_scan_mask = ~(0); | ||
466 | /* | ||
467 | * There is a restriction in the chip - the hysteresis can not be odd. | ||
468 | * If the hysteresis is set to odd value then chip gets into lock state | ||
469 | * and not functional anymore. | ||
470 | * After chip reset the thresholds are in undefined state, so we need to | ||
471 | * initialize thresholds to some initial values and then prevent | ||
472 | * userspace setting odd hysteresis. | ||
473 | * | ||
474 | * Set threshold low voltage to 2V, threshold high voltage to 4V | ||
475 | * for both GND-Open and Supply-Open sensing modes. | ||
476 | */ | ||
477 | priv->threshold_lo[0] = priv->threshold_lo[1] = 2; | ||
478 | priv->threshold_hi[0] = priv->threshold_hi[1] = 4; | ||
479 | hi8435_writew(priv, HI8435_GOCENHYS_REG, 0x206); | ||
480 | hi8435_writew(priv, HI8435_SOCENHYS_REG, 0x206); | ||
481 | |||
482 | ret = iio_triggered_event_setup(idev, NULL, hi8435_trigger_handler); | ||
483 | if (ret) | ||
484 | return ret; | ||
485 | |||
486 | ret = iio_device_register(idev); | ||
487 | if (ret < 0) { | ||
488 | dev_err(&spi->dev, "unable to register device\n"); | ||
489 | goto unregister_triggered_event; | ||
490 | } | ||
491 | |||
492 | return 0; | ||
493 | |||
494 | unregister_triggered_event: | ||
495 | iio_triggered_event_cleanup(idev); | ||
496 | return ret; | ||
497 | } | ||
498 | |||
499 | static int hi8435_remove(struct spi_device *spi) | ||
500 | { | ||
501 | struct iio_dev *idev = spi_get_drvdata(spi); | ||
502 | |||
503 | iio_device_unregister(idev); | ||
504 | iio_triggered_event_cleanup(idev); | ||
505 | |||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | static const struct of_device_id hi8435_dt_ids[] = { | ||
510 | { .compatible = "holt,hi8435" }, | ||
511 | {}, | ||
512 | }; | ||
513 | MODULE_DEVICE_TABLE(of, hi8435_dt_ids); | ||
514 | |||
515 | static const struct spi_device_id hi8435_id[] = { | ||
516 | { "hi8435", 0}, | ||
517 | { } | ||
518 | }; | ||
519 | MODULE_DEVICE_TABLE(spi, hi8435_id); | ||
520 | |||
521 | static struct spi_driver hi8435_driver = { | ||
522 | .driver = { | ||
523 | .name = DRV_NAME, | ||
524 | .of_match_table = of_match_ptr(hi8435_dt_ids), | ||
525 | }, | ||
526 | .probe = hi8435_probe, | ||
527 | .remove = hi8435_remove, | ||
528 | .id_table = hi8435_id, | ||
529 | }; | ||
530 | module_spi_driver(hi8435_driver); | ||
531 | |||
532 | MODULE_LICENSE("GPL"); | ||
533 | MODULE_AUTHOR("Vladimir Barinov"); | ||
534 | MODULE_DESCRIPTION("HI-8435 threshold detector"); | ||
diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c index 44bf815adb6c..54a8302aaace 100644 --- a/drivers/iio/adc/max1027.c +++ b/drivers/iio/adc/max1027.c | |||
@@ -508,6 +508,7 @@ static int max1027_remove(struct spi_device *spi) | |||
508 | static struct spi_driver max1027_driver = { | 508 | static struct spi_driver max1027_driver = { |
509 | .driver = { | 509 | .driver = { |
510 | .name = "max1027", | 510 | .name = "max1027", |
511 | .of_match_table = of_match_ptr(max1027_adc_dt_ids), | ||
511 | .owner = THIS_MODULE, | 512 | .owner = THIS_MODULE, |
512 | }, | 513 | }, |
513 | .probe = max1027_probe, | 514 | .probe = max1027_probe, |
diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c index b19e4f9d16e0..41a21e986c1a 100644 --- a/drivers/iio/adc/mcp320x.c +++ b/drivers/iio/adc/mcp320x.c | |||
@@ -404,6 +404,7 @@ MODULE_DEVICE_TABLE(spi, mcp320x_id); | |||
404 | static struct spi_driver mcp320x_driver = { | 404 | static struct spi_driver mcp320x_driver = { |
405 | .driver = { | 405 | .driver = { |
406 | .name = "mcp320x", | 406 | .name = "mcp320x", |
407 | .of_match_table = of_match_ptr(mcp320x_dt_ids), | ||
407 | .owner = THIS_MODULE, | 408 | .owner = THIS_MODULE, |
408 | }, | 409 | }, |
409 | .probe = mcp320x_probe, | 410 | .probe = mcp320x_probe, |
diff --git a/drivers/iio/adc/ti-adc128s052.c b/drivers/iio/adc/ti-adc128s052.c index 915be6b60097..98c0d2b444bf 100644 --- a/drivers/iio/adc/ti-adc128s052.c +++ b/drivers/iio/adc/ti-adc128s052.c | |||
@@ -174,6 +174,13 @@ static int adc128_remove(struct spi_device *spi) | |||
174 | return 0; | 174 | return 0; |
175 | } | 175 | } |
176 | 176 | ||
177 | static const struct of_device_id adc128_of_match[] = { | ||
178 | { .compatible = "ti,adc128s052", }, | ||
179 | { .compatible = "ti,adc122s021", }, | ||
180 | { /* sentinel */ }, | ||
181 | }; | ||
182 | MODULE_DEVICE_TABLE(of, adc128_of_match); | ||
183 | |||
177 | static const struct spi_device_id adc128_id[] = { | 184 | static const struct spi_device_id adc128_id[] = { |
178 | { "adc128s052", 0}, /* index into adc128_config */ | 185 | { "adc128s052", 0}, /* index into adc128_config */ |
179 | { "adc122s021", 1}, | 186 | { "adc122s021", 1}, |
@@ -184,6 +191,7 @@ MODULE_DEVICE_TABLE(spi, adc128_id); | |||
184 | static struct spi_driver adc128_driver = { | 191 | static struct spi_driver adc128_driver = { |
185 | .driver = { | 192 | .driver = { |
186 | .name = "adc128s052", | 193 | .name = "adc128s052", |
194 | .of_match_table = of_match_ptr(adc128_of_match), | ||
187 | .owner = THIS_MODULE, | 195 | .owner = THIS_MODULE, |
188 | }, | 196 | }, |
189 | .probe = adc128_probe, | 197 | .probe = adc128_probe, |
diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c index df12c57e6ce0..becbb0aef232 100644 --- a/drivers/iio/adc/twl6030-gpadc.c +++ b/drivers/iio/adc/twl6030-gpadc.c | |||
@@ -875,6 +875,7 @@ static const struct of_device_id of_twl6030_match_tbl[] = { | |||
875 | }, | 875 | }, |
876 | { /* end */ } | 876 | { /* end */ } |
877 | }; | 877 | }; |
878 | MODULE_DEVICE_TABLE(of, of_twl6030_match_tbl); | ||
878 | 879 | ||
879 | static int twl6030_gpadc_probe(struct platform_device *pdev) | 880 | static int twl6030_gpadc_probe(struct platform_device *pdev) |
880 | { | 881 | { |
diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c index 6bf4c20eb231..599cde3d03a1 100644 --- a/drivers/iio/adc/vf610_adc.c +++ b/drivers/iio/adc/vf610_adc.c | |||
@@ -34,8 +34,11 @@ | |||
34 | #include <linux/err.h> | 34 | #include <linux/err.h> |
35 | 35 | ||
36 | #include <linux/iio/iio.h> | 36 | #include <linux/iio/iio.h> |
37 | #include <linux/iio/buffer.h> | ||
37 | #include <linux/iio/sysfs.h> | 38 | #include <linux/iio/sysfs.h> |
38 | #include <linux/iio/driver.h> | 39 | #include <linux/iio/trigger.h> |
40 | #include <linux/iio/trigger_consumer.h> | ||
41 | #include <linux/iio/triggered_buffer.h> | ||
39 | 42 | ||
40 | /* This will be the driver name the kernel reports */ | 43 | /* This will be the driver name the kernel reports */ |
41 | #define DRIVER_NAME "vf610-adc" | 44 | #define DRIVER_NAME "vf610-adc" |
@@ -170,6 +173,7 @@ struct vf610_adc { | |||
170 | u32 sample_freq_avail[5]; | 173 | u32 sample_freq_avail[5]; |
171 | 174 | ||
172 | struct completion completion; | 175 | struct completion completion; |
176 | u16 buffer[8]; | ||
173 | }; | 177 | }; |
174 | 178 | ||
175 | static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 }; | 179 | static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 }; |
@@ -505,12 +509,24 @@ static const struct iio_chan_spec_ext_info vf610_ext_info[] = { | |||
505 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ | 509 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ |
506 | BIT(IIO_CHAN_INFO_SAMP_FREQ), \ | 510 | BIT(IIO_CHAN_INFO_SAMP_FREQ), \ |
507 | .ext_info = vf610_ext_info, \ | 511 | .ext_info = vf610_ext_info, \ |
512 | .scan_index = (_idx), \ | ||
513 | .scan_type = { \ | ||
514 | .sign = 'u', \ | ||
515 | .realbits = 12, \ | ||
516 | .storagebits = 16, \ | ||
517 | }, \ | ||
508 | } | 518 | } |
509 | 519 | ||
510 | #define VF610_ADC_TEMPERATURE_CHAN(_idx, _chan_type) { \ | 520 | #define VF610_ADC_TEMPERATURE_CHAN(_idx, _chan_type) { \ |
511 | .type = (_chan_type), \ | 521 | .type = (_chan_type), \ |
512 | .channel = (_idx), \ | 522 | .channel = (_idx), \ |
513 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ | 523 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ |
524 | .scan_index = (_idx), \ | ||
525 | .scan_type = { \ | ||
526 | .sign = 'u', \ | ||
527 | .realbits = 12, \ | ||
528 | .storagebits = 16, \ | ||
529 | }, \ | ||
514 | } | 530 | } |
515 | 531 | ||
516 | static const struct iio_chan_spec vf610_adc_iio_channels[] = { | 532 | static const struct iio_chan_spec vf610_adc_iio_channels[] = { |
@@ -531,6 +547,7 @@ static const struct iio_chan_spec vf610_adc_iio_channels[] = { | |||
531 | VF610_ADC_CHAN(14, IIO_VOLTAGE), | 547 | VF610_ADC_CHAN(14, IIO_VOLTAGE), |
532 | VF610_ADC_CHAN(15, IIO_VOLTAGE), | 548 | VF610_ADC_CHAN(15, IIO_VOLTAGE), |
533 | VF610_ADC_TEMPERATURE_CHAN(26, IIO_TEMP), | 549 | VF610_ADC_TEMPERATURE_CHAN(26, IIO_TEMP), |
550 | IIO_CHAN_SOFT_TIMESTAMP(32), | ||
534 | /* sentinel */ | 551 | /* sentinel */ |
535 | }; | 552 | }; |
536 | 553 | ||
@@ -559,13 +576,20 @@ static int vf610_adc_read_data(struct vf610_adc *info) | |||
559 | 576 | ||
560 | static irqreturn_t vf610_adc_isr(int irq, void *dev_id) | 577 | static irqreturn_t vf610_adc_isr(int irq, void *dev_id) |
561 | { | 578 | { |
562 | struct vf610_adc *info = (struct vf610_adc *)dev_id; | 579 | struct iio_dev *indio_dev = (struct iio_dev *)dev_id; |
580 | struct vf610_adc *info = iio_priv(indio_dev); | ||
563 | int coco; | 581 | int coco; |
564 | 582 | ||
565 | coco = readl(info->regs + VF610_REG_ADC_HS); | 583 | coco = readl(info->regs + VF610_REG_ADC_HS); |
566 | if (coco & VF610_ADC_HS_COCO0) { | 584 | if (coco & VF610_ADC_HS_COCO0) { |
567 | info->value = vf610_adc_read_data(info); | 585 | info->value = vf610_adc_read_data(info); |
568 | complete(&info->completion); | 586 | if (iio_buffer_enabled(indio_dev)) { |
587 | info->buffer[0] = info->value; | ||
588 | iio_push_to_buffers_with_timestamp(indio_dev, | ||
589 | info->buffer, iio_get_time_ns()); | ||
590 | iio_trigger_notify_done(indio_dev->trig); | ||
591 | } else | ||
592 | complete(&info->completion); | ||
569 | } | 593 | } |
570 | 594 | ||
571 | return IRQ_HANDLED; | 595 | return IRQ_HANDLED; |
@@ -613,8 +637,12 @@ static int vf610_read_raw(struct iio_dev *indio_dev, | |||
613 | case IIO_CHAN_INFO_RAW: | 637 | case IIO_CHAN_INFO_RAW: |
614 | case IIO_CHAN_INFO_PROCESSED: | 638 | case IIO_CHAN_INFO_PROCESSED: |
615 | mutex_lock(&indio_dev->mlock); | 639 | mutex_lock(&indio_dev->mlock); |
616 | reinit_completion(&info->completion); | 640 | if (iio_buffer_enabled(indio_dev)) { |
641 | mutex_unlock(&indio_dev->mlock); | ||
642 | return -EBUSY; | ||
643 | } | ||
617 | 644 | ||
645 | reinit_completion(&info->completion); | ||
618 | hc_cfg = VF610_ADC_ADCHC(chan->channel); | 646 | hc_cfg = VF610_ADC_ADCHC(chan->channel); |
619 | hc_cfg |= VF610_ADC_AIEN; | 647 | hc_cfg |= VF610_ADC_AIEN; |
620 | writel(hc_cfg, info->regs + VF610_REG_ADC_HC0); | 648 | writel(hc_cfg, info->regs + VF610_REG_ADC_HC0); |
@@ -694,6 +722,56 @@ static int vf610_write_raw(struct iio_dev *indio_dev, | |||
694 | return -EINVAL; | 722 | return -EINVAL; |
695 | } | 723 | } |
696 | 724 | ||
725 | static int vf610_adc_buffer_postenable(struct iio_dev *indio_dev) | ||
726 | { | ||
727 | struct vf610_adc *info = iio_priv(indio_dev); | ||
728 | unsigned int channel; | ||
729 | int ret; | ||
730 | int val; | ||
731 | |||
732 | ret = iio_triggered_buffer_postenable(indio_dev); | ||
733 | if (ret) | ||
734 | return ret; | ||
735 | |||
736 | val = readl(info->regs + VF610_REG_ADC_GC); | ||
737 | val |= VF610_ADC_ADCON; | ||
738 | writel(val, info->regs + VF610_REG_ADC_GC); | ||
739 | |||
740 | channel = find_first_bit(indio_dev->active_scan_mask, | ||
741 | indio_dev->masklength); | ||
742 | |||
743 | val = VF610_ADC_ADCHC(channel); | ||
744 | val |= VF610_ADC_AIEN; | ||
745 | |||
746 | writel(val, info->regs + VF610_REG_ADC_HC0); | ||
747 | |||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | static int vf610_adc_buffer_predisable(struct iio_dev *indio_dev) | ||
752 | { | ||
753 | struct vf610_adc *info = iio_priv(indio_dev); | ||
754 | unsigned int hc_cfg = 0; | ||
755 | int val; | ||
756 | |||
757 | val = readl(info->regs + VF610_REG_ADC_GC); | ||
758 | val &= ~VF610_ADC_ADCON; | ||
759 | writel(val, info->regs + VF610_REG_ADC_GC); | ||
760 | |||
761 | hc_cfg |= VF610_ADC_CONV_DISABLE; | ||
762 | hc_cfg &= ~VF610_ADC_AIEN; | ||
763 | |||
764 | writel(hc_cfg, info->regs + VF610_REG_ADC_HC0); | ||
765 | |||
766 | return iio_triggered_buffer_predisable(indio_dev); | ||
767 | } | ||
768 | |||
769 | static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = { | ||
770 | .postenable = &vf610_adc_buffer_postenable, | ||
771 | .predisable = &vf610_adc_buffer_predisable, | ||
772 | .validate_scan_mask = &iio_validate_scan_mask_onehot, | ||
773 | }; | ||
774 | |||
697 | static int vf610_adc_reg_access(struct iio_dev *indio_dev, | 775 | static int vf610_adc_reg_access(struct iio_dev *indio_dev, |
698 | unsigned reg, unsigned writeval, | 776 | unsigned reg, unsigned writeval, |
699 | unsigned *readval) | 777 | unsigned *readval) |
@@ -753,7 +831,7 @@ static int vf610_adc_probe(struct platform_device *pdev) | |||
753 | 831 | ||
754 | ret = devm_request_irq(info->dev, irq, | 832 | ret = devm_request_irq(info->dev, irq, |
755 | vf610_adc_isr, 0, | 833 | vf610_adc_isr, 0, |
756 | dev_name(&pdev->dev), info); | 834 | dev_name(&pdev->dev), indio_dev); |
757 | if (ret < 0) { | 835 | if (ret < 0) { |
758 | dev_err(&pdev->dev, "failed requesting irq, irq = %d\n", irq); | 836 | dev_err(&pdev->dev, "failed requesting irq, irq = %d\n", irq); |
759 | return ret; | 837 | return ret; |
@@ -806,15 +884,23 @@ static int vf610_adc_probe(struct platform_device *pdev) | |||
806 | vf610_adc_cfg_init(info); | 884 | vf610_adc_cfg_init(info); |
807 | vf610_adc_hw_init(info); | 885 | vf610_adc_hw_init(info); |
808 | 886 | ||
887 | ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, | ||
888 | NULL, &iio_triggered_buffer_setup_ops); | ||
889 | if (ret < 0) { | ||
890 | dev_err(&pdev->dev, "Couldn't initialise the buffer\n"); | ||
891 | goto error_iio_device_register; | ||
892 | } | ||
893 | |||
809 | ret = iio_device_register(indio_dev); | 894 | ret = iio_device_register(indio_dev); |
810 | if (ret) { | 895 | if (ret) { |
811 | dev_err(&pdev->dev, "Couldn't register the device.\n"); | 896 | dev_err(&pdev->dev, "Couldn't register the device.\n"); |
812 | goto error_iio_device_register; | 897 | goto error_adc_buffer_init; |
813 | } | 898 | } |
814 | 899 | ||
815 | return 0; | 900 | return 0; |
816 | 901 | ||
817 | 902 | error_adc_buffer_init: | |
903 | iio_triggered_buffer_cleanup(indio_dev); | ||
818 | error_iio_device_register: | 904 | error_iio_device_register: |
819 | clk_disable_unprepare(info->clk); | 905 | clk_disable_unprepare(info->clk); |
820 | error_adc_clk_enable: | 906 | error_adc_clk_enable: |
@@ -829,6 +915,7 @@ static int vf610_adc_remove(struct platform_device *pdev) | |||
829 | struct vf610_adc *info = iio_priv(indio_dev); | 915 | struct vf610_adc *info = iio_priv(indio_dev); |
830 | 916 | ||
831 | iio_device_unregister(indio_dev); | 917 | iio_device_unregister(indio_dev); |
918 | iio_triggered_buffer_cleanup(indio_dev); | ||
832 | regulator_disable(info->vref); | 919 | regulator_disable(info->vref); |
833 | clk_disable_unprepare(info->clk); | 920 | clk_disable_unprepare(info->clk); |
834 | 921 | ||
diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c index ce93bd8e3f68..0370624a35db 100644 --- a/drivers/iio/adc/xilinx-xadc-core.c +++ b/drivers/iio/adc/xilinx-xadc-core.c | |||
@@ -273,33 +273,13 @@ static void xadc_zynq_unmask_worker(struct work_struct *work) | |||
273 | schedule_delayed_work(&xadc->zynq_unmask_work, | 273 | schedule_delayed_work(&xadc->zynq_unmask_work, |
274 | msecs_to_jiffies(XADC_ZYNQ_UNMASK_TIMEOUT)); | 274 | msecs_to_jiffies(XADC_ZYNQ_UNMASK_TIMEOUT)); |
275 | } | 275 | } |
276 | } | ||
277 | |||
278 | static irqreturn_t xadc_zynq_threaded_interrupt_handler(int irq, void *devid) | ||
279 | { | ||
280 | struct iio_dev *indio_dev = devid; | ||
281 | struct xadc *xadc = iio_priv(indio_dev); | ||
282 | unsigned int alarm; | ||
283 | |||
284 | spin_lock_irq(&xadc->lock); | ||
285 | alarm = xadc->zynq_alarm; | ||
286 | xadc->zynq_alarm = 0; | ||
287 | spin_unlock_irq(&xadc->lock); | ||
288 | |||
289 | xadc_handle_events(indio_dev, xadc_zynq_transform_alarm(alarm)); | ||
290 | 276 | ||
291 | /* unmask the required interrupts in timer. */ | ||
292 | schedule_delayed_work(&xadc->zynq_unmask_work, | ||
293 | msecs_to_jiffies(XADC_ZYNQ_UNMASK_TIMEOUT)); | ||
294 | |||
295 | return IRQ_HANDLED; | ||
296 | } | 277 | } |
297 | 278 | ||
298 | static irqreturn_t xadc_zynq_interrupt_handler(int irq, void *devid) | 279 | static irqreturn_t xadc_zynq_interrupt_handler(int irq, void *devid) |
299 | { | 280 | { |
300 | struct iio_dev *indio_dev = devid; | 281 | struct iio_dev *indio_dev = devid; |
301 | struct xadc *xadc = iio_priv(indio_dev); | 282 | struct xadc *xadc = iio_priv(indio_dev); |
302 | irqreturn_t ret = IRQ_HANDLED; | ||
303 | uint32_t status; | 283 | uint32_t status; |
304 | 284 | ||
305 | xadc_read_reg(xadc, XADC_ZYNQ_REG_INTSTS, &status); | 285 | xadc_read_reg(xadc, XADC_ZYNQ_REG_INTSTS, &status); |
@@ -321,18 +301,23 @@ static irqreturn_t xadc_zynq_interrupt_handler(int irq, void *devid) | |||
321 | 301 | ||
322 | status &= XADC_ZYNQ_INT_ALARM_MASK; | 302 | status &= XADC_ZYNQ_INT_ALARM_MASK; |
323 | if (status) { | 303 | if (status) { |
324 | xadc->zynq_alarm |= status; | ||
325 | xadc->zynq_masked_alarm |= status; | 304 | xadc->zynq_masked_alarm |= status; |
326 | /* | 305 | /* |
327 | * mask the current event interrupt, | 306 | * mask the current event interrupt, |
328 | * unmask it when the interrupt is no more active. | 307 | * unmask it when the interrupt is no more active. |
329 | */ | 308 | */ |
330 | xadc_zynq_update_intmsk(xadc, 0, 0); | 309 | xadc_zynq_update_intmsk(xadc, 0, 0); |
331 | ret = IRQ_WAKE_THREAD; | 310 | |
311 | xadc_handle_events(indio_dev, | ||
312 | xadc_zynq_transform_alarm(status)); | ||
313 | |||
314 | /* unmask the required interrupts in timer. */ | ||
315 | schedule_delayed_work(&xadc->zynq_unmask_work, | ||
316 | msecs_to_jiffies(XADC_ZYNQ_UNMASK_TIMEOUT)); | ||
332 | } | 317 | } |
333 | spin_unlock(&xadc->lock); | 318 | spin_unlock(&xadc->lock); |
334 | 319 | ||
335 | return ret; | 320 | return IRQ_HANDLED; |
336 | } | 321 | } |
337 | 322 | ||
338 | #define XADC_ZYNQ_TCK_RATE_MAX 50000000 | 323 | #define XADC_ZYNQ_TCK_RATE_MAX 50000000 |
@@ -437,7 +422,6 @@ static const struct xadc_ops xadc_zynq_ops = { | |||
437 | .setup = xadc_zynq_setup, | 422 | .setup = xadc_zynq_setup, |
438 | .get_dclk_rate = xadc_zynq_get_dclk_rate, | 423 | .get_dclk_rate = xadc_zynq_get_dclk_rate, |
439 | .interrupt_handler = xadc_zynq_interrupt_handler, | 424 | .interrupt_handler = xadc_zynq_interrupt_handler, |
440 | .threaded_interrupt_handler = xadc_zynq_threaded_interrupt_handler, | ||
441 | .update_alarm = xadc_zynq_update_alarm, | 425 | .update_alarm = xadc_zynq_update_alarm, |
442 | }; | 426 | }; |
443 | 427 | ||
@@ -1225,9 +1209,8 @@ static int xadc_probe(struct platform_device *pdev) | |||
1225 | if (ret) | 1209 | if (ret) |
1226 | goto err_free_samplerate_trigger; | 1210 | goto err_free_samplerate_trigger; |
1227 | 1211 | ||
1228 | ret = request_threaded_irq(irq, xadc->ops->interrupt_handler, | 1212 | ret = request_irq(irq, xadc->ops->interrupt_handler, 0, |
1229 | xadc->ops->threaded_interrupt_handler, | 1213 | dev_name(&pdev->dev), indio_dev); |
1230 | 0, dev_name(&pdev->dev), indio_dev); | ||
1231 | if (ret) | 1214 | if (ret) |
1232 | goto err_clk_disable_unprepare; | 1215 | goto err_clk_disable_unprepare; |
1233 | 1216 | ||
diff --git a/drivers/iio/adc/xilinx-xadc.h b/drivers/iio/adc/xilinx-xadc.h index 54adc5087210..f6f081965647 100644 --- a/drivers/iio/adc/xilinx-xadc.h +++ b/drivers/iio/adc/xilinx-xadc.h | |||
@@ -60,7 +60,6 @@ struct xadc { | |||
60 | 60 | ||
61 | enum xadc_external_mux_mode external_mux_mode; | 61 | enum xadc_external_mux_mode external_mux_mode; |
62 | 62 | ||
63 | unsigned int zynq_alarm; | ||
64 | unsigned int zynq_masked_alarm; | 63 | unsigned int zynq_masked_alarm; |
65 | unsigned int zynq_intmask; | 64 | unsigned int zynq_intmask; |
66 | struct delayed_work zynq_unmask_work; | 65 | struct delayed_work zynq_unmask_work; |
@@ -79,7 +78,6 @@ struct xadc_ops { | |||
79 | void (*update_alarm)(struct xadc *, unsigned int); | 78 | void (*update_alarm)(struct xadc *, unsigned int); |
80 | unsigned long (*get_dclk_rate)(struct xadc *); | 79 | unsigned long (*get_dclk_rate)(struct xadc *); |
81 | irqreturn_t (*interrupt_handler)(int, void *); | 80 | irqreturn_t (*interrupt_handler)(int, void *); |
82 | irqreturn_t (*threaded_interrupt_handler)(int, void *); | ||
83 | 81 | ||
84 | unsigned int flags; | 82 | unsigned int flags; |
85 | }; | 83 | }; |
diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c index c0d364ebaea8..32b82a2dc894 100644 --- a/drivers/iio/amplifiers/ad8366.c +++ b/drivers/iio/amplifiers/ad8366.c | |||
@@ -195,6 +195,7 @@ static const struct spi_device_id ad8366_id[] = { | |||
195 | {"ad8366", 0}, | 195 | {"ad8366", 0}, |
196 | {} | 196 | {} |
197 | }; | 197 | }; |
198 | MODULE_DEVICE_TABLE(spi, ad8366_id); | ||
198 | 199 | ||
199 | static struct spi_driver ad8366_driver = { | 200 | static struct spi_driver ad8366_driver = { |
200 | .driver = { | 201 | .driver = { |
diff --git a/drivers/iio/buffer/Kconfig b/drivers/iio/buffer/Kconfig new file mode 100644 index 000000000000..0a7b2fd3699b --- /dev/null +++ b/drivers/iio/buffer/Kconfig | |||
@@ -0,0 +1,24 @@ | |||
1 | # | ||
2 | # Industrial I/O generic buffer implementations | ||
3 | # | ||
4 | # When adding new entries keep the list in alphabetical order | ||
5 | |||
6 | config IIO_BUFFER_CB | ||
7 | tristate "IIO callback buffer used for push in-kernel interfaces" | ||
8 | help | ||
9 | Should be selected by any drivers that do in-kernel push | ||
10 | usage. That is, those where the data is pushed to the consumer. | ||
11 | |||
12 | config IIO_KFIFO_BUF | ||
13 | tristate "Industrial I/O buffering based on kfifo" | ||
14 | help | ||
15 | A simple fifo based on kfifo. Note that this currently provides | ||
16 | no buffer events so it is up to userspace to work out how | ||
17 | often to read from the buffer. | ||
18 | |||
19 | config IIO_TRIGGERED_BUFFER | ||
20 | tristate | ||
21 | select IIO_TRIGGER | ||
22 | select IIO_KFIFO_BUF | ||
23 | help | ||
24 | Provides helper functions for setting up triggered buffers. | ||
diff --git a/drivers/iio/buffer/Makefile b/drivers/iio/buffer/Makefile new file mode 100644 index 000000000000..4d193b9a9123 --- /dev/null +++ b/drivers/iio/buffer/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # | ||
2 | # Makefile for the industrial I/O buffer implementations | ||
3 | # | ||
4 | |||
5 | # When adding new entries keep the list in alphabetical order | ||
6 | obj-$(CONFIG_IIO_BUFFER_CB) += industrialio-buffer-cb.o | ||
7 | obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o | ||
8 | obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o | ||
diff --git a/drivers/iio/buffer_cb.c b/drivers/iio/buffer/industrialio-buffer-cb.c index 1648e6e5a848..323079c3ccce 100644 --- a/drivers/iio/buffer_cb.c +++ b/drivers/iio/buffer/industrialio-buffer-cb.c | |||
@@ -1,4 +1,12 @@ | |||
1 | /* The industrial I/O callback buffer | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify it | ||
4 | * under the terms of the GNU General Public License version 2 as published by | ||
5 | * the Free Software Foundation. | ||
6 | */ | ||
7 | |||
1 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
9 | #include <linux/module.h> | ||
2 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
3 | #include <linux/err.h> | 11 | #include <linux/err.h> |
4 | #include <linux/export.h> | 12 | #include <linux/export.h> |
@@ -124,3 +132,7 @@ struct iio_channel | |||
124 | return cb_buffer->channels; | 132 | return cb_buffer->channels; |
125 | } | 133 | } |
126 | EXPORT_SYMBOL_GPL(iio_channel_cb_get_channels); | 134 | EXPORT_SYMBOL_GPL(iio_channel_cb_get_channels); |
135 | |||
136 | MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); | ||
137 | MODULE_DESCRIPTION("Industrial I/O callback buffer"); | ||
138 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/iio/industrialio-triggered-buffer.c b/drivers/iio/buffer/industrialio-triggered-buffer.c index 4b2858ba1fd6..4b2858ba1fd6 100644 --- a/drivers/iio/industrialio-triggered-buffer.c +++ b/drivers/iio/buffer/industrialio-triggered-buffer.c | |||
diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/buffer/kfifo_buf.c index c5b999f0c519..c5b999f0c519 100644 --- a/drivers/iio/kfifo_buf.c +++ b/drivers/iio/buffer/kfifo_buf.c | |||
diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig new file mode 100644 index 000000000000..3061b7299f0f --- /dev/null +++ b/drivers/iio/chemical/Kconfig | |||
@@ -0,0 +1,15 @@ | |||
1 | # | ||
2 | # Chemical sensors | ||
3 | # | ||
4 | |||
5 | menu "Chemical Sensors" | ||
6 | |||
7 | config VZ89X | ||
8 | tristate "SGX Sensortech MiCS VZ89X VOC sensor" | ||
9 | depends on I2C | ||
10 | help | ||
11 | Say Y here to build I2C interface support for the SGX | ||
12 | Sensortech MiCS VZ89X VOC (Volatile Organic Compounds) | ||
13 | sensors | ||
14 | |||
15 | endmenu | ||
diff --git a/drivers/iio/chemical/Makefile b/drivers/iio/chemical/Makefile new file mode 100644 index 000000000000..7292f2ded587 --- /dev/null +++ b/drivers/iio/chemical/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # | ||
2 | # Makefile for IIO chemical sensors | ||
3 | # | ||
4 | |||
5 | # When adding new entries keep the list in alphabetical order | ||
6 | obj-$(CONFIG_VZ89X) += vz89x.o | ||
diff --git a/drivers/iio/chemical/vz89x.c b/drivers/iio/chemical/vz89x.c new file mode 100644 index 000000000000..b45420039ca2 --- /dev/null +++ b/drivers/iio/chemical/vz89x.c | |||
@@ -0,0 +1,237 @@ | |||
1 | /* | ||
2 | * vz89x.c - Support for SGX Sensortech MiCS VZ89X VOC sensors | ||
3 | * | ||
4 | * Copyright (C) 2015 Matt Ranostay <mranostay@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/mutex.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/i2c.h> | ||
22 | |||
23 | #include <linux/iio/iio.h> | ||
24 | #include <linux/iio/sysfs.h> | ||
25 | |||
26 | #define VZ89X_REG_MEASUREMENT 0x09 | ||
27 | #define VZ89X_REG_MEASUREMENT_SIZE 6 | ||
28 | |||
29 | #define VZ89X_VOC_CO2_IDX 0 | ||
30 | #define VZ89X_VOC_SHORT_IDX 1 | ||
31 | #define VZ89X_VOC_TVOC_IDX 2 | ||
32 | #define VZ89X_VOC_RESISTANCE_IDX 3 | ||
33 | |||
34 | struct vz89x_data { | ||
35 | struct i2c_client *client; | ||
36 | struct mutex lock; | ||
37 | unsigned long last_update; | ||
38 | |||
39 | u8 buffer[VZ89X_REG_MEASUREMENT_SIZE]; | ||
40 | }; | ||
41 | |||
42 | static const struct iio_chan_spec vz89x_channels[] = { | ||
43 | { | ||
44 | .type = IIO_CONCENTRATION, | ||
45 | .channel2 = IIO_MOD_CO2, | ||
46 | .modified = 1, | ||
47 | .info_mask_separate = | ||
48 | BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_RAW), | ||
49 | .address = VZ89X_VOC_CO2_IDX, | ||
50 | }, | ||
51 | { | ||
52 | .type = IIO_CONCENTRATION, | ||
53 | .channel2 = IIO_MOD_VOC, | ||
54 | .modified = 1, | ||
55 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
56 | .address = VZ89X_VOC_SHORT_IDX, | ||
57 | .extend_name = "short", | ||
58 | }, | ||
59 | { | ||
60 | .type = IIO_CONCENTRATION, | ||
61 | .channel2 = IIO_MOD_VOC, | ||
62 | .modified = 1, | ||
63 | .info_mask_separate = | ||
64 | BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_RAW), | ||
65 | .address = VZ89X_VOC_TVOC_IDX, | ||
66 | }, | ||
67 | { | ||
68 | .type = IIO_RESISTANCE, | ||
69 | .info_mask_separate = | ||
70 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | ||
71 | .address = VZ89X_VOC_RESISTANCE_IDX, | ||
72 | }, | ||
73 | }; | ||
74 | |||
75 | static IIO_CONST_ATTR(in_concentration_co2_scale, "0.00000698689"); | ||
76 | static IIO_CONST_ATTR(in_concentration_voc_scale, "0.00000000436681223"); | ||
77 | |||
78 | static struct attribute *vz89x_attributes[] = { | ||
79 | &iio_const_attr_in_concentration_co2_scale.dev_attr.attr, | ||
80 | &iio_const_attr_in_concentration_voc_scale.dev_attr.attr, | ||
81 | NULL, | ||
82 | }; | ||
83 | |||
84 | static const struct attribute_group vz89x_attrs_group = { | ||
85 | .attrs = vz89x_attributes, | ||
86 | }; | ||
87 | |||
88 | static int vz89x_get_measurement(struct vz89x_data *data) | ||
89 | { | ||
90 | int ret; | ||
91 | int i; | ||
92 | |||
93 | /* sensor can only be polled once a second max per datasheet */ | ||
94 | if (!time_after(jiffies, data->last_update + HZ)) | ||
95 | return 0; | ||
96 | |||
97 | ret = i2c_smbus_write_word_data(data->client, | ||
98 | VZ89X_REG_MEASUREMENT, 0); | ||
99 | if (ret < 0) | ||
100 | return ret; | ||
101 | |||
102 | for (i = 0; i < VZ89X_REG_MEASUREMENT_SIZE; i++) { | ||
103 | ret = i2c_smbus_read_byte(data->client); | ||
104 | if (ret < 0) | ||
105 | return ret; | ||
106 | data->buffer[i] = ret; | ||
107 | } | ||
108 | |||
109 | data->last_update = jiffies; | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static int vz89x_get_resistance_reading(struct vz89x_data *data) | ||
115 | { | ||
116 | u8 *buf = &data->buffer[VZ89X_VOC_TVOC_IDX]; | ||
117 | |||
118 | return buf[0] | (buf[1] << 8) | (buf[2] << 16); | ||
119 | } | ||
120 | |||
121 | static int vz89x_read_raw(struct iio_dev *indio_dev, | ||
122 | struct iio_chan_spec const *chan, int *val, | ||
123 | int *val2, long mask) | ||
124 | { | ||
125 | struct vz89x_data *data = iio_priv(indio_dev); | ||
126 | int ret = -EINVAL; | ||
127 | |||
128 | switch (mask) { | ||
129 | case IIO_CHAN_INFO_RAW: | ||
130 | mutex_lock(&data->lock); | ||
131 | ret = vz89x_get_measurement(data); | ||
132 | mutex_unlock(&data->lock); | ||
133 | |||
134 | if (ret) | ||
135 | return ret; | ||
136 | |||
137 | switch (chan->address) { | ||
138 | case VZ89X_VOC_CO2_IDX: | ||
139 | case VZ89X_VOC_SHORT_IDX: | ||
140 | case VZ89X_VOC_TVOC_IDX: | ||
141 | *val = data->buffer[chan->address]; | ||
142 | return IIO_VAL_INT; | ||
143 | case VZ89X_VOC_RESISTANCE_IDX: | ||
144 | *val = vz89x_get_resistance_reading(data); | ||
145 | return IIO_VAL_INT; | ||
146 | default: | ||
147 | return -EINVAL; | ||
148 | } | ||
149 | break; | ||
150 | case IIO_CHAN_INFO_SCALE: | ||
151 | switch (chan->type) { | ||
152 | case IIO_RESISTANCE: | ||
153 | *val = 10; | ||
154 | return IIO_VAL_INT; | ||
155 | default: | ||
156 | return -EINVAL; | ||
157 | } | ||
158 | break; | ||
159 | case IIO_CHAN_INFO_OFFSET: | ||
160 | switch (chan->address) { | ||
161 | case VZ89X_VOC_CO2_IDX: | ||
162 | *val = 44; | ||
163 | *val2 = 250000; | ||
164 | return IIO_VAL_INT_PLUS_MICRO; | ||
165 | case VZ89X_VOC_TVOC_IDX: | ||
166 | *val = -13; | ||
167 | return IIO_VAL_INT; | ||
168 | default: | ||
169 | return -EINVAL; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | return ret; | ||
174 | } | ||
175 | |||
176 | static const struct iio_info vz89x_info = { | ||
177 | .attrs = &vz89x_attrs_group, | ||
178 | .read_raw = vz89x_read_raw, | ||
179 | .driver_module = THIS_MODULE, | ||
180 | }; | ||
181 | |||
182 | static int vz89x_probe(struct i2c_client *client, | ||
183 | const struct i2c_device_id *id) | ||
184 | { | ||
185 | struct iio_dev *indio_dev; | ||
186 | struct vz89x_data *data; | ||
187 | |||
188 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA | | ||
189 | I2C_FUNC_SMBUS_BYTE)) | ||
190 | return -ENODEV; | ||
191 | |||
192 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | ||
193 | if (!indio_dev) | ||
194 | return -ENOMEM; | ||
195 | |||
196 | data = iio_priv(indio_dev); | ||
197 | i2c_set_clientdata(client, indio_dev); | ||
198 | data->client = client; | ||
199 | data->last_update = jiffies - HZ; | ||
200 | mutex_init(&data->lock); | ||
201 | |||
202 | indio_dev->dev.parent = &client->dev; | ||
203 | indio_dev->info = &vz89x_info, | ||
204 | indio_dev->name = dev_name(&client->dev); | ||
205 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
206 | |||
207 | indio_dev->channels = vz89x_channels; | ||
208 | indio_dev->num_channels = ARRAY_SIZE(vz89x_channels); | ||
209 | |||
210 | return devm_iio_device_register(&client->dev, indio_dev); | ||
211 | } | ||
212 | |||
213 | static const struct i2c_device_id vz89x_id[] = { | ||
214 | { "vz89x", 0 }, | ||
215 | { } | ||
216 | }; | ||
217 | MODULE_DEVICE_TABLE(i2c, vz89x_id); | ||
218 | |||
219 | static const struct of_device_id vz89x_dt_ids[] = { | ||
220 | { .compatible = "sgx,vz89x" }, | ||
221 | { } | ||
222 | }; | ||
223 | MODULE_DEVICE_TABLE(of, vz89x_dt_ids); | ||
224 | |||
225 | static struct i2c_driver vz89x_driver = { | ||
226 | .driver = { | ||
227 | .name = "vz89x", | ||
228 | .of_match_table = of_match_ptr(vz89x_dt_ids), | ||
229 | }, | ||
230 | .probe = vz89x_probe, | ||
231 | .id_table = vz89x_id, | ||
232 | }; | ||
233 | module_i2c_driver(vz89x_driver); | ||
234 | |||
235 | MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>"); | ||
236 | MODULE_DESCRIPTION("SGX Sensortech MiCS VZ89X VOC sensors"); | ||
237 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 2e7fdb502645..25258e2c1a82 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c | |||
@@ -44,6 +44,28 @@ st_sensors_write_data_with_mask_error: | |||
44 | return err; | 44 | return err; |
45 | } | 45 | } |
46 | 46 | ||
47 | int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev, | ||
48 | unsigned reg, unsigned writeval, | ||
49 | unsigned *readval) | ||
50 | { | ||
51 | struct st_sensor_data *sdata = iio_priv(indio_dev); | ||
52 | u8 readdata; | ||
53 | int err; | ||
54 | |||
55 | if (!readval) | ||
56 | return sdata->tf->write_byte(&sdata->tb, sdata->dev, | ||
57 | (u8)reg, (u8)writeval); | ||
58 | |||
59 | err = sdata->tf->read_byte(&sdata->tb, sdata->dev, (u8)reg, &readdata); | ||
60 | if (err < 0) | ||
61 | return err; | ||
62 | |||
63 | *readval = (unsigned)readdata; | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | EXPORT_SYMBOL(st_sensors_debugfs_reg_access); | ||
68 | |||
47 | static int st_sensors_match_odr(struct st_sensor_settings *sensor_settings, | 69 | static int st_sensors_match_odr(struct st_sensor_settings *sensor_settings, |
48 | unsigned int odr, struct st_sensor_odr_avl *odr_out) | 70 | unsigned int odr, struct st_sensor_odr_avl *odr_out) |
49 | { | 71 | { |
diff --git a/drivers/iio/dac/ad7303.c b/drivers/iio/dac/ad7303.c index fa2810032968..18a4ad5ff8c5 100644 --- a/drivers/iio/dac/ad7303.c +++ b/drivers/iio/dac/ad7303.c | |||
@@ -281,6 +281,12 @@ static int ad7303_remove(struct spi_device *spi) | |||
281 | return 0; | 281 | return 0; |
282 | } | 282 | } |
283 | 283 | ||
284 | static const struct of_device_id ad7303_spi_of_match[] = { | ||
285 | { .compatible = "adi,ad7303", }, | ||
286 | { /* sentinel */ }, | ||
287 | }; | ||
288 | MODULE_DEVICE_TABLE(of, ad7303_spi_of_match); | ||
289 | |||
284 | static const struct spi_device_id ad7303_spi_ids[] = { | 290 | static const struct spi_device_id ad7303_spi_ids[] = { |
285 | { "ad7303", 0 }, | 291 | { "ad7303", 0 }, |
286 | {} | 292 | {} |
@@ -290,6 +296,7 @@ MODULE_DEVICE_TABLE(spi, ad7303_spi_ids); | |||
290 | static struct spi_driver ad7303_driver = { | 296 | static struct spi_driver ad7303_driver = { |
291 | .driver = { | 297 | .driver = { |
292 | .name = "ad7303", | 298 | .name = "ad7303", |
299 | .of_match_table = of_match_ptr(ad7303_spi_of_match), | ||
293 | .owner = THIS_MODULE, | 300 | .owner = THIS_MODULE, |
294 | }, | 301 | }, |
295 | .probe = ad7303_probe, | 302 | .probe = ad7303_probe, |
diff --git a/drivers/iio/dac/max5821.c b/drivers/iio/dac/max5821.c index 28b8748ea824..86e9e112f554 100644 --- a/drivers/iio/dac/max5821.c +++ b/drivers/iio/dac/max5821.c | |||
@@ -387,6 +387,7 @@ static const struct of_device_id max5821_of_match[] = { | |||
387 | { .compatible = "maxim,max5821" }, | 387 | { .compatible = "maxim,max5821" }, |
388 | { } | 388 | { } |
389 | }; | 389 | }; |
390 | MODULE_DEVICE_TABLE(of, max5821_of_match); | ||
390 | 391 | ||
391 | static struct i2c_driver max5821_driver = { | 392 | static struct i2c_driver max5821_driver = { |
392 | .driver = { | 393 | .driver = { |
diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index 9890c81c027d..73f27e0a08dd 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c | |||
@@ -616,15 +616,24 @@ static int adf4350_remove(struct spi_device *spi) | |||
616 | return 0; | 616 | return 0; |
617 | } | 617 | } |
618 | 618 | ||
619 | static const struct of_device_id adf4350_of_match[] = { | ||
620 | { .compatible = "adi,adf4350", }, | ||
621 | { .compatible = "adi,adf4351", }, | ||
622 | { /* sentinel */ }, | ||
623 | }; | ||
624 | MODULE_DEVICE_TABLE(of, adf4350_of_match); | ||
625 | |||
619 | static const struct spi_device_id adf4350_id[] = { | 626 | static const struct spi_device_id adf4350_id[] = { |
620 | {"adf4350", 4350}, | 627 | {"adf4350", 4350}, |
621 | {"adf4351", 4351}, | 628 | {"adf4351", 4351}, |
622 | {} | 629 | {} |
623 | }; | 630 | }; |
631 | MODULE_DEVICE_TABLE(spi, adf4350_id); | ||
624 | 632 | ||
625 | static struct spi_driver adf4350_driver = { | 633 | static struct spi_driver adf4350_driver = { |
626 | .driver = { | 634 | .driver = { |
627 | .name = "adf4350", | 635 | .name = "adf4350", |
636 | .of_match_table = of_match_ptr(adf4350_of_match), | ||
628 | .owner = THIS_MODULE, | 637 | .owner = THIS_MODULE, |
629 | }, | 638 | }, |
630 | .probe = adf4350_probe, | 639 | .probe = adf4350_probe, |
diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig index 8d2439345673..e816d29d6a62 100644 --- a/drivers/iio/gyro/Kconfig +++ b/drivers/iio/gyro/Kconfig | |||
@@ -52,15 +52,26 @@ config ADXRS450 | |||
52 | 52 | ||
53 | config BMG160 | 53 | config BMG160 |
54 | tristate "BOSCH BMG160 Gyro Sensor" | 54 | tristate "BOSCH BMG160 Gyro Sensor" |
55 | depends on I2C | 55 | depends on (I2C || SPI_MASTER) |
56 | select IIO_BUFFER | 56 | select IIO_BUFFER |
57 | select IIO_TRIGGERED_BUFFER | 57 | select IIO_TRIGGERED_BUFFER |
58 | select BMG160_I2C if (I2C) | ||
59 | select BMG160_SPI if (SPI) | ||
58 | help | 60 | help |
59 | Say yes here to build support for Bosch BMG160 Tri-axis Gyro Sensor | 61 | Say yes here to build support for BOSCH BMG160 Tri-axis Gyro Sensor |
60 | driver. This driver also supports BMI055 gyroscope. | 62 | driver connected via I2C or SPI. This driver also supports BMI055 |
63 | gyroscope. | ||
61 | 64 | ||
62 | This driver can also be built as a module. If so, the module | 65 | This driver can also be built as a module. If so, the module |
63 | will be called bmg160. | 66 | will be called bmg160_i2c or bmg160_spi. |
67 | |||
68 | config BMG160_I2C | ||
69 | tristate | ||
70 | select REGMAP_I2C | ||
71 | |||
72 | config BMG160_SPI | ||
73 | tristate | ||
74 | select REGMAP_SPI | ||
64 | 75 | ||
65 | config HID_SENSOR_GYRO_3D | 76 | config HID_SENSOR_GYRO_3D |
66 | depends on HID_SENSOR_HUB | 77 | depends on HID_SENSOR_HUB |
diff --git a/drivers/iio/gyro/Makefile b/drivers/iio/gyro/Makefile index f46341b39139..f866a4be0667 100644 --- a/drivers/iio/gyro/Makefile +++ b/drivers/iio/gyro/Makefile | |||
@@ -8,7 +8,9 @@ obj-$(CONFIG_ADIS16130) += adis16130.o | |||
8 | obj-$(CONFIG_ADIS16136) += adis16136.o | 8 | obj-$(CONFIG_ADIS16136) += adis16136.o |
9 | obj-$(CONFIG_ADIS16260) += adis16260.o | 9 | obj-$(CONFIG_ADIS16260) += adis16260.o |
10 | obj-$(CONFIG_ADXRS450) += adxrs450.o | 10 | obj-$(CONFIG_ADXRS450) += adxrs450.o |
11 | obj-$(CONFIG_BMG160) += bmg160.o | 11 | obj-$(CONFIG_BMG160) += bmg160_core.o |
12 | obj-$(CONFIG_BMG160_I2C) += bmg160_i2c.o | ||
13 | obj-$(CONFIG_BMG160_SPI) += bmg160_spi.o | ||
12 | 14 | ||
13 | obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o | 15 | obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o |
14 | 16 | ||
diff --git a/drivers/iio/gyro/bmg160.h b/drivers/iio/gyro/bmg160.h new file mode 100644 index 000000000000..72db723c8fb6 --- /dev/null +++ b/drivers/iio/gyro/bmg160.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef BMG160_H_ | ||
2 | #define BMG160_H_ | ||
3 | |||
4 | extern const struct dev_pm_ops bmg160_pm_ops; | ||
5 | |||
6 | int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq, | ||
7 | const char *name); | ||
8 | void bmg160_core_remove(struct device *dev); | ||
9 | |||
10 | #endif /* BMG160_H_ */ | ||
diff --git a/drivers/iio/gyro/bmg160.c b/drivers/iio/gyro/bmg160_core.c index 460bf715d541..02ff789852a0 100644 --- a/drivers/iio/gyro/bmg160.c +++ b/drivers/iio/gyro/bmg160_core.c | |||
@@ -13,7 +13,6 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/i2c.h> | ||
17 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
18 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
19 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
@@ -28,8 +27,9 @@ | |||
28 | #include <linux/iio/events.h> | 27 | #include <linux/iio/events.h> |
29 | #include <linux/iio/trigger_consumer.h> | 28 | #include <linux/iio/trigger_consumer.h> |
30 | #include <linux/iio/triggered_buffer.h> | 29 | #include <linux/iio/triggered_buffer.h> |
30 | #include <linux/regmap.h> | ||
31 | #include "bmg160.h" | ||
31 | 32 | ||
32 | #define BMG160_DRV_NAME "bmg160" | ||
33 | #define BMG160_IRQ_NAME "bmg160_event" | 33 | #define BMG160_IRQ_NAME "bmg160_event" |
34 | #define BMG160_GPIO_NAME "gpio_int" | 34 | #define BMG160_GPIO_NAME "gpio_int" |
35 | 35 | ||
@@ -97,7 +97,8 @@ | |||
97 | #define BMG160_AUTO_SUSPEND_DELAY_MS 2000 | 97 | #define BMG160_AUTO_SUSPEND_DELAY_MS 2000 |
98 | 98 | ||
99 | struct bmg160_data { | 99 | struct bmg160_data { |
100 | struct i2c_client *client; | 100 | struct device *dev; |
101 | struct regmap *regmap; | ||
101 | struct iio_trigger *dready_trig; | 102 | struct iio_trigger *dready_trig; |
102 | struct iio_trigger *motion_trig; | 103 | struct iio_trigger *motion_trig; |
103 | struct mutex mutex; | 104 | struct mutex mutex; |
@@ -108,6 +109,7 @@ struct bmg160_data { | |||
108 | int slope_thres; | 109 | int slope_thres; |
109 | bool dready_trigger_on; | 110 | bool dready_trigger_on; |
110 | bool motion_trigger_on; | 111 | bool motion_trigger_on; |
112 | int irq; | ||
111 | }; | 113 | }; |
112 | 114 | ||
113 | enum bmg160_axis { | 115 | enum bmg160_axis { |
@@ -138,10 +140,9 @@ static int bmg160_set_mode(struct bmg160_data *data, u8 mode) | |||
138 | { | 140 | { |
139 | int ret; | 141 | int ret; |
140 | 142 | ||
141 | ret = i2c_smbus_write_byte_data(data->client, | 143 | ret = regmap_write(data->regmap, BMG160_REG_PMU_LPW, mode); |
142 | BMG160_REG_PMU_LPW, mode); | ||
143 | if (ret < 0) { | 144 | if (ret < 0) { |
144 | dev_err(&data->client->dev, "Error writing reg_pmu_lpw\n"); | 145 | dev_err(data->dev, "Error writing reg_pmu_lpw\n"); |
145 | return ret; | 146 | return ret; |
146 | } | 147 | } |
147 | 148 | ||
@@ -169,10 +170,9 @@ static int bmg160_set_bw(struct bmg160_data *data, int val) | |||
169 | if (bw_bits < 0) | 170 | if (bw_bits < 0) |
170 | return bw_bits; | 171 | return bw_bits; |
171 | 172 | ||
172 | ret = i2c_smbus_write_byte_data(data->client, BMG160_REG_PMU_BW, | 173 | ret = regmap_write(data->regmap, BMG160_REG_PMU_BW, bw_bits); |
173 | bw_bits); | ||
174 | if (ret < 0) { | 174 | if (ret < 0) { |
175 | dev_err(&data->client->dev, "Error writing reg_pmu_bw\n"); | 175 | dev_err(data->dev, "Error writing reg_pmu_bw\n"); |
176 | return ret; | 176 | return ret; |
177 | } | 177 | } |
178 | 178 | ||
@@ -184,16 +184,17 @@ static int bmg160_set_bw(struct bmg160_data *data, int val) | |||
184 | static int bmg160_chip_init(struct bmg160_data *data) | 184 | static int bmg160_chip_init(struct bmg160_data *data) |
185 | { | 185 | { |
186 | int ret; | 186 | int ret; |
187 | unsigned int val; | ||
187 | 188 | ||
188 | ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_CHIP_ID); | 189 | ret = regmap_read(data->regmap, BMG160_REG_CHIP_ID, &val); |
189 | if (ret < 0) { | 190 | if (ret < 0) { |
190 | dev_err(&data->client->dev, "Error reading reg_chip_id\n"); | 191 | dev_err(data->dev, "Error reading reg_chip_id\n"); |
191 | return ret; | 192 | return ret; |
192 | } | 193 | } |
193 | 194 | ||
194 | dev_dbg(&data->client->dev, "Chip Id %x\n", ret); | 195 | dev_dbg(data->dev, "Chip Id %x\n", val); |
195 | if (ret != BMG160_CHIP_ID_VAL) { | 196 | if (val != BMG160_CHIP_ID_VAL) { |
196 | dev_err(&data->client->dev, "invalid chip %x\n", ret); | 197 | dev_err(data->dev, "invalid chip %x\n", val); |
197 | return -ENODEV; | 198 | return -ENODEV; |
198 | } | 199 | } |
199 | 200 | ||
@@ -210,42 +211,33 @@ static int bmg160_chip_init(struct bmg160_data *data) | |||
210 | return ret; | 211 | return ret; |
211 | 212 | ||
212 | /* Set Default Range */ | 213 | /* Set Default Range */ |
213 | ret = i2c_smbus_write_byte_data(data->client, | 214 | ret = regmap_write(data->regmap, BMG160_REG_RANGE, BMG160_RANGE_500DPS); |
214 | BMG160_REG_RANGE, | ||
215 | BMG160_RANGE_500DPS); | ||
216 | if (ret < 0) { | 215 | if (ret < 0) { |
217 | dev_err(&data->client->dev, "Error writing reg_range\n"); | 216 | dev_err(data->dev, "Error writing reg_range\n"); |
218 | return ret; | 217 | return ret; |
219 | } | 218 | } |
220 | data->dps_range = BMG160_RANGE_500DPS; | 219 | data->dps_range = BMG160_RANGE_500DPS; |
221 | 220 | ||
222 | ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_SLOPE_THRES); | 221 | ret = regmap_read(data->regmap, BMG160_REG_SLOPE_THRES, &val); |
223 | if (ret < 0) { | 222 | if (ret < 0) { |
224 | dev_err(&data->client->dev, "Error reading reg_slope_thres\n"); | 223 | dev_err(data->dev, "Error reading reg_slope_thres\n"); |
225 | return ret; | 224 | return ret; |
226 | } | 225 | } |
227 | data->slope_thres = ret; | 226 | data->slope_thres = val; |
228 | 227 | ||
229 | /* Set default interrupt mode */ | 228 | /* Set default interrupt mode */ |
230 | ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_INT_EN_1); | 229 | ret = regmap_update_bits(data->regmap, BMG160_REG_INT_EN_1, |
230 | BMG160_INT1_BIT_OD, 0); | ||
231 | if (ret < 0) { | 231 | if (ret < 0) { |
232 | dev_err(&data->client->dev, "Error reading reg_int_en_1\n"); | 232 | dev_err(data->dev, "Error updating bits in reg_int_en_1\n"); |
233 | return ret; | ||
234 | } | ||
235 | ret &= ~BMG160_INT1_BIT_OD; | ||
236 | ret = i2c_smbus_write_byte_data(data->client, | ||
237 | BMG160_REG_INT_EN_1, ret); | ||
238 | if (ret < 0) { | ||
239 | dev_err(&data->client->dev, "Error writing reg_int_en_1\n"); | ||
240 | return ret; | 233 | return ret; |
241 | } | 234 | } |
242 | 235 | ||
243 | ret = i2c_smbus_write_byte_data(data->client, | 236 | ret = regmap_write(data->regmap, BMG160_REG_INT_RST_LATCH, |
244 | BMG160_REG_INT_RST_LATCH, | 237 | BMG160_INT_MODE_LATCH_INT | |
245 | BMG160_INT_MODE_LATCH_INT | | 238 | BMG160_INT_MODE_LATCH_RESET); |
246 | BMG160_INT_MODE_LATCH_RESET); | ||
247 | if (ret < 0) { | 239 | if (ret < 0) { |
248 | dev_err(&data->client->dev, | 240 | dev_err(data->dev, |
249 | "Error writing reg_motion_intr\n"); | 241 | "Error writing reg_motion_intr\n"); |
250 | return ret; | 242 | return ret; |
251 | } | 243 | } |
@@ -259,17 +251,17 @@ static int bmg160_set_power_state(struct bmg160_data *data, bool on) | |||
259 | int ret; | 251 | int ret; |
260 | 252 | ||
261 | if (on) | 253 | if (on) |
262 | ret = pm_runtime_get_sync(&data->client->dev); | 254 | ret = pm_runtime_get_sync(data->dev); |
263 | else { | 255 | else { |
264 | pm_runtime_mark_last_busy(&data->client->dev); | 256 | pm_runtime_mark_last_busy(data->dev); |
265 | ret = pm_runtime_put_autosuspend(&data->client->dev); | 257 | ret = pm_runtime_put_autosuspend(data->dev); |
266 | } | 258 | } |
267 | 259 | ||
268 | if (ret < 0) { | 260 | if (ret < 0) { |
269 | dev_err(&data->client->dev, | 261 | dev_err(data->dev, |
270 | "Failed: bmg160_set_power_state for %d\n", on); | 262 | "Failed: bmg160_set_power_state for %d\n", on); |
271 | if (on) | 263 | if (on) |
272 | pm_runtime_put_noidle(&data->client->dev); | 264 | pm_runtime_put_noidle(data->dev); |
273 | 265 | ||
274 | return ret; | 266 | return ret; |
275 | } | 267 | } |
@@ -284,43 +276,30 @@ static int bmg160_setup_any_motion_interrupt(struct bmg160_data *data, | |||
284 | int ret; | 276 | int ret; |
285 | 277 | ||
286 | /* Enable/Disable INT_MAP0 mapping */ | 278 | /* Enable/Disable INT_MAP0 mapping */ |
287 | ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_INT_MAP_0); | 279 | ret = regmap_update_bits(data->regmap, BMG160_REG_INT_MAP_0, |
288 | if (ret < 0) { | 280 | BMG160_INT_MAP_0_BIT_ANY, |
289 | dev_err(&data->client->dev, "Error reading reg_int_map0\n"); | 281 | (status ? BMG160_INT_MAP_0_BIT_ANY : 0)); |
290 | return ret; | ||
291 | } | ||
292 | if (status) | ||
293 | ret |= BMG160_INT_MAP_0_BIT_ANY; | ||
294 | else | ||
295 | ret &= ~BMG160_INT_MAP_0_BIT_ANY; | ||
296 | |||
297 | ret = i2c_smbus_write_byte_data(data->client, | ||
298 | BMG160_REG_INT_MAP_0, | ||
299 | ret); | ||
300 | if (ret < 0) { | 282 | if (ret < 0) { |
301 | dev_err(&data->client->dev, "Error writing reg_int_map0\n"); | 283 | dev_err(data->dev, "Error updating bits reg_int_map0\n"); |
302 | return ret; | 284 | return ret; |
303 | } | 285 | } |
304 | 286 | ||
305 | /* Enable/Disable slope interrupts */ | 287 | /* Enable/Disable slope interrupts */ |
306 | if (status) { | 288 | if (status) { |
307 | /* Update slope thres */ | 289 | /* Update slope thres */ |
308 | ret = i2c_smbus_write_byte_data(data->client, | 290 | ret = regmap_write(data->regmap, BMG160_REG_SLOPE_THRES, |
309 | BMG160_REG_SLOPE_THRES, | 291 | data->slope_thres); |
310 | data->slope_thres); | ||
311 | if (ret < 0) { | 292 | if (ret < 0) { |
312 | dev_err(&data->client->dev, | 293 | dev_err(data->dev, |
313 | "Error writing reg_slope_thres\n"); | 294 | "Error writing reg_slope_thres\n"); |
314 | return ret; | 295 | return ret; |
315 | } | 296 | } |
316 | 297 | ||
317 | ret = i2c_smbus_write_byte_data(data->client, | 298 | ret = regmap_write(data->regmap, BMG160_REG_MOTION_INTR, |
318 | BMG160_REG_MOTION_INTR, | 299 | BMG160_INT_MOTION_X | BMG160_INT_MOTION_Y | |
319 | BMG160_INT_MOTION_X | | 300 | BMG160_INT_MOTION_Z); |
320 | BMG160_INT_MOTION_Y | | ||
321 | BMG160_INT_MOTION_Z); | ||
322 | if (ret < 0) { | 301 | if (ret < 0) { |
323 | dev_err(&data->client->dev, | 302 | dev_err(data->dev, |
324 | "Error writing reg_motion_intr\n"); | 303 | "Error writing reg_motion_intr\n"); |
325 | return ret; | 304 | return ret; |
326 | } | 305 | } |
@@ -331,28 +310,26 @@ static int bmg160_setup_any_motion_interrupt(struct bmg160_data *data, | |||
331 | * to set latched mode, we will be flooded anyway with INTR | 310 | * to set latched mode, we will be flooded anyway with INTR |
332 | */ | 311 | */ |
333 | if (!data->dready_trigger_on) { | 312 | if (!data->dready_trigger_on) { |
334 | ret = i2c_smbus_write_byte_data(data->client, | 313 | ret = regmap_write(data->regmap, |
335 | BMG160_REG_INT_RST_LATCH, | 314 | BMG160_REG_INT_RST_LATCH, |
336 | BMG160_INT_MODE_LATCH_INT | | 315 | BMG160_INT_MODE_LATCH_INT | |
337 | BMG160_INT_MODE_LATCH_RESET); | 316 | BMG160_INT_MODE_LATCH_RESET); |
338 | if (ret < 0) { | 317 | if (ret < 0) { |
339 | dev_err(&data->client->dev, | 318 | dev_err(data->dev, |
340 | "Error writing reg_rst_latch\n"); | 319 | "Error writing reg_rst_latch\n"); |
341 | return ret; | 320 | return ret; |
342 | } | 321 | } |
343 | } | 322 | } |
344 | 323 | ||
345 | ret = i2c_smbus_write_byte_data(data->client, | 324 | ret = regmap_write(data->regmap, BMG160_REG_INT_EN_0, |
346 | BMG160_REG_INT_EN_0, | 325 | BMG160_DATA_ENABLE_INT); |
347 | BMG160_DATA_ENABLE_INT); | ||
348 | 326 | ||
349 | } else | 327 | } else { |
350 | ret = i2c_smbus_write_byte_data(data->client, | 328 | ret = regmap_write(data->regmap, BMG160_REG_INT_EN_0, 0); |
351 | BMG160_REG_INT_EN_0, | 329 | } |
352 | 0); | ||
353 | 330 | ||
354 | if (ret < 0) { | 331 | if (ret < 0) { |
355 | dev_err(&data->client->dev, "Error writing reg_int_en0\n"); | 332 | dev_err(data->dev, "Error writing reg_int_en0\n"); |
356 | return ret; | 333 | return ret; |
357 | } | 334 | } |
358 | 335 | ||
@@ -365,59 +342,43 @@ static int bmg160_setup_new_data_interrupt(struct bmg160_data *data, | |||
365 | int ret; | 342 | int ret; |
366 | 343 | ||
367 | /* Enable/Disable INT_MAP1 mapping */ | 344 | /* Enable/Disable INT_MAP1 mapping */ |
368 | ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_INT_MAP_1); | 345 | ret = regmap_update_bits(data->regmap, BMG160_REG_INT_MAP_1, |
369 | if (ret < 0) { | 346 | BMG160_INT_MAP_1_BIT_NEW_DATA, |
370 | dev_err(&data->client->dev, "Error reading reg_int_map1\n"); | 347 | (status ? BMG160_INT_MAP_1_BIT_NEW_DATA : 0)); |
371 | return ret; | ||
372 | } | ||
373 | |||
374 | if (status) | ||
375 | ret |= BMG160_INT_MAP_1_BIT_NEW_DATA; | ||
376 | else | ||
377 | ret &= ~BMG160_INT_MAP_1_BIT_NEW_DATA; | ||
378 | |||
379 | ret = i2c_smbus_write_byte_data(data->client, | ||
380 | BMG160_REG_INT_MAP_1, | ||
381 | ret); | ||
382 | if (ret < 0) { | 348 | if (ret < 0) { |
383 | dev_err(&data->client->dev, "Error writing reg_int_map1\n"); | 349 | dev_err(data->dev, "Error updating bits in reg_int_map1\n"); |
384 | return ret; | 350 | return ret; |
385 | } | 351 | } |
386 | 352 | ||
387 | if (status) { | 353 | if (status) { |
388 | ret = i2c_smbus_write_byte_data(data->client, | 354 | ret = regmap_write(data->regmap, BMG160_REG_INT_RST_LATCH, |
389 | BMG160_REG_INT_RST_LATCH, | 355 | BMG160_INT_MODE_NON_LATCH_INT | |
390 | BMG160_INT_MODE_NON_LATCH_INT | | 356 | BMG160_INT_MODE_LATCH_RESET); |
391 | BMG160_INT_MODE_LATCH_RESET); | ||
392 | if (ret < 0) { | 357 | if (ret < 0) { |
393 | dev_err(&data->client->dev, | 358 | dev_err(data->dev, |
394 | "Error writing reg_rst_latch\n"); | 359 | "Error writing reg_rst_latch\n"); |
395 | return ret; | 360 | return ret; |
396 | } | 361 | } |
397 | 362 | ||
398 | ret = i2c_smbus_write_byte_data(data->client, | 363 | ret = regmap_write(data->regmap, BMG160_REG_INT_EN_0, |
399 | BMG160_REG_INT_EN_0, | 364 | BMG160_DATA_ENABLE_INT); |
400 | BMG160_DATA_ENABLE_INT); | ||
401 | 365 | ||
402 | } else { | 366 | } else { |
403 | /* Restore interrupt mode */ | 367 | /* Restore interrupt mode */ |
404 | ret = i2c_smbus_write_byte_data(data->client, | 368 | ret = regmap_write(data->regmap, BMG160_REG_INT_RST_LATCH, |
405 | BMG160_REG_INT_RST_LATCH, | 369 | BMG160_INT_MODE_LATCH_INT | |
406 | BMG160_INT_MODE_LATCH_INT | | 370 | BMG160_INT_MODE_LATCH_RESET); |
407 | BMG160_INT_MODE_LATCH_RESET); | ||
408 | if (ret < 0) { | 371 | if (ret < 0) { |
409 | dev_err(&data->client->dev, | 372 | dev_err(data->dev, |
410 | "Error writing reg_rst_latch\n"); | 373 | "Error writing reg_rst_latch\n"); |
411 | return ret; | 374 | return ret; |
412 | } | 375 | } |
413 | 376 | ||
414 | ret = i2c_smbus_write_byte_data(data->client, | 377 | ret = regmap_write(data->regmap, BMG160_REG_INT_EN_0, 0); |
415 | BMG160_REG_INT_EN_0, | ||
416 | 0); | ||
417 | } | 378 | } |
418 | 379 | ||
419 | if (ret < 0) { | 380 | if (ret < 0) { |
420 | dev_err(&data->client->dev, "Error writing reg_int_en0\n"); | 381 | dev_err(data->dev, "Error writing reg_int_en0\n"); |
421 | return ret; | 382 | return ret; |
422 | } | 383 | } |
423 | 384 | ||
@@ -444,12 +405,10 @@ static int bmg160_set_scale(struct bmg160_data *data, int val) | |||
444 | 405 | ||
445 | for (i = 0; i < ARRAY_SIZE(bmg160_scale_table); ++i) { | 406 | for (i = 0; i < ARRAY_SIZE(bmg160_scale_table); ++i) { |
446 | if (bmg160_scale_table[i].scale == val) { | 407 | if (bmg160_scale_table[i].scale == val) { |
447 | ret = i2c_smbus_write_byte_data( | 408 | ret = regmap_write(data->regmap, BMG160_REG_RANGE, |
448 | data->client, | 409 | bmg160_scale_table[i].dps_range); |
449 | BMG160_REG_RANGE, | ||
450 | bmg160_scale_table[i].dps_range); | ||
451 | if (ret < 0) { | 410 | if (ret < 0) { |
452 | dev_err(&data->client->dev, | 411 | dev_err(data->dev, |
453 | "Error writing reg_range\n"); | 412 | "Error writing reg_range\n"); |
454 | return ret; | 413 | return ret; |
455 | } | 414 | } |
@@ -464,6 +423,7 @@ static int bmg160_set_scale(struct bmg160_data *data, int val) | |||
464 | static int bmg160_get_temp(struct bmg160_data *data, int *val) | 423 | static int bmg160_get_temp(struct bmg160_data *data, int *val) |
465 | { | 424 | { |
466 | int ret; | 425 | int ret; |
426 | unsigned int raw_val; | ||
467 | 427 | ||
468 | mutex_lock(&data->mutex); | 428 | mutex_lock(&data->mutex); |
469 | ret = bmg160_set_power_state(data, true); | 429 | ret = bmg160_set_power_state(data, true); |
@@ -472,15 +432,15 @@ static int bmg160_get_temp(struct bmg160_data *data, int *val) | |||
472 | return ret; | 432 | return ret; |
473 | } | 433 | } |
474 | 434 | ||
475 | ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_TEMP); | 435 | ret = regmap_read(data->regmap, BMG160_REG_TEMP, &raw_val); |
476 | if (ret < 0) { | 436 | if (ret < 0) { |
477 | dev_err(&data->client->dev, "Error reading reg_temp\n"); | 437 | dev_err(data->dev, "Error reading reg_temp\n"); |
478 | bmg160_set_power_state(data, false); | 438 | bmg160_set_power_state(data, false); |
479 | mutex_unlock(&data->mutex); | 439 | mutex_unlock(&data->mutex); |
480 | return ret; | 440 | return ret; |
481 | } | 441 | } |
482 | 442 | ||
483 | *val = sign_extend32(ret, 7); | 443 | *val = sign_extend32(raw_val, 7); |
484 | ret = bmg160_set_power_state(data, false); | 444 | ret = bmg160_set_power_state(data, false); |
485 | mutex_unlock(&data->mutex); | 445 | mutex_unlock(&data->mutex); |
486 | if (ret < 0) | 446 | if (ret < 0) |
@@ -492,6 +452,7 @@ static int bmg160_get_temp(struct bmg160_data *data, int *val) | |||
492 | static int bmg160_get_axis(struct bmg160_data *data, int axis, int *val) | 452 | static int bmg160_get_axis(struct bmg160_data *data, int axis, int *val) |
493 | { | 453 | { |
494 | int ret; | 454 | int ret; |
455 | unsigned int raw_val; | ||
495 | 456 | ||
496 | mutex_lock(&data->mutex); | 457 | mutex_lock(&data->mutex); |
497 | ret = bmg160_set_power_state(data, true); | 458 | ret = bmg160_set_power_state(data, true); |
@@ -500,15 +461,16 @@ static int bmg160_get_axis(struct bmg160_data *data, int axis, int *val) | |||
500 | return ret; | 461 | return ret; |
501 | } | 462 | } |
502 | 463 | ||
503 | ret = i2c_smbus_read_word_data(data->client, BMG160_AXIS_TO_REG(axis)); | 464 | ret = regmap_bulk_read(data->regmap, BMG160_AXIS_TO_REG(axis), &raw_val, |
465 | 2); | ||
504 | if (ret < 0) { | 466 | if (ret < 0) { |
505 | dev_err(&data->client->dev, "Error reading axis %d\n", axis); | 467 | dev_err(data->dev, "Error reading axis %d\n", axis); |
506 | bmg160_set_power_state(data, false); | 468 | bmg160_set_power_state(data, false); |
507 | mutex_unlock(&data->mutex); | 469 | mutex_unlock(&data->mutex); |
508 | return ret; | 470 | return ret; |
509 | } | 471 | } |
510 | 472 | ||
511 | *val = sign_extend32(ret, 15); | 473 | *val = sign_extend32(raw_val, 15); |
512 | ret = bmg160_set_power_state(data, false); | 474 | ret = bmg160_set_power_state(data, false); |
513 | mutex_unlock(&data->mutex); | 475 | mutex_unlock(&data->mutex); |
514 | if (ret < 0) | 476 | if (ret < 0) |
@@ -807,12 +769,13 @@ static irqreturn_t bmg160_trigger_handler(int irq, void *p) | |||
807 | struct iio_dev *indio_dev = pf->indio_dev; | 769 | struct iio_dev *indio_dev = pf->indio_dev; |
808 | struct bmg160_data *data = iio_priv(indio_dev); | 770 | struct bmg160_data *data = iio_priv(indio_dev); |
809 | int bit, ret, i = 0; | 771 | int bit, ret, i = 0; |
772 | unsigned int val; | ||
810 | 773 | ||
811 | mutex_lock(&data->mutex); | 774 | mutex_lock(&data->mutex); |
812 | for_each_set_bit(bit, indio_dev->active_scan_mask, | 775 | for_each_set_bit(bit, indio_dev->active_scan_mask, |
813 | indio_dev->masklength) { | 776 | indio_dev->masklength) { |
814 | ret = i2c_smbus_read_word_data(data->client, | 777 | ret = regmap_bulk_read(data->regmap, BMG160_AXIS_TO_REG(bit), |
815 | BMG160_AXIS_TO_REG(bit)); | 778 | &val, 2); |
816 | if (ret < 0) { | 779 | if (ret < 0) { |
817 | mutex_unlock(&data->mutex); | 780 | mutex_unlock(&data->mutex); |
818 | goto err; | 781 | goto err; |
@@ -840,12 +803,11 @@ static int bmg160_trig_try_reen(struct iio_trigger *trig) | |||
840 | return 0; | 803 | return 0; |
841 | 804 | ||
842 | /* Set latched mode interrupt and clear any latched interrupt */ | 805 | /* Set latched mode interrupt and clear any latched interrupt */ |
843 | ret = i2c_smbus_write_byte_data(data->client, | 806 | ret = regmap_write(data->regmap, BMG160_REG_INT_RST_LATCH, |
844 | BMG160_REG_INT_RST_LATCH, | 807 | BMG160_INT_MODE_LATCH_INT | |
845 | BMG160_INT_MODE_LATCH_INT | | 808 | BMG160_INT_MODE_LATCH_RESET); |
846 | BMG160_INT_MODE_LATCH_RESET); | ||
847 | if (ret < 0) { | 809 | if (ret < 0) { |
848 | dev_err(&data->client->dev, "Error writing reg_rst_latch\n"); | 810 | dev_err(data->dev, "Error writing reg_rst_latch\n"); |
849 | return ret; | 811 | return ret; |
850 | } | 812 | } |
851 | 813 | ||
@@ -907,33 +869,34 @@ static irqreturn_t bmg160_event_handler(int irq, void *private) | |||
907 | struct bmg160_data *data = iio_priv(indio_dev); | 869 | struct bmg160_data *data = iio_priv(indio_dev); |
908 | int ret; | 870 | int ret; |
909 | int dir; | 871 | int dir; |
872 | unsigned int val; | ||
910 | 873 | ||
911 | ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_INT_STATUS_2); | 874 | ret = regmap_read(data->regmap, BMG160_REG_INT_STATUS_2, &val); |
912 | if (ret < 0) { | 875 | if (ret < 0) { |
913 | dev_err(&data->client->dev, "Error reading reg_int_status2\n"); | 876 | dev_err(data->dev, "Error reading reg_int_status2\n"); |
914 | goto ack_intr_status; | 877 | goto ack_intr_status; |
915 | } | 878 | } |
916 | 879 | ||
917 | if (ret & 0x08) | 880 | if (val & 0x08) |
918 | dir = IIO_EV_DIR_RISING; | 881 | dir = IIO_EV_DIR_RISING; |
919 | else | 882 | else |
920 | dir = IIO_EV_DIR_FALLING; | 883 | dir = IIO_EV_DIR_FALLING; |
921 | 884 | ||
922 | if (ret & BMG160_ANY_MOTION_BIT_X) | 885 | if (val & BMG160_ANY_MOTION_BIT_X) |
923 | iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL, | 886 | iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL, |
924 | 0, | 887 | 0, |
925 | IIO_MOD_X, | 888 | IIO_MOD_X, |
926 | IIO_EV_TYPE_ROC, | 889 | IIO_EV_TYPE_ROC, |
927 | dir), | 890 | dir), |
928 | iio_get_time_ns()); | 891 | iio_get_time_ns()); |
929 | if (ret & BMG160_ANY_MOTION_BIT_Y) | 892 | if (val & BMG160_ANY_MOTION_BIT_Y) |
930 | iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL, | 893 | iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL, |
931 | 0, | 894 | 0, |
932 | IIO_MOD_Y, | 895 | IIO_MOD_Y, |
933 | IIO_EV_TYPE_ROC, | 896 | IIO_EV_TYPE_ROC, |
934 | dir), | 897 | dir), |
935 | iio_get_time_ns()); | 898 | iio_get_time_ns()); |
936 | if (ret & BMG160_ANY_MOTION_BIT_Z) | 899 | if (val & BMG160_ANY_MOTION_BIT_Z) |
937 | iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL, | 900 | iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL, |
938 | 0, | 901 | 0, |
939 | IIO_MOD_Z, | 902 | IIO_MOD_Z, |
@@ -943,12 +906,11 @@ static irqreturn_t bmg160_event_handler(int irq, void *private) | |||
943 | 906 | ||
944 | ack_intr_status: | 907 | ack_intr_status: |
945 | if (!data->dready_trigger_on) { | 908 | if (!data->dready_trigger_on) { |
946 | ret = i2c_smbus_write_byte_data(data->client, | 909 | ret = regmap_write(data->regmap, BMG160_REG_INT_RST_LATCH, |
947 | BMG160_REG_INT_RST_LATCH, | 910 | BMG160_INT_MODE_LATCH_INT | |
948 | BMG160_INT_MODE_LATCH_INT | | 911 | BMG160_INT_MODE_LATCH_RESET); |
949 | BMG160_INT_MODE_LATCH_RESET); | ||
950 | if (ret < 0) | 912 | if (ret < 0) |
951 | dev_err(&data->client->dev, | 913 | dev_err(data->dev, |
952 | "Error writing reg_rst_latch\n"); | 914 | "Error writing reg_rst_latch\n"); |
953 | } | 915 | } |
954 | 916 | ||
@@ -993,18 +955,13 @@ static const struct iio_buffer_setup_ops bmg160_buffer_setup_ops = { | |||
993 | .postdisable = bmg160_buffer_postdisable, | 955 | .postdisable = bmg160_buffer_postdisable, |
994 | }; | 956 | }; |
995 | 957 | ||
996 | static int bmg160_gpio_probe(struct i2c_client *client, | 958 | static int bmg160_gpio_probe(struct bmg160_data *data) |
997 | struct bmg160_data *data) | ||
998 | 959 | ||
999 | { | 960 | { |
1000 | struct device *dev; | 961 | struct device *dev; |
1001 | struct gpio_desc *gpio; | 962 | struct gpio_desc *gpio; |
1002 | int ret; | ||
1003 | |||
1004 | if (!client) | ||
1005 | return -EINVAL; | ||
1006 | 963 | ||
1007 | dev = &client->dev; | 964 | dev = data->dev; |
1008 | 965 | ||
1009 | /* data ready gpio interrupt pin */ | 966 | /* data ready gpio interrupt pin */ |
1010 | gpio = devm_gpiod_get_index(dev, BMG160_GPIO_NAME, 0, GPIOD_IN); | 967 | gpio = devm_gpiod_get_index(dev, BMG160_GPIO_NAME, 0, GPIOD_IN); |
@@ -1013,11 +970,12 @@ static int bmg160_gpio_probe(struct i2c_client *client, | |||
1013 | return PTR_ERR(gpio); | 970 | return PTR_ERR(gpio); |
1014 | } | 971 | } |
1015 | 972 | ||
1016 | ret = gpiod_to_irq(gpio); | 973 | data->irq = gpiod_to_irq(gpio); |
1017 | 974 | ||
1018 | dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); | 975 | dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), |
976 | data->irq); | ||
1019 | 977 | ||
1020 | return ret; | 978 | return 0; |
1021 | } | 979 | } |
1022 | 980 | ||
1023 | static const char *bmg160_match_acpi_device(struct device *dev) | 981 | static const char *bmg160_match_acpi_device(struct device *dev) |
@@ -1031,21 +989,22 @@ static const char *bmg160_match_acpi_device(struct device *dev) | |||
1031 | return dev_name(dev); | 989 | return dev_name(dev); |
1032 | } | 990 | } |
1033 | 991 | ||
1034 | static int bmg160_probe(struct i2c_client *client, | 992 | int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq, |
1035 | const struct i2c_device_id *id) | 993 | const char *name) |
1036 | { | 994 | { |
1037 | struct bmg160_data *data; | 995 | struct bmg160_data *data; |
1038 | struct iio_dev *indio_dev; | 996 | struct iio_dev *indio_dev; |
1039 | int ret; | 997 | int ret; |
1040 | const char *name = NULL; | ||
1041 | 998 | ||
1042 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | 999 | indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); |
1043 | if (!indio_dev) | 1000 | if (!indio_dev) |
1044 | return -ENOMEM; | 1001 | return -ENOMEM; |
1045 | 1002 | ||
1046 | data = iio_priv(indio_dev); | 1003 | data = iio_priv(indio_dev); |
1047 | i2c_set_clientdata(client, indio_dev); | 1004 | dev_set_drvdata(dev, indio_dev); |
1048 | data->client = client; | 1005 | data->dev = dev; |
1006 | data->irq = irq; | ||
1007 | data->regmap = regmap; | ||
1049 | 1008 | ||
1050 | ret = bmg160_chip_init(data); | 1009 | ret = bmg160_chip_init(data); |
1051 | if (ret < 0) | 1010 | if (ret < 0) |
@@ -1053,25 +1012,22 @@ static int bmg160_probe(struct i2c_client *client, | |||
1053 | 1012 | ||
1054 | mutex_init(&data->mutex); | 1013 | mutex_init(&data->mutex); |
1055 | 1014 | ||
1056 | if (id) | 1015 | if (ACPI_HANDLE(dev)) |
1057 | name = id->name; | 1016 | name = bmg160_match_acpi_device(dev); |
1058 | 1017 | ||
1059 | if (ACPI_HANDLE(&client->dev)) | 1018 | indio_dev->dev.parent = dev; |
1060 | name = bmg160_match_acpi_device(&client->dev); | ||
1061 | |||
1062 | indio_dev->dev.parent = &client->dev; | ||
1063 | indio_dev->channels = bmg160_channels; | 1019 | indio_dev->channels = bmg160_channels; |
1064 | indio_dev->num_channels = ARRAY_SIZE(bmg160_channels); | 1020 | indio_dev->num_channels = ARRAY_SIZE(bmg160_channels); |
1065 | indio_dev->name = name; | 1021 | indio_dev->name = name; |
1066 | indio_dev->modes = INDIO_DIRECT_MODE; | 1022 | indio_dev->modes = INDIO_DIRECT_MODE; |
1067 | indio_dev->info = &bmg160_info; | 1023 | indio_dev->info = &bmg160_info; |
1068 | 1024 | ||
1069 | if (client->irq <= 0) | 1025 | if (data->irq <= 0) |
1070 | client->irq = bmg160_gpio_probe(client, data); | 1026 | bmg160_gpio_probe(data); |
1071 | 1027 | ||
1072 | if (client->irq > 0) { | 1028 | if (data->irq > 0) { |
1073 | ret = devm_request_threaded_irq(&client->dev, | 1029 | ret = devm_request_threaded_irq(dev, |
1074 | client->irq, | 1030 | data->irq, |
1075 | bmg160_data_rdy_trig_poll, | 1031 | bmg160_data_rdy_trig_poll, |
1076 | bmg160_event_handler, | 1032 | bmg160_event_handler, |
1077 | IRQF_TRIGGER_RISING, | 1033 | IRQF_TRIGGER_RISING, |
@@ -1080,28 +1036,28 @@ static int bmg160_probe(struct i2c_client *client, | |||
1080 | if (ret) | 1036 | if (ret) |
1081 | return ret; | 1037 | return ret; |
1082 | 1038 | ||
1083 | data->dready_trig = devm_iio_trigger_alloc(&client->dev, | 1039 | data->dready_trig = devm_iio_trigger_alloc(dev, |
1084 | "%s-dev%d", | 1040 | "%s-dev%d", |
1085 | indio_dev->name, | 1041 | indio_dev->name, |
1086 | indio_dev->id); | 1042 | indio_dev->id); |
1087 | if (!data->dready_trig) | 1043 | if (!data->dready_trig) |
1088 | return -ENOMEM; | 1044 | return -ENOMEM; |
1089 | 1045 | ||
1090 | data->motion_trig = devm_iio_trigger_alloc(&client->dev, | 1046 | data->motion_trig = devm_iio_trigger_alloc(dev, |
1091 | "%s-any-motion-dev%d", | 1047 | "%s-any-motion-dev%d", |
1092 | indio_dev->name, | 1048 | indio_dev->name, |
1093 | indio_dev->id); | 1049 | indio_dev->id); |
1094 | if (!data->motion_trig) | 1050 | if (!data->motion_trig) |
1095 | return -ENOMEM; | 1051 | return -ENOMEM; |
1096 | 1052 | ||
1097 | data->dready_trig->dev.parent = &client->dev; | 1053 | data->dready_trig->dev.parent = dev; |
1098 | data->dready_trig->ops = &bmg160_trigger_ops; | 1054 | data->dready_trig->ops = &bmg160_trigger_ops; |
1099 | iio_trigger_set_drvdata(data->dready_trig, indio_dev); | 1055 | iio_trigger_set_drvdata(data->dready_trig, indio_dev); |
1100 | ret = iio_trigger_register(data->dready_trig); | 1056 | ret = iio_trigger_register(data->dready_trig); |
1101 | if (ret) | 1057 | if (ret) |
1102 | return ret; | 1058 | return ret; |
1103 | 1059 | ||
1104 | data->motion_trig->dev.parent = &client->dev; | 1060 | data->motion_trig->dev.parent = dev; |
1105 | data->motion_trig->ops = &bmg160_trigger_ops; | 1061 | data->motion_trig->ops = &bmg160_trigger_ops; |
1106 | iio_trigger_set_drvdata(data->motion_trig, indio_dev); | 1062 | iio_trigger_set_drvdata(data->motion_trig, indio_dev); |
1107 | ret = iio_trigger_register(data->motion_trig); | 1063 | ret = iio_trigger_register(data->motion_trig); |
@@ -1116,25 +1072,25 @@ static int bmg160_probe(struct i2c_client *client, | |||
1116 | bmg160_trigger_handler, | 1072 | bmg160_trigger_handler, |
1117 | &bmg160_buffer_setup_ops); | 1073 | &bmg160_buffer_setup_ops); |
1118 | if (ret < 0) { | 1074 | if (ret < 0) { |
1119 | dev_err(&client->dev, | 1075 | dev_err(dev, |
1120 | "iio triggered buffer setup failed\n"); | 1076 | "iio triggered buffer setup failed\n"); |
1121 | goto err_trigger_unregister; | 1077 | goto err_trigger_unregister; |
1122 | } | 1078 | } |
1123 | 1079 | ||
1124 | ret = iio_device_register(indio_dev); | 1080 | ret = iio_device_register(indio_dev); |
1125 | if (ret < 0) { | 1081 | if (ret < 0) { |
1126 | dev_err(&client->dev, "unable to register iio device\n"); | 1082 | dev_err(dev, "unable to register iio device\n"); |
1127 | goto err_buffer_cleanup; | 1083 | goto err_buffer_cleanup; |
1128 | } | 1084 | } |
1129 | 1085 | ||
1130 | ret = pm_runtime_set_active(&client->dev); | 1086 | ret = pm_runtime_set_active(dev); |
1131 | if (ret) | 1087 | if (ret) |
1132 | goto err_iio_unregister; | 1088 | goto err_iio_unregister; |
1133 | 1089 | ||
1134 | pm_runtime_enable(&client->dev); | 1090 | pm_runtime_enable(dev); |
1135 | pm_runtime_set_autosuspend_delay(&client->dev, | 1091 | pm_runtime_set_autosuspend_delay(dev, |
1136 | BMG160_AUTO_SUSPEND_DELAY_MS); | 1092 | BMG160_AUTO_SUSPEND_DELAY_MS); |
1137 | pm_runtime_use_autosuspend(&client->dev); | 1093 | pm_runtime_use_autosuspend(dev); |
1138 | 1094 | ||
1139 | return 0; | 1095 | return 0; |
1140 | 1096 | ||
@@ -1150,15 +1106,16 @@ err_trigger_unregister: | |||
1150 | 1106 | ||
1151 | return ret; | 1107 | return ret; |
1152 | } | 1108 | } |
1109 | EXPORT_SYMBOL_GPL(bmg160_core_probe); | ||
1153 | 1110 | ||
1154 | static int bmg160_remove(struct i2c_client *client) | 1111 | void bmg160_core_remove(struct device *dev) |
1155 | { | 1112 | { |
1156 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | 1113 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
1157 | struct bmg160_data *data = iio_priv(indio_dev); | 1114 | struct bmg160_data *data = iio_priv(indio_dev); |
1158 | 1115 | ||
1159 | pm_runtime_disable(&client->dev); | 1116 | pm_runtime_disable(dev); |
1160 | pm_runtime_set_suspended(&client->dev); | 1117 | pm_runtime_set_suspended(dev); |
1161 | pm_runtime_put_noidle(&client->dev); | 1118 | pm_runtime_put_noidle(dev); |
1162 | 1119 | ||
1163 | iio_device_unregister(indio_dev); | 1120 | iio_device_unregister(indio_dev); |
1164 | iio_triggered_buffer_cleanup(indio_dev); | 1121 | iio_triggered_buffer_cleanup(indio_dev); |
@@ -1171,14 +1128,13 @@ static int bmg160_remove(struct i2c_client *client) | |||
1171 | mutex_lock(&data->mutex); | 1128 | mutex_lock(&data->mutex); |
1172 | bmg160_set_mode(data, BMG160_MODE_DEEP_SUSPEND); | 1129 | bmg160_set_mode(data, BMG160_MODE_DEEP_SUSPEND); |
1173 | mutex_unlock(&data->mutex); | 1130 | mutex_unlock(&data->mutex); |
1174 | |||
1175 | return 0; | ||
1176 | } | 1131 | } |
1132 | EXPORT_SYMBOL_GPL(bmg160_core_remove); | ||
1177 | 1133 | ||
1178 | #ifdef CONFIG_PM_SLEEP | 1134 | #ifdef CONFIG_PM_SLEEP |
1179 | static int bmg160_suspend(struct device *dev) | 1135 | static int bmg160_suspend(struct device *dev) |
1180 | { | 1136 | { |
1181 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | 1137 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
1182 | struct bmg160_data *data = iio_priv(indio_dev); | 1138 | struct bmg160_data *data = iio_priv(indio_dev); |
1183 | 1139 | ||
1184 | mutex_lock(&data->mutex); | 1140 | mutex_lock(&data->mutex); |
@@ -1190,7 +1146,7 @@ static int bmg160_suspend(struct device *dev) | |||
1190 | 1146 | ||
1191 | static int bmg160_resume(struct device *dev) | 1147 | static int bmg160_resume(struct device *dev) |
1192 | { | 1148 | { |
1193 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | 1149 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
1194 | struct bmg160_data *data = iio_priv(indio_dev); | 1150 | struct bmg160_data *data = iio_priv(indio_dev); |
1195 | 1151 | ||
1196 | mutex_lock(&data->mutex); | 1152 | mutex_lock(&data->mutex); |
@@ -1206,13 +1162,13 @@ static int bmg160_resume(struct device *dev) | |||
1206 | #ifdef CONFIG_PM | 1162 | #ifdef CONFIG_PM |
1207 | static int bmg160_runtime_suspend(struct device *dev) | 1163 | static int bmg160_runtime_suspend(struct device *dev) |
1208 | { | 1164 | { |
1209 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | 1165 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
1210 | struct bmg160_data *data = iio_priv(indio_dev); | 1166 | struct bmg160_data *data = iio_priv(indio_dev); |
1211 | int ret; | 1167 | int ret; |
1212 | 1168 | ||
1213 | ret = bmg160_set_mode(data, BMG160_MODE_SUSPEND); | 1169 | ret = bmg160_set_mode(data, BMG160_MODE_SUSPEND); |
1214 | if (ret < 0) { | 1170 | if (ret < 0) { |
1215 | dev_err(&data->client->dev, "set mode failed\n"); | 1171 | dev_err(data->dev, "set mode failed\n"); |
1216 | return -EAGAIN; | 1172 | return -EAGAIN; |
1217 | } | 1173 | } |
1218 | 1174 | ||
@@ -1221,7 +1177,7 @@ static int bmg160_runtime_suspend(struct device *dev) | |||
1221 | 1177 | ||
1222 | static int bmg160_runtime_resume(struct device *dev) | 1178 | static int bmg160_runtime_resume(struct device *dev) |
1223 | { | 1179 | { |
1224 | struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | 1180 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
1225 | struct bmg160_data *data = iio_priv(indio_dev); | 1181 | struct bmg160_data *data = iio_priv(indio_dev); |
1226 | int ret; | 1182 | int ret; |
1227 | 1183 | ||
@@ -1235,39 +1191,12 @@ static int bmg160_runtime_resume(struct device *dev) | |||
1235 | } | 1191 | } |
1236 | #endif | 1192 | #endif |
1237 | 1193 | ||
1238 | static const struct dev_pm_ops bmg160_pm_ops = { | 1194 | const struct dev_pm_ops bmg160_pm_ops = { |
1239 | SET_SYSTEM_SLEEP_PM_OPS(bmg160_suspend, bmg160_resume) | 1195 | SET_SYSTEM_SLEEP_PM_OPS(bmg160_suspend, bmg160_resume) |
1240 | SET_RUNTIME_PM_OPS(bmg160_runtime_suspend, | 1196 | SET_RUNTIME_PM_OPS(bmg160_runtime_suspend, |
1241 | bmg160_runtime_resume, NULL) | 1197 | bmg160_runtime_resume, NULL) |
1242 | }; | 1198 | }; |
1243 | 1199 | EXPORT_SYMBOL_GPL(bmg160_pm_ops); | |
1244 | static const struct acpi_device_id bmg160_acpi_match[] = { | ||
1245 | {"BMG0160", 0}, | ||
1246 | {"BMI055B", 0}, | ||
1247 | {}, | ||
1248 | }; | ||
1249 | |||
1250 | MODULE_DEVICE_TABLE(acpi, bmg160_acpi_match); | ||
1251 | |||
1252 | static const struct i2c_device_id bmg160_id[] = { | ||
1253 | {"bmg160", 0}, | ||
1254 | {"bmi055_gyro", 0}, | ||
1255 | {} | ||
1256 | }; | ||
1257 | |||
1258 | MODULE_DEVICE_TABLE(i2c, bmg160_id); | ||
1259 | |||
1260 | static struct i2c_driver bmg160_driver = { | ||
1261 | .driver = { | ||
1262 | .name = BMG160_DRV_NAME, | ||
1263 | .acpi_match_table = ACPI_PTR(bmg160_acpi_match), | ||
1264 | .pm = &bmg160_pm_ops, | ||
1265 | }, | ||
1266 | .probe = bmg160_probe, | ||
1267 | .remove = bmg160_remove, | ||
1268 | .id_table = bmg160_id, | ||
1269 | }; | ||
1270 | module_i2c_driver(bmg160_driver); | ||
1271 | 1200 | ||
1272 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); | 1201 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); |
1273 | MODULE_LICENSE("GPL v2"); | 1202 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/iio/gyro/bmg160_i2c.c b/drivers/iio/gyro/bmg160_i2c.c new file mode 100644 index 000000000000..90126a5a7663 --- /dev/null +++ b/drivers/iio/gyro/bmg160_i2c.c | |||
@@ -0,0 +1,71 @@ | |||
1 | #include <linux/i2c.h> | ||
2 | #include <linux/regmap.h> | ||
3 | #include <linux/iio/iio.h> | ||
4 | #include <linux/module.h> | ||
5 | #include <linux/acpi.h> | ||
6 | |||
7 | #include "bmg160.h" | ||
8 | |||
9 | static const struct regmap_config bmg160_regmap_i2c_conf = { | ||
10 | .reg_bits = 8, | ||
11 | .val_bits = 8, | ||
12 | .max_register = 0x3f | ||
13 | }; | ||
14 | |||
15 | static int bmg160_i2c_probe(struct i2c_client *client, | ||
16 | const struct i2c_device_id *id) | ||
17 | { | ||
18 | struct regmap *regmap; | ||
19 | const char *name = NULL; | ||
20 | |||
21 | regmap = devm_regmap_init_i2c(client, &bmg160_regmap_i2c_conf); | ||
22 | if (IS_ERR(regmap)) { | ||
23 | dev_err(&client->dev, "Failed to register i2c regmap %d\n", | ||
24 | (int)PTR_ERR(regmap)); | ||
25 | return PTR_ERR(regmap); | ||
26 | } | ||
27 | |||
28 | if (id) | ||
29 | name = id->name; | ||
30 | |||
31 | return bmg160_core_probe(&client->dev, regmap, client->irq, name); | ||
32 | } | ||
33 | |||
34 | static int bmg160_i2c_remove(struct i2c_client *client) | ||
35 | { | ||
36 | bmg160_core_remove(&client->dev); | ||
37 | |||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | static const struct acpi_device_id bmg160_acpi_match[] = { | ||
42 | {"BMG0160", 0}, | ||
43 | {"BMI055B", 0}, | ||
44 | {}, | ||
45 | }; | ||
46 | |||
47 | MODULE_DEVICE_TABLE(acpi, bmg160_acpi_match); | ||
48 | |||
49 | static const struct i2c_device_id bmg160_i2c_id[] = { | ||
50 | {"bmg160", 0}, | ||
51 | {"bmi055_gyro", 0}, | ||
52 | {} | ||
53 | }; | ||
54 | |||
55 | MODULE_DEVICE_TABLE(i2c, bmg160_i2c_id); | ||
56 | |||
57 | static struct i2c_driver bmg160_i2c_driver = { | ||
58 | .driver = { | ||
59 | .name = "bmg160_i2c", | ||
60 | .acpi_match_table = ACPI_PTR(bmg160_acpi_match), | ||
61 | .pm = &bmg160_pm_ops, | ||
62 | }, | ||
63 | .probe = bmg160_i2c_probe, | ||
64 | .remove = bmg160_i2c_remove, | ||
65 | .id_table = bmg160_i2c_id, | ||
66 | }; | ||
67 | module_i2c_driver(bmg160_i2c_driver); | ||
68 | |||
69 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); | ||
70 | MODULE_LICENSE("GPL v2"); | ||
71 | MODULE_DESCRIPTION("BMG160 I2C Gyro driver"); | ||
diff --git a/drivers/iio/gyro/bmg160_spi.c b/drivers/iio/gyro/bmg160_spi.c new file mode 100644 index 000000000000..021ea5fe6a37 --- /dev/null +++ b/drivers/iio/gyro/bmg160_spi.c | |||
@@ -0,0 +1,57 @@ | |||
1 | #include <linux/spi/spi.h> | ||
2 | #include <linux/regmap.h> | ||
3 | #include <linux/iio/iio.h> | ||
4 | #include <linux/module.h> | ||
5 | |||
6 | #include "bmg160.h" | ||
7 | |||
8 | static const struct regmap_config bmg160_regmap_spi_conf = { | ||
9 | .reg_bits = 8, | ||
10 | .val_bits = 8, | ||
11 | .max_register = 0x3f, | ||
12 | }; | ||
13 | |||
14 | static int bmg160_spi_probe(struct spi_device *spi) | ||
15 | { | ||
16 | struct regmap *regmap; | ||
17 | const struct spi_device_id *id = spi_get_device_id(spi); | ||
18 | |||
19 | regmap = devm_regmap_init_spi(spi, &bmg160_regmap_spi_conf); | ||
20 | if (IS_ERR(regmap)) { | ||
21 | dev_err(&spi->dev, "Failed to register spi regmap %d\n", | ||
22 | (int)PTR_ERR(regmap)); | ||
23 | return PTR_ERR(regmap); | ||
24 | } | ||
25 | |||
26 | return bmg160_core_probe(&spi->dev, regmap, spi->irq, id->name); | ||
27 | } | ||
28 | |||
29 | static int bmg160_spi_remove(struct spi_device *spi) | ||
30 | { | ||
31 | bmg160_core_remove(&spi->dev); | ||
32 | |||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | static const struct spi_device_id bmg160_spi_id[] = { | ||
37 | {"bmg160", 0}, | ||
38 | {"bmi055_gyro", 0}, | ||
39 | {} | ||
40 | }; | ||
41 | |||
42 | MODULE_DEVICE_TABLE(spi, bmg160_spi_id); | ||
43 | |||
44 | static struct spi_driver bmg160_spi_driver = { | ||
45 | .driver = { | ||
46 | .name = "bmg160_spi", | ||
47 | .pm = &bmg160_pm_ops, | ||
48 | }, | ||
49 | .probe = bmg160_spi_probe, | ||
50 | .remove = bmg160_spi_remove, | ||
51 | .id_table = bmg160_spi_id, | ||
52 | }; | ||
53 | module_spi_driver(bmg160_spi_driver); | ||
54 | |||
55 | MODULE_AUTHOR("Markus Pargmann <mpa@pengutronix.de>"); | ||
56 | MODULE_LICENSE("GPL v2"); | ||
57 | MODULE_DESCRIPTION("BMG160 SPI Gyro driver"); | ||
diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index 4b993a5bc9a1..02eddcebeea3 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c | |||
@@ -383,6 +383,7 @@ static const struct iio_info gyro_info = { | |||
383 | .attrs = &st_gyro_attribute_group, | 383 | .attrs = &st_gyro_attribute_group, |
384 | .read_raw = &st_gyro_read_raw, | 384 | .read_raw = &st_gyro_read_raw, |
385 | .write_raw = &st_gyro_write_raw, | 385 | .write_raw = &st_gyro_write_raw, |
386 | .debugfs_reg_access = &st_sensors_debugfs_reg_access, | ||
386 | }; | 387 | }; |
387 | 388 | ||
388 | #ifdef CONFIG_IIO_TRIGGER | 389 | #ifdef CONFIG_IIO_TRIGGER |
diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig index 688c0d1cb47d..353ee9ade95d 100644 --- a/drivers/iio/humidity/Kconfig +++ b/drivers/iio/humidity/Kconfig | |||
@@ -12,6 +12,16 @@ config DHT11 | |||
12 | Other sensors should work as well as long as they speak the | 12 | Other sensors should work as well as long as they speak the |
13 | same protocol. | 13 | same protocol. |
14 | 14 | ||
15 | config HDC100X | ||
16 | tristate "TI HDC100x relative humidity and temperature sensor" | ||
17 | depends on I2C | ||
18 | help | ||
19 | Say yes here to build support for the TI HDC100x series of | ||
20 | relative humidity and temperature sensors. | ||
21 | |||
22 | To compile this driver as a module, choose M here: the module | ||
23 | will be called hdc100x. | ||
24 | |||
15 | config SI7005 | 25 | config SI7005 |
16 | tristate "SI7005 relative humidity and temperature sensor" | 26 | tristate "SI7005 relative humidity and temperature sensor" |
17 | depends on I2C | 27 | depends on I2C |
diff --git a/drivers/iio/humidity/Makefile b/drivers/iio/humidity/Makefile index 86e2d26e9f4d..3e62c0a12d5e 100644 --- a/drivers/iio/humidity/Makefile +++ b/drivers/iio/humidity/Makefile | |||
@@ -3,5 +3,6 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_DHT11) += dht11.o | 5 | obj-$(CONFIG_DHT11) += dht11.o |
6 | obj-$(CONFIG_HDC100X) += hdc100x.o | ||
6 | obj-$(CONFIG_SI7005) += si7005.o | 7 | obj-$(CONFIG_SI7005) += si7005.o |
7 | obj-$(CONFIG_SI7020) += si7020.o | 8 | obj-$(CONFIG_SI7020) += si7020.o |
diff --git a/drivers/iio/humidity/hdc100x.c b/drivers/iio/humidity/hdc100x.c new file mode 100644 index 000000000000..28245782ecfb --- /dev/null +++ b/drivers/iio/humidity/hdc100x.c | |||
@@ -0,0 +1,319 @@ | |||
1 | /* | ||
2 | * hdc100x.c - Support for the TI HDC100x temperature + humidity sensors | ||
3 | * | ||
4 | * Copyright (C) 2015 Matt Ranostay <mranostay@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/delay.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/i2c.h> | ||
22 | |||
23 | #include <linux/iio/iio.h> | ||
24 | #include <linux/iio/sysfs.h> | ||
25 | |||
26 | #define HDC100X_REG_TEMP 0x00 | ||
27 | #define HDC100X_REG_HUMIDITY 0x01 | ||
28 | |||
29 | #define HDC100X_REG_CONFIG 0x02 | ||
30 | #define HDC100X_REG_CONFIG_HEATER_EN BIT(13) | ||
31 | |||
32 | struct hdc100x_data { | ||
33 | struct i2c_client *client; | ||
34 | struct mutex lock; | ||
35 | u16 config; | ||
36 | |||
37 | /* integration time of the sensor */ | ||
38 | int adc_int_us[2]; | ||
39 | }; | ||
40 | |||
41 | /* integration time in us */ | ||
42 | static const int hdc100x_int_time[][3] = { | ||
43 | { 6350, 3650, 0 }, /* IIO_TEMP channel*/ | ||
44 | { 6500, 3850, 2500 }, /* IIO_HUMIDITYRELATIVE channel */ | ||
45 | }; | ||
46 | |||
47 | /* HDC100X_REG_CONFIG shift and mask values */ | ||
48 | static const struct { | ||
49 | int shift; | ||
50 | int mask; | ||
51 | } hdc100x_resolution_shift[2] = { | ||
52 | { /* IIO_TEMP channel */ | ||
53 | .shift = 10, | ||
54 | .mask = 1 | ||
55 | }, | ||
56 | { /* IIO_HUMIDITYRELATIVE channel */ | ||
57 | .shift = 8, | ||
58 | .mask = 2, | ||
59 | }, | ||
60 | }; | ||
61 | |||
62 | static IIO_CONST_ATTR(temp_integration_time_available, | ||
63 | "0.00365 0.00635"); | ||
64 | |||
65 | static IIO_CONST_ATTR(humidityrelative_integration_time_available, | ||
66 | "0.0025 0.00385 0.0065"); | ||
67 | |||
68 | static IIO_CONST_ATTR(out_current_heater_raw_available, | ||
69 | "0 1"); | ||
70 | |||
71 | static struct attribute *hdc100x_attributes[] = { | ||
72 | &iio_const_attr_temp_integration_time_available.dev_attr.attr, | ||
73 | &iio_const_attr_humidityrelative_integration_time_available.dev_attr.attr, | ||
74 | &iio_const_attr_out_current_heater_raw_available.dev_attr.attr, | ||
75 | NULL | ||
76 | }; | ||
77 | |||
78 | static struct attribute_group hdc100x_attribute_group = { | ||
79 | .attrs = hdc100x_attributes, | ||
80 | }; | ||
81 | |||
82 | static const struct iio_chan_spec hdc100x_channels[] = { | ||
83 | { | ||
84 | .type = IIO_TEMP, | ||
85 | .address = HDC100X_REG_TEMP, | ||
86 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | ||
87 | BIT(IIO_CHAN_INFO_SCALE) | | ||
88 | BIT(IIO_CHAN_INFO_INT_TIME) | | ||
89 | BIT(IIO_CHAN_INFO_OFFSET), | ||
90 | }, | ||
91 | { | ||
92 | .type = IIO_HUMIDITYRELATIVE, | ||
93 | .address = HDC100X_REG_HUMIDITY, | ||
94 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | ||
95 | BIT(IIO_CHAN_INFO_SCALE) | | ||
96 | BIT(IIO_CHAN_INFO_INT_TIME) | ||
97 | }, | ||
98 | { | ||
99 | .type = IIO_CURRENT, | ||
100 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
101 | .extend_name = "heater", | ||
102 | .output = 1, | ||
103 | }, | ||
104 | }; | ||
105 | |||
106 | static int hdc100x_update_config(struct hdc100x_data *data, int mask, int val) | ||
107 | { | ||
108 | int tmp = (~mask & data->config) | val; | ||
109 | int ret; | ||
110 | |||
111 | ret = i2c_smbus_write_word_swapped(data->client, | ||
112 | HDC100X_REG_CONFIG, tmp); | ||
113 | if (!ret) | ||
114 | data->config = tmp; | ||
115 | |||
116 | return ret; | ||
117 | } | ||
118 | |||
119 | static int hdc100x_set_it_time(struct hdc100x_data *data, int chan, int val2) | ||
120 | { | ||
121 | int shift = hdc100x_resolution_shift[chan].shift; | ||
122 | int ret = -EINVAL; | ||
123 | int i; | ||
124 | |||
125 | for (i = 0; i < ARRAY_SIZE(hdc100x_int_time[chan]); i++) { | ||
126 | if (val2 && val2 == hdc100x_int_time[chan][i]) { | ||
127 | ret = hdc100x_update_config(data, | ||
128 | hdc100x_resolution_shift[chan].mask << shift, | ||
129 | i << shift); | ||
130 | if (!ret) | ||
131 | data->adc_int_us[chan] = val2; | ||
132 | break; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | return ret; | ||
137 | } | ||
138 | |||
139 | static int hdc100x_get_measurement(struct hdc100x_data *data, | ||
140 | struct iio_chan_spec const *chan) | ||
141 | { | ||
142 | struct i2c_client *client = data->client; | ||
143 | int delay = data->adc_int_us[chan->address]; | ||
144 | int ret; | ||
145 | int val; | ||
146 | |||
147 | /* start measurement */ | ||
148 | ret = i2c_smbus_write_byte(client, chan->address); | ||
149 | if (ret < 0) { | ||
150 | dev_err(&client->dev, "cannot start measurement"); | ||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | /* wait for integration time to pass */ | ||
155 | usleep_range(delay, delay + 1000); | ||
156 | |||
157 | /* | ||
158 | * i2c_smbus_read_word_data cannot() be used here due to the command | ||
159 | * value not being understood and causes NAKs preventing any reading | ||
160 | * from being accessed. | ||
161 | */ | ||
162 | ret = i2c_smbus_read_byte(client); | ||
163 | if (ret < 0) { | ||
164 | dev_err(&client->dev, "cannot read high byte measurement"); | ||
165 | return ret; | ||
166 | } | ||
167 | val = ret << 6; | ||
168 | |||
169 | ret = i2c_smbus_read_byte(client); | ||
170 | if (ret < 0) { | ||
171 | dev_err(&client->dev, "cannot read low byte measurement"); | ||
172 | return ret; | ||
173 | } | ||
174 | val |= ret >> 2; | ||
175 | |||
176 | return val; | ||
177 | } | ||
178 | |||
179 | static int hdc100x_get_heater_status(struct hdc100x_data *data) | ||
180 | { | ||
181 | return !!(data->config & HDC100X_REG_CONFIG_HEATER_EN); | ||
182 | } | ||
183 | |||
184 | static int hdc100x_read_raw(struct iio_dev *indio_dev, | ||
185 | struct iio_chan_spec const *chan, int *val, | ||
186 | int *val2, long mask) | ||
187 | { | ||
188 | struct hdc100x_data *data = iio_priv(indio_dev); | ||
189 | |||
190 | switch (mask) { | ||
191 | case IIO_CHAN_INFO_RAW: { | ||
192 | int ret; | ||
193 | |||
194 | mutex_lock(&data->lock); | ||
195 | if (chan->type == IIO_CURRENT) { | ||
196 | *val = hdc100x_get_heater_status(data); | ||
197 | ret = IIO_VAL_INT; | ||
198 | } else { | ||
199 | ret = hdc100x_get_measurement(data, chan); | ||
200 | if (ret >= 0) { | ||
201 | *val = ret; | ||
202 | ret = IIO_VAL_INT; | ||
203 | } | ||
204 | } | ||
205 | mutex_unlock(&data->lock); | ||
206 | return ret; | ||
207 | } | ||
208 | case IIO_CHAN_INFO_INT_TIME: | ||
209 | *val = 0; | ||
210 | *val2 = data->adc_int_us[chan->address]; | ||
211 | return IIO_VAL_INT_PLUS_MICRO; | ||
212 | case IIO_CHAN_INFO_SCALE: | ||
213 | if (chan->type == IIO_TEMP) { | ||
214 | *val = 165; | ||
215 | *val2 = 65536 >> 2; | ||
216 | return IIO_VAL_FRACTIONAL; | ||
217 | } else { | ||
218 | *val = 0; | ||
219 | *val2 = 10000; | ||
220 | return IIO_VAL_INT_PLUS_MICRO; | ||
221 | } | ||
222 | break; | ||
223 | case IIO_CHAN_INFO_OFFSET: | ||
224 | *val = -40; | ||
225 | return IIO_VAL_INT; | ||
226 | default: | ||
227 | return -EINVAL; | ||
228 | } | ||
229 | } | ||
230 | |||
231 | static int hdc100x_write_raw(struct iio_dev *indio_dev, | ||
232 | struct iio_chan_spec const *chan, | ||
233 | int val, int val2, long mask) | ||
234 | { | ||
235 | struct hdc100x_data *data = iio_priv(indio_dev); | ||
236 | int ret = -EINVAL; | ||
237 | |||
238 | switch (mask) { | ||
239 | case IIO_CHAN_INFO_INT_TIME: | ||
240 | if (val != 0) | ||
241 | return -EINVAL; | ||
242 | |||
243 | mutex_lock(&data->lock); | ||
244 | ret = hdc100x_set_it_time(data, chan->address, val2); | ||
245 | mutex_unlock(&data->lock); | ||
246 | return ret; | ||
247 | case IIO_CHAN_INFO_RAW: | ||
248 | if (chan->type != IIO_CURRENT || val2 != 0) | ||
249 | return -EINVAL; | ||
250 | |||
251 | mutex_lock(&data->lock); | ||
252 | ret = hdc100x_update_config(data, HDC100X_REG_CONFIG_HEATER_EN, | ||
253 | val ? HDC100X_REG_CONFIG_HEATER_EN : 0); | ||
254 | mutex_unlock(&data->lock); | ||
255 | return ret; | ||
256 | default: | ||
257 | return -EINVAL; | ||
258 | } | ||
259 | } | ||
260 | |||
261 | static const struct iio_info hdc100x_info = { | ||
262 | .read_raw = hdc100x_read_raw, | ||
263 | .write_raw = hdc100x_write_raw, | ||
264 | .attrs = &hdc100x_attribute_group, | ||
265 | .driver_module = THIS_MODULE, | ||
266 | }; | ||
267 | |||
268 | static int hdc100x_probe(struct i2c_client *client, | ||
269 | const struct i2c_device_id *id) | ||
270 | { | ||
271 | struct iio_dev *indio_dev; | ||
272 | struct hdc100x_data *data; | ||
273 | |||
274 | if (!i2c_check_functionality(client->adapter, | ||
275 | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BYTE)) | ||
276 | return -ENODEV; | ||
277 | |||
278 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | ||
279 | if (!indio_dev) | ||
280 | return -ENOMEM; | ||
281 | |||
282 | data = iio_priv(indio_dev); | ||
283 | i2c_set_clientdata(client, indio_dev); | ||
284 | data->client = client; | ||
285 | mutex_init(&data->lock); | ||
286 | |||
287 | indio_dev->dev.parent = &client->dev; | ||
288 | indio_dev->name = dev_name(&client->dev); | ||
289 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
290 | indio_dev->info = &hdc100x_info; | ||
291 | |||
292 | indio_dev->channels = hdc100x_channels; | ||
293 | indio_dev->num_channels = ARRAY_SIZE(hdc100x_channels); | ||
294 | |||
295 | /* be sure we are in a known state */ | ||
296 | hdc100x_set_it_time(data, 0, hdc100x_int_time[0][0]); | ||
297 | hdc100x_set_it_time(data, 1, hdc100x_int_time[1][0]); | ||
298 | |||
299 | return devm_iio_device_register(&client->dev, indio_dev); | ||
300 | } | ||
301 | |||
302 | static const struct i2c_device_id hdc100x_id[] = { | ||
303 | { "hdc100x", 0 }, | ||
304 | { } | ||
305 | }; | ||
306 | MODULE_DEVICE_TABLE(i2c, hdc100x_id); | ||
307 | |||
308 | static struct i2c_driver hdc100x_driver = { | ||
309 | .driver = { | ||
310 | .name = "hdc100x", | ||
311 | }, | ||
312 | .probe = hdc100x_probe, | ||
313 | .id_table = hdc100x_id, | ||
314 | }; | ||
315 | module_i2c_driver(hdc100x_driver); | ||
316 | |||
317 | MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>"); | ||
318 | MODULE_DESCRIPTION("TI HDC100x humidity and temperature sensor driver"); | ||
319 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/iio/humidity/si7020.c b/drivers/iio/humidity/si7020.c index fa3b809aff5e..12128d1ca570 100644 --- a/drivers/iio/humidity/si7020.c +++ b/drivers/iio/humidity/si7020.c | |||
@@ -57,8 +57,12 @@ static int si7020_read_raw(struct iio_dev *indio_dev, | |||
57 | if (ret < 0) | 57 | if (ret < 0) |
58 | return ret; | 58 | return ret; |
59 | *val = ret >> 2; | 59 | *val = ret >> 2; |
60 | /* | ||
61 | * Humidity values can slightly exceed the 0-100%RH | ||
62 | * range and should be corrected by software | ||
63 | */ | ||
60 | if (chan->type == IIO_HUMIDITYRELATIVE) | 64 | if (chan->type == IIO_HUMIDITYRELATIVE) |
61 | *val &= GENMASK(11, 0); | 65 | *val = clamp_val(*val, 786, 13893); |
62 | return IIO_VAL_INT; | 66 | return IIO_VAL_INT; |
63 | case IIO_CHAN_INFO_SCALE: | 67 | case IIO_CHAN_INFO_SCALE: |
64 | if (chan->type == IIO_TEMP) | 68 | if (chan->type == IIO_TEMP) |
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index b3fcc2c449d8..208358f9e7e3 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c | |||
@@ -75,6 +75,8 @@ static const char * const iio_chan_type_name_spec[] = { | |||
75 | [IIO_ENERGY] = "energy", | 75 | [IIO_ENERGY] = "energy", |
76 | [IIO_DISTANCE] = "distance", | 76 | [IIO_DISTANCE] = "distance", |
77 | [IIO_VELOCITY] = "velocity", | 77 | [IIO_VELOCITY] = "velocity", |
78 | [IIO_CONCENTRATION] = "concentration", | ||
79 | [IIO_RESISTANCE] = "resistance", | ||
78 | }; | 80 | }; |
79 | 81 | ||
80 | static const char * const iio_modifier_names[] = { | 82 | static const char * const iio_modifier_names[] = { |
@@ -111,6 +113,8 @@ static const char * const iio_modifier_names[] = { | |||
111 | [IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)", | 113 | [IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)", |
112 | [IIO_MOD_I] = "i", | 114 | [IIO_MOD_I] = "i", |
113 | [IIO_MOD_Q] = "q", | 115 | [IIO_MOD_Q] = "q", |
116 | [IIO_MOD_CO2] = "co2", | ||
117 | [IIO_MOD_VOC] = "voc", | ||
114 | }; | 118 | }; |
115 | 119 | ||
116 | /* relies on pairs of these shared then separate */ | 120 | /* relies on pairs of these shared then separate */ |
@@ -962,7 +966,7 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev) | |||
962 | static void iio_dev_release(struct device *device) | 966 | static void iio_dev_release(struct device *device) |
963 | { | 967 | { |
964 | struct iio_dev *indio_dev = dev_to_iio_dev(device); | 968 | struct iio_dev *indio_dev = dev_to_iio_dev(device); |
965 | if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) | 969 | if (indio_dev->modes & (INDIO_BUFFER_TRIGGERED | INDIO_EVENT_TRIGGERED)) |
966 | iio_device_unregister_trigger_consumer(indio_dev); | 970 | iio_device_unregister_trigger_consumer(indio_dev); |
967 | iio_device_unregister_eventset(indio_dev); | 971 | iio_device_unregister_eventset(indio_dev); |
968 | iio_device_unregister_sysfs(indio_dev); | 972 | iio_device_unregister_sysfs(indio_dev); |
@@ -1153,6 +1157,8 @@ static long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
1153 | 1157 | ||
1154 | if (cmd == IIO_GET_EVENT_FD_IOCTL) { | 1158 | if (cmd == IIO_GET_EVENT_FD_IOCTL) { |
1155 | fd = iio_event_getfd(indio_dev); | 1159 | fd = iio_event_getfd(indio_dev); |
1160 | if (fd < 0) | ||
1161 | return fd; | ||
1156 | if (copy_to_user(ip, &fd, sizeof(fd))) | 1162 | if (copy_to_user(ip, &fd, sizeof(fd))) |
1157 | return -EFAULT; | 1163 | return -EFAULT; |
1158 | return 0; | 1164 | return 0; |
@@ -1241,7 +1247,7 @@ int iio_device_register(struct iio_dev *indio_dev) | |||
1241 | "Failed to register event set\n"); | 1247 | "Failed to register event set\n"); |
1242 | goto error_free_sysfs; | 1248 | goto error_free_sysfs; |
1243 | } | 1249 | } |
1244 | if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) | 1250 | if (indio_dev->modes & (INDIO_BUFFER_TRIGGERED | INDIO_EVENT_TRIGGERED)) |
1245 | iio_device_register_trigger_consumer(indio_dev); | 1251 | iio_device_register_trigger_consumer(indio_dev); |
1246 | 1252 | ||
1247 | if ((indio_dev->modes & INDIO_ALL_BUFFER_MODES) && | 1253 | if ((indio_dev->modes & INDIO_ALL_BUFFER_MODES) && |
diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index 570606c2adbd..ae2806aafb72 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c | |||
@@ -366,10 +366,18 @@ static ssize_t iio_trigger_write_current(struct device *dev, | |||
366 | 366 | ||
367 | indio_dev->trig = trig; | 367 | indio_dev->trig = trig; |
368 | 368 | ||
369 | if (oldtrig) | 369 | if (oldtrig) { |
370 | if (indio_dev->modes & INDIO_EVENT_TRIGGERED) | ||
371 | iio_trigger_detach_poll_func(oldtrig, | ||
372 | indio_dev->pollfunc_event); | ||
370 | iio_trigger_put(oldtrig); | 373 | iio_trigger_put(oldtrig); |
371 | if (indio_dev->trig) | 374 | } |
375 | if (indio_dev->trig) { | ||
372 | iio_trigger_get(indio_dev->trig); | 376 | iio_trigger_get(indio_dev->trig); |
377 | if (indio_dev->modes & INDIO_EVENT_TRIGGERED) | ||
378 | iio_trigger_attach_poll_func(indio_dev->trig, | ||
379 | indio_dev->pollfunc_event); | ||
380 | } | ||
373 | 381 | ||
374 | return len; | 382 | return len; |
375 | } | 383 | } |
diff --git a/drivers/iio/industrialio-triggered-event.c b/drivers/iio/industrialio-triggered-event.c new file mode 100644 index 000000000000..8cc254fac16a --- /dev/null +++ b/drivers/iio/industrialio-triggered-event.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Cogent Embedded, Inc. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/export.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/iio/iio.h> | ||
14 | #include <linux/iio/triggered_event.h> | ||
15 | #include <linux/iio/trigger_consumer.h> | ||
16 | |||
17 | /** | ||
18 | * iio_triggered_event_setup() - Setup pollfunc_event for triggered event | ||
19 | * @indio_dev: IIO device structure | ||
20 | * @h: Function which will be used as pollfunc_event top half | ||
21 | * @thread: Function which will be used as pollfunc_event bottom half | ||
22 | * | ||
23 | * This function combines some common tasks which will normally be performed | ||
24 | * when setting up a triggered event. It will allocate the pollfunc_event and | ||
25 | * set mode to use it for triggered event. | ||
26 | * | ||
27 | * Before calling this function the indio_dev structure should already be | ||
28 | * completely initialized, but not yet registered. In practice this means that | ||
29 | * this function should be called right before iio_device_register(). | ||
30 | * | ||
31 | * To free the resources allocated by this function call | ||
32 | * iio_triggered_event_cleanup(). | ||
33 | */ | ||
34 | int iio_triggered_event_setup(struct iio_dev *indio_dev, | ||
35 | irqreturn_t (*h)(int irq, void *p), | ||
36 | irqreturn_t (*thread)(int irq, void *p)) | ||
37 | { | ||
38 | indio_dev->pollfunc_event = iio_alloc_pollfunc(h, | ||
39 | thread, | ||
40 | IRQF_ONESHOT, | ||
41 | indio_dev, | ||
42 | "%s_consumer%d", | ||
43 | indio_dev->name, | ||
44 | indio_dev->id); | ||
45 | if (indio_dev->pollfunc_event == NULL) | ||
46 | return -ENOMEM; | ||
47 | |||
48 | /* Flag that events polling is possible */ | ||
49 | indio_dev->modes |= INDIO_EVENT_TRIGGERED; | ||
50 | |||
51 | return 0; | ||
52 | } | ||
53 | EXPORT_SYMBOL(iio_triggered_event_setup); | ||
54 | |||
55 | /** | ||
56 | * iio_triggered_event_cleanup() - Free resources allocated by iio_triggered_event_setup() | ||
57 | * @indio_dev: IIO device structure | ||
58 | */ | ||
59 | void iio_triggered_event_cleanup(struct iio_dev *indio_dev) | ||
60 | { | ||
61 | indio_dev->modes &= ~INDIO_EVENT_TRIGGERED; | ||
62 | iio_dealloc_pollfunc(indio_dev->pollfunc_event); | ||
63 | } | ||
64 | EXPORT_SYMBOL(iio_triggered_event_cleanup); | ||
65 | |||
66 | MODULE_AUTHOR("Vladimir Barinov"); | ||
67 | MODULE_DESCRIPTION("IIO helper functions for setting up triggered events"); | ||
68 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 7ed859a700c4..cfd3df8416bb 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig | |||
@@ -50,6 +50,19 @@ config APDS9300 | |||
50 | To compile this driver as a module, choose M here: the | 50 | To compile this driver as a module, choose M here: the |
51 | module will be called apds9300. | 51 | module will be called apds9300. |
52 | 52 | ||
53 | config APDS9960 | ||
54 | tristate "Avago APDS9960 gesture/RGB/ALS/proximity sensor" | ||
55 | select REGMAP_I2C | ||
56 | select IIO_BUFFER | ||
57 | select IIO_KFIFO_BUF | ||
58 | depends on I2C | ||
59 | help | ||
60 | Say Y here to build I2C interface support for the Avago | ||
61 | APDS9960 gesture/RGB/ALS/proximity sensor. | ||
62 | |||
63 | To compile this driver as a module, choose M here: the | ||
64 | module will be called apds9960 | ||
65 | |||
53 | config BH1750 | 66 | config BH1750 |
54 | tristate "ROHM BH1750 ambient light sensor" | 67 | tristate "ROHM BH1750 ambient light sensor" |
55 | depends on I2C | 68 | depends on I2C |
@@ -287,6 +300,16 @@ config TSL4531 | |||
287 | To compile this driver as a module, choose M here: the | 300 | To compile this driver as a module, choose M here: the |
288 | module will be called tsl4531. | 301 | module will be called tsl4531. |
289 | 302 | ||
303 | config US5182D | ||
304 | tristate "UPISEMI light and proximity sensor" | ||
305 | depends on I2C | ||
306 | help | ||
307 | If you say yes here you get support for the UPISEMI US5182D | ||
308 | ambient light and proximity sensor. | ||
309 | |||
310 | This driver can also be built as a module. If so, the module | ||
311 | will be called us5182d. | ||
312 | |||
290 | config VCNL4000 | 313 | config VCNL4000 |
291 | tristate "VCNL4000 combined ALS and proximity sensor" | 314 | tristate "VCNL4000 combined ALS and proximity sensor" |
292 | depends on I2C | 315 | depends on I2C |
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index 91c74c014b6f..b2c31053db0c 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile | |||
@@ -7,6 +7,7 @@ obj-$(CONFIG_ACPI_ALS) += acpi-als.o | |||
7 | obj-$(CONFIG_ADJD_S311) += adjd_s311.o | 7 | obj-$(CONFIG_ADJD_S311) += adjd_s311.o |
8 | obj-$(CONFIG_AL3320A) += al3320a.o | 8 | obj-$(CONFIG_AL3320A) += al3320a.o |
9 | obj-$(CONFIG_APDS9300) += apds9300.o | 9 | obj-$(CONFIG_APDS9300) += apds9300.o |
10 | obj-$(CONFIG_APDS9960) += apds9960.o | ||
10 | obj-$(CONFIG_BH1750) += bh1750.o | 11 | obj-$(CONFIG_BH1750) += bh1750.o |
11 | obj-$(CONFIG_CM32181) += cm32181.o | 12 | obj-$(CONFIG_CM32181) += cm32181.o |
12 | obj-$(CONFIG_CM3232) += cm3232.o | 13 | obj-$(CONFIG_CM3232) += cm3232.o |
@@ -27,4 +28,5 @@ obj-$(CONFIG_STK3310) += stk3310.o | |||
27 | obj-$(CONFIG_TCS3414) += tcs3414.o | 28 | obj-$(CONFIG_TCS3414) += tcs3414.o |
28 | obj-$(CONFIG_TCS3472) += tcs3472.o | 29 | obj-$(CONFIG_TCS3472) += tcs3472.o |
29 | obj-$(CONFIG_TSL4531) += tsl4531.o | 30 | obj-$(CONFIG_TSL4531) += tsl4531.o |
31 | obj-$(CONFIG_US5182D) += us5182d.o | ||
30 | obj-$(CONFIG_VCNL4000) += vcnl4000.o | 32 | obj-$(CONFIG_VCNL4000) += vcnl4000.o |
diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c new file mode 100644 index 000000000000..bf80ce47926b --- /dev/null +++ b/drivers/iio/light/apds9960.c | |||
@@ -0,0 +1,1130 @@ | |||
1 | /* | ||
2 | * apds9960.c - Support for Avago APDS9960 gesture/RGB/ALS/proximity sensor | ||
3 | * | ||
4 | * Copyright (C) 2015 Matt Ranostay <mranostay@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * TODO: gesture + proximity calib offsets | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/mutex.h> | ||
24 | #include <linux/err.h> | ||
25 | #include <linux/irq.h> | ||
26 | #include <linux/gpio.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <linux/pm_runtime.h> | ||
29 | #include <linux/regmap.h> | ||
30 | #include <linux/iio/iio.h> | ||
31 | #include <linux/iio/buffer.h> | ||
32 | #include <linux/iio/events.h> | ||
33 | #include <linux/iio/kfifo_buf.h> | ||
34 | #include <linux/iio/sysfs.h> | ||
35 | #include <linux/of_gpio.h> | ||
36 | |||
37 | #define APDS9960_REGMAP_NAME "apds9960_regmap" | ||
38 | #define APDS9960_DRV_NAME "apds9960" | ||
39 | |||
40 | #define APDS9960_REG_RAM_START 0x00 | ||
41 | #define APDS9960_REG_RAM_END 0x7f | ||
42 | |||
43 | #define APDS9960_REG_ENABLE 0x80 | ||
44 | #define APDS9960_REG_ATIME 0x81 | ||
45 | #define APDS9960_REG_WTIME 0x83 | ||
46 | |||
47 | #define APDS9960_REG_AILTL 0x84 | ||
48 | #define APDS9960_REG_AILTH 0x85 | ||
49 | #define APDS9960_REG_AIHTL 0x86 | ||
50 | #define APDS9960_REG_AIHTH 0x87 | ||
51 | |||
52 | #define APDS9960_REG_PILT 0x89 | ||
53 | #define APDS9960_REG_PIHT 0x8b | ||
54 | #define APDS9960_REG_PERS 0x8c | ||
55 | |||
56 | #define APDS9960_REG_CONFIG_1 0x8d | ||
57 | #define APDS9960_REG_PPULSE 0x8e | ||
58 | |||
59 | #define APDS9960_REG_CONTROL 0x8f | ||
60 | #define APDS9960_REG_CONTROL_AGAIN_MASK 0x03 | ||
61 | #define APDS9960_REG_CONTROL_PGAIN_MASK 0x0c | ||
62 | #define APDS9960_REG_CONTROL_AGAIN_MASK_SHIFT 0 | ||
63 | #define APDS9960_REG_CONTROL_PGAIN_MASK_SHIFT 2 | ||
64 | |||
65 | #define APDS9960_REG_CONFIG_2 0x90 | ||
66 | #define APDS9960_REG_CONFIG_2_GGAIN_MASK 0x60 | ||
67 | #define APDS9960_REG_CONFIG_2_GGAIN_MASK_SHIFT 5 | ||
68 | |||
69 | #define APDS9960_REG_ID 0x92 | ||
70 | |||
71 | #define APDS9960_REG_STATUS 0x93 | ||
72 | #define APDS9960_REG_STATUS_PS_INT BIT(5) | ||
73 | #define APDS9960_REG_STATUS_ALS_INT BIT(4) | ||
74 | #define APDS9960_REG_STATUS_GINT BIT(2) | ||
75 | |||
76 | #define APDS9960_REG_PDATA 0x9c | ||
77 | #define APDS9960_REG_POFFSET_UR 0x9d | ||
78 | #define APDS9960_REG_POFFSET_DL 0x9e | ||
79 | #define APDS9960_REG_CONFIG_3 0x9f | ||
80 | |||
81 | #define APDS9960_REG_GPENTH 0xa0 | ||
82 | #define APDS9960_REG_GEXTH 0xa1 | ||
83 | |||
84 | #define APDS9960_REG_GCONF_1 0xa2 | ||
85 | #define APDS9960_REG_GCONF_1_GFIFO_THRES_MASK 0xc0 | ||
86 | #define APDS9960_REG_GCONF_1_GFIFO_THRES_MASK_SHIFT 6 | ||
87 | |||
88 | #define APDS9960_REG_GCONF_2 0xa3 | ||
89 | #define APDS9960_REG_GOFFSET_U 0xa4 | ||
90 | #define APDS9960_REG_GOFFSET_D 0xa5 | ||
91 | #define APDS9960_REG_GPULSE 0xa6 | ||
92 | #define APDS9960_REG_GOFFSET_L 0xa7 | ||
93 | #define APDS9960_REG_GOFFSET_R 0xa9 | ||
94 | #define APDS9960_REG_GCONF_3 0xaa | ||
95 | |||
96 | #define APDS9960_REG_GCONF_4 0xab | ||
97 | #define APDS9960_REG_GFLVL 0xae | ||
98 | #define APDS9960_REG_GSTATUS 0xaf | ||
99 | |||
100 | #define APDS9960_REG_IFORCE 0xe4 | ||
101 | #define APDS9960_REG_PICLEAR 0xe5 | ||
102 | #define APDS9960_REG_CICLEAR 0xe6 | ||
103 | #define APDS9960_REG_AICLEAR 0xe7 | ||
104 | |||
105 | #define APDS9960_DEFAULT_PERS 0x33 | ||
106 | #define APDS9960_DEFAULT_GPENTH 0x50 | ||
107 | #define APDS9960_DEFAULT_GEXTH 0x40 | ||
108 | |||
109 | #define APDS9960_MAX_PXS_THRES_VAL 255 | ||
110 | #define APDS9960_MAX_ALS_THRES_VAL 0xffff | ||
111 | #define APDS9960_MAX_INT_TIME_IN_US 1000000 | ||
112 | |||
113 | enum apds9960_als_channel_idx { | ||
114 | IDX_ALS_CLEAR, IDX_ALS_RED, IDX_ALS_GREEN, IDX_ALS_BLUE, | ||
115 | }; | ||
116 | |||
117 | #define APDS9960_REG_ALS_BASE 0x94 | ||
118 | #define APDS9960_REG_ALS_CHANNEL(_colour) \ | ||
119 | (APDS9960_REG_ALS_BASE + (IDX_ALS_##_colour * 2)) | ||
120 | |||
121 | enum apds9960_gesture_channel_idx { | ||
122 | IDX_DIR_UP, IDX_DIR_DOWN, IDX_DIR_LEFT, IDX_DIR_RIGHT, | ||
123 | }; | ||
124 | |||
125 | #define APDS9960_REG_GFIFO_BASE 0xfc | ||
126 | #define APDS9960_REG_GFIFO_DIR(_dir) \ | ||
127 | (APDS9960_REG_GFIFO_BASE + IDX_DIR_##_dir) | ||
128 | |||
129 | struct apds9960_data { | ||
130 | struct i2c_client *client; | ||
131 | struct iio_dev *indio_dev; | ||
132 | struct mutex lock; | ||
133 | |||
134 | /* regmap fields */ | ||
135 | struct regmap *regmap; | ||
136 | struct regmap_field *reg_int_als; | ||
137 | struct regmap_field *reg_int_ges; | ||
138 | struct regmap_field *reg_int_pxs; | ||
139 | |||
140 | struct regmap_field *reg_enable_als; | ||
141 | struct regmap_field *reg_enable_ges; | ||
142 | struct regmap_field *reg_enable_pxs; | ||
143 | |||
144 | /* state */ | ||
145 | int als_int; | ||
146 | int pxs_int; | ||
147 | int gesture_mode_running; | ||
148 | |||
149 | /* gain values */ | ||
150 | int als_gain; | ||
151 | int pxs_gain; | ||
152 | |||
153 | /* integration time value in us */ | ||
154 | int als_adc_int_us; | ||
155 | |||
156 | /* gesture buffer */ | ||
157 | u8 buffer[4]; /* 4 8-bit channels */ | ||
158 | }; | ||
159 | |||
160 | static const struct reg_default apds9960_reg_defaults[] = { | ||
161 | /* Default ALS integration time = 2.48ms */ | ||
162 | { APDS9960_REG_ATIME, 0xff }, | ||
163 | }; | ||
164 | |||
165 | static const struct regmap_range apds9960_volatile_ranges[] = { | ||
166 | regmap_reg_range(APDS9960_REG_STATUS, | ||
167 | APDS9960_REG_PDATA), | ||
168 | regmap_reg_range(APDS9960_REG_GFLVL, | ||
169 | APDS9960_REG_GSTATUS), | ||
170 | regmap_reg_range(APDS9960_REG_GFIFO_DIR(UP), | ||
171 | APDS9960_REG_GFIFO_DIR(RIGHT)), | ||
172 | regmap_reg_range(APDS9960_REG_IFORCE, | ||
173 | APDS9960_REG_AICLEAR), | ||
174 | }; | ||
175 | |||
176 | static const struct regmap_access_table apds9960_volatile_table = { | ||
177 | .yes_ranges = apds9960_volatile_ranges, | ||
178 | .n_yes_ranges = ARRAY_SIZE(apds9960_volatile_ranges), | ||
179 | }; | ||
180 | |||
181 | static const struct regmap_range apds9960_precious_ranges[] = { | ||
182 | regmap_reg_range(APDS9960_REG_RAM_START, APDS9960_REG_RAM_END), | ||
183 | }; | ||
184 | |||
185 | static const struct regmap_access_table apds9960_precious_table = { | ||
186 | .yes_ranges = apds9960_precious_ranges, | ||
187 | .n_yes_ranges = ARRAY_SIZE(apds9960_precious_ranges), | ||
188 | }; | ||
189 | |||
190 | static const struct regmap_range apds9960_readable_ranges[] = { | ||
191 | regmap_reg_range(APDS9960_REG_ENABLE, | ||
192 | APDS9960_REG_GSTATUS), | ||
193 | regmap_reg_range(APDS9960_REG_GFIFO_DIR(UP), | ||
194 | APDS9960_REG_GFIFO_DIR(RIGHT)), | ||
195 | }; | ||
196 | |||
197 | static const struct regmap_access_table apds9960_readable_table = { | ||
198 | .yes_ranges = apds9960_readable_ranges, | ||
199 | .n_yes_ranges = ARRAY_SIZE(apds9960_readable_ranges), | ||
200 | }; | ||
201 | |||
202 | static const struct regmap_range apds9960_writeable_ranges[] = { | ||
203 | regmap_reg_range(APDS9960_REG_ENABLE, APDS9960_REG_CONFIG_2), | ||
204 | regmap_reg_range(APDS9960_REG_POFFSET_UR, APDS9960_REG_GCONF_4), | ||
205 | regmap_reg_range(APDS9960_REG_IFORCE, APDS9960_REG_AICLEAR), | ||
206 | }; | ||
207 | |||
208 | static const struct regmap_access_table apds9960_writeable_table = { | ||
209 | .yes_ranges = apds9960_writeable_ranges, | ||
210 | .n_yes_ranges = ARRAY_SIZE(apds9960_writeable_ranges), | ||
211 | }; | ||
212 | |||
213 | static const struct regmap_config apds9960_regmap_config = { | ||
214 | .name = APDS9960_REGMAP_NAME, | ||
215 | .reg_bits = 8, | ||
216 | .val_bits = 8, | ||
217 | .use_single_rw = 1, | ||
218 | |||
219 | .volatile_table = &apds9960_volatile_table, | ||
220 | .precious_table = &apds9960_precious_table, | ||
221 | .rd_table = &apds9960_readable_table, | ||
222 | .wr_table = &apds9960_writeable_table, | ||
223 | |||
224 | .reg_defaults = apds9960_reg_defaults, | ||
225 | .num_reg_defaults = ARRAY_SIZE(apds9960_reg_defaults), | ||
226 | .max_register = APDS9960_REG_GFIFO_DIR(RIGHT), | ||
227 | .cache_type = REGCACHE_RBTREE, | ||
228 | }; | ||
229 | |||
230 | static const struct iio_event_spec apds9960_pxs_event_spec[] = { | ||
231 | { | ||
232 | .type = IIO_EV_TYPE_THRESH, | ||
233 | .dir = IIO_EV_DIR_RISING, | ||
234 | .mask_separate = BIT(IIO_EV_INFO_VALUE) | | ||
235 | BIT(IIO_EV_INFO_ENABLE), | ||
236 | }, | ||
237 | { | ||
238 | .type = IIO_EV_TYPE_THRESH, | ||
239 | .dir = IIO_EV_DIR_FALLING, | ||
240 | .mask_separate = BIT(IIO_EV_INFO_VALUE) | | ||
241 | BIT(IIO_EV_INFO_ENABLE), | ||
242 | }, | ||
243 | }; | ||
244 | |||
245 | static const struct iio_event_spec apds9960_als_event_spec[] = { | ||
246 | { | ||
247 | .type = IIO_EV_TYPE_THRESH, | ||
248 | .dir = IIO_EV_DIR_RISING, | ||
249 | .mask_separate = BIT(IIO_EV_INFO_VALUE) | | ||
250 | BIT(IIO_EV_INFO_ENABLE), | ||
251 | }, | ||
252 | { | ||
253 | .type = IIO_EV_TYPE_THRESH, | ||
254 | .dir = IIO_EV_DIR_FALLING, | ||
255 | .mask_separate = BIT(IIO_EV_INFO_VALUE) | | ||
256 | BIT(IIO_EV_INFO_ENABLE), | ||
257 | }, | ||
258 | }; | ||
259 | |||
260 | #define APDS9960_GESTURE_CHANNEL(_dir, _si) { \ | ||
261 | .type = IIO_PROXIMITY, \ | ||
262 | .channel = _si + 1, \ | ||
263 | .scan_index = _si, \ | ||
264 | .indexed = 1, \ | ||
265 | .scan_type = { \ | ||
266 | .sign = 'u', \ | ||
267 | .realbits = 8, \ | ||
268 | .storagebits = 8, \ | ||
269 | }, \ | ||
270 | } | ||
271 | |||
272 | #define APDS9960_INTENSITY_CHANNEL(_colour) { \ | ||
273 | .type = IIO_INTENSITY, \ | ||
274 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | ||
275 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ | ||
276 | BIT(IIO_CHAN_INFO_INT_TIME), \ | ||
277 | .channel2 = IIO_MOD_LIGHT_##_colour, \ | ||
278 | .address = APDS9960_REG_ALS_CHANNEL(_colour), \ | ||
279 | .modified = 1, \ | ||
280 | .scan_index = -1, \ | ||
281 | } | ||
282 | |||
283 | static const unsigned long apds9960_scan_masks[] = {0xf, 0}; | ||
284 | |||
285 | static const struct iio_chan_spec apds9960_channels[] = { | ||
286 | { | ||
287 | .type = IIO_PROXIMITY, | ||
288 | .address = APDS9960_REG_PDATA, | ||
289 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
290 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), | ||
291 | .channel = 0, | ||
292 | .indexed = 0, | ||
293 | .scan_index = -1, | ||
294 | |||
295 | .event_spec = apds9960_pxs_event_spec, | ||
296 | .num_event_specs = ARRAY_SIZE(apds9960_pxs_event_spec), | ||
297 | }, | ||
298 | /* Gesture Sensor */ | ||
299 | APDS9960_GESTURE_CHANNEL(UP, 0), | ||
300 | APDS9960_GESTURE_CHANNEL(DOWN, 1), | ||
301 | APDS9960_GESTURE_CHANNEL(LEFT, 2), | ||
302 | APDS9960_GESTURE_CHANNEL(RIGHT, 3), | ||
303 | /* ALS */ | ||
304 | { | ||
305 | .type = IIO_INTENSITY, | ||
306 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
307 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | | ||
308 | BIT(IIO_CHAN_INFO_INT_TIME), | ||
309 | .channel2 = IIO_MOD_LIGHT_CLEAR, | ||
310 | .address = APDS9960_REG_ALS_CHANNEL(CLEAR), | ||
311 | .modified = 1, | ||
312 | .scan_index = -1, | ||
313 | |||
314 | .event_spec = apds9960_als_event_spec, | ||
315 | .num_event_specs = ARRAY_SIZE(apds9960_als_event_spec), | ||
316 | }, | ||
317 | /* RGB Sensor */ | ||
318 | APDS9960_INTENSITY_CHANNEL(RED), | ||
319 | APDS9960_INTENSITY_CHANNEL(GREEN), | ||
320 | APDS9960_INTENSITY_CHANNEL(BLUE), | ||
321 | }; | ||
322 | |||
323 | /* integration time in us */ | ||
324 | static const int apds9960_int_time[][2] = | ||
325 | { {28000, 246}, {100000, 219}, {200000, 182}, {700000, 0} }; | ||
326 | |||
327 | /* gain mapping */ | ||
328 | static const int apds9960_pxs_gain_map[] = {1, 2, 4, 8}; | ||
329 | static const int apds9960_als_gain_map[] = {1, 4, 16, 64}; | ||
330 | |||
331 | static IIO_CONST_ATTR(proximity_scale_available, "1 2 4 8"); | ||
332 | static IIO_CONST_ATTR(intensity_scale_available, "1 4 16 64"); | ||
333 | static IIO_CONST_ATTR_INT_TIME_AVAIL("0.028 0.1 0.2 0.7"); | ||
334 | |||
335 | static struct attribute *apds9960_attributes[] = { | ||
336 | &iio_const_attr_proximity_scale_available.dev_attr.attr, | ||
337 | &iio_const_attr_intensity_scale_available.dev_attr.attr, | ||
338 | &iio_const_attr_integration_time_available.dev_attr.attr, | ||
339 | NULL, | ||
340 | }; | ||
341 | |||
342 | static struct attribute_group apds9960_attribute_group = { | ||
343 | .attrs = apds9960_attributes, | ||
344 | }; | ||
345 | |||
346 | static const struct reg_field apds9960_reg_field_int_als = | ||
347 | REG_FIELD(APDS9960_REG_ENABLE, 4, 4); | ||
348 | |||
349 | static const struct reg_field apds9960_reg_field_int_ges = | ||
350 | REG_FIELD(APDS9960_REG_GCONF_4, 1, 1); | ||
351 | |||
352 | static const struct reg_field apds9960_reg_field_int_pxs = | ||
353 | REG_FIELD(APDS9960_REG_ENABLE, 5, 5); | ||
354 | |||
355 | static const struct reg_field apds9960_reg_field_enable_als = | ||
356 | REG_FIELD(APDS9960_REG_ENABLE, 1, 1); | ||
357 | |||
358 | static const struct reg_field apds9960_reg_field_enable_ges = | ||
359 | REG_FIELD(APDS9960_REG_ENABLE, 6, 6); | ||
360 | |||
361 | static const struct reg_field apds9960_reg_field_enable_pxs = | ||
362 | REG_FIELD(APDS9960_REG_ENABLE, 2, 2); | ||
363 | |||
364 | static int apds9960_set_it_time(struct apds9960_data *data, int val2) | ||
365 | { | ||
366 | int ret = -EINVAL; | ||
367 | int idx; | ||
368 | |||
369 | for (idx = 0; idx < ARRAY_SIZE(apds9960_int_time); idx++) { | ||
370 | if (apds9960_int_time[idx][0] == val2) { | ||
371 | mutex_lock(&data->lock); | ||
372 | ret = regmap_write(data->regmap, APDS9960_REG_ATIME, | ||
373 | apds9960_int_time[idx][1]); | ||
374 | if (!ret) | ||
375 | data->als_adc_int_us = val2; | ||
376 | mutex_unlock(&data->lock); | ||
377 | break; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | static int apds9960_set_pxs_gain(struct apds9960_data *data, int val) | ||
385 | { | ||
386 | int ret = -EINVAL; | ||
387 | int idx; | ||
388 | |||
389 | for (idx = 0; idx < ARRAY_SIZE(apds9960_pxs_gain_map); idx++) { | ||
390 | if (apds9960_pxs_gain_map[idx] == val) { | ||
391 | /* pxs + gesture gains are mirrored */ | ||
392 | mutex_lock(&data->lock); | ||
393 | ret = regmap_update_bits(data->regmap, | ||
394 | APDS9960_REG_CONTROL, | ||
395 | APDS9960_REG_CONTROL_PGAIN_MASK, | ||
396 | idx << APDS9960_REG_CONTROL_PGAIN_MASK_SHIFT); | ||
397 | if (ret) { | ||
398 | mutex_unlock(&data->lock); | ||
399 | break; | ||
400 | } | ||
401 | |||
402 | ret = regmap_update_bits(data->regmap, | ||
403 | APDS9960_REG_CONFIG_2, | ||
404 | APDS9960_REG_CONFIG_2_GGAIN_MASK, | ||
405 | idx << APDS9960_REG_CONFIG_2_GGAIN_MASK_SHIFT); | ||
406 | if (!ret) | ||
407 | data->pxs_gain = idx; | ||
408 | mutex_unlock(&data->lock); | ||
409 | break; | ||
410 | } | ||
411 | } | ||
412 | |||
413 | return ret; | ||
414 | } | ||
415 | |||
416 | static int apds9960_set_als_gain(struct apds9960_data *data, int val) | ||
417 | { | ||
418 | int ret = -EINVAL; | ||
419 | int idx; | ||
420 | |||
421 | for (idx = 0; idx < ARRAY_SIZE(apds9960_als_gain_map); idx++) { | ||
422 | if (apds9960_als_gain_map[idx] == val) { | ||
423 | mutex_lock(&data->lock); | ||
424 | ret = regmap_update_bits(data->regmap, | ||
425 | APDS9960_REG_CONTROL, | ||
426 | APDS9960_REG_CONTROL_AGAIN_MASK, idx); | ||
427 | if (!ret) | ||
428 | data->als_gain = idx; | ||
429 | mutex_unlock(&data->lock); | ||
430 | break; | ||
431 | } | ||
432 | } | ||
433 | |||
434 | return ret; | ||
435 | } | ||
436 | |||
437 | #ifdef CONFIG_PM | ||
438 | static int apds9960_set_power_state(struct apds9960_data *data, bool on) | ||
439 | { | ||
440 | struct device *dev = &data->client->dev; | ||
441 | int ret = 0; | ||
442 | |||
443 | mutex_lock(&data->lock); | ||
444 | |||
445 | if (on) { | ||
446 | int suspended; | ||
447 | |||
448 | suspended = pm_runtime_suspended(dev); | ||
449 | ret = pm_runtime_get_sync(dev); | ||
450 | |||
451 | /* Allow one integration cycle before allowing a reading */ | ||
452 | if (suspended) | ||
453 | usleep_range(data->als_adc_int_us, | ||
454 | APDS9960_MAX_INT_TIME_IN_US); | ||
455 | } else { | ||
456 | ret = pm_runtime_put_autosuspend(dev); | ||
457 | } | ||
458 | |||
459 | mutex_unlock(&data->lock); | ||
460 | |||
461 | return ret; | ||
462 | } | ||
463 | #else | ||
464 | static int apds9960_set_power_state(struct apds9960_data *data, bool on) | ||
465 | { | ||
466 | return 0; | ||
467 | } | ||
468 | #endif | ||
469 | |||
470 | static int apds9960_read_raw(struct iio_dev *indio_dev, | ||
471 | struct iio_chan_spec const *chan, | ||
472 | int *val, int *val2, long mask) | ||
473 | { | ||
474 | struct apds9960_data *data = iio_priv(indio_dev); | ||
475 | u16 buf; | ||
476 | int ret = -EINVAL; | ||
477 | |||
478 | if (data->gesture_mode_running) | ||
479 | return -EBUSY; | ||
480 | |||
481 | switch (mask) { | ||
482 | case IIO_CHAN_INFO_RAW: | ||
483 | apds9960_set_power_state(data, true); | ||
484 | switch (chan->type) { | ||
485 | case IIO_PROXIMITY: | ||
486 | ret = regmap_read(data->regmap, chan->address, val); | ||
487 | if (!ret) | ||
488 | ret = IIO_VAL_INT; | ||
489 | break; | ||
490 | case IIO_INTENSITY: | ||
491 | ret = regmap_bulk_read(data->regmap, chan->address, | ||
492 | &buf, 2); | ||
493 | if (!ret) | ||
494 | ret = IIO_VAL_INT; | ||
495 | *val = le16_to_cpu(buf); | ||
496 | break; | ||
497 | default: | ||
498 | ret = -EINVAL; | ||
499 | } | ||
500 | apds9960_set_power_state(data, false); | ||
501 | break; | ||
502 | case IIO_CHAN_INFO_INT_TIME: | ||
503 | /* RGB + ALS sensors only have integration time */ | ||
504 | mutex_lock(&data->lock); | ||
505 | switch (chan->type) { | ||
506 | case IIO_INTENSITY: | ||
507 | *val = 0; | ||
508 | *val2 = data->als_adc_int_us; | ||
509 | ret = IIO_VAL_INT_PLUS_MICRO; | ||
510 | break; | ||
511 | default: | ||
512 | ret = -EINVAL; | ||
513 | } | ||
514 | mutex_unlock(&data->lock); | ||
515 | break; | ||
516 | case IIO_CHAN_INFO_SCALE: | ||
517 | mutex_lock(&data->lock); | ||
518 | switch (chan->type) { | ||
519 | case IIO_PROXIMITY: | ||
520 | *val = apds9960_pxs_gain_map[data->pxs_gain]; | ||
521 | ret = IIO_VAL_INT; | ||
522 | break; | ||
523 | case IIO_INTENSITY: | ||
524 | *val = apds9960_als_gain_map[data->als_gain]; | ||
525 | ret = IIO_VAL_INT; | ||
526 | break; | ||
527 | default: | ||
528 | ret = -EINVAL; | ||
529 | } | ||
530 | mutex_unlock(&data->lock); | ||
531 | break; | ||
532 | } | ||
533 | |||
534 | return ret; | ||
535 | }; | ||
536 | |||
537 | static int apds9960_write_raw(struct iio_dev *indio_dev, | ||
538 | struct iio_chan_spec const *chan, | ||
539 | int val, int val2, long mask) | ||
540 | { | ||
541 | struct apds9960_data *data = iio_priv(indio_dev); | ||
542 | |||
543 | switch (mask) { | ||
544 | case IIO_CHAN_INFO_INT_TIME: | ||
545 | /* RGB + ALS sensors only have int time */ | ||
546 | switch (chan->type) { | ||
547 | case IIO_INTENSITY: | ||
548 | if (val != 0) | ||
549 | return -EINVAL; | ||
550 | return apds9960_set_it_time(data, val2); | ||
551 | default: | ||
552 | return -EINVAL; | ||
553 | } | ||
554 | case IIO_CHAN_INFO_SCALE: | ||
555 | if (val2 != 0) | ||
556 | return -EINVAL; | ||
557 | switch (chan->type) { | ||
558 | case IIO_PROXIMITY: | ||
559 | return apds9960_set_pxs_gain(data, val); | ||
560 | case IIO_INTENSITY: | ||
561 | return apds9960_set_als_gain(data, val); | ||
562 | default: | ||
563 | return -EINVAL; | ||
564 | } | ||
565 | default: | ||
566 | return -EINVAL; | ||
567 | }; | ||
568 | |||
569 | return 0; | ||
570 | } | ||
571 | |||
572 | static inline int apds9960_get_thres_reg(const struct iio_chan_spec *chan, | ||
573 | enum iio_event_direction dir, | ||
574 | u8 *reg) | ||
575 | { | ||
576 | switch (dir) { | ||
577 | case IIO_EV_DIR_RISING: | ||
578 | switch (chan->type) { | ||
579 | case IIO_PROXIMITY: | ||
580 | *reg = APDS9960_REG_PIHT; | ||
581 | break; | ||
582 | case IIO_INTENSITY: | ||
583 | *reg = APDS9960_REG_AIHTL; | ||
584 | break; | ||
585 | default: | ||
586 | return -EINVAL; | ||
587 | } | ||
588 | break; | ||
589 | case IIO_EV_DIR_FALLING: | ||
590 | switch (chan->type) { | ||
591 | case IIO_PROXIMITY: | ||
592 | *reg = APDS9960_REG_PILT; | ||
593 | break; | ||
594 | case IIO_INTENSITY: | ||
595 | *reg = APDS9960_REG_AILTL; | ||
596 | break; | ||
597 | default: | ||
598 | return -EINVAL; | ||
599 | } | ||
600 | break; | ||
601 | default: | ||
602 | return -EINVAL; | ||
603 | } | ||
604 | |||
605 | return 0; | ||
606 | } | ||
607 | |||
608 | static int apds9960_read_event(struct iio_dev *indio_dev, | ||
609 | const struct iio_chan_spec *chan, | ||
610 | enum iio_event_type type, | ||
611 | enum iio_event_direction dir, | ||
612 | enum iio_event_info info, | ||
613 | int *val, int *val2) | ||
614 | { | ||
615 | u8 reg; | ||
616 | u16 buf; | ||
617 | int ret = 0; | ||
618 | struct apds9960_data *data = iio_priv(indio_dev); | ||
619 | |||
620 | if (info != IIO_EV_INFO_VALUE) | ||
621 | return -EINVAL; | ||
622 | |||
623 | ret = apds9960_get_thres_reg(chan, dir, ®); | ||
624 | if (ret < 0) | ||
625 | return ret; | ||
626 | |||
627 | if (chan->type == IIO_PROXIMITY) { | ||
628 | ret = regmap_read(data->regmap, reg, val); | ||
629 | if (ret < 0) | ||
630 | return ret; | ||
631 | } else if (chan->type == IIO_INTENSITY) { | ||
632 | ret = regmap_bulk_read(data->regmap, reg, &buf, 2); | ||
633 | if (ret < 0) | ||
634 | return ret; | ||
635 | *val = le16_to_cpu(buf); | ||
636 | } else | ||
637 | return -EINVAL; | ||
638 | |||
639 | *val2 = 0; | ||
640 | |||
641 | return IIO_VAL_INT; | ||
642 | } | ||
643 | |||
644 | static int apds9960_write_event(struct iio_dev *indio_dev, | ||
645 | const struct iio_chan_spec *chan, | ||
646 | enum iio_event_type type, | ||
647 | enum iio_event_direction dir, | ||
648 | enum iio_event_info info, | ||
649 | int val, int val2) | ||
650 | { | ||
651 | u8 reg; | ||
652 | u16 buf; | ||
653 | int ret = 0; | ||
654 | struct apds9960_data *data = iio_priv(indio_dev); | ||
655 | |||
656 | if (info != IIO_EV_INFO_VALUE) | ||
657 | return -EINVAL; | ||
658 | |||
659 | ret = apds9960_get_thres_reg(chan, dir, ®); | ||
660 | if (ret < 0) | ||
661 | return ret; | ||
662 | |||
663 | if (chan->type == IIO_PROXIMITY) { | ||
664 | if (val < 0 || val > APDS9960_MAX_PXS_THRES_VAL) | ||
665 | return -EINVAL; | ||
666 | ret = regmap_write(data->regmap, reg, val); | ||
667 | if (ret < 0) | ||
668 | return ret; | ||
669 | } else if (chan->type == IIO_INTENSITY) { | ||
670 | if (val < 0 || val > APDS9960_MAX_ALS_THRES_VAL) | ||
671 | return -EINVAL; | ||
672 | buf = cpu_to_le16(val); | ||
673 | ret = regmap_bulk_write(data->regmap, reg, &buf, 2); | ||
674 | if (ret < 0) | ||
675 | return ret; | ||
676 | } else | ||
677 | return -EINVAL; | ||
678 | |||
679 | return 0; | ||
680 | } | ||
681 | |||
682 | static int apds9960_read_event_config(struct iio_dev *indio_dev, | ||
683 | const struct iio_chan_spec *chan, | ||
684 | enum iio_event_type type, | ||
685 | enum iio_event_direction dir) | ||
686 | { | ||
687 | struct apds9960_data *data = iio_priv(indio_dev); | ||
688 | |||
689 | switch (chan->type) { | ||
690 | case IIO_PROXIMITY: | ||
691 | return data->pxs_int; | ||
692 | case IIO_INTENSITY: | ||
693 | return data->als_int; | ||
694 | default: | ||
695 | return -EINVAL; | ||
696 | } | ||
697 | |||
698 | return 0; | ||
699 | } | ||
700 | |||
701 | static int apds9960_write_event_config(struct iio_dev *indio_dev, | ||
702 | const struct iio_chan_spec *chan, | ||
703 | enum iio_event_type type, | ||
704 | enum iio_event_direction dir, | ||
705 | int state) | ||
706 | { | ||
707 | struct apds9960_data *data = iio_priv(indio_dev); | ||
708 | int ret; | ||
709 | |||
710 | state = !!state; | ||
711 | |||
712 | switch (chan->type) { | ||
713 | case IIO_PROXIMITY: | ||
714 | if (data->pxs_int == state) | ||
715 | return -EINVAL; | ||
716 | |||
717 | ret = regmap_field_write(data->reg_int_pxs, state); | ||
718 | if (ret) | ||
719 | return ret; | ||
720 | data->pxs_int = state; | ||
721 | apds9960_set_power_state(data, state); | ||
722 | break; | ||
723 | case IIO_INTENSITY: | ||
724 | if (data->als_int == state) | ||
725 | return -EINVAL; | ||
726 | |||
727 | ret = regmap_field_write(data->reg_int_als, state); | ||
728 | if (ret) | ||
729 | return ret; | ||
730 | data->als_int = state; | ||
731 | apds9960_set_power_state(data, state); | ||
732 | break; | ||
733 | default: | ||
734 | return -EINVAL; | ||
735 | } | ||
736 | |||
737 | return 0; | ||
738 | } | ||
739 | |||
740 | static const struct iio_info apds9960_info = { | ||
741 | .driver_module = THIS_MODULE, | ||
742 | .attrs = &apds9960_attribute_group, | ||
743 | .read_raw = apds9960_read_raw, | ||
744 | .write_raw = apds9960_write_raw, | ||
745 | .read_event_value = apds9960_read_event, | ||
746 | .write_event_value = apds9960_write_event, | ||
747 | .read_event_config = apds9960_read_event_config, | ||
748 | .write_event_config = apds9960_write_event_config, | ||
749 | |||
750 | }; | ||
751 | |||
752 | static inline int apds9660_fifo_is_empty(struct apds9960_data *data) | ||
753 | { | ||
754 | int cnt; | ||
755 | int ret; | ||
756 | |||
757 | ret = regmap_read(data->regmap, APDS9960_REG_GFLVL, &cnt); | ||
758 | if (ret) | ||
759 | return ret; | ||
760 | |||
761 | return cnt; | ||
762 | } | ||
763 | |||
764 | static void apds9960_read_gesture_fifo(struct apds9960_data *data) | ||
765 | { | ||
766 | int ret, cnt = 0; | ||
767 | |||
768 | mutex_lock(&data->lock); | ||
769 | data->gesture_mode_running = 1; | ||
770 | |||
771 | while (cnt-- || (cnt = apds9660_fifo_is_empty(data) > 0)) { | ||
772 | ret = regmap_bulk_read(data->regmap, APDS9960_REG_GFIFO_BASE, | ||
773 | &data->buffer, 4); | ||
774 | |||
775 | if (ret) | ||
776 | goto err_read; | ||
777 | |||
778 | iio_push_to_buffers(data->indio_dev, data->buffer); | ||
779 | } | ||
780 | |||
781 | err_read: | ||
782 | data->gesture_mode_running = 0; | ||
783 | mutex_unlock(&data->lock); | ||
784 | } | ||
785 | |||
786 | static irqreturn_t apds9960_interrupt_handler(int irq, void *private) | ||
787 | { | ||
788 | struct iio_dev *indio_dev = private; | ||
789 | struct apds9960_data *data = iio_priv(indio_dev); | ||
790 | int ret, status; | ||
791 | |||
792 | ret = regmap_read(data->regmap, APDS9960_REG_STATUS, &status); | ||
793 | if (ret < 0) { | ||
794 | dev_err(&data->client->dev, "irq status reg read failed\n"); | ||
795 | return IRQ_HANDLED; | ||
796 | } | ||
797 | |||
798 | if ((status & APDS9960_REG_STATUS_ALS_INT) && data->als_int) { | ||
799 | iio_push_event(indio_dev, | ||
800 | IIO_UNMOD_EVENT_CODE(IIO_INTENSITY, 0, | ||
801 | IIO_EV_TYPE_THRESH, | ||
802 | IIO_EV_DIR_EITHER), | ||
803 | iio_get_time_ns()); | ||
804 | regmap_write(data->regmap, APDS9960_REG_CICLEAR, 1); | ||
805 | } | ||
806 | |||
807 | if ((status & APDS9960_REG_STATUS_PS_INT) && data->pxs_int) { | ||
808 | iio_push_event(indio_dev, | ||
809 | IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0, | ||
810 | IIO_EV_TYPE_THRESH, | ||
811 | IIO_EV_DIR_EITHER), | ||
812 | iio_get_time_ns()); | ||
813 | regmap_write(data->regmap, APDS9960_REG_PICLEAR, 1); | ||
814 | } | ||
815 | |||
816 | if (status & APDS9960_REG_STATUS_GINT) | ||
817 | apds9960_read_gesture_fifo(data); | ||
818 | |||
819 | return IRQ_HANDLED; | ||
820 | } | ||
821 | |||
822 | static int apds9960_set_powermode(struct apds9960_data *data, bool state) | ||
823 | { | ||
824 | return regmap_update_bits(data->regmap, APDS9960_REG_ENABLE, 1, state); | ||
825 | } | ||
826 | |||
827 | static int apds9960_buffer_postenable(struct iio_dev *indio_dev) | ||
828 | { | ||
829 | struct apds9960_data *data = iio_priv(indio_dev); | ||
830 | int ret; | ||
831 | |||
832 | ret = regmap_field_write(data->reg_int_ges, 1); | ||
833 | if (ret) | ||
834 | return ret; | ||
835 | |||
836 | ret = regmap_field_write(data->reg_enable_ges, 1); | ||
837 | if (ret) | ||
838 | return ret; | ||
839 | |||
840 | pm_runtime_get_sync(&data->client->dev); | ||
841 | |||
842 | return 0; | ||
843 | } | ||
844 | |||
845 | static int apds9960_buffer_predisable(struct iio_dev *indio_dev) | ||
846 | { | ||
847 | struct apds9960_data *data = iio_priv(indio_dev); | ||
848 | int ret; | ||
849 | |||
850 | ret = regmap_field_write(data->reg_enable_ges, 0); | ||
851 | if (ret) | ||
852 | return ret; | ||
853 | |||
854 | ret = regmap_field_write(data->reg_int_ges, 0); | ||
855 | if (ret) | ||
856 | return ret; | ||
857 | |||
858 | pm_runtime_put_autosuspend(&data->client->dev); | ||
859 | |||
860 | return 0; | ||
861 | } | ||
862 | |||
863 | static const struct iio_buffer_setup_ops apds9960_buffer_setup_ops = { | ||
864 | .postenable = apds9960_buffer_postenable, | ||
865 | .predisable = apds9960_buffer_predisable, | ||
866 | }; | ||
867 | |||
868 | static int apds9960_regfield_init(struct apds9960_data *data) | ||
869 | { | ||
870 | struct device *dev = &data->client->dev; | ||
871 | struct regmap *regmap = data->regmap; | ||
872 | |||
873 | data->reg_int_als = devm_regmap_field_alloc(dev, regmap, | ||
874 | apds9960_reg_field_int_als); | ||
875 | if (IS_ERR(data->reg_int_als)) { | ||
876 | dev_err(dev, "INT ALS reg field init failed\n"); | ||
877 | return PTR_ERR(data->reg_int_als); | ||
878 | } | ||
879 | |||
880 | data->reg_int_ges = devm_regmap_field_alloc(dev, regmap, | ||
881 | apds9960_reg_field_int_ges); | ||
882 | if (IS_ERR(data->reg_int_ges)) { | ||
883 | dev_err(dev, "INT gesture reg field init failed\n"); | ||
884 | return PTR_ERR(data->reg_int_ges); | ||
885 | } | ||
886 | |||
887 | data->reg_int_pxs = devm_regmap_field_alloc(dev, regmap, | ||
888 | apds9960_reg_field_int_pxs); | ||
889 | if (IS_ERR(data->reg_int_pxs)) { | ||
890 | dev_err(dev, "INT pxs reg field init failed\n"); | ||
891 | return PTR_ERR(data->reg_int_pxs); | ||
892 | } | ||
893 | |||
894 | data->reg_enable_als = devm_regmap_field_alloc(dev, regmap, | ||
895 | apds9960_reg_field_enable_als); | ||
896 | if (IS_ERR(data->reg_enable_als)) { | ||
897 | dev_err(dev, "Enable ALS reg field init failed\n"); | ||
898 | return PTR_ERR(data->reg_enable_als); | ||
899 | } | ||
900 | |||
901 | data->reg_enable_ges = devm_regmap_field_alloc(dev, regmap, | ||
902 | apds9960_reg_field_enable_ges); | ||
903 | if (IS_ERR(data->reg_enable_ges)) { | ||
904 | dev_err(dev, "Enable gesture reg field init failed\n"); | ||
905 | return PTR_ERR(data->reg_enable_ges); | ||
906 | } | ||
907 | |||
908 | data->reg_enable_pxs = devm_regmap_field_alloc(dev, regmap, | ||
909 | apds9960_reg_field_enable_pxs); | ||
910 | if (IS_ERR(data->reg_enable_pxs)) { | ||
911 | dev_err(dev, "Enable PXS reg field init failed\n"); | ||
912 | return PTR_ERR(data->reg_enable_pxs); | ||
913 | } | ||
914 | |||
915 | return 0; | ||
916 | } | ||
917 | |||
918 | static int apds9960_chip_init(struct apds9960_data *data) | ||
919 | { | ||
920 | int ret; | ||
921 | |||
922 | /* Default IT for ALS of 28 ms */ | ||
923 | ret = apds9960_set_it_time(data, 28000); | ||
924 | if (ret) | ||
925 | return ret; | ||
926 | |||
927 | /* Ensure gesture interrupt is OFF */ | ||
928 | ret = regmap_field_write(data->reg_int_ges, 0); | ||
929 | if (ret) | ||
930 | return ret; | ||
931 | |||
932 | /* Disable gesture sensor, since polling is useless from user-space */ | ||
933 | ret = regmap_field_write(data->reg_enable_ges, 0); | ||
934 | if (ret) | ||
935 | return ret; | ||
936 | |||
937 | /* Ensure proximity interrupt is OFF */ | ||
938 | ret = regmap_field_write(data->reg_int_pxs, 0); | ||
939 | if (ret) | ||
940 | return ret; | ||
941 | |||
942 | /* Enable proximity sensor for polling */ | ||
943 | ret = regmap_field_write(data->reg_enable_pxs, 1); | ||
944 | if (ret) | ||
945 | return ret; | ||
946 | |||
947 | /* Ensure ALS interrupt is OFF */ | ||
948 | ret = regmap_field_write(data->reg_int_als, 0); | ||
949 | if (ret) | ||
950 | return ret; | ||
951 | |||
952 | /* Enable ALS sensor for polling */ | ||
953 | ret = regmap_field_write(data->reg_enable_als, 1); | ||
954 | if (ret) | ||
955 | return ret; | ||
956 | /* | ||
957 | * When enabled trigger an interrupt after 3 readings | ||
958 | * outside threshold for ALS + PXS | ||
959 | */ | ||
960 | ret = regmap_write(data->regmap, APDS9960_REG_PERS, | ||
961 | APDS9960_DEFAULT_PERS); | ||
962 | if (ret) | ||
963 | return ret; | ||
964 | |||
965 | /* | ||
966 | * Wait for 4 event outside gesture threshold to prevent interrupt | ||
967 | * flooding. | ||
968 | */ | ||
969 | ret = regmap_update_bits(data->regmap, APDS9960_REG_GCONF_1, | ||
970 | APDS9960_REG_GCONF_1_GFIFO_THRES_MASK, | ||
971 | BIT(0) << APDS9960_REG_GCONF_1_GFIFO_THRES_MASK_SHIFT); | ||
972 | if (ret) | ||
973 | return ret; | ||
974 | |||
975 | /* Default ENTER and EXIT thresholds for the GESTURE engine. */ | ||
976 | ret = regmap_write(data->regmap, APDS9960_REG_GPENTH, | ||
977 | APDS9960_DEFAULT_GPENTH); | ||
978 | if (ret) | ||
979 | return ret; | ||
980 | |||
981 | ret = regmap_write(data->regmap, APDS9960_REG_GEXTH, | ||
982 | APDS9960_DEFAULT_GEXTH); | ||
983 | if (ret) | ||
984 | return ret; | ||
985 | |||
986 | return apds9960_set_powermode(data, 1); | ||
987 | } | ||
988 | |||
989 | static int apds9960_probe(struct i2c_client *client, | ||
990 | const struct i2c_device_id *id) | ||
991 | { | ||
992 | struct apds9960_data *data; | ||
993 | struct iio_buffer *buffer; | ||
994 | struct iio_dev *indio_dev; | ||
995 | int ret; | ||
996 | |||
997 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | ||
998 | if (!indio_dev) | ||
999 | return -ENOMEM; | ||
1000 | |||
1001 | buffer = devm_iio_kfifo_allocate(&client->dev); | ||
1002 | if (!buffer) | ||
1003 | return -ENOMEM; | ||
1004 | |||
1005 | iio_device_attach_buffer(indio_dev, buffer); | ||
1006 | |||
1007 | indio_dev->info = &apds9960_info; | ||
1008 | indio_dev->name = APDS9960_DRV_NAME; | ||
1009 | indio_dev->channels = apds9960_channels; | ||
1010 | indio_dev->num_channels = ARRAY_SIZE(apds9960_channels); | ||
1011 | indio_dev->available_scan_masks = apds9960_scan_masks; | ||
1012 | indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE); | ||
1013 | indio_dev->setup_ops = &apds9960_buffer_setup_ops; | ||
1014 | |||
1015 | data = iio_priv(indio_dev); | ||
1016 | i2c_set_clientdata(client, indio_dev); | ||
1017 | |||
1018 | data->regmap = devm_regmap_init_i2c(client, &apds9960_regmap_config); | ||
1019 | if (IS_ERR(data->regmap)) { | ||
1020 | dev_err(&client->dev, "regmap initialization failed.\n"); | ||
1021 | return PTR_ERR(data->regmap); | ||
1022 | } | ||
1023 | |||
1024 | data->client = client; | ||
1025 | data->indio_dev = indio_dev; | ||
1026 | mutex_init(&data->lock); | ||
1027 | |||
1028 | ret = pm_runtime_set_active(&client->dev); | ||
1029 | if (ret) | ||
1030 | goto error_power_down; | ||
1031 | |||
1032 | pm_runtime_enable(&client->dev); | ||
1033 | pm_runtime_set_autosuspend_delay(&client->dev, 5000); | ||
1034 | pm_runtime_use_autosuspend(&client->dev); | ||
1035 | |||
1036 | apds9960_set_power_state(data, true); | ||
1037 | |||
1038 | ret = apds9960_regfield_init(data); | ||
1039 | if (ret) | ||
1040 | goto error_power_down; | ||
1041 | |||
1042 | ret = apds9960_chip_init(data); | ||
1043 | if (ret) | ||
1044 | goto error_power_down; | ||
1045 | |||
1046 | if (client->irq <= 0) { | ||
1047 | dev_err(&client->dev, "no valid irq defined\n"); | ||
1048 | ret = -EINVAL; | ||
1049 | goto error_power_down; | ||
1050 | } | ||
1051 | ret = devm_request_threaded_irq(&client->dev, client->irq, | ||
1052 | NULL, apds9960_interrupt_handler, | ||
1053 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
1054 | "apds9960_event", | ||
1055 | indio_dev); | ||
1056 | if (ret) { | ||
1057 | dev_err(&client->dev, "request irq (%d) failed\n", client->irq); | ||
1058 | goto error_power_down; | ||
1059 | } | ||
1060 | |||
1061 | ret = iio_device_register(indio_dev); | ||
1062 | if (ret) | ||
1063 | goto error_power_down; | ||
1064 | |||
1065 | apds9960_set_power_state(data, false); | ||
1066 | |||
1067 | return 0; | ||
1068 | |||
1069 | error_power_down: | ||
1070 | apds9960_set_power_state(data, false); | ||
1071 | |||
1072 | return ret; | ||
1073 | } | ||
1074 | |||
1075 | static int apds9960_remove(struct i2c_client *client) | ||
1076 | { | ||
1077 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | ||
1078 | struct apds9960_data *data = iio_priv(indio_dev); | ||
1079 | |||
1080 | iio_device_unregister(indio_dev); | ||
1081 | pm_runtime_disable(&client->dev); | ||
1082 | pm_runtime_set_suspended(&client->dev); | ||
1083 | apds9960_set_powermode(data, 0); | ||
1084 | |||
1085 | return 0; | ||
1086 | } | ||
1087 | |||
1088 | #ifdef CONFIG_PM | ||
1089 | static int apds9960_runtime_suspend(struct device *dev) | ||
1090 | { | ||
1091 | struct apds9960_data *data = | ||
1092 | iio_priv(i2c_get_clientdata(to_i2c_client(dev))); | ||
1093 | |||
1094 | return apds9960_set_powermode(data, 0); | ||
1095 | } | ||
1096 | |||
1097 | static int apds9960_runtime_resume(struct device *dev) | ||
1098 | { | ||
1099 | struct apds9960_data *data = | ||
1100 | iio_priv(i2c_get_clientdata(to_i2c_client(dev))); | ||
1101 | |||
1102 | return apds9960_set_powermode(data, 1); | ||
1103 | } | ||
1104 | #endif | ||
1105 | |||
1106 | static const struct dev_pm_ops apds9960_pm_ops = { | ||
1107 | SET_RUNTIME_PM_OPS(apds9960_runtime_suspend, | ||
1108 | apds9960_runtime_resume, NULL) | ||
1109 | }; | ||
1110 | |||
1111 | static const struct i2c_device_id apds9960_id[] = { | ||
1112 | { "apds9960", 0 }, | ||
1113 | {} | ||
1114 | }; | ||
1115 | MODULE_DEVICE_TABLE(i2c, apds9960_id); | ||
1116 | |||
1117 | static struct i2c_driver apds9960_driver = { | ||
1118 | .driver = { | ||
1119 | .name = APDS9960_DRV_NAME, | ||
1120 | .pm = &apds9960_pm_ops, | ||
1121 | }, | ||
1122 | .probe = apds9960_probe, | ||
1123 | .remove = apds9960_remove, | ||
1124 | .id_table = apds9960_id, | ||
1125 | }; | ||
1126 | module_i2c_driver(apds9960_driver); | ||
1127 | |||
1128 | MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>"); | ||
1129 | MODULE_DESCRIPTION("ADPS9960 Gesture/RGB/ALS/Proximity sensor"); | ||
1130 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c index 923aa6aef0ed..01e111e72d4b 100644 --- a/drivers/iio/light/opt3001.c +++ b/drivers/iio/light/opt3001.c | |||
@@ -793,7 +793,6 @@ static struct i2c_driver opt3001_driver = { | |||
793 | .driver = { | 793 | .driver = { |
794 | .name = "opt3001", | 794 | .name = "opt3001", |
795 | .of_match_table = of_match_ptr(opt3001_of_match), | 795 | .of_match_table = of_match_ptr(opt3001_of_match), |
796 | .owner = THIS_MODULE, | ||
797 | }, | 796 | }, |
798 | }; | 797 | }; |
799 | 798 | ||
diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c index 993eb201148e..013b21779db9 100644 --- a/drivers/iio/light/stk3310.c +++ b/drivers/iio/light/stk3310.c | |||
@@ -35,8 +35,8 @@ | |||
35 | #define STK3310_REG_ID 0x3E | 35 | #define STK3310_REG_ID 0x3E |
36 | #define STK3310_MAX_REG 0x80 | 36 | #define STK3310_MAX_REG 0x80 |
37 | 37 | ||
38 | #define STK3310_STATE_EN_PS 0x01 | 38 | #define STK3310_STATE_EN_PS BIT(0) |
39 | #define STK3310_STATE_EN_ALS 0x02 | 39 | #define STK3310_STATE_EN_ALS BIT(1) |
40 | #define STK3310_STATE_STANDBY 0x00 | 40 | #define STK3310_STATE_STANDBY 0x00 |
41 | 41 | ||
42 | #define STK3310_CHIP_ID_VAL 0x13 | 42 | #define STK3310_CHIP_ID_VAL 0x13 |
@@ -241,8 +241,11 @@ static int stk3310_write_event(struct iio_dev *indio_dev, | |||
241 | struct stk3310_data *data = iio_priv(indio_dev); | 241 | struct stk3310_data *data = iio_priv(indio_dev); |
242 | struct i2c_client *client = data->client; | 242 | struct i2c_client *client = data->client; |
243 | 243 | ||
244 | regmap_field_read(data->reg_ps_gain, &index); | 244 | ret = regmap_field_read(data->reg_ps_gain, &index); |
245 | if (val > stk3310_ps_max[index]) | 245 | if (ret < 0) |
246 | return ret; | ||
247 | |||
248 | if (val < 0 || val > stk3310_ps_max[index]) | ||
246 | return -EINVAL; | 249 | return -EINVAL; |
247 | 250 | ||
248 | if (dir == IIO_EV_DIR_RISING) | 251 | if (dir == IIO_EV_DIR_RISING) |
@@ -266,9 +269,12 @@ static int stk3310_read_event_config(struct iio_dev *indio_dev, | |||
266 | enum iio_event_direction dir) | 269 | enum iio_event_direction dir) |
267 | { | 270 | { |
268 | unsigned int event_val; | 271 | unsigned int event_val; |
272 | int ret; | ||
269 | struct stk3310_data *data = iio_priv(indio_dev); | 273 | struct stk3310_data *data = iio_priv(indio_dev); |
270 | 274 | ||
271 | regmap_field_read(data->reg_int_ps, &event_val); | 275 | ret = regmap_field_read(data->reg_int_ps, &event_val); |
276 | if (ret < 0) | ||
277 | return ret; | ||
272 | 278 | ||
273 | return event_val; | 279 | return event_val; |
274 | } | 280 | } |
@@ -307,14 +313,16 @@ static int stk3310_read_raw(struct iio_dev *indio_dev, | |||
307 | struct stk3310_data *data = iio_priv(indio_dev); | 313 | struct stk3310_data *data = iio_priv(indio_dev); |
308 | struct i2c_client *client = data->client; | 314 | struct i2c_client *client = data->client; |
309 | 315 | ||
316 | if (chan->type != IIO_LIGHT && chan->type != IIO_PROXIMITY) | ||
317 | return -EINVAL; | ||
318 | |||
310 | switch (mask) { | 319 | switch (mask) { |
311 | case IIO_CHAN_INFO_RAW: | 320 | case IIO_CHAN_INFO_RAW: |
312 | if (chan->type == IIO_LIGHT) | 321 | if (chan->type == IIO_LIGHT) |
313 | reg = STK3310_REG_ALS_DATA_MSB; | 322 | reg = STK3310_REG_ALS_DATA_MSB; |
314 | else if (chan->type == IIO_PROXIMITY) | ||
315 | reg = STK3310_REG_PS_DATA_MSB; | ||
316 | else | 323 | else |
317 | return -EINVAL; | 324 | reg = STK3310_REG_PS_DATA_MSB; |
325 | |||
318 | mutex_lock(&data->lock); | 326 | mutex_lock(&data->lock); |
319 | ret = regmap_bulk_read(data->regmap, reg, &buf, 2); | 327 | ret = regmap_bulk_read(data->regmap, reg, &buf, 2); |
320 | if (ret < 0) { | 328 | if (ret < 0) { |
@@ -327,17 +335,23 @@ static int stk3310_read_raw(struct iio_dev *indio_dev, | |||
327 | return IIO_VAL_INT; | 335 | return IIO_VAL_INT; |
328 | case IIO_CHAN_INFO_INT_TIME: | 336 | case IIO_CHAN_INFO_INT_TIME: |
329 | if (chan->type == IIO_LIGHT) | 337 | if (chan->type == IIO_LIGHT) |
330 | regmap_field_read(data->reg_als_it, &index); | 338 | ret = regmap_field_read(data->reg_als_it, &index); |
331 | else | 339 | else |
332 | regmap_field_read(data->reg_ps_it, &index); | 340 | ret = regmap_field_read(data->reg_ps_it, &index); |
341 | if (ret < 0) | ||
342 | return ret; | ||
343 | |||
333 | *val = stk3310_it_table[index][0]; | 344 | *val = stk3310_it_table[index][0]; |
334 | *val2 = stk3310_it_table[index][1]; | 345 | *val2 = stk3310_it_table[index][1]; |
335 | return IIO_VAL_INT_PLUS_MICRO; | 346 | return IIO_VAL_INT_PLUS_MICRO; |
336 | case IIO_CHAN_INFO_SCALE: | 347 | case IIO_CHAN_INFO_SCALE: |
337 | if (chan->type == IIO_LIGHT) | 348 | if (chan->type == IIO_LIGHT) |
338 | regmap_field_read(data->reg_als_gain, &index); | 349 | ret = regmap_field_read(data->reg_als_gain, &index); |
339 | else | 350 | else |
340 | regmap_field_read(data->reg_ps_gain, &index); | 351 | ret = regmap_field_read(data->reg_ps_gain, &index); |
352 | if (ret < 0) | ||
353 | return ret; | ||
354 | |||
341 | *val = stk3310_scale_table[index][0]; | 355 | *val = stk3310_scale_table[index][0]; |
342 | *val2 = stk3310_scale_table[index][1]; | 356 | *val2 = stk3310_scale_table[index][1]; |
343 | return IIO_VAL_INT_PLUS_MICRO; | 357 | return IIO_VAL_INT_PLUS_MICRO; |
@@ -354,6 +368,9 @@ static int stk3310_write_raw(struct iio_dev *indio_dev, | |||
354 | int index; | 368 | int index; |
355 | struct stk3310_data *data = iio_priv(indio_dev); | 369 | struct stk3310_data *data = iio_priv(indio_dev); |
356 | 370 | ||
371 | if (chan->type != IIO_LIGHT && chan->type != IIO_PROXIMITY) | ||
372 | return -EINVAL; | ||
373 | |||
357 | switch (mask) { | 374 | switch (mask) { |
358 | case IIO_CHAN_INFO_INT_TIME: | 375 | case IIO_CHAN_INFO_INT_TIME: |
359 | index = stk3310_get_index(stk3310_it_table, | 376 | index = stk3310_get_index(stk3310_it_table, |
@@ -368,7 +385,7 @@ static int stk3310_write_raw(struct iio_dev *indio_dev, | |||
368 | ret = regmap_field_write(data->reg_ps_it, index); | 385 | ret = regmap_field_write(data->reg_ps_it, index); |
369 | if (ret < 0) | 386 | if (ret < 0) |
370 | dev_err(&data->client->dev, | 387 | dev_err(&data->client->dev, |
371 | "sensor configuration failed\n"); | 388 | "sensor configuration failed\n"); |
372 | mutex_unlock(&data->lock); | 389 | mutex_unlock(&data->lock); |
373 | return ret; | 390 | return ret; |
374 | 391 | ||
@@ -385,7 +402,7 @@ static int stk3310_write_raw(struct iio_dev *indio_dev, | |||
385 | ret = regmap_field_write(data->reg_ps_gain, index); | 402 | ret = regmap_field_write(data->reg_ps_gain, index); |
386 | if (ret < 0) | 403 | if (ret < 0) |
387 | dev_err(&data->client->dev, | 404 | dev_err(&data->client->dev, |
388 | "sensor configuration failed\n"); | 405 | "sensor configuration failed\n"); |
389 | mutex_unlock(&data->lock); | 406 | mutex_unlock(&data->lock); |
390 | return ret; | 407 | return ret; |
391 | } | 408 | } |
@@ -419,8 +436,8 @@ static int stk3310_set_state(struct stk3310_data *data, u8 state) | |||
419 | dev_err(&client->dev, "failed to change sensor state\n"); | 436 | dev_err(&client->dev, "failed to change sensor state\n"); |
420 | } else if (state != STK3310_STATE_STANDBY) { | 437 | } else if (state != STK3310_STATE_STANDBY) { |
421 | /* Don't reset the 'enabled' flags if we're going in standby */ | 438 | /* Don't reset the 'enabled' flags if we're going in standby */ |
422 | data->ps_enabled = !!(state & 0x01); | 439 | data->ps_enabled = !!(state & STK3310_STATE_EN_PS); |
423 | data->als_enabled = !!(state & 0x02); | 440 | data->als_enabled = !!(state & STK3310_STATE_EN_ALS); |
424 | } | 441 | } |
425 | mutex_unlock(&data->lock); | 442 | mutex_unlock(&data->lock); |
426 | 443 | ||
@@ -435,7 +452,10 @@ static int stk3310_init(struct iio_dev *indio_dev) | |||
435 | struct stk3310_data *data = iio_priv(indio_dev); | 452 | struct stk3310_data *data = iio_priv(indio_dev); |
436 | struct i2c_client *client = data->client; | 453 | struct i2c_client *client = data->client; |
437 | 454 | ||
438 | regmap_read(data->regmap, STK3310_REG_ID, &chipid); | 455 | ret = regmap_read(data->regmap, STK3310_REG_ID, &chipid); |
456 | if (ret < 0) | ||
457 | return ret; | ||
458 | |||
439 | if (chipid != STK3310_CHIP_ID_VAL && | 459 | if (chipid != STK3310_CHIP_ID_VAL && |
440 | chipid != STK3311_CHIP_ID_VAL) { | 460 | chipid != STK3311_CHIP_ID_VAL) { |
441 | dev_err(&client->dev, "invalid chip id: 0x%x\n", chipid); | 461 | dev_err(&client->dev, "invalid chip id: 0x%x\n", chipid); |
@@ -604,8 +624,13 @@ static int stk3310_probe(struct i2c_client *client, | |||
604 | if (ret < 0) | 624 | if (ret < 0) |
605 | return ret; | 625 | return ret; |
606 | 626 | ||
607 | if (client->irq < 0) | 627 | if (client->irq < 0) { |
608 | client->irq = stk3310_gpio_probe(client); | 628 | client->irq = stk3310_gpio_probe(client); |
629 | if (client->irq < 0) { | ||
630 | ret = client->irq; | ||
631 | goto err_standby; | ||
632 | } | ||
633 | } | ||
609 | 634 | ||
610 | if (client->irq >= 0) { | 635 | if (client->irq >= 0) { |
611 | ret = devm_request_threaded_irq(&client->dev, client->irq, | 636 | ret = devm_request_threaded_irq(&client->dev, client->irq, |
@@ -614,17 +639,23 @@ static int stk3310_probe(struct i2c_client *client, | |||
614 | IRQF_TRIGGER_FALLING | | 639 | IRQF_TRIGGER_FALLING | |
615 | IRQF_ONESHOT, | 640 | IRQF_ONESHOT, |
616 | STK3310_EVENT, indio_dev); | 641 | STK3310_EVENT, indio_dev); |
617 | if (ret < 0) | 642 | if (ret < 0) { |
618 | dev_err(&client->dev, "request irq %d failed\n", | 643 | dev_err(&client->dev, "request irq %d failed\n", |
619 | client->irq); | 644 | client->irq); |
645 | goto err_standby; | ||
646 | } | ||
620 | } | 647 | } |
621 | 648 | ||
622 | ret = iio_device_register(indio_dev); | 649 | ret = iio_device_register(indio_dev); |
623 | if (ret < 0) { | 650 | if (ret < 0) { |
624 | dev_err(&client->dev, "device_register failed\n"); | 651 | dev_err(&client->dev, "device_register failed\n"); |
625 | stk3310_set_state(data, STK3310_STATE_STANDBY); | 652 | goto err_standby; |
626 | } | 653 | } |
627 | 654 | ||
655 | return 0; | ||
656 | |||
657 | err_standby: | ||
658 | stk3310_set_state(data, STK3310_STATE_STANDBY); | ||
628 | return ret; | 659 | return ret; |
629 | } | 660 | } |
630 | 661 | ||
@@ -648,7 +679,7 @@ static int stk3310_suspend(struct device *dev) | |||
648 | 679 | ||
649 | static int stk3310_resume(struct device *dev) | 680 | static int stk3310_resume(struct device *dev) |
650 | { | 681 | { |
651 | int state = 0; | 682 | u8 state = 0; |
652 | struct stk3310_data *data; | 683 | struct stk3310_data *data; |
653 | 684 | ||
654 | data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); | 685 | data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); |
diff --git a/drivers/iio/light/tsl4531.c b/drivers/iio/light/tsl4531.c index 26979183d27c..cf94ec72b181 100644 --- a/drivers/iio/light/tsl4531.c +++ b/drivers/iio/light/tsl4531.c | |||
@@ -158,9 +158,9 @@ static int tsl4531_check_id(struct i2c_client *client) | |||
158 | case TSL45313_ID: | 158 | case TSL45313_ID: |
159 | case TSL45315_ID: | 159 | case TSL45315_ID: |
160 | case TSL45317_ID: | 160 | case TSL45317_ID: |
161 | return 1; | ||
162 | default: | ||
163 | return 0; | 161 | return 0; |
162 | default: | ||
163 | return -ENODEV; | ||
164 | } | 164 | } |
165 | } | 165 | } |
166 | 166 | ||
@@ -180,9 +180,10 @@ static int tsl4531_probe(struct i2c_client *client, | |||
180 | data->client = client; | 180 | data->client = client; |
181 | mutex_init(&data->lock); | 181 | mutex_init(&data->lock); |
182 | 182 | ||
183 | if (!tsl4531_check_id(client)) { | 183 | ret = tsl4531_check_id(client); |
184 | if (ret) { | ||
184 | dev_err(&client->dev, "no TSL4531 sensor\n"); | 185 | dev_err(&client->dev, "no TSL4531 sensor\n"); |
185 | return -ENODEV; | 186 | return ret; |
186 | } | 187 | } |
187 | 188 | ||
188 | ret = i2c_smbus_write_byte_data(data->client, TSL4531_CONTROL, | 189 | ret = i2c_smbus_write_byte_data(data->client, TSL4531_CONTROL, |
diff --git a/drivers/iio/light/us5182d.c b/drivers/iio/light/us5182d.c new file mode 100644 index 000000000000..49dab3cb3e23 --- /dev/null +++ b/drivers/iio/light/us5182d.c | |||
@@ -0,0 +1,507 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015 Intel Corporation | ||
3 | * | ||
4 | * Driver for UPISEMI us5182d Proximity and Ambient Light Sensor. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * To do: Interrupt support. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/acpi.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/i2c.h> | ||
23 | #include <linux/iio/iio.h> | ||
24 | #include <linux/iio/sysfs.h> | ||
25 | #include <linux/mutex.h> | ||
26 | |||
27 | #define US5182D_REG_CFG0 0x00 | ||
28 | #define US5182D_CFG0_ONESHOT_EN BIT(6) | ||
29 | #define US5182D_CFG0_SHUTDOWN_EN BIT(7) | ||
30 | #define US5182D_CFG0_WORD_ENABLE BIT(0) | ||
31 | |||
32 | #define US5182D_REG_CFG1 0x01 | ||
33 | #define US5182D_CFG1_ALS_RES16 BIT(4) | ||
34 | #define US5182D_CFG1_AGAIN_DEFAULT 0x00 | ||
35 | |||
36 | #define US5182D_REG_CFG2 0x02 | ||
37 | #define US5182D_CFG2_PX_RES16 BIT(4) | ||
38 | #define US5182D_CFG2_PXGAIN_DEFAULT BIT(2) | ||
39 | |||
40 | #define US5182D_REG_CFG3 0x03 | ||
41 | #define US5182D_CFG3_LED_CURRENT100 (BIT(4) | BIT(5)) | ||
42 | |||
43 | #define US5182D_REG_CFG4 0x10 | ||
44 | |||
45 | /* | ||
46 | * Registers for tuning the auto dark current cancelling feature. | ||
47 | * DARK_TH(reg 0x27,0x28) - threshold (counts) for auto dark cancelling. | ||
48 | * when ALS > DARK_TH --> ALS_Code = ALS - Upper(0x2A) * Dark | ||
49 | * when ALS < DARK_TH --> ALS_Code = ALS - Lower(0x29) * Dark | ||
50 | */ | ||
51 | #define US5182D_REG_UDARK_TH 0x27 | ||
52 | #define US5182D_REG_DARK_AUTO_EN 0x2b | ||
53 | #define US5182D_REG_AUTO_LDARK_GAIN 0x29 | ||
54 | #define US5182D_REG_AUTO_HDARK_GAIN 0x2a | ||
55 | |||
56 | #define US5182D_OPMODE_ALS 0x01 | ||
57 | #define US5182D_OPMODE_PX 0x02 | ||
58 | #define US5182D_OPMODE_SHIFT 4 | ||
59 | |||
60 | #define US5182D_REG_DARK_AUTO_EN_DEFAULT 0x80 | ||
61 | #define US5182D_REG_AUTO_LDARK_GAIN_DEFAULT 0x16 | ||
62 | #define US5182D_REG_AUTO_HDARK_GAIN_DEFAULT 0x00 | ||
63 | |||
64 | #define US5182D_REG_ADL 0x0c | ||
65 | #define US5182D_REG_PDL 0x0e | ||
66 | |||
67 | #define US5182D_REG_MODE_STORE 0x21 | ||
68 | #define US5182D_STORE_MODE 0x01 | ||
69 | |||
70 | #define US5182D_REG_CHIPID 0xb2 | ||
71 | |||
72 | #define US5182D_OPMODE_MASK GENMASK(5, 4) | ||
73 | #define US5182D_AGAIN_MASK 0x07 | ||
74 | #define US5182D_RESET_CHIP 0x01 | ||
75 | |||
76 | #define US5182D_CHIPID 0x26 | ||
77 | #define US5182D_DRV_NAME "us5182d" | ||
78 | |||
79 | #define US5182D_GA_RESOLUTION 1000 | ||
80 | |||
81 | #define US5182D_READ_BYTE 1 | ||
82 | #define US5182D_READ_WORD 2 | ||
83 | #define US5182D_OPSTORE_SLEEP_TIME 20 /* ms */ | ||
84 | |||
85 | /* Available ranges: [12354, 7065, 3998, 2202, 1285, 498, 256, 138] lux */ | ||
86 | static const int us5182d_scales[] = {188500, 107800, 61000, 33600, 19600, 7600, | ||
87 | 3900, 2100}; | ||
88 | |||
89 | /* | ||
90 | * Experimental thresholds that work with US5182D sensor on evaluation board | ||
91 | * roughly between 12-32 lux | ||
92 | */ | ||
93 | static u16 us5182d_dark_ths_vals[] = {170, 200, 512, 512, 800, 2000, 4000, | ||
94 | 8000}; | ||
95 | |||
96 | enum mode { | ||
97 | US5182D_ALS_PX, | ||
98 | US5182D_ALS_ONLY, | ||
99 | US5182D_PX_ONLY | ||
100 | }; | ||
101 | |||
102 | struct us5182d_data { | ||
103 | struct i2c_client *client; | ||
104 | struct mutex lock; | ||
105 | |||
106 | /* Glass attenuation factor */ | ||
107 | u32 ga; | ||
108 | |||
109 | /* Dark gain tuning */ | ||
110 | u8 lower_dark_gain; | ||
111 | u8 upper_dark_gain; | ||
112 | u16 *us5182d_dark_ths; | ||
113 | |||
114 | u8 opmode; | ||
115 | }; | ||
116 | |||
117 | static IIO_CONST_ATTR(in_illuminance_scale_available, | ||
118 | "0.0021 0.0039 0.0076 0.0196 0.0336 0.061 0.1078 0.1885"); | ||
119 | |||
120 | static struct attribute *us5182d_attrs[] = { | ||
121 | &iio_const_attr_in_illuminance_scale_available.dev_attr.attr, | ||
122 | NULL | ||
123 | }; | ||
124 | |||
125 | static const struct attribute_group us5182d_attr_group = { | ||
126 | .attrs = us5182d_attrs, | ||
127 | }; | ||
128 | |||
129 | static const struct { | ||
130 | u8 reg; | ||
131 | u8 val; | ||
132 | } us5182d_regvals[] = { | ||
133 | {US5182D_REG_CFG0, (US5182D_CFG0_SHUTDOWN_EN | | ||
134 | US5182D_CFG0_WORD_ENABLE)}, | ||
135 | {US5182D_REG_CFG1, US5182D_CFG1_ALS_RES16}, | ||
136 | {US5182D_REG_CFG2, (US5182D_CFG2_PX_RES16 | | ||
137 | US5182D_CFG2_PXGAIN_DEFAULT)}, | ||
138 | {US5182D_REG_CFG3, US5182D_CFG3_LED_CURRENT100}, | ||
139 | {US5182D_REG_MODE_STORE, US5182D_STORE_MODE}, | ||
140 | {US5182D_REG_CFG4, 0x00}, | ||
141 | }; | ||
142 | |||
143 | static const struct iio_chan_spec us5182d_channels[] = { | ||
144 | { | ||
145 | .type = IIO_LIGHT, | ||
146 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | ||
147 | BIT(IIO_CHAN_INFO_SCALE), | ||
148 | }, | ||
149 | { | ||
150 | .type = IIO_PROXIMITY, | ||
151 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
152 | } | ||
153 | }; | ||
154 | |||
155 | static int us5182d_get_als(struct us5182d_data *data) | ||
156 | { | ||
157 | int ret; | ||
158 | unsigned long result; | ||
159 | |||
160 | ret = i2c_smbus_read_word_data(data->client, | ||
161 | US5182D_REG_ADL); | ||
162 | if (ret < 0) | ||
163 | return ret; | ||
164 | |||
165 | result = ret * data->ga / US5182D_GA_RESOLUTION; | ||
166 | if (result > 0xffff) | ||
167 | result = 0xffff; | ||
168 | |||
169 | return result; | ||
170 | } | ||
171 | |||
172 | static int us5182d_set_opmode(struct us5182d_data *data, u8 mode) | ||
173 | { | ||
174 | int ret; | ||
175 | |||
176 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0); | ||
177 | if (ret < 0) | ||
178 | return ret; | ||
179 | |||
180 | /* | ||
181 | * In oneshot mode the chip will power itself down after taking the | ||
182 | * required measurement. | ||
183 | */ | ||
184 | ret = ret | US5182D_CFG0_ONESHOT_EN; | ||
185 | |||
186 | /* update mode */ | ||
187 | ret = ret & ~US5182D_OPMODE_MASK; | ||
188 | ret = ret | (mode << US5182D_OPMODE_SHIFT); | ||
189 | |||
190 | /* | ||
191 | * After updating the operating mode, the chip requires that | ||
192 | * the operation is stored, by writing 1 in the STORE_MODE | ||
193 | * register (auto-clearing). | ||
194 | */ | ||
195 | ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret); | ||
196 | if (ret < 0) | ||
197 | return ret; | ||
198 | |||
199 | if (mode == data->opmode) | ||
200 | return 0; | ||
201 | |||
202 | ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_MODE_STORE, | ||
203 | US5182D_STORE_MODE); | ||
204 | if (ret < 0) | ||
205 | return ret; | ||
206 | |||
207 | data->opmode = mode; | ||
208 | msleep(US5182D_OPSTORE_SLEEP_TIME); | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | static int us5182d_read_raw(struct iio_dev *indio_dev, | ||
214 | struct iio_chan_spec const *chan, int *val, | ||
215 | int *val2, long mask) | ||
216 | { | ||
217 | struct us5182d_data *data = iio_priv(indio_dev); | ||
218 | int ret; | ||
219 | |||
220 | switch (mask) { | ||
221 | case IIO_CHAN_INFO_RAW: | ||
222 | switch (chan->type) { | ||
223 | case IIO_LIGHT: | ||
224 | mutex_lock(&data->lock); | ||
225 | ret = us5182d_set_opmode(data, US5182D_OPMODE_ALS); | ||
226 | if (ret < 0) | ||
227 | goto out_err; | ||
228 | |||
229 | ret = us5182d_get_als(data); | ||
230 | if (ret < 0) | ||
231 | goto out_err; | ||
232 | mutex_unlock(&data->lock); | ||
233 | *val = ret; | ||
234 | return IIO_VAL_INT; | ||
235 | case IIO_PROXIMITY: | ||
236 | mutex_lock(&data->lock); | ||
237 | ret = us5182d_set_opmode(data, US5182D_OPMODE_PX); | ||
238 | if (ret < 0) | ||
239 | goto out_err; | ||
240 | |||
241 | ret = i2c_smbus_read_word_data(data->client, | ||
242 | US5182D_REG_PDL); | ||
243 | if (ret < 0) | ||
244 | goto out_err; | ||
245 | mutex_unlock(&data->lock); | ||
246 | *val = ret; | ||
247 | return IIO_VAL_INT; | ||
248 | default: | ||
249 | return -EINVAL; | ||
250 | } | ||
251 | |||
252 | case IIO_CHAN_INFO_SCALE: | ||
253 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1); | ||
254 | if (ret < 0) | ||
255 | return ret; | ||
256 | |||
257 | *val = 0; | ||
258 | *val2 = us5182d_scales[ret & US5182D_AGAIN_MASK]; | ||
259 | |||
260 | return IIO_VAL_INT_PLUS_MICRO; | ||
261 | default: | ||
262 | return -EINVAL; | ||
263 | } | ||
264 | |||
265 | return -EINVAL; | ||
266 | out_err: | ||
267 | mutex_unlock(&data->lock); | ||
268 | return ret; | ||
269 | } | ||
270 | |||
271 | /** | ||
272 | * us5182d_update_dark_th - update Darh_Th registers | ||
273 | * @data us5182d_data structure | ||
274 | * @index index in us5182d_dark_ths array to use for the updated value | ||
275 | * | ||
276 | * Function needs to be called with a lock held because it needs two i2c write | ||
277 | * byte operations as these registers (0x27 0x28) don't work in word mode | ||
278 | * accessing. | ||
279 | */ | ||
280 | static int us5182d_update_dark_th(struct us5182d_data *data, int index) | ||
281 | { | ||
282 | __be16 dark_th = cpu_to_be16(data->us5182d_dark_ths[index]); | ||
283 | int ret; | ||
284 | |||
285 | ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_UDARK_TH, | ||
286 | ((u8 *)&dark_th)[0]); | ||
287 | if (ret < 0) | ||
288 | return ret; | ||
289 | |||
290 | return i2c_smbus_write_byte_data(data->client, US5182D_REG_UDARK_TH + 1, | ||
291 | ((u8 *)&dark_th)[1]); | ||
292 | } | ||
293 | |||
294 | /** | ||
295 | * us5182d_apply_scale - update the ALS scale | ||
296 | * @data us5182d_data structure | ||
297 | * @index index in us5182d_scales array to use for the updated value | ||
298 | * | ||
299 | * Function needs to be called with a lock held as we're having more than one | ||
300 | * i2c operation. | ||
301 | */ | ||
302 | static int us5182d_apply_scale(struct us5182d_data *data, int index) | ||
303 | { | ||
304 | int ret; | ||
305 | |||
306 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1); | ||
307 | if (ret < 0) | ||
308 | return ret; | ||
309 | |||
310 | ret = ret & (~US5182D_AGAIN_MASK); | ||
311 | ret |= index; | ||
312 | |||
313 | ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG1, ret); | ||
314 | if (ret < 0) | ||
315 | return ret; | ||
316 | |||
317 | return us5182d_update_dark_th(data, index); | ||
318 | } | ||
319 | |||
320 | static int us5182d_write_raw(struct iio_dev *indio_dev, | ||
321 | struct iio_chan_spec const *chan, int val, | ||
322 | int val2, long mask) | ||
323 | { | ||
324 | struct us5182d_data *data = iio_priv(indio_dev); | ||
325 | int ret, i; | ||
326 | |||
327 | switch (mask) { | ||
328 | case IIO_CHAN_INFO_SCALE: | ||
329 | if (val != 0) | ||
330 | return -EINVAL; | ||
331 | for (i = 0; i < ARRAY_SIZE(us5182d_scales); i++) | ||
332 | if (val2 == us5182d_scales[i]) { | ||
333 | mutex_lock(&data->lock); | ||
334 | ret = us5182d_apply_scale(data, i); | ||
335 | mutex_unlock(&data->lock); | ||
336 | return ret; | ||
337 | } | ||
338 | break; | ||
339 | default: | ||
340 | return -EINVAL; | ||
341 | } | ||
342 | |||
343 | return -EINVAL; | ||
344 | } | ||
345 | |||
346 | static const struct iio_info us5182d_info = { | ||
347 | .driver_module = THIS_MODULE, | ||
348 | .read_raw = us5182d_read_raw, | ||
349 | .write_raw = us5182d_write_raw, | ||
350 | .attrs = &us5182d_attr_group, | ||
351 | }; | ||
352 | |||
353 | static int us5182d_reset(struct iio_dev *indio_dev) | ||
354 | { | ||
355 | struct us5182d_data *data = iio_priv(indio_dev); | ||
356 | |||
357 | return i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG3, | ||
358 | US5182D_RESET_CHIP); | ||
359 | } | ||
360 | |||
361 | static int us5182d_init(struct iio_dev *indio_dev) | ||
362 | { | ||
363 | struct us5182d_data *data = iio_priv(indio_dev); | ||
364 | int i, ret; | ||
365 | |||
366 | ret = us5182d_reset(indio_dev); | ||
367 | if (ret < 0) | ||
368 | return ret; | ||
369 | |||
370 | data->opmode = 0; | ||
371 | for (i = 0; i < ARRAY_SIZE(us5182d_regvals); i++) { | ||
372 | ret = i2c_smbus_write_byte_data(data->client, | ||
373 | us5182d_regvals[i].reg, | ||
374 | us5182d_regvals[i].val); | ||
375 | if (ret < 0) | ||
376 | return ret; | ||
377 | } | ||
378 | |||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | static void us5182d_get_platform_data(struct iio_dev *indio_dev) | ||
383 | { | ||
384 | struct us5182d_data *data = iio_priv(indio_dev); | ||
385 | |||
386 | if (device_property_read_u32(&data->client->dev, "upisemi,glass-coef", | ||
387 | &data->ga)) | ||
388 | data->ga = US5182D_GA_RESOLUTION; | ||
389 | if (device_property_read_u16_array(&data->client->dev, | ||
390 | "upisemi,dark-ths", | ||
391 | data->us5182d_dark_ths, | ||
392 | ARRAY_SIZE(us5182d_dark_ths_vals))) | ||
393 | data->us5182d_dark_ths = us5182d_dark_ths_vals; | ||
394 | if (device_property_read_u8(&data->client->dev, | ||
395 | "upisemi,upper-dark-gain", | ||
396 | &data->upper_dark_gain)) | ||
397 | data->upper_dark_gain = US5182D_REG_AUTO_HDARK_GAIN_DEFAULT; | ||
398 | if (device_property_read_u8(&data->client->dev, | ||
399 | "upisemi,lower-dark-gain", | ||
400 | &data->lower_dark_gain)) | ||
401 | data->lower_dark_gain = US5182D_REG_AUTO_LDARK_GAIN_DEFAULT; | ||
402 | } | ||
403 | |||
404 | static int us5182d_dark_gain_config(struct iio_dev *indio_dev) | ||
405 | { | ||
406 | struct us5182d_data *data = iio_priv(indio_dev); | ||
407 | int ret; | ||
408 | |||
409 | ret = us5182d_update_dark_th(data, US5182D_CFG1_AGAIN_DEFAULT); | ||
410 | if (ret < 0) | ||
411 | return ret; | ||
412 | |||
413 | ret = i2c_smbus_write_byte_data(data->client, | ||
414 | US5182D_REG_AUTO_LDARK_GAIN, | ||
415 | data->lower_dark_gain); | ||
416 | if (ret < 0) | ||
417 | return ret; | ||
418 | |||
419 | ret = i2c_smbus_write_byte_data(data->client, | ||
420 | US5182D_REG_AUTO_HDARK_GAIN, | ||
421 | data->upper_dark_gain); | ||
422 | if (ret < 0) | ||
423 | return ret; | ||
424 | |||
425 | return i2c_smbus_write_byte_data(data->client, US5182D_REG_DARK_AUTO_EN, | ||
426 | US5182D_REG_DARK_AUTO_EN_DEFAULT); | ||
427 | } | ||
428 | |||
429 | static int us5182d_probe(struct i2c_client *client, | ||
430 | const struct i2c_device_id *id) | ||
431 | { | ||
432 | struct us5182d_data *data; | ||
433 | struct iio_dev *indio_dev; | ||
434 | int ret; | ||
435 | |||
436 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | ||
437 | if (!indio_dev) | ||
438 | return -ENOMEM; | ||
439 | |||
440 | data = iio_priv(indio_dev); | ||
441 | i2c_set_clientdata(client, indio_dev); | ||
442 | data->client = client; | ||
443 | |||
444 | mutex_init(&data->lock); | ||
445 | |||
446 | indio_dev->dev.parent = &client->dev; | ||
447 | indio_dev->info = &us5182d_info; | ||
448 | indio_dev->name = US5182D_DRV_NAME; | ||
449 | indio_dev->channels = us5182d_channels; | ||
450 | indio_dev->num_channels = ARRAY_SIZE(us5182d_channels); | ||
451 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
452 | |||
453 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CHIPID); | ||
454 | if (ret != US5182D_CHIPID) { | ||
455 | dev_err(&data->client->dev, | ||
456 | "Failed to detect US5182 light chip\n"); | ||
457 | return (ret < 0) ? ret : -ENODEV; | ||
458 | } | ||
459 | |||
460 | us5182d_get_platform_data(indio_dev); | ||
461 | ret = us5182d_init(indio_dev); | ||
462 | if (ret < 0) | ||
463 | return ret; | ||
464 | |||
465 | ret = us5182d_dark_gain_config(indio_dev); | ||
466 | if (ret < 0) | ||
467 | return ret; | ||
468 | |||
469 | return iio_device_register(indio_dev); | ||
470 | } | ||
471 | |||
472 | static int us5182d_remove(struct i2c_client *client) | ||
473 | { | ||
474 | iio_device_unregister(i2c_get_clientdata(client)); | ||
475 | return i2c_smbus_write_byte_data(client, US5182D_REG_CFG0, | ||
476 | US5182D_CFG0_SHUTDOWN_EN); | ||
477 | } | ||
478 | |||
479 | static const struct acpi_device_id us5182d_acpi_match[] = { | ||
480 | { "USD5182", 0}, | ||
481 | {} | ||
482 | }; | ||
483 | |||
484 | MODULE_DEVICE_TABLE(acpi, us5182d_acpi_match); | ||
485 | |||
486 | static const struct i2c_device_id us5182d_id[] = { | ||
487 | {"usd5182", 0}, | ||
488 | {} | ||
489 | }; | ||
490 | |||
491 | MODULE_DEVICE_TABLE(i2c, us5182d_id); | ||
492 | |||
493 | static struct i2c_driver us5182d_driver = { | ||
494 | .driver = { | ||
495 | .name = US5182D_DRV_NAME, | ||
496 | .acpi_match_table = ACPI_PTR(us5182d_acpi_match), | ||
497 | }, | ||
498 | .probe = us5182d_probe, | ||
499 | .remove = us5182d_remove, | ||
500 | .id_table = us5182d_id, | ||
501 | |||
502 | }; | ||
503 | module_i2c_driver(us5182d_driver); | ||
504 | |||
505 | MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>"); | ||
506 | MODULE_DESCRIPTION("Driver for us5182d Proximity and Light Sensor"); | ||
507 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index efb9350b0d76..868abada3409 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig | |||
@@ -24,6 +24,24 @@ config AK09911 | |||
24 | help | 24 | help |
25 | Deprecated: AK09911 is now supported by AK8975 driver. | 25 | Deprecated: AK09911 is now supported by AK8975 driver. |
26 | 26 | ||
27 | config BMC150_MAGN | ||
28 | tristate "Bosch BMC150 Magnetometer Driver" | ||
29 | depends on I2C | ||
30 | select REGMAP_I2C | ||
31 | select IIO_BUFFER | ||
32 | select IIO_TRIGGERED_BUFFER | ||
33 | help | ||
34 | Say yes here to build support for the BMC150 magnetometer. | ||
35 | |||
36 | Currently this only supports the device via an i2c interface. | ||
37 | |||
38 | This is a combo module with both accelerometer and magnetometer. | ||
39 | This driver is only implementing magnetometer part, which has | ||
40 | its own address and register map. | ||
41 | |||
42 | To compile this driver as a module, choose M here: the module will be | ||
43 | called bmc150_magn. | ||
44 | |||
27 | config MAG3110 | 45 | config MAG3110 |
28 | tristate "Freescale MAG3110 3-Axis Magnetometer" | 46 | tristate "Freescale MAG3110 3-Axis Magnetometer" |
29 | depends on I2C | 47 | depends on I2C |
@@ -87,19 +105,4 @@ config IIO_ST_MAGN_SPI_3AXIS | |||
87 | depends on IIO_ST_MAGN_3AXIS | 105 | depends on IIO_ST_MAGN_3AXIS |
88 | depends on IIO_ST_SENSORS_SPI | 106 | depends on IIO_ST_SENSORS_SPI |
89 | 107 | ||
90 | config BMC150_MAGN | ||
91 | tristate "Bosch BMC150 Magnetometer Driver" | ||
92 | depends on I2C | ||
93 | select REGMAP_I2C | ||
94 | select IIO_BUFFER | ||
95 | select IIO_TRIGGERED_BUFFER | ||
96 | help | ||
97 | Say yes here to build support for the BMC150 magnetometer. | ||
98 | |||
99 | Currently this only supports the device via an i2c interface. | ||
100 | |||
101 | This is a combo module with both accelerometer and magnetometer. | ||
102 | This driver is only implementing magnetometer part, which has | ||
103 | its own address and register map. | ||
104 | |||
105 | endmenu | 108 | endmenu |
diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile index 33b1d4d54ee7..2c72df458ec2 100644 --- a/drivers/iio/magnetometer/Makefile +++ b/drivers/iio/magnetometer/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | # When adding new entries keep the list in alphabetical order | 5 | # When adding new entries keep the list in alphabetical order |
6 | obj-$(CONFIG_AK8975) += ak8975.o | 6 | obj-$(CONFIG_AK8975) += ak8975.o |
7 | obj-$(CONFIG_BMC150_MAGN) += bmc150_magn.o | ||
7 | obj-$(CONFIG_MAG3110) += mag3110.o | 8 | obj-$(CONFIG_MAG3110) += mag3110.o |
8 | obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o | 9 | obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o |
9 | obj-$(CONFIG_MMC35240) += mmc35240.o | 10 | obj-$(CONFIG_MMC35240) += mmc35240.o |
@@ -14,5 +15,3 @@ st_magn-$(CONFIG_IIO_BUFFER) += st_magn_buffer.o | |||
14 | 15 | ||
15 | obj-$(CONFIG_IIO_ST_MAGN_I2C_3AXIS) += st_magn_i2c.o | 16 | obj-$(CONFIG_IIO_ST_MAGN_I2C_3AXIS) += st_magn_i2c.o |
16 | obj-$(CONFIG_IIO_ST_MAGN_SPI_3AXIS) += st_magn_spi.o | 17 | obj-$(CONFIG_IIO_ST_MAGN_SPI_3AXIS) += st_magn_spi.o |
17 | |||
18 | obj-$(CONFIG_BMC150_MAGN) += bmc150_magn.o | ||
diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c index f8dc4b85d70c..b27f0146647b 100644 --- a/drivers/iio/magnetometer/st_magn_core.c +++ b/drivers/iio/magnetometer/st_magn_core.c | |||
@@ -560,6 +560,7 @@ static const struct iio_info magn_info = { | |||
560 | .attrs = &st_magn_attribute_group, | 560 | .attrs = &st_magn_attribute_group, |
561 | .read_raw = &st_magn_read_raw, | 561 | .read_raw = &st_magn_read_raw, |
562 | .write_raw = &st_magn_write_raw, | 562 | .write_raw = &st_magn_write_raw, |
563 | .debugfs_reg_access = &st_sensors_debugfs_reg_access, | ||
563 | }; | 564 | }; |
564 | 565 | ||
565 | #ifdef CONFIG_IIO_TRIGGER | 566 | #ifdef CONFIG_IIO_TRIGGER |
diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c index eb41d2b92c24..b39a2fb0671c 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c | |||
@@ -400,6 +400,7 @@ static const struct iio_info press_info = { | |||
400 | .attrs = &st_press_attribute_group, | 400 | .attrs = &st_press_attribute_group, |
401 | .read_raw = &st_press_read_raw, | 401 | .read_raw = &st_press_read_raw, |
402 | .write_raw = &st_press_write_raw, | 402 | .write_raw = &st_press_write_raw, |
403 | .debugfs_reg_access = &st_sensors_debugfs_reg_access, | ||
403 | }; | 404 | }; |
404 | 405 | ||
405 | #ifdef CONFIG_IIO_TRIGGER | 406 | #ifdef CONFIG_IIO_TRIGGER |
diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig index 41a8d8ffa0de..ef4c73db5b53 100644 --- a/drivers/iio/proximity/Kconfig +++ b/drivers/iio/proximity/Kconfig | |||
@@ -20,6 +20,18 @@ endmenu | |||
20 | 20 | ||
21 | menu "Proximity sensors" | 21 | menu "Proximity sensors" |
22 | 22 | ||
23 | config LIDAR_LITE_V2 | ||
24 | tristate "PulsedLight LIDAR sensor" | ||
25 | select IIO_BUFFER | ||
26 | select IIO_TRIGGERED_BUFFER | ||
27 | depends on I2C | ||
28 | help | ||
29 | Say Y to build a driver for PulsedLight LIDAR range finding | ||
30 | sensor. | ||
31 | |||
32 | To compile this driver as a module, choose M here: the | ||
33 | module will be called pulsedlight-lite-v2 | ||
34 | |||
23 | config SX9500 | 35 | config SX9500 |
24 | tristate "SX9500 Semtech proximity sensor" | 36 | tristate "SX9500 Semtech proximity sensor" |
25 | select IIO_BUFFER | 37 | select IIO_BUFFER |
diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile index 9818dc562abd..9aadd9a8ee99 100644 --- a/drivers/iio/proximity/Makefile +++ b/drivers/iio/proximity/Makefile | |||
@@ -4,4 +4,5 @@ | |||
4 | 4 | ||
5 | # When adding new entries keep the list in alphabetical order | 5 | # When adding new entries keep the list in alphabetical order |
6 | obj-$(CONFIG_AS3935) += as3935.o | 6 | obj-$(CONFIG_AS3935) += as3935.o |
7 | obj-$(CONFIG_LIDAR_LITE_V2) += pulsedlight-lidar-lite-v2.o | ||
7 | obj-$(CONFIG_SX9500) += sx9500.o | 8 | obj-$(CONFIG_SX9500) += sx9500.o |
diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c index bc0d68efd455..e95035136889 100644 --- a/drivers/iio/proximity/as3935.c +++ b/drivers/iio/proximity/as3935.c | |||
@@ -434,6 +434,12 @@ static int as3935_remove(struct spi_device *spi) | |||
434 | return 0; | 434 | return 0; |
435 | } | 435 | } |
436 | 436 | ||
437 | static const struct of_device_id as3935_of_match[] = { | ||
438 | { .compatible = "ams,as3935", }, | ||
439 | { /* sentinel */ }, | ||
440 | }; | ||
441 | MODULE_DEVICE_TABLE(of, as3935_of_match); | ||
442 | |||
437 | static const struct spi_device_id as3935_id[] = { | 443 | static const struct spi_device_id as3935_id[] = { |
438 | {"as3935", 0}, | 444 | {"as3935", 0}, |
439 | {}, | 445 | {}, |
@@ -443,6 +449,7 @@ MODULE_DEVICE_TABLE(spi, as3935_id); | |||
443 | static struct spi_driver as3935_driver = { | 449 | static struct spi_driver as3935_driver = { |
444 | .driver = { | 450 | .driver = { |
445 | .name = "as3935", | 451 | .name = "as3935", |
452 | .of_match_table = of_match_ptr(as3935_of_match), | ||
446 | .owner = THIS_MODULE, | 453 | .owner = THIS_MODULE, |
447 | .pm = AS3935_PM_OPS, | 454 | .pm = AS3935_PM_OPS, |
448 | }, | 455 | }, |
diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c new file mode 100644 index 000000000000..185a7ab4f31b --- /dev/null +++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c | |||
@@ -0,0 +1,288 @@ | |||
1 | /* | ||
2 | * pulsedlight-lidar-lite-v2.c - Support for PulsedLight LIDAR sensor | ||
3 | * | ||
4 | * Copyright (C) 2015 Matt Ranostay <mranostay@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * TODO: runtime pm, interrupt mode, and signal strength reporting | ||
17 | */ | ||
18 | |||
19 | #include <linux/err.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/i2c.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/iio/iio.h> | ||
25 | #include <linux/iio/sysfs.h> | ||
26 | #include <linux/iio/buffer.h> | ||
27 | #include <linux/iio/trigger.h> | ||
28 | #include <linux/iio/triggered_buffer.h> | ||
29 | #include <linux/iio/trigger_consumer.h> | ||
30 | |||
31 | #define LIDAR_REG_CONTROL 0x00 | ||
32 | #define LIDAR_REG_CONTROL_ACQUIRE BIT(2) | ||
33 | |||
34 | #define LIDAR_REG_STATUS 0x01 | ||
35 | #define LIDAR_REG_STATUS_INVALID BIT(3) | ||
36 | #define LIDAR_REG_STATUS_READY BIT(0) | ||
37 | |||
38 | #define LIDAR_REG_DATA_HBYTE 0x0f | ||
39 | #define LIDAR_REG_DATA_LBYTE 0x10 | ||
40 | |||
41 | #define LIDAR_DRV_NAME "lidar" | ||
42 | |||
43 | struct lidar_data { | ||
44 | struct iio_dev *indio_dev; | ||
45 | struct i2c_client *client; | ||
46 | |||
47 | u16 buffer[8]; /* 2 byte distance + 8 byte timestamp */ | ||
48 | }; | ||
49 | |||
50 | static const struct iio_chan_spec lidar_channels[] = { | ||
51 | { | ||
52 | .type = IIO_DISTANCE, | ||
53 | .info_mask_separate = | ||
54 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | ||
55 | .scan_index = 0, | ||
56 | .scan_type = { | ||
57 | .sign = 'u', | ||
58 | .realbits = 16, | ||
59 | .storagebits = 16, | ||
60 | }, | ||
61 | }, | ||
62 | IIO_CHAN_SOFT_TIMESTAMP(1), | ||
63 | }; | ||
64 | |||
65 | static int lidar_read_byte(struct lidar_data *data, int reg) | ||
66 | { | ||
67 | struct i2c_client *client = data->client; | ||
68 | int ret; | ||
69 | |||
70 | /* | ||
71 | * Device needs a STOP condition between address write, and data read | ||
72 | * so in turn i2c_smbus_read_byte_data cannot be used | ||
73 | */ | ||
74 | |||
75 | ret = i2c_smbus_write_byte(client, reg); | ||
76 | if (ret < 0) { | ||
77 | dev_err(&client->dev, "cannot write addr value"); | ||
78 | return ret; | ||
79 | } | ||
80 | |||
81 | ret = i2c_smbus_read_byte(client); | ||
82 | if (ret < 0) | ||
83 | dev_err(&client->dev, "cannot read data value"); | ||
84 | |||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | static inline int lidar_write_control(struct lidar_data *data, int val) | ||
89 | { | ||
90 | return i2c_smbus_write_byte_data(data->client, LIDAR_REG_CONTROL, val); | ||
91 | } | ||
92 | |||
93 | static int lidar_read_measurement(struct lidar_data *data, u16 *reg) | ||
94 | { | ||
95 | int ret; | ||
96 | int val; | ||
97 | |||
98 | ret = lidar_read_byte(data, LIDAR_REG_DATA_HBYTE); | ||
99 | if (ret < 0) | ||
100 | return ret; | ||
101 | val = ret << 8; | ||
102 | |||
103 | ret = lidar_read_byte(data, LIDAR_REG_DATA_LBYTE); | ||
104 | if (ret < 0) | ||
105 | return ret; | ||
106 | |||
107 | val |= ret; | ||
108 | *reg = val; | ||
109 | |||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static int lidar_get_measurement(struct lidar_data *data, u16 *reg) | ||
114 | { | ||
115 | struct i2c_client *client = data->client; | ||
116 | int tries = 10; | ||
117 | int ret; | ||
118 | |||
119 | /* start sample */ | ||
120 | ret = lidar_write_control(data, LIDAR_REG_CONTROL_ACQUIRE); | ||
121 | if (ret < 0) { | ||
122 | dev_err(&client->dev, "cannot send start measurement command"); | ||
123 | return ret; | ||
124 | } | ||
125 | |||
126 | while (tries--) { | ||
127 | usleep_range(1000, 2000); | ||
128 | |||
129 | ret = lidar_read_byte(data, LIDAR_REG_STATUS); | ||
130 | if (ret < 0) | ||
131 | break; | ||
132 | |||
133 | /* return 0 since laser is likely pointed out of range */ | ||
134 | if (ret & LIDAR_REG_STATUS_INVALID) { | ||
135 | *reg = 0; | ||
136 | ret = 0; | ||
137 | break; | ||
138 | } | ||
139 | |||
140 | /* sample ready to read */ | ||
141 | if (!(ret & LIDAR_REG_STATUS_READY)) { | ||
142 | ret = lidar_read_measurement(data, reg); | ||
143 | break; | ||
144 | } | ||
145 | ret = -EIO; | ||
146 | } | ||
147 | |||
148 | return ret; | ||
149 | } | ||
150 | |||
151 | static int lidar_read_raw(struct iio_dev *indio_dev, | ||
152 | struct iio_chan_spec const *chan, | ||
153 | int *val, int *val2, long mask) | ||
154 | { | ||
155 | struct lidar_data *data = iio_priv(indio_dev); | ||
156 | int ret = -EINVAL; | ||
157 | |||
158 | mutex_lock(&indio_dev->mlock); | ||
159 | |||
160 | if (iio_buffer_enabled(indio_dev) && mask == IIO_CHAN_INFO_RAW) { | ||
161 | ret = -EBUSY; | ||
162 | goto error_busy; | ||
163 | } | ||
164 | |||
165 | switch (mask) { | ||
166 | case IIO_CHAN_INFO_RAW: { | ||
167 | u16 reg; | ||
168 | |||
169 | ret = lidar_get_measurement(data, ®); | ||
170 | if (!ret) { | ||
171 | *val = reg; | ||
172 | ret = IIO_VAL_INT; | ||
173 | } | ||
174 | break; | ||
175 | } | ||
176 | case IIO_CHAN_INFO_SCALE: | ||
177 | *val = 0; | ||
178 | *val2 = 10000; | ||
179 | ret = IIO_VAL_INT_PLUS_MICRO; | ||
180 | break; | ||
181 | } | ||
182 | |||
183 | error_busy: | ||
184 | mutex_unlock(&indio_dev->mlock); | ||
185 | |||
186 | return ret; | ||
187 | } | ||
188 | |||
189 | static irqreturn_t lidar_trigger_handler(int irq, void *private) | ||
190 | { | ||
191 | struct iio_poll_func *pf = private; | ||
192 | struct iio_dev *indio_dev = pf->indio_dev; | ||
193 | struct lidar_data *data = iio_priv(indio_dev); | ||
194 | int ret; | ||
195 | |||
196 | ret = lidar_get_measurement(data, data->buffer); | ||
197 | if (!ret) { | ||
198 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | ||
199 | iio_get_time_ns()); | ||
200 | } else { | ||
201 | dev_err(&data->client->dev, "cannot read LIDAR measurement"); | ||
202 | } | ||
203 | |||
204 | iio_trigger_notify_done(indio_dev->trig); | ||
205 | |||
206 | return IRQ_HANDLED; | ||
207 | } | ||
208 | |||
209 | static const struct iio_info lidar_info = { | ||
210 | .driver_module = THIS_MODULE, | ||
211 | .read_raw = lidar_read_raw, | ||
212 | }; | ||
213 | |||
214 | static int lidar_probe(struct i2c_client *client, | ||
215 | const struct i2c_device_id *id) | ||
216 | { | ||
217 | struct lidar_data *data; | ||
218 | struct iio_dev *indio_dev; | ||
219 | int ret; | ||
220 | |||
221 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | ||
222 | if (!indio_dev) | ||
223 | return -ENOMEM; | ||
224 | |||
225 | indio_dev->info = &lidar_info; | ||
226 | indio_dev->name = LIDAR_DRV_NAME; | ||
227 | indio_dev->channels = lidar_channels; | ||
228 | indio_dev->num_channels = ARRAY_SIZE(lidar_channels); | ||
229 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
230 | |||
231 | data = iio_priv(indio_dev); | ||
232 | i2c_set_clientdata(client, indio_dev); | ||
233 | |||
234 | data->client = client; | ||
235 | data->indio_dev = indio_dev; | ||
236 | |||
237 | ret = iio_triggered_buffer_setup(indio_dev, NULL, | ||
238 | lidar_trigger_handler, NULL); | ||
239 | if (ret) | ||
240 | return ret; | ||
241 | |||
242 | ret = iio_device_register(indio_dev); | ||
243 | if (ret) | ||
244 | goto error_unreg_buffer; | ||
245 | |||
246 | return 0; | ||
247 | |||
248 | error_unreg_buffer: | ||
249 | iio_triggered_buffer_cleanup(indio_dev); | ||
250 | |||
251 | return ret; | ||
252 | } | ||
253 | |||
254 | static int lidar_remove(struct i2c_client *client) | ||
255 | { | ||
256 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | ||
257 | |||
258 | iio_device_unregister(indio_dev); | ||
259 | iio_triggered_buffer_cleanup(indio_dev); | ||
260 | |||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | static const struct i2c_device_id lidar_id[] = { | ||
265 | {"lidar-lite-v2", 0}, | ||
266 | { }, | ||
267 | }; | ||
268 | MODULE_DEVICE_TABLE(i2c, lidar_id); | ||
269 | |||
270 | static const struct of_device_id lidar_dt_ids[] = { | ||
271 | { .compatible = "pulsedlight,lidar-lite-v2" }, | ||
272 | { } | ||
273 | }; | ||
274 | |||
275 | static struct i2c_driver lidar_driver = { | ||
276 | .driver = { | ||
277 | .name = LIDAR_DRV_NAME, | ||
278 | .of_match_table = of_match_ptr(lidar_dt_ids), | ||
279 | }, | ||
280 | .probe = lidar_probe, | ||
281 | .remove = lidar_remove, | ||
282 | .id_table = lidar_id, | ||
283 | }; | ||
284 | module_i2c_driver(lidar_driver); | ||
285 | |||
286 | MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>"); | ||
287 | MODULE_DESCRIPTION("PulsedLight LIDAR sensor"); | ||
288 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c index 5d033a5af615..3fd3ba426a84 100644 --- a/drivers/iio/temperature/mlx90614.c +++ b/drivers/iio/temperature/mlx90614.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net> | 4 | * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net> |
5 | * Copyright (c) 2015 Essensium NV | 5 | * Copyright (c) 2015 Essensium NV |
6 | * Copyright (c) 2015 Melexis | ||
6 | * | 7 | * |
7 | * This file is subject to the terms and conditions of version 2 of | 8 | * This file is subject to the terms and conditions of version 2 of |
8 | * the GNU General Public License. See the file COPYING in the main | 9 | * the GNU General Public License. See the file COPYING in the main |
@@ -20,7 +21,6 @@ | |||
20 | * always has a pull-up so we do not need an extra GPIO to drive it high. If | 21 | * always has a pull-up so we do not need an extra GPIO to drive it high. If |
21 | * the "wakeup" GPIO is not given, power management will be disabled. | 22 | * the "wakeup" GPIO is not given, power management will be disabled. |
22 | * | 23 | * |
23 | * TODO: filter configuration | ||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/err.h> | 26 | #include <linux/err.h> |
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/pm_runtime.h> | 32 | #include <linux/pm_runtime.h> |
33 | 33 | ||
34 | #include <linux/iio/iio.h> | 34 | #include <linux/iio/iio.h> |
35 | #include <linux/iio/sysfs.h> | ||
35 | 36 | ||
36 | #define MLX90614_OP_RAM 0x00 | 37 | #define MLX90614_OP_RAM 0x00 |
37 | #define MLX90614_OP_EEPROM 0x20 | 38 | #define MLX90614_OP_EEPROM 0x20 |
@@ -79,6 +80,20 @@ struct mlx90614_data { | |||
79 | unsigned long ready_timestamp; /* in jiffies */ | 80 | unsigned long ready_timestamp; /* in jiffies */ |
80 | }; | 81 | }; |
81 | 82 | ||
83 | /* Bandwidth values for IIR filtering */ | ||
84 | static const int mlx90614_iir_values[] = {77, 31, 20, 15, 723, 153, 110, 86}; | ||
85 | static IIO_CONST_ATTR(in_temp_object_filter_low_pass_3db_frequency_available, | ||
86 | "0.15 0.20 0.31 0.77 0.86 1.10 1.53 7.23"); | ||
87 | |||
88 | static struct attribute *mlx90614_attributes[] = { | ||
89 | &iio_const_attr_in_temp_object_filter_low_pass_3db_frequency_available.dev_attr.attr, | ||
90 | NULL, | ||
91 | }; | ||
92 | |||
93 | static const struct attribute_group mlx90614_attr_group = { | ||
94 | .attrs = mlx90614_attributes, | ||
95 | }; | ||
96 | |||
82 | /* | 97 | /* |
83 | * Erase an address and write word. | 98 | * Erase an address and write word. |
84 | * The mutex must be locked before calling. | 99 | * The mutex must be locked before calling. |
@@ -117,6 +132,42 @@ static s32 mlx90614_write_word(const struct i2c_client *client, u8 command, | |||
117 | return ret; | 132 | return ret; |
118 | } | 133 | } |
119 | 134 | ||
135 | /* | ||
136 | * Find the IIR value inside mlx90614_iir_values array and return its position | ||
137 | * which is equivalent to the bit value in sensor register | ||
138 | */ | ||
139 | static inline s32 mlx90614_iir_search(const struct i2c_client *client, | ||
140 | int value) | ||
141 | { | ||
142 | int i; | ||
143 | s32 ret; | ||
144 | |||
145 | for (i = 0; i < ARRAY_SIZE(mlx90614_iir_values); ++i) { | ||
146 | if (value == mlx90614_iir_values[i]) | ||
147 | break; | ||
148 | } | ||
149 | |||
150 | if (i == ARRAY_SIZE(mlx90614_iir_values)) | ||
151 | return -EINVAL; | ||
152 | |||
153 | /* | ||
154 | * CONFIG register values must not be changed so | ||
155 | * we must read them before we actually write | ||
156 | * changes | ||
157 | */ | ||
158 | ret = i2c_smbus_read_word_data(client, MLX90614_CONFIG); | ||
159 | if (ret > 0) | ||
160 | return ret; | ||
161 | |||
162 | /* Write changed values */ | ||
163 | ret = mlx90614_write_word(client, MLX90614_CONFIG, | ||
164 | (i << MLX90614_CONFIG_IIR_SHIFT) | | ||
165 | (((u16) ((0x7 << MLX90614_CONFIG_FIR_SHIFT) | | ||
166 | ((u16) ret & (~((u16) MLX90614_CONFIG_FIR_MASK))))) & | ||
167 | (~(u16) MLX90614_CONFIG_IIR_MASK))); | ||
168 | return ret; | ||
169 | } | ||
170 | |||
120 | #ifdef CONFIG_PM | 171 | #ifdef CONFIG_PM |
121 | /* | 172 | /* |
122 | * If @startup is true, make sure MLX90614_TIMING_STARTUP ms have elapsed since | 173 | * If @startup is true, make sure MLX90614_TIMING_STARTUP ms have elapsed since |
@@ -236,6 +287,21 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev, | |||
236 | *val2 = ret * MLX90614_CONST_EMISSIVITY_RESOLUTION; | 287 | *val2 = ret * MLX90614_CONST_EMISSIVITY_RESOLUTION; |
237 | } | 288 | } |
238 | return IIO_VAL_INT_PLUS_NANO; | 289 | return IIO_VAL_INT_PLUS_NANO; |
290 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: /* IIR setting with | ||
291 | FIR = 1024 */ | ||
292 | mlx90614_power_get(data, false); | ||
293 | mutex_lock(&data->lock); | ||
294 | ret = i2c_smbus_read_word_data(data->client, MLX90614_CONFIG); | ||
295 | mutex_unlock(&data->lock); | ||
296 | mlx90614_power_put(data); | ||
297 | |||
298 | if (ret < 0) | ||
299 | return ret; | ||
300 | |||
301 | *val = mlx90614_iir_values[ret & MLX90614_CONFIG_IIR_MASK] / 100; | ||
302 | *val2 = (mlx90614_iir_values[ret & MLX90614_CONFIG_IIR_MASK] % 100) * | ||
303 | 10000; | ||
304 | return IIO_VAL_INT_PLUS_MICRO; | ||
239 | default: | 305 | default: |
240 | return -EINVAL; | 306 | return -EINVAL; |
241 | } | 307 | } |
@@ -263,6 +329,18 @@ static int mlx90614_write_raw(struct iio_dev *indio_dev, | |||
263 | mlx90614_power_put(data); | 329 | mlx90614_power_put(data); |
264 | 330 | ||
265 | return ret; | 331 | return ret; |
332 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: /* IIR Filter setting */ | ||
333 | if (val < 0 || val2 < 0) | ||
334 | return -EINVAL; | ||
335 | |||
336 | mlx90614_power_get(data, false); | ||
337 | mutex_lock(&data->lock); | ||
338 | ret = mlx90614_iir_search(data->client, | ||
339 | val * 100 + val2 / 10000); | ||
340 | mutex_unlock(&data->lock); | ||
341 | mlx90614_power_put(data); | ||
342 | |||
343 | return ret; | ||
266 | default: | 344 | default: |
267 | return -EINVAL; | 345 | return -EINVAL; |
268 | } | 346 | } |
@@ -275,6 +353,8 @@ static int mlx90614_write_raw_get_fmt(struct iio_dev *indio_dev, | |||
275 | switch (mask) { | 353 | switch (mask) { |
276 | case IIO_CHAN_INFO_CALIBEMISSIVITY: | 354 | case IIO_CHAN_INFO_CALIBEMISSIVITY: |
277 | return IIO_VAL_INT_PLUS_NANO; | 355 | return IIO_VAL_INT_PLUS_NANO; |
356 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: | ||
357 | return IIO_VAL_INT_PLUS_MICRO; | ||
278 | default: | 358 | default: |
279 | return -EINVAL; | 359 | return -EINVAL; |
280 | } | 360 | } |
@@ -294,7 +374,8 @@ static const struct iio_chan_spec mlx90614_channels[] = { | |||
294 | .modified = 1, | 374 | .modified = 1, |
295 | .channel2 = IIO_MOD_TEMP_OBJECT, | 375 | .channel2 = IIO_MOD_TEMP_OBJECT, |
296 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | 376 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
297 | BIT(IIO_CHAN_INFO_CALIBEMISSIVITY), | 377 | BIT(IIO_CHAN_INFO_CALIBEMISSIVITY) | |
378 | BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), | ||
298 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | 379 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | |
299 | BIT(IIO_CHAN_INFO_SCALE), | 380 | BIT(IIO_CHAN_INFO_SCALE), |
300 | }, | 381 | }, |
@@ -305,7 +386,8 @@ static const struct iio_chan_spec mlx90614_channels[] = { | |||
305 | .channel = 1, | 386 | .channel = 1, |
306 | .channel2 = IIO_MOD_TEMP_OBJECT, | 387 | .channel2 = IIO_MOD_TEMP_OBJECT, |
307 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | 388 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
308 | BIT(IIO_CHAN_INFO_CALIBEMISSIVITY), | 389 | BIT(IIO_CHAN_INFO_CALIBEMISSIVITY) | |
390 | BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), | ||
309 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | 391 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | |
310 | BIT(IIO_CHAN_INFO_SCALE), | 392 | BIT(IIO_CHAN_INFO_SCALE), |
311 | }, | 393 | }, |
@@ -315,6 +397,7 @@ static const struct iio_info mlx90614_info = { | |||
315 | .read_raw = mlx90614_read_raw, | 397 | .read_raw = mlx90614_read_raw, |
316 | .write_raw = mlx90614_write_raw, | 398 | .write_raw = mlx90614_write_raw, |
317 | .write_raw_get_fmt = mlx90614_write_raw_get_fmt, | 399 | .write_raw_get_fmt = mlx90614_write_raw_get_fmt, |
400 | .attrs = &mlx90614_attr_group, | ||
318 | .driver_module = THIS_MODULE, | 401 | .driver_module = THIS_MODULE, |
319 | }; | 402 | }; |
320 | 403 | ||
@@ -569,5 +652,6 @@ module_i2c_driver(mlx90614_driver); | |||
569 | 652 | ||
570 | MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); | 653 | MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); |
571 | MODULE_AUTHOR("Vianney le Clément de Saint-Marcq <vianney.leclement@essensium.com>"); | 654 | MODULE_AUTHOR("Vianney le Clément de Saint-Marcq <vianney.leclement@essensium.com>"); |
655 | MODULE_AUTHOR("Crt Mori <cmo@melexis.com>"); | ||
572 | MODULE_DESCRIPTION("Melexis MLX90614 contactless IR temperature sensor driver"); | 656 | MODULE_DESCRIPTION("Melexis MLX90614 contactless IR temperature sensor driver"); |
573 | MODULE_LICENSE("GPL"); | 657 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/staging/iio/adc/lpc32xx_adc.c b/drivers/staging/iio/adc/lpc32xx_adc.c index 5331c442fcfc..bcf4ebb2e3ab 100644 --- a/drivers/staging/iio/adc/lpc32xx_adc.c +++ b/drivers/staging/iio/adc/lpc32xx_adc.c | |||
@@ -137,7 +137,7 @@ static int lpc32xx_adc_probe(struct platform_device *pdev) | |||
137 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 137 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
138 | if (!res) { | 138 | if (!res) { |
139 | dev_err(&pdev->dev, "failed to get platform I/O memory\n"); | 139 | dev_err(&pdev->dev, "failed to get platform I/O memory\n"); |
140 | return -EBUSY; | 140 | return -ENXIO; |
141 | } | 141 | } |
142 | 142 | ||
143 | iodev = devm_iio_device_alloc(&pdev->dev, sizeof(*info)); | 143 | iodev = devm_iio_device_alloc(&pdev->dev, sizeof(*info)); |
@@ -162,7 +162,7 @@ static int lpc32xx_adc_probe(struct platform_device *pdev) | |||
162 | irq = platform_get_irq(pdev, 0); | 162 | irq = platform_get_irq(pdev, 0); |
163 | if (irq <= 0) { | 163 | if (irq <= 0) { |
164 | dev_err(&pdev->dev, "failed getting interrupt resource\n"); | 164 | dev_err(&pdev->dev, "failed getting interrupt resource\n"); |
165 | return -EINVAL; | 165 | return -ENXIO; |
166 | } | 166 | } |
167 | 167 | ||
168 | retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0, | 168 | retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0, |
diff --git a/drivers/staging/iio/iio_dummy_evgen.c b/drivers/staging/iio/iio_dummy_evgen.c index 6d38854c38c8..86d8447ac08f 100644 --- a/drivers/staging/iio/iio_dummy_evgen.c +++ b/drivers/staging/iio/iio_dummy_evgen.c | |||
@@ -24,9 +24,21 @@ | |||
24 | #include "iio_dummy_evgen.h" | 24 | #include "iio_dummy_evgen.h" |
25 | #include <linux/iio/iio.h> | 25 | #include <linux/iio/iio.h> |
26 | #include <linux/iio/sysfs.h> | 26 | #include <linux/iio/sysfs.h> |
27 | #include <linux/irq_work.h> | ||
27 | 28 | ||
28 | /* Fiddly bit of faking and irq without hardware */ | 29 | /* Fiddly bit of faking and irq without hardware */ |
29 | #define IIO_EVENTGEN_NO 10 | 30 | #define IIO_EVENTGEN_NO 10 |
31 | |||
32 | /** | ||
33 | * struct iio_dummy_handle_irq - helper struct to simulate interrupt generation | ||
34 | * @work: irq_work used to run handlers from hardirq context | ||
35 | * @irq: fake irq line number to trigger an interrupt | ||
36 | */ | ||
37 | struct iio_dummy_handle_irq { | ||
38 | struct irq_work work; | ||
39 | int irq; | ||
40 | }; | ||
41 | |||
30 | /** | 42 | /** |
31 | * struct iio_dummy_evgen - evgen state | 43 | * struct iio_dummy_evgen - evgen state |
32 | * @chip: irq chip we are faking | 44 | * @chip: irq chip we are faking |
@@ -35,6 +47,7 @@ | |||
35 | * @inuse: mask of which irqs are connected | 47 | * @inuse: mask of which irqs are connected |
36 | * @regs: irq regs we are faking | 48 | * @regs: irq regs we are faking |
37 | * @lock: protect the evgen state | 49 | * @lock: protect the evgen state |
50 | * @handler: helper for a 'hardware-like' interrupt simulation | ||
38 | */ | 51 | */ |
39 | struct iio_dummy_eventgen { | 52 | struct iio_dummy_eventgen { |
40 | struct irq_chip chip; | 53 | struct irq_chip chip; |
@@ -43,6 +56,7 @@ struct iio_dummy_eventgen { | |||
43 | bool inuse[IIO_EVENTGEN_NO]; | 56 | bool inuse[IIO_EVENTGEN_NO]; |
44 | struct iio_dummy_regs regs[IIO_EVENTGEN_NO]; | 57 | struct iio_dummy_regs regs[IIO_EVENTGEN_NO]; |
45 | struct mutex lock; | 58 | struct mutex lock; |
59 | struct iio_dummy_handle_irq handler; | ||
46 | }; | 60 | }; |
47 | 61 | ||
48 | /* We can only ever have one instance of this 'device' */ | 62 | /* We can only ever have one instance of this 'device' */ |
@@ -67,6 +81,14 @@ static void iio_dummy_event_irqunmask(struct irq_data *d) | |||
67 | evgen->enabled[d->irq - evgen->base] = true; | 81 | evgen->enabled[d->irq - evgen->base] = true; |
68 | } | 82 | } |
69 | 83 | ||
84 | static void iio_dummy_work_handler(struct irq_work *work) | ||
85 | { | ||
86 | struct iio_dummy_handle_irq *irq_handler; | ||
87 | |||
88 | irq_handler = container_of(work, struct iio_dummy_handle_irq, work); | ||
89 | handle_simple_irq(irq_handler->irq, irq_to_desc(irq_handler->irq)); | ||
90 | } | ||
91 | |||
70 | static int iio_dummy_evgen_create(void) | 92 | static int iio_dummy_evgen_create(void) |
71 | { | 93 | { |
72 | int ret, i; | 94 | int ret, i; |
@@ -91,6 +113,7 @@ static int iio_dummy_evgen_create(void) | |||
91 | IRQ_NOREQUEST | IRQ_NOAUTOEN, | 113 | IRQ_NOREQUEST | IRQ_NOAUTOEN, |
92 | IRQ_NOPROBE); | 114 | IRQ_NOPROBE); |
93 | } | 115 | } |
116 | init_irq_work(&iio_evgen->handler.work, iio_dummy_work_handler); | ||
94 | mutex_init(&iio_evgen->lock); | 117 | mutex_init(&iio_evgen->lock); |
95 | return 0; | 118 | return 0; |
96 | } | 119 | } |
@@ -169,8 +192,9 @@ static ssize_t iio_evgen_poke(struct device *dev, | |||
169 | iio_evgen->regs[this_attr->address].reg_id = this_attr->address; | 192 | iio_evgen->regs[this_attr->address].reg_id = this_attr->address; |
170 | iio_evgen->regs[this_attr->address].reg_data = event; | 193 | iio_evgen->regs[this_attr->address].reg_data = event; |
171 | 194 | ||
195 | iio_evgen->handler.irq = iio_evgen->base + this_attr->address; | ||
172 | if (iio_evgen->enabled[this_attr->address]) | 196 | if (iio_evgen->enabled[this_attr->address]) |
173 | handle_nested_irq(iio_evgen->base + this_attr->address); | 197 | irq_work_queue(&iio_evgen->handler.work); |
174 | 198 | ||
175 | return len; | 199 | return len; |
176 | } | 200 | } |
diff --git a/drivers/staging/iio/iio_simple_dummy.h b/drivers/staging/iio/iio_simple_dummy.h index 8d00224e6fad..5c2f4d0401dc 100644 --- a/drivers/staging/iio/iio_simple_dummy.h +++ b/drivers/staging/iio/iio_simple_dummy.h | |||
@@ -46,6 +46,7 @@ struct iio_dummy_state { | |||
46 | int event_irq; | 46 | int event_irq; |
47 | int event_val; | 47 | int event_val; |
48 | bool event_en; | 48 | bool event_en; |
49 | s64 event_timestamp; | ||
49 | #endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ | 50 | #endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ |
50 | }; | 51 | }; |
51 | 52 | ||
diff --git a/drivers/staging/iio/iio_simple_dummy_events.c b/drivers/staging/iio/iio_simple_dummy_events.c index 73108baf80ad..bfbf1c56bd22 100644 --- a/drivers/staging/iio/iio_simple_dummy_events.c +++ b/drivers/staging/iio/iio_simple_dummy_events.c | |||
@@ -153,6 +153,15 @@ int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev, | |||
153 | return 0; | 153 | return 0; |
154 | } | 154 | } |
155 | 155 | ||
156 | static irqreturn_t iio_simple_dummy_get_timestamp(int irq, void *private) | ||
157 | { | ||
158 | struct iio_dev *indio_dev = private; | ||
159 | struct iio_dummy_state *st = iio_priv(indio_dev); | ||
160 | |||
161 | st->event_timestamp = iio_get_time_ns(); | ||
162 | return IRQ_HANDLED; | ||
163 | } | ||
164 | |||
156 | /** | 165 | /** |
157 | * iio_simple_dummy_event_handler() - identify and pass on event | 166 | * iio_simple_dummy_event_handler() - identify and pass on event |
158 | * @irq: irq of event line | 167 | * @irq: irq of event line |
@@ -177,7 +186,7 @@ static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private) | |||
177 | IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0, | 186 | IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0, |
178 | IIO_EV_DIR_RISING, | 187 | IIO_EV_DIR_RISING, |
179 | IIO_EV_TYPE_THRESH, 0, 0, 0), | 188 | IIO_EV_TYPE_THRESH, 0, 0, 0), |
180 | iio_get_time_ns()); | 189 | st->event_timestamp); |
181 | break; | 190 | break; |
182 | case 1: | 191 | case 1: |
183 | if (st->activity_running > st->event_val) | 192 | if (st->activity_running > st->event_val) |
@@ -187,7 +196,7 @@ static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private) | |||
187 | IIO_EV_DIR_RISING, | 196 | IIO_EV_DIR_RISING, |
188 | IIO_EV_TYPE_THRESH, | 197 | IIO_EV_TYPE_THRESH, |
189 | 0, 0, 0), | 198 | 0, 0, 0), |
190 | iio_get_time_ns()); | 199 | st->event_timestamp); |
191 | break; | 200 | break; |
192 | case 2: | 201 | case 2: |
193 | if (st->activity_walking < st->event_val) | 202 | if (st->activity_walking < st->event_val) |
@@ -197,14 +206,14 @@ static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private) | |||
197 | IIO_EV_DIR_FALLING, | 206 | IIO_EV_DIR_FALLING, |
198 | IIO_EV_TYPE_THRESH, | 207 | IIO_EV_TYPE_THRESH, |
199 | 0, 0, 0), | 208 | 0, 0, 0), |
200 | iio_get_time_ns()); | 209 | st->event_timestamp); |
201 | break; | 210 | break; |
202 | case 3: | 211 | case 3: |
203 | iio_push_event(indio_dev, | 212 | iio_push_event(indio_dev, |
204 | IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD, | 213 | IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD, |
205 | IIO_EV_DIR_NONE, | 214 | IIO_EV_DIR_NONE, |
206 | IIO_EV_TYPE_CHANGE, 0, 0, 0), | 215 | IIO_EV_TYPE_CHANGE, 0, 0, 0), |
207 | iio_get_time_ns()); | 216 | st->event_timestamp); |
208 | break; | 217 | break; |
209 | default: | 218 | default: |
210 | break; | 219 | break; |
@@ -238,7 +247,7 @@ int iio_simple_dummy_events_register(struct iio_dev *indio_dev) | |||
238 | st->regs = iio_dummy_evgen_get_regs(st->event_irq); | 247 | st->regs = iio_dummy_evgen_get_regs(st->event_irq); |
239 | 248 | ||
240 | ret = request_threaded_irq(st->event_irq, | 249 | ret = request_threaded_irq(st->event_irq, |
241 | NULL, | 250 | &iio_simple_dummy_get_timestamp, |
242 | &iio_simple_dummy_event_handler, | 251 | &iio_simple_dummy_event_handler, |
243 | IRQF_ONESHOT, | 252 | IRQF_ONESHOT, |
244 | "iio_simple_event", | 253 | "iio_simple_event", |
diff --git a/drivers/staging/iio/magnetometer/hmc5843.h b/drivers/staging/iio/magnetometer/hmc5843.h index f3d0da2fe458..06f35d3828e4 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.h +++ b/drivers/staging/iio/magnetometer/hmc5843.h | |||
@@ -48,7 +48,7 @@ struct hmc5843_data { | |||
48 | }; | 48 | }; |
49 | 49 | ||
50 | int hmc5843_common_probe(struct device *dev, struct regmap *regmap, | 50 | int hmc5843_common_probe(struct device *dev, struct regmap *regmap, |
51 | enum hmc5843_ids id); | 51 | enum hmc5843_ids id, const char *name); |
52 | int hmc5843_common_remove(struct device *dev); | 52 | int hmc5843_common_remove(struct device *dev); |
53 | 53 | ||
54 | int hmc5843_common_suspend(struct device *dev); | 54 | int hmc5843_common_suspend(struct device *dev); |
diff --git a/drivers/staging/iio/magnetometer/hmc5843_core.c b/drivers/staging/iio/magnetometer/hmc5843_core.c index fffca3a9f637..4aab0228a195 100644 --- a/drivers/staging/iio/magnetometer/hmc5843_core.c +++ b/drivers/staging/iio/magnetometer/hmc5843_core.c | |||
@@ -577,7 +577,7 @@ int hmc5843_common_resume(struct device *dev) | |||
577 | EXPORT_SYMBOL(hmc5843_common_resume); | 577 | EXPORT_SYMBOL(hmc5843_common_resume); |
578 | 578 | ||
579 | int hmc5843_common_probe(struct device *dev, struct regmap *regmap, | 579 | int hmc5843_common_probe(struct device *dev, struct regmap *regmap, |
580 | enum hmc5843_ids id) | 580 | enum hmc5843_ids id, const char *name) |
581 | { | 581 | { |
582 | struct hmc5843_data *data; | 582 | struct hmc5843_data *data; |
583 | struct iio_dev *indio_dev; | 583 | struct iio_dev *indio_dev; |
@@ -597,7 +597,7 @@ int hmc5843_common_probe(struct device *dev, struct regmap *regmap, | |||
597 | mutex_init(&data->lock); | 597 | mutex_init(&data->lock); |
598 | 598 | ||
599 | indio_dev->dev.parent = dev; | 599 | indio_dev->dev.parent = dev; |
600 | indio_dev->name = dev->driver->name; | 600 | indio_dev->name = name; |
601 | indio_dev->info = &hmc5843_info; | 601 | indio_dev->info = &hmc5843_info; |
602 | indio_dev->modes = INDIO_DIRECT_MODE; | 602 | indio_dev->modes = INDIO_DIRECT_MODE; |
603 | indio_dev->channels = data->variant->channels; | 603 | indio_dev->channels = data->variant->channels; |
diff --git a/drivers/staging/iio/magnetometer/hmc5843_i2c.c b/drivers/staging/iio/magnetometer/hmc5843_i2c.c index ff08667fa2f6..3e06ceb32059 100644 --- a/drivers/staging/iio/magnetometer/hmc5843_i2c.c +++ b/drivers/staging/iio/magnetometer/hmc5843_i2c.c | |||
@@ -61,7 +61,7 @@ static int hmc5843_i2c_probe(struct i2c_client *cli, | |||
61 | { | 61 | { |
62 | return hmc5843_common_probe(&cli->dev, | 62 | return hmc5843_common_probe(&cli->dev, |
63 | devm_regmap_init_i2c(cli, &hmc5843_i2c_regmap_config), | 63 | devm_regmap_init_i2c(cli, &hmc5843_i2c_regmap_config), |
64 | id->driver_data); | 64 | id->driver_data, id->name); |
65 | } | 65 | } |
66 | 66 | ||
67 | static int hmc5843_i2c_remove(struct i2c_client *client) | 67 | static int hmc5843_i2c_remove(struct i2c_client *client) |
diff --git a/drivers/staging/iio/magnetometer/hmc5843_spi.c b/drivers/staging/iio/magnetometer/hmc5843_spi.c index 8e658f736e1f..1549192c0dec 100644 --- a/drivers/staging/iio/magnetometer/hmc5843_spi.c +++ b/drivers/staging/iio/magnetometer/hmc5843_spi.c | |||
@@ -59,6 +59,7 @@ static const struct regmap_config hmc5843_spi_regmap_config = { | |||
59 | static int hmc5843_spi_probe(struct spi_device *spi) | 59 | static int hmc5843_spi_probe(struct spi_device *spi) |
60 | { | 60 | { |
61 | int ret; | 61 | int ret; |
62 | const struct spi_device_id *id = spi_get_device_id(spi); | ||
62 | 63 | ||
63 | spi->mode = SPI_MODE_3; | 64 | spi->mode = SPI_MODE_3; |
64 | spi->max_speed_hz = 8000000; | 65 | spi->max_speed_hz = 8000000; |
@@ -69,7 +70,7 @@ static int hmc5843_spi_probe(struct spi_device *spi) | |||
69 | 70 | ||
70 | return hmc5843_common_probe(&spi->dev, | 71 | return hmc5843_common_probe(&spi->dev, |
71 | devm_regmap_init_spi(spi, &hmc5843_spi_regmap_config), | 72 | devm_regmap_init_spi(spi, &hmc5843_spi_regmap_config), |
72 | HMC5983_ID); | 73 | id->driver_data, id->name); |
73 | } | 74 | } |
74 | 75 | ||
75 | static int hmc5843_spi_remove(struct spi_device *spi) | 76 | static int hmc5843_spi_remove(struct spi_device *spi) |
@@ -81,6 +82,7 @@ static const struct spi_device_id hmc5843_id[] = { | |||
81 | { "hmc5983", HMC5983_ID }, | 82 | { "hmc5983", HMC5983_ID }, |
82 | { } | 83 | { } |
83 | }; | 84 | }; |
85 | MODULE_DEVICE_TABLE(spi, hmc5843_id); | ||
84 | 86 | ||
85 | static struct spi_driver hmc5843_driver = { | 87 | static struct spi_driver hmc5843_driver = { |
86 | .driver = { | 88 | .driver = { |
diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h index 3c17cd7fdf06..2fe939c73cd2 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h | |||
@@ -271,6 +271,10 @@ void st_sensors_power_enable(struct iio_dev *indio_dev); | |||
271 | 271 | ||
272 | void st_sensors_power_disable(struct iio_dev *indio_dev); | 272 | void st_sensors_power_disable(struct iio_dev *indio_dev); |
273 | 273 | ||
274 | int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev, | ||
275 | unsigned reg, unsigned writeval, | ||
276 | unsigned *readval); | ||
277 | |||
274 | int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr); | 278 | int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr); |
275 | 279 | ||
276 | int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable); | 280 | int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable); |
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 7bb7f673cb3f..19c94c9acc81 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h | |||
@@ -294,6 +294,7 @@ static inline s64 iio_get_time_ns(void) | |||
294 | #define INDIO_BUFFER_TRIGGERED 0x02 | 294 | #define INDIO_BUFFER_TRIGGERED 0x02 |
295 | #define INDIO_BUFFER_SOFTWARE 0x04 | 295 | #define INDIO_BUFFER_SOFTWARE 0x04 |
296 | #define INDIO_BUFFER_HARDWARE 0x08 | 296 | #define INDIO_BUFFER_HARDWARE 0x08 |
297 | #define INDIO_EVENT_TRIGGERED 0x10 | ||
297 | 298 | ||
298 | #define INDIO_ALL_BUFFER_MODES \ | 299 | #define INDIO_ALL_BUFFER_MODES \ |
299 | (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE | INDIO_BUFFER_SOFTWARE) | 300 | (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE | INDIO_BUFFER_SOFTWARE) |
@@ -457,6 +458,7 @@ struct iio_buffer_setup_ops { | |||
457 | * @scan_index_timestamp:[INTERN] cache of the index to the timestamp | 458 | * @scan_index_timestamp:[INTERN] cache of the index to the timestamp |
458 | * @trig: [INTERN] current device trigger (buffer modes) | 459 | * @trig: [INTERN] current device trigger (buffer modes) |
459 | * @pollfunc: [DRIVER] function run on trigger being received | 460 | * @pollfunc: [DRIVER] function run on trigger being received |
461 | * @pollfunc_event: [DRIVER] function run on events trigger being received | ||
460 | * @channels: [DRIVER] channel specification structure table | 462 | * @channels: [DRIVER] channel specification structure table |
461 | * @num_channels: [DRIVER] number of channels specified in @channels. | 463 | * @num_channels: [DRIVER] number of channels specified in @channels. |
462 | * @channel_attr_list: [INTERN] keep track of automatically created channel | 464 | * @channel_attr_list: [INTERN] keep track of automatically created channel |
@@ -495,6 +497,7 @@ struct iio_dev { | |||
495 | unsigned scan_index_timestamp; | 497 | unsigned scan_index_timestamp; |
496 | struct iio_trigger *trig; | 498 | struct iio_trigger *trig; |
497 | struct iio_poll_func *pollfunc; | 499 | struct iio_poll_func *pollfunc; |
500 | struct iio_poll_func *pollfunc_event; | ||
498 | 501 | ||
499 | struct iio_chan_spec const *channels; | 502 | struct iio_chan_spec const *channels; |
500 | int num_channels; | 503 | int num_channels; |
diff --git a/include/linux/iio/triggered_event.h b/include/linux/iio/triggered_event.h new file mode 100644 index 000000000000..8fe8537085bb --- /dev/null +++ b/include/linux/iio/triggered_event.h | |||
@@ -0,0 +1,11 @@ | |||
1 | #ifndef _LINUX_IIO_TRIGGERED_EVENT_H_ | ||
2 | #define _LINUX_IIO_TRIGGERED_EVENT_H_ | ||
3 | |||
4 | #include <linux/interrupt.h> | ||
5 | |||
6 | int iio_triggered_event_setup(struct iio_dev *indio_dev, | ||
7 | irqreturn_t (*h)(int irq, void *p), | ||
8 | irqreturn_t (*thread)(int irq, void *p)); | ||
9 | void iio_triggered_event_cleanup(struct iio_dev *indio_dev); | ||
10 | |||
11 | #endif | ||
diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h index 2f8b11722204..7c63bd67c36e 100644 --- a/include/uapi/linux/iio/types.h +++ b/include/uapi/linux/iio/types.h | |||
@@ -35,6 +35,8 @@ enum iio_chan_type { | |||
35 | IIO_ENERGY, | 35 | IIO_ENERGY, |
36 | IIO_DISTANCE, | 36 | IIO_DISTANCE, |
37 | IIO_VELOCITY, | 37 | IIO_VELOCITY, |
38 | IIO_CONCENTRATION, | ||
39 | IIO_RESISTANCE, | ||
38 | }; | 40 | }; |
39 | 41 | ||
40 | enum iio_modifier { | 42 | enum iio_modifier { |
@@ -72,6 +74,8 @@ enum iio_modifier { | |||
72 | IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z, | 74 | IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z, |
73 | IIO_MOD_I, | 75 | IIO_MOD_I, |
74 | IIO_MOD_Q, | 76 | IIO_MOD_Q, |
77 | IIO_MOD_CO2, | ||
78 | IIO_MOD_VOC, | ||
75 | }; | 79 | }; |
76 | 80 | ||
77 | enum iio_event_type { | 81 | enum iio_event_type { |
diff --git a/tools/iio/generic_buffer.c b/tools/iio/generic_buffer.c index 9f7b85bf6ada..01c4f67801e0 100644 --- a/tools/iio/generic_buffer.c +++ b/tools/iio/generic_buffer.c | |||
@@ -328,6 +328,15 @@ int main(int argc, char **argv) | |||
328 | "diag %s\n", dev_dir_name); | 328 | "diag %s\n", dev_dir_name); |
329 | goto error_free_triggername; | 329 | goto error_free_triggername; |
330 | } | 330 | } |
331 | if (!num_channels) { | ||
332 | fprintf(stderr, | ||
333 | "No channels are enabled, we have nothing to scan.\n"); | ||
334 | fprintf(stderr, "Enable channels manually in " | ||
335 | FORMAT_SCAN_ELEMENTS_DIR | ||
336 | "/*_en and try again.\n", dev_dir_name); | ||
337 | ret = -ENOENT; | ||
338 | goto error_free_triggername; | ||
339 | } | ||
331 | 340 | ||
332 | /* | 341 | /* |
333 | * Construct the directory name for the associated buffer. | 342 | * Construct the directory name for the associated buffer. |
diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c index cd3fd41b481d..d51eb04202e9 100644 --- a/tools/iio/iio_event_monitor.c +++ b/tools/iio/iio_event_monitor.c | |||
@@ -284,7 +284,11 @@ int main(int argc, char **argv) | |||
284 | ret = ioctl(fd, IIO_GET_EVENT_FD_IOCTL, &event_fd); | 284 | ret = ioctl(fd, IIO_GET_EVENT_FD_IOCTL, &event_fd); |
285 | if (ret == -1 || event_fd == -1) { | 285 | if (ret == -1 || event_fd == -1) { |
286 | ret = -errno; | 286 | ret = -errno; |
287 | fprintf(stderr, "Failed to retrieve event fd\n"); | 287 | if (ret == -ENODEV) |
288 | fprintf(stderr, | ||
289 | "This device does not support events\n"); | ||
290 | else | ||
291 | fprintf(stderr, "Failed to retrieve event fd\n"); | ||
288 | if (close(fd) == -1) | 292 | if (close(fd) == -1) |
289 | perror("Failed to close character device file"); | 293 | perror("Failed to close character device file"); |
290 | 294 | ||