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.
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index 42d360f..8ce14c8 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_falling_en
 What:		/sys/.../iio:deviceX/events/in_voltageY_thresh_rising_en
 What:		/sys/.../iio:deviceX/events/in_voltageY_thresh_falling_en
+What:		/sys/.../iio:deviceX/events/in_voltageY_thresh_either_en
 What:		/sys/.../iio:deviceX/events/in_tempY_thresh_rising_en
 What:		/sys/.../iio:deviceX/events/in_tempY_thresh_falling_en
 KernelVersion:	2.6.37
@@ -1459,3 +1460,22 @@
 		measurements and return the average value as output data. Each
 		value resulted from <type>[_name]_oversampling_ratio measurements
 		is considered as one sample for <type>[_name]_sampling_frequency.
+
+What:		/sys/bus/iio/devices/iio:deviceX/in_concentration_raw
+What:		/sys/bus/iio/devices/iio:deviceX/in_concentrationX_raw
+What:		/sys/bus/iio/devices/iio:deviceX/in_concentration_co2_raw
+What:		/sys/bus/iio/devices/iio:deviceX/in_concentrationX_co2_raw
+What:		/sys/bus/iio/devices/iio:deviceX/in_concentration_voc_raw
+What:		/sys/bus/iio/devices/iio:deviceX/in_concentrationX_voc_raw
+KernelVersion:	4.3
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Raw (unscaled no offset etc.) percentage reading of a substance.
+
+What:		/sys/bus/iio/devices/iio:deviceX/in_resistance_raw
+What:		/sys/bus/iio/devices/iio:deviceX/in_resistanceX_raw
+KernelVersion:	4.3
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Raw (unscaled no offset etc.) resistance reading that can be processed
+		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 0000000..f30b4c4
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-iio-adc-hi8435
@@ -0,0 +1,43 @@
+What:		/sys/bus/iio/devices/iio:deviceX/in_voltageY_sensing_mode
+Date:		August 2015
+KernelVersion:	4.2.0
+Contact:	source@cogentembedded.com
+Description:
+		Program sensor type for threshold detector inputs.
+		Could be either "GND-Open" or "Supply-Open" mode. Y is a
+		threshold detector input channel. Channels 0..7, 8..15, 16..23
+		and 24..31 has common sensor types.
+
+What:		/sys/bus/iio/devices/iio:deviceX/events/in_voltageY_thresh_falling_value
+Date:		August 2015
+KernelVersion:	4.2.0
+Contact:	source@cogentembedded.com
+Description:
+		Channel Y low voltage threshold. If sensor input voltage goes lower then
+		this value then the threshold falling event is pushed.
+		Depending on in_voltageY_sensing_mode the low voltage threshold
+		is separately set for "GND-Open" and "Supply-Open" modes.
+		Channels 0..31 have common low threshold values, but could have different
+		sensing_modes.
+		The low voltage threshold range is between 2..21V.
+		Hysteresis between low and high thresholds can not be lower then 2 and
+		can not be odd.
+		If falling threshold results hysteresis to odd value then rising
+		threshold is automatically subtracted by one.
+
+What:		/sys/bus/iio/devices/iio:deviceX/events/in_voltageY_thresh_rising_value
+Date:		August 2015
+KernelVersion:	4.2.0
+Contact:	source@cogentembedded.com
+Description:
+		Channel Y high voltage threshold. If sensor input voltage goes higher then
+		this value then the threshold rising event is pushed.
+		Depending on in_voltageY_sensing_mode the high voltage threshold
+		is separately set for "GND-Open" and "Supply-Open" modes.
+		Channels 0..31 have common high threshold values, but could have different
+		sensing_modes.
+		The high voltage threshold range is between 3..22V.
+		Hysteresis between low and high thresholds can not be lower then 2 and
+		can not be odd.
+		If rising threshold results hysteresis to odd value then falling
+		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 0000000..c0c1ea9
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-iio-chemical-vz89x
@@ -0,0 +1,7 @@
+What:		/sys/bus/iio/devices/iio:deviceX/in_concentration_VOC_short_raw
+Date:		September 2015
+KernelVersion:	4.3
+Contact:	Matt Ranostay <mranostay@gmail.com>
+Description:
+		Get the raw calibration VOC value from the sensor.
+		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 0000000..b72bb62
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-iio-humidity-hdc100x
@@ -0,0 +1,9 @@
+What:		/sys/bus/iio/devices/iio:deviceX/out_current_heater_raw
+What:		/sys/bus/iio/devices/iio:deviceX/out_current_heater_raw_available
+KernelVersion:	4.3
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Controls the heater device within the humidity sensor to get
+		rid of excess condensation.
+
+		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 bbb0392..04ac623 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs
+++ b/Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs
@@ -18,3 +18,25 @@
 		trigger. In order to associate the trigger with an IIO device
 		one should write this name string to
 		/sys/bus/iio/devices/iio:deviceY/trigger/current_trigger.
+
+What:		/sys/bus/iio/devices/iio_sysfs_trigger/add_trigger
+KernelVersion:	2.6.39
+Contact:	linux-iio@vger.kernel.org
+Description:
+		This attribute is provided by the iio-trig-sysfs stand-alone
+		driver and it is used to activate the creation of a new trigger.
+		In order to achieve this, one should write a positive integer
+		into the associated file, which will serve as the id of the
+		trigger. If the trigger with the specified id is already present
+		in the system, an invalid argument message will be returned.
+
+What:		/sys/bus/iio/devices/iio_sysfs_trigger/remove_trigger
+KernelVersion:	2.6.39
+Contact:	linux-iio@vger.kernel.org
+Description:
+		This attribute is used to unregister and delete a previously
+		created trigger from the list of available triggers. In order to
+		achieve this, one should write a positive integer into the
+		associated file, representing the id of the trigger that needs
+		to be removed. If the trigger can't be found, an invalid
+		argument message will be returned to the user.
diff --git a/Documentation/DocBook/iio.tmpl b/Documentation/DocBook/iio.tmpl
index 06bb53d..98be322 100644
--- a/Documentation/DocBook/iio.tmpl
+++ b/Documentation/DocBook/iio.tmpl
@@ -578,7 +578,7 @@
     work together.
     </para>
     <sect2 id="iiotrigbufsetup"> <title> IIO triggered buffer setup</title>
-!Edrivers/iio/industrialio-triggered-buffer.c
+!Edrivers/iio/buffer/industrialio-triggered-buffer.c
 !Finclude/linux/iio/iio.h iio_buffer_setup_ops
 
 
diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
index d77d412..c50cf13 100644
--- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
@@ -54,7 +54,6 @@
 fsl,mag3110		MAG3110: Xtrinsic High Accuracy, 3D Magnetometer
 fsl,mc13892		MC13892: Power Management Integrated Circuit (PMIC) for i.MX35/51
 fsl,mma8450		MMA8450Q: Xtrinsic Low-power, 3-axis Xtrinsic Accelerometer
-fsl,mma8452		MMA8452Q: 3-axis 12-bit / 8-bit Digital Accelerometer
 fsl,mpr121		MPR121: Proximity Capacitive Touch Sensor Controller
 fsl,sgtl5000		SGTL5000: Ultra Low-Power Audio Codec
 gmt,g751		G751: Digital Temperature Sensor and Thermal Watchdog with Two-Wire Interface
@@ -80,6 +79,7 @@
 ovti,ov5642		OV5642: Color CMOS QSXGA (5-megapixel) Image Sensor with OmniBSI and Embedded TrueFocus
 pericom,pt7c4338	Real-time Clock Module
 plx,pex8648		48-Lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch
+pulsedlight,lidar-lite-v2	Pulsedlight LIDAR range-finding sensor
 ramtron,24c64		i2c serial eeprom  (24cxx)
 ricoh,r2025sd		I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
 ricoh,r2221tl		I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
@@ -88,6 +88,7 @@
 ricoh,rv5c386		I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
 ricoh,rv5c387a		I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
 samsung,24ad0xd1	S524AD0XF1 (128K/256K-bit Serial EEPROM for Low Power)
+sgx,vz89x		SGX Sensortech VZ89X Sensors
 sii,s35390a		2-wire CMOS real-time clock
 skyworks,sky81452	Skyworks SKY81452: Six-Channel White LED Driver with Touch Panel Bias Supply
 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 0000000..e3c3746
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/accel/mma8452.txt
@@ -0,0 +1,24 @@
+Freescale MMA8452Q, MMA8453Q, MMA8652FC or MMA8653FC triaxial accelerometer
+
+Required properties:
+
+  - compatible: should contain one of
+    * "fsl,mma8452"
+    * "fsl,mma8453"
+    * "fsl,mma8652"
+    * "fsl,mma8653"
+  - reg: the I2C address of the chip
+
+Optional properties:
+
+  - interrupt-parent: should be the phandle for the interrupt controller
+  - interrupts: interrupt mapping for GPIO IRQ
+
+Example:
+
+	mma8453fc@1d {
+		compatible = "fsl,mma8453";
+		reg = <0x1d>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <5 0>;
+	};
diff --git a/Documentation/devicetree/bindings/iio/adc/hi8435.txt b/Documentation/devicetree/bindings/iio/adc/hi8435.txt
new file mode 100644
index 0000000..3b0348c
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/hi8435.txt
@@ -0,0 +1,21 @@
+Holt Integrated Circuits HI-8435 threshold detector bindings
+
+Required properties:
+ - compatible: should be "holt,hi8435"
+ - reg: spi chip select number for the device
+
+Recommended properties:
+ - spi-max-frequency: definition as per
+		Documentation/devicetree/bindings/spi/spi-bus.txt
+
+Optional properties:
+ - gpios: GPIO used for controlling the reset pin
+
+Example:
+sensor@0 {
+	compatible = "holt,hi8435";
+	reg = <0>;
+	gpios = <&gpio6 1 0>;
+
+	spi-max-frequency = <1000000>;
+};
diff --git a/Documentation/devicetree/bindings/iio/light/apds9960.txt b/Documentation/devicetree/bindings/iio/light/apds9960.txt
new file mode 100644
index 0000000..174b709
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/light/apds9960.txt
@@ -0,0 +1,22 @@
+* Avago APDS9960 gesture/RGB/ALS/proximity sensor
+
+http://www.avagotech.com/docs/AV02-4191EN
+
+Required properties:
+
+  - compatible: must be "avago,apds9960"
+  - reg: the I2c address of the sensor
+  - interrupt-parent: should be the phandle for the interrupt controller
+  - interrupts : the sole interrupt generated by the device
+
+  Refer to interrupt-controller/interrupts.txt for generic interrupt client
+  node bindings.
+
+Example:
+
+apds9960@39 {
+	compatible = "avago,apds9960";
+	reg = <0x39>;
+	interrupt-parent = <&gpio1>;
+	interrupts = <16 1>;
+};
diff --git a/Documentation/devicetree/bindings/iio/light/us5182d.txt b/Documentation/devicetree/bindings/iio/light/us5182d.txt
new file mode 100644
index 0000000..6f0a530
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/light/us5182d.txt
@@ -0,0 +1,34 @@
+* UPISEMI us5182d I2C ALS and Proximity sensor
+
+Required properties:
+- compatible: must be "upisemi,usd5182"
+- reg: the I2C address of the device
+
+Optional properties:
+- upisemi,glass-coef: glass attenuation factor - compensation factor of
+                      resolution 1000 for material transmittance.
+- upisemi,dark-ths: array of 8 elements containing 16-bit thresholds (adc
+                    counts) corresponding to every scale.
+- upisemi,upper-dark-gain: 8-bit dark gain compensation factor(4 int and 4
+                           fractional bits - Q4.4) applied when light > threshold
+- upisemi,lower-dark-gain: 8-bit dark gain compensation factor(4 int and 4
+                           fractional bits - Q4.4) applied when light < threshold
+
+If the optional properties are not specified these factors will default to the
+values in the below example.
+The glass-coef defaults to no compensation for the covering material.
+The threshold array defaults to experimental values that work with US5182D
+sensor on evaluation board - roughly between 12-32 lux.
+There will be no dark-gain compensation by default when ALS > thresh
+(0 * dark-gain), and a 1.35 compensation factor when ALS < thresh.
+
+Example:
+
+    usd5182@39 {
+                compatible = "upisemi,usd5182";
+                reg = <0x39>;
+                upisemi,glass-coef = < 1000 >;
+                upisemi,dark-ths = /bits/ 16 <170 200 512 512 800 2000 4000 8000>;
+                upisemi,upper-dark-gain = /bits/ 8 <0x00>;
+                upisemi,lower-dark-gain = /bits/ 8 <0x16>;
+    };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 82d2ac9..13e54a0 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -101,6 +101,7 @@
 hisilicon	Hisilicon Limited.
 hit	Hitachi Ltd.
 hitex	Hitex Development Tools
+holt	Holt Integrated Circuits, Inc.
 honeywell	Honeywell
 hp	Hewlett Packard
 i2se	I2SE GmbH
@@ -169,6 +170,7 @@
 picochip	Picochip Ltd
 plathome	Plat'Home Co., Ltd.
 pixcir  PIXCIR MICROELECTRONICS Co., Ltd
+pulsedlight	PulsedLight, Inc
 powervr	PowerVR (deprecated, use img)
 qca	Qualcomm Atheros, Inc.
 qcom	Qualcomm Technologies, Inc
@@ -191,6 +193,7 @@
 schindler	Schindler
 seagate	Seagate Technology PLC
 semtech	Semtech Corporation
+sgx	SGX Sensortech
 sharp	Sharp Corporation
 sil	Silicon Image
 silabs	Silicon Laboratories
@@ -223,6 +226,7 @@
 toumaz	Toumaz
 tplink	TP-LINK Technologies Co., Ltd.
 truly	Truly Semiconductors Limited
+upisemi	uPI Semiconductor Corp.
 usi	Universal Scientific Industrial Co., Ltd.
 v3	V3 Semiconductor
 variscite	Variscite Ltd.
diff --git a/MAINTAINERS b/MAINTAINERS
index 7b181d5..6d7af82 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6918,6 +6918,13 @@
 F:	include/linux/mlx5/
 F:	drivers/infiniband/hw/mlx5/
 
+MELEXIS MLX90614 DRIVER
+M:	Crt Mori <cmo@melexis.com>
+L:	linux-iio@vger.kernel.org
+W:	http://www.melexis.com
+S:	Supported
+F:	drivers/iio/temperature/mlx90614.c
+
 MN88472 MEDIA DRIVER
 M:	Antti Palosaari <crope@iki.fi>
 L:	linux-media@vger.kernel.org
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index 4011eff..119c94d 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -19,27 +19,7 @@
 	  acquisition methods.
 
 if IIO_BUFFER
-
-config IIO_BUFFER_CB
-	bool "IIO callback buffer used for push in-kernel interfaces"
-	help
-	  Should be selected by any drivers that do in-kernel push
-	  usage.  That is, those where the data is pushed to the consumer.
-
-config IIO_KFIFO_BUF
-	tristate "Industrial I/O buffering based on kfifo"
-	help
-	  A simple fifo based on kfifo.  Note that this currently provides
-	  no buffer events so it is up to userspace to work out how
-	  often to read from the buffer.
-
-config IIO_TRIGGERED_BUFFER
-	tristate
-	select IIO_TRIGGER
-	select IIO_KFIFO_BUF
-	help
-	  Provides helper functions for setting up triggered buffers.
-
+	source "drivers/iio/buffer/Kconfig"
 endif # IIO_BUFFER
 
 config IIO_TRIGGER
@@ -58,9 +38,16 @@
 	This value controls the maximum number of consumers that a
 	given trigger may handle. Default is 2.
 
+config IIO_TRIGGERED_EVENT
+	tristate
+	select IIO_TRIGGER
+	help
+	  Provides helper functions for setting up triggered events.
+
 source "drivers/iio/accel/Kconfig"
 source "drivers/iio/adc/Kconfig"
 source "drivers/iio/amplifiers/Kconfig"
+source "drivers/iio/chemical/Kconfig"
 source "drivers/iio/common/Kconfig"
 source "drivers/iio/dac/Kconfig"
 source "drivers/iio/frequency/Kconfig"
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index 698afc2..e210055 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -6,14 +6,14 @@
 industrialio-y := industrialio-core.o industrialio-event.o inkern.o
 industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o
 industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o
-industrialio-$(CONFIG_IIO_BUFFER_CB) += buffer_cb.o
 
-obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o
-obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o
+obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o
 
 obj-y += accel/
 obj-y += adc/
 obj-y += amplifiers/
+obj-y += buffer/
+obj-y += chemical/
 obj-y += common/
 obj-y += dac/
 obj-y += gyro/
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index a59047d..8172ae5 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -100,13 +100,13 @@
 	  be called kxcjk-1013.
 
 config MMA8452
-	tristate "Freescale MMA8452Q Accelerometer Driver"
+	tristate "Freescale MMA8452Q and similar Accelerometers Driver"
 	depends on I2C
 	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
 	help
-	  Say yes here to build support for the Freescale MMA8452Q 3-axis
-	  accelerometer.
+	  Say yes here to build support for the following Freescale 3-axis
+	  accelerometers: MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called mma8452.
@@ -137,6 +137,19 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called mma9553.
 
+config MXC4005
+	tristate "Memsic MXC4005XC 3-Axis Accelerometer Driver"
+	depends on I2C
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	select REGMAP_I2C
+	help
+	  Say yes here to build support for the Memsic MXC4005XC 3-axis
+	  accelerometer.
+
+	  To compile this driver as a module, choose M. The module will be
+	  called mxc4005.
+
 config STK8312
 	tristate "Sensortek STK8312 3-Axis Accelerometer Driver"
 	depends on I2C
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index ebd2675..020dda0 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -14,6 +14,8 @@
 obj-$(CONFIG_MMA9551)		+= mma9551.o
 obj-$(CONFIG_MMA9553)		+= mma9553.o
 
+obj-$(CONFIG_MXC4005)		+= mxc4005.o
+
 obj-$(CONFIG_STK8312)		+= stk8312.o
 obj-$(CONFIG_STK8BA50)		+= stk8ba50.o
 
diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c
index b921d84..1eccc2d 100644
--- a/drivers/iio/accel/mma8452.c
+++ b/drivers/iio/accel/mma8452.c
@@ -1,6 +1,12 @@
 /*
- * mma8452.c - Support for Freescale MMA8452Q 3-axis 12-bit accelerometer
+ * mma8452.c - Support for following Freescale 3-axis accelerometers:
  *
+ * MMA8452Q (12 bit)
+ * MMA8453Q (10 bit)
+ * MMA8652FC (12 bit)
+ * MMA8653FC (10 bit)
+ *
+ * Copyright 2015 Martin Kepplinger <martin.kepplinger@theobroma-systems.com>
  * Copyright 2014 Peter Meerwald <pmeerw@pmeerw.net>
  *
  * This file is subject to the terms and conditions of version 2 of
@@ -22,10 +28,11 @@
 #include <linux/iio/triggered_buffer.h>
 #include <linux/iio/events.h>
 #include <linux/delay.h>
+#include <linux/of_device.h>
 
 #define MMA8452_STATUS				0x00
 #define  MMA8452_STATUS_DRDY			(BIT(2) | BIT(1) | BIT(0))
-#define MMA8452_OUT_X				0x01 /* MSB first, 12-bit  */
+#define MMA8452_OUT_X				0x01 /* MSB first */
 #define MMA8452_OUT_Y				0x03
 #define MMA8452_OUT_Z				0x05
 #define MMA8452_INT_SRC				0x0c
@@ -38,6 +45,16 @@
 #define  MMA8452_DATA_CFG_HPF_MASK		BIT(4)
 #define MMA8452_HP_FILTER_CUTOFF		0x0f
 #define  MMA8452_HP_FILTER_CUTOFF_SEL_MASK	GENMASK(1, 0)
+#define MMA8452_FF_MT_CFG			0x15
+#define  MMA8452_FF_MT_CFG_OAE			BIT(6)
+#define  MMA8452_FF_MT_CFG_ELE			BIT(7)
+#define MMA8452_FF_MT_SRC			0x16
+#define  MMA8452_FF_MT_SRC_XHE			BIT(1)
+#define  MMA8452_FF_MT_SRC_YHE			BIT(3)
+#define  MMA8452_FF_MT_SRC_ZHE			BIT(5)
+#define MMA8452_FF_MT_THS			0x17
+#define  MMA8452_FF_MT_THS_MASK			0x7f
+#define MMA8452_FF_MT_COUNT			0x18
 #define MMA8452_TRANSIENT_CFG			0x1d
 #define  MMA8452_TRANSIENT_CFG_HPF_BYP		BIT(0)
 #define  MMA8452_TRANSIENT_CFG_CHAN(chan)	BIT(chan + 1)
@@ -65,15 +82,65 @@
 #define MMA8452_MAX_REG				0x31
 
 #define  MMA8452_INT_DRDY			BIT(0)
+#define  MMA8452_INT_FF_MT			BIT(2)
 #define  MMA8452_INT_TRANS			BIT(5)
 
 #define  MMA8452_DEVICE_ID			0x2a
+#define  MMA8453_DEVICE_ID			0x3a
+#define MMA8652_DEVICE_ID			0x4a
+#define MMA8653_DEVICE_ID			0x5a
 
 struct mma8452_data {
 	struct i2c_client *client;
 	struct mutex lock;
 	u8 ctrl_reg1;
 	u8 data_cfg;
+	const struct mma_chip_info *chip_info;
+};
+
+/**
+ * struct mma_chip_info - chip specific data for Freescale's accelerometers
+ * @chip_id:			WHO_AM_I register's value
+ * @channels:			struct iio_chan_spec matching the device's
+ *				capabilities
+ * @num_channels:		number of channels
+ * @mma_scales:			scale factors for converting register values
+ *				to m/s^2; 3 modes: 2g, 4g, 8g; 2 integers
+ *				per mode: m/s^2 and micro m/s^2
+ * @ev_cfg:			event config register address
+ * @ev_cfg_ele:			latch bit in event config register
+ * @ev_cfg_chan_shift:		number of the bit to enable events in X
+ *				direction; in event config register
+ * @ev_src:			event source register address
+ * @ev_src_xe:			bit in event source register that indicates
+ *				an event in X direction
+ * @ev_src_ye:			bit in event source register that indicates
+ *				an event in Y direction
+ * @ev_src_ze:			bit in event source register that indicates
+ *				an event in Z direction
+ * @ev_ths:			event threshold register address
+ * @ev_ths_mask:		mask for the threshold value
+ * @ev_count:			event count (period) register address
+ *
+ * Since not all chips supported by the driver support comparing high pass
+ * filtered data for events (interrupts), different interrupt sources are
+ * used for different chips and the relevant registers are included here.
+ */
+struct mma_chip_info {
+	u8 chip_id;
+	const struct iio_chan_spec *channels;
+	int num_channels;
+	const int mma_scales[3][2];
+	u8 ev_cfg;
+	u8 ev_cfg_ele;
+	u8 ev_cfg_chan_shift;
+	u8 ev_src;
+	u8 ev_src_xe;
+	u8 ev_src_ye;
+	u8 ev_src_ze;
+	u8 ev_ths;
+	u8 ev_ths_mask;
+	u8 ev_count;
 };
 
 static int mma8452_drdy(struct mma8452_data *data)
@@ -143,16 +210,6 @@
 	{6, 250000}, {1, 560000}
 };
 
-/*
- * Hardware has fullscale of -2G, -4G, -8G corresponding to raw value -2048
- * The userspace interface uses m/s^2 and we declare micro units
- * So scale factor is given by:
- *	g * N * 1000000 / 2048 for N = 2, 4, 8 and g = 9.80665
- */
-static const int mma8452_scales[3][2] = {
-	{0, 9577}, {0, 19154}, {0, 38307}
-};
-
 /* Datasheet table 35  (step time vs sample frequency) */
 static const int mma8452_transient_time_step_us[8] = {
 	1250,
@@ -189,8 +246,11 @@
 					struct device_attribute *attr,
 					char *buf)
 {
-	return mma8452_show_int_plus_micros(buf, mma8452_scales,
-					    ARRAY_SIZE(mma8452_scales));
+	struct mma8452_data *data = iio_priv(i2c_get_clientdata(
+					     to_i2c_client(dev)));
+
+	return mma8452_show_int_plus_micros(buf, data->chip_info->mma_scales,
+		ARRAY_SIZE(data->chip_info->mma_scales));
 }
 
 static ssize_t mma8452_show_hp_cutoff_avail(struct device *dev,
@@ -221,9 +281,8 @@
 
 static int mma8452_get_scale_index(struct mma8452_data *data, int val, int val2)
 {
-	return mma8452_get_int_plus_micros_index(mma8452_scales,
-						 ARRAY_SIZE(mma8452_scales),
-						 val, val2);
+	return mma8452_get_int_plus_micros_index(data->chip_info->mma_scales,
+			ARRAY_SIZE(data->chip_info->mma_scales), val, val2);
 }
 
 static int mma8452_get_hp_filter_index(struct mma8452_data *data,
@@ -270,14 +329,15 @@
 		if (ret < 0)
 			return ret;
 
-		*val = sign_extend32(be16_to_cpu(buffer[chan->scan_index]) >> 4,
-				     11);
+		*val = sign_extend32(be16_to_cpu(
+			buffer[chan->scan_index]) >> chan->scan_type.shift,
+			chan->scan_type.realbits - 1);
 
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
 		i = data->data_cfg & MMA8452_DATA_CFG_FS_MASK;
-		*val = mma8452_scales[i][0];
-		*val2 = mma8452_scales[i][1];
+		*val = data->chip_info->mma_scales[i][0];
+		*val2 = data->chip_info->mma_scales[i][1];
 
 		return IIO_VAL_INT_PLUS_MICRO;
 	case IIO_CHAN_INFO_SAMP_FREQ:
@@ -439,17 +499,17 @@
 	switch (info) {
 	case IIO_EV_INFO_VALUE:
 		ret = i2c_smbus_read_byte_data(data->client,
-					       MMA8452_TRANSIENT_THS);
+					       data->chip_info->ev_ths);
 		if (ret < 0)
 			return ret;
 
-		*val = ret & MMA8452_TRANSIENT_THS_MASK;
+		*val = ret & data->chip_info->ev_ths_mask;
 
 		return IIO_VAL_INT;
 
 	case IIO_EV_INFO_PERIOD:
 		ret = i2c_smbus_read_byte_data(data->client,
-					       MMA8452_TRANSIENT_COUNT);
+					       data->chip_info->ev_count);
 		if (ret < 0)
 			return ret;
 
@@ -497,7 +557,8 @@
 		if (val < 0 || val > MMA8452_TRANSIENT_THS_MASK)
 			return -EINVAL;
 
-		return mma8452_change_config(data, MMA8452_TRANSIENT_THS, val);
+		return mma8452_change_config(data, data->chip_info->ev_ths,
+					     val);
 
 	case IIO_EV_INFO_PERIOD:
 		steps = (val * USEC_PER_SEC + val2) /
@@ -507,7 +568,7 @@
 		if (steps < 0 || steps > 0xff)
 			return -EINVAL;
 
-		return mma8452_change_config(data, MMA8452_TRANSIENT_COUNT,
+		return mma8452_change_config(data, data->chip_info->ev_count,
 					     steps);
 
 	case IIO_EV_INFO_HIGH_PASS_FILTER_3DB:
@@ -538,13 +599,15 @@
 				     enum iio_event_direction dir)
 {
 	struct mma8452_data *data = iio_priv(indio_dev);
+	const struct mma_chip_info *chip = data->chip_info;
 	int ret;
 
-	ret = i2c_smbus_read_byte_data(data->client, MMA8452_TRANSIENT_CFG);
+	ret = i2c_smbus_read_byte_data(data->client,
+				       data->chip_info->ev_cfg);
 	if (ret < 0)
 		return ret;
 
-	return ret & MMA8452_TRANSIENT_CFG_CHAN(chan->scan_index) ? 1 : 0;
+	return !!(ret & BIT(chan->scan_index + chip->ev_cfg_chan_shift));
 }
 
 static int mma8452_write_event_config(struct iio_dev *indio_dev,
@@ -554,20 +617,22 @@
 				      int state)
 {
 	struct mma8452_data *data = iio_priv(indio_dev);
+	const struct mma_chip_info *chip = data->chip_info;
 	int val;
 
-	val = i2c_smbus_read_byte_data(data->client, MMA8452_TRANSIENT_CFG);
+	val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg);
 	if (val < 0)
 		return val;
 
 	if (state)
-		val |= MMA8452_TRANSIENT_CFG_CHAN(chan->scan_index);
+		val |= BIT(chan->scan_index + chip->ev_cfg_chan_shift);
 	else
-		val &= ~MMA8452_TRANSIENT_CFG_CHAN(chan->scan_index);
+		val &= ~BIT(chan->scan_index + chip->ev_cfg_chan_shift);
 
-	val |= MMA8452_TRANSIENT_CFG_ELE;
+	val |= chip->ev_cfg_ele;
+	val |= MMA8452_FF_MT_CFG_OAE;
 
-	return mma8452_change_config(data, MMA8452_TRANSIENT_CFG, val);
+	return mma8452_change_config(data, chip->ev_cfg, val);
 }
 
 static void mma8452_transient_interrupt(struct iio_dev *indio_dev)
@@ -576,25 +641,25 @@
 	s64 ts = iio_get_time_ns();
 	int src;
 
-	src = i2c_smbus_read_byte_data(data->client, MMA8452_TRANSIENT_SRC);
+	src = i2c_smbus_read_byte_data(data->client, data->chip_info->ev_src);
 	if (src < 0)
 		return;
 
-	if (src & MMA8452_TRANSIENT_SRC_XTRANSE)
+	if (src & data->chip_info->ev_src_xe)
 		iio_push_event(indio_dev,
 			       IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X,
 						  IIO_EV_TYPE_MAG,
 						  IIO_EV_DIR_RISING),
 			       ts);
 
-	if (src & MMA8452_TRANSIENT_SRC_YTRANSE)
+	if (src & data->chip_info->ev_src_ye)
 		iio_push_event(indio_dev,
 			       IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_Y,
 						  IIO_EV_TYPE_MAG,
 						  IIO_EV_DIR_RISING),
 			       ts);
 
-	if (src & MMA8452_TRANSIENT_SRC_ZTRANSE)
+	if (src & data->chip_info->ev_src_ze)
 		iio_push_event(indio_dev,
 			       IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_Z,
 						  IIO_EV_TYPE_MAG,
@@ -606,6 +671,7 @@
 {
 	struct iio_dev *indio_dev = p;
 	struct mma8452_data *data = iio_priv(indio_dev);
+	const struct mma_chip_info *chip = data->chip_info;
 	int ret = IRQ_NONE;
 	int src;
 
@@ -618,7 +684,10 @@
 		ret = IRQ_HANDLED;
 	}
 
-	if (src & MMA8452_INT_TRANS) {
+	if ((src & MMA8452_INT_TRANS &&
+	     chip->ev_src == MMA8452_TRANSIENT_SRC) ||
+	    (src & MMA8452_INT_FF_MT &&
+	     chip->ev_src == MMA8452_FF_MT_SRC)) {
 		mma8452_transient_interrupt(indio_dev);
 		ret = IRQ_HANDLED;
 	}
@@ -680,6 +749,16 @@
 	},
 };
 
+static const struct iio_event_spec mma8452_motion_event[] = {
+	{
+		.type = IIO_EV_TYPE_MAG,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_ENABLE),
+		.mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
+					BIT(IIO_EV_INFO_PERIOD)
+	},
+};
+
 /*
  * Threshold is configured in fixed 8G/127 steps regardless of
  * currently selected scale for measurement.
@@ -693,10 +772,9 @@
 
 static struct attribute_group mma8452_event_attribute_group = {
 	.attrs = mma8452_event_attributes,
-	.name = "events",
 };
 
-#define MMA8452_CHANNEL(axis, idx) { \
+#define MMA8452_CHANNEL(axis, idx, bits) { \
 	.type = IIO_ACCEL, \
 	.modified = 1, \
 	.channel2 = IIO_MOD_##axis, \
@@ -708,22 +786,144 @@
 	.scan_index = idx, \
 	.scan_type = { \
 		.sign = 's', \
-		.realbits = 12, \
+		.realbits = (bits), \
 		.storagebits = 16, \
-		.shift = 4, \
+		.shift = 16 - (bits), \
 		.endianness = IIO_BE, \
 	}, \
 	.event_spec = mma8452_transient_event, \
 	.num_event_specs = ARRAY_SIZE(mma8452_transient_event), \
 }
 
+#define MMA8652_CHANNEL(axis, idx, bits) { \
+	.type = IIO_ACCEL, \
+	.modified = 1, \
+	.channel2 = IIO_MOD_##axis, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+		BIT(IIO_CHAN_INFO_CALIBBIAS), \
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+		BIT(IIO_CHAN_INFO_SCALE), \
+	.scan_index = idx, \
+	.scan_type = { \
+		.sign = 's', \
+		.realbits = (bits), \
+		.storagebits = 16, \
+		.shift = 16 - (bits), \
+		.endianness = IIO_BE, \
+	}, \
+	.event_spec = mma8452_motion_event, \
+	.num_event_specs = ARRAY_SIZE(mma8452_motion_event), \
+}
+
 static const struct iio_chan_spec mma8452_channels[] = {
-	MMA8452_CHANNEL(X, 0),
-	MMA8452_CHANNEL(Y, 1),
-	MMA8452_CHANNEL(Z, 2),
+	MMA8452_CHANNEL(X, 0, 12),
+	MMA8452_CHANNEL(Y, 1, 12),
+	MMA8452_CHANNEL(Z, 2, 12),
 	IIO_CHAN_SOFT_TIMESTAMP(3),
 };
 
+static const struct iio_chan_spec mma8453_channels[] = {
+	MMA8452_CHANNEL(X, 0, 10),
+	MMA8452_CHANNEL(Y, 1, 10),
+	MMA8452_CHANNEL(Z, 2, 10),
+	IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+static const struct iio_chan_spec mma8652_channels[] = {
+	MMA8652_CHANNEL(X, 0, 12),
+	MMA8652_CHANNEL(Y, 1, 12),
+	MMA8652_CHANNEL(Z, 2, 12),
+	IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+static const struct iio_chan_spec mma8653_channels[] = {
+	MMA8652_CHANNEL(X, 0, 10),
+	MMA8652_CHANNEL(Y, 1, 10),
+	MMA8652_CHANNEL(Z, 2, 10),
+	IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+enum {
+	mma8452,
+	mma8453,
+	mma8652,
+	mma8653,
+};
+
+static const struct mma_chip_info mma_chip_info_table[] = {
+	[mma8452] = {
+		.chip_id = MMA8452_DEVICE_ID,
+		.channels = mma8452_channels,
+		.num_channels = ARRAY_SIZE(mma8452_channels),
+		/*
+		 * Hardware has fullscale of -2G, -4G, -8G corresponding to
+		 * raw value -2048 for 12 bit or -512 for 10 bit.
+		 * The userspace interface uses m/s^2 and we declare micro units
+		 * So scale factor for 12 bit here is given by:
+		 *	g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665
+		 */
+		.mma_scales = { {0, 9577}, {0, 19154}, {0, 38307} },
+		.ev_cfg = MMA8452_TRANSIENT_CFG,
+		.ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE,
+		.ev_cfg_chan_shift = 1,
+		.ev_src = MMA8452_TRANSIENT_SRC,
+		.ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE,
+		.ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE,
+		.ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE,
+		.ev_ths = MMA8452_TRANSIENT_THS,
+		.ev_ths_mask = MMA8452_TRANSIENT_THS_MASK,
+		.ev_count = MMA8452_TRANSIENT_COUNT,
+	},
+	[mma8453] = {
+		.chip_id = MMA8453_DEVICE_ID,
+		.channels = mma8453_channels,
+		.num_channels = ARRAY_SIZE(mma8453_channels),
+		.mma_scales = { {0, 38307}, {0, 76614}, {0, 153228} },
+		.ev_cfg = MMA8452_TRANSIENT_CFG,
+		.ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE,
+		.ev_cfg_chan_shift = 1,
+		.ev_src = MMA8452_TRANSIENT_SRC,
+		.ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE,
+		.ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE,
+		.ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE,
+		.ev_ths = MMA8452_TRANSIENT_THS,
+		.ev_ths_mask = MMA8452_TRANSIENT_THS_MASK,
+		.ev_count = MMA8452_TRANSIENT_COUNT,
+	},
+	[mma8652] = {
+		.chip_id = MMA8652_DEVICE_ID,
+		.channels = mma8652_channels,
+		.num_channels = ARRAY_SIZE(mma8652_channels),
+		.mma_scales = { {0, 9577}, {0, 19154}, {0, 38307} },
+		.ev_cfg = MMA8452_FF_MT_CFG,
+		.ev_cfg_ele = MMA8452_FF_MT_CFG_ELE,
+		.ev_cfg_chan_shift = 3,
+		.ev_src = MMA8452_FF_MT_SRC,
+		.ev_src_xe = MMA8452_FF_MT_SRC_XHE,
+		.ev_src_ye = MMA8452_FF_MT_SRC_YHE,
+		.ev_src_ze = MMA8452_FF_MT_SRC_ZHE,
+		.ev_ths = MMA8452_FF_MT_THS,
+		.ev_ths_mask = MMA8452_FF_MT_THS_MASK,
+		.ev_count = MMA8452_FF_MT_COUNT,
+	},
+	[mma8653] = {
+		.chip_id = MMA8653_DEVICE_ID,
+		.channels = mma8653_channels,
+		.num_channels = ARRAY_SIZE(mma8653_channels),
+		.mma_scales = { {0, 38307}, {0, 76614}, {0, 153228} },
+		.ev_cfg = MMA8452_FF_MT_CFG,
+		.ev_cfg_ele = MMA8452_FF_MT_CFG_ELE,
+		.ev_cfg_chan_shift = 3,
+		.ev_src = MMA8452_FF_MT_SRC,
+		.ev_src_xe = MMA8452_FF_MT_SRC_XHE,
+		.ev_src_ye = MMA8452_FF_MT_SRC_YHE,
+		.ev_src_ze = MMA8452_FF_MT_SRC_ZHE,
+		.ev_ths = MMA8452_FF_MT_THS,
+		.ev_ths_mask = MMA8452_FF_MT_THS_MASK,
+		.ev_count = MMA8452_FF_MT_COUNT,
+	},
+};
+
 static struct attribute *mma8452_attributes[] = {
 	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
 	&iio_dev_attr_in_accel_scale_available.dev_attr.attr,
@@ -841,18 +1041,28 @@
 	return -ETIMEDOUT;
 }
 
+static const struct of_device_id mma8452_dt_ids[] = {
+	{ .compatible = "fsl,mma8452", .data = &mma_chip_info_table[mma8452] },
+	{ .compatible = "fsl,mma8453", .data = &mma_chip_info_table[mma8453] },
+	{ .compatible = "fsl,mma8652", .data = &mma_chip_info_table[mma8652] },
+	{ .compatible = "fsl,mma8653", .data = &mma_chip_info_table[mma8653] },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, mma8452_dt_ids);
+
 static int mma8452_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct mma8452_data *data;
 	struct iio_dev *indio_dev;
 	int ret;
+	const struct of_device_id *match;
 
-	ret = i2c_smbus_read_byte_data(client, MMA8452_WHO_AM_I);
-	if (ret < 0)
-		return ret;
-	if (ret != MMA8452_DEVICE_ID)
+	match = of_match_device(mma8452_dt_ids, &client->dev);
+	if (!match) {
+		dev_err(&client->dev, "unknown device model\n");
 		return -ENODEV;
+	}
 
 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 	if (!indio_dev)
@@ -861,14 +1071,33 @@
 	data = iio_priv(indio_dev);
 	data->client = client;
 	mutex_init(&data->lock);
+	data->chip_info = match->data;
+
+	ret = i2c_smbus_read_byte_data(client, MMA8452_WHO_AM_I);
+	if (ret < 0)
+		return ret;
+
+	switch (ret) {
+	case MMA8452_DEVICE_ID:
+	case MMA8453_DEVICE_ID:
+	case MMA8652_DEVICE_ID:
+	case MMA8653_DEVICE_ID:
+		if (ret == data->chip_info->chip_id)
+			break;
+	default:
+		return -ENODEV;
+	}
+
+	dev_info(&client->dev, "registering %s accelerometer; ID 0x%x\n",
+		 match->compatible, data->chip_info->chip_id);
 
 	i2c_set_clientdata(client, indio_dev);
 	indio_dev->info = &mma8452_info;
 	indio_dev->name = id->name;
 	indio_dev->dev.parent = &client->dev;
 	indio_dev->modes = INDIO_DIRECT_MODE;
-	indio_dev->channels = mma8452_channels;
-	indio_dev->num_channels = ARRAY_SIZE(mma8452_channels);
+	indio_dev->channels = data->chip_info->channels;
+	indio_dev->num_channels = data->chip_info->num_channels;
 	indio_dev->available_scan_masks = mma8452_scan_masks;
 
 	ret = mma8452_reset(client);
@@ -892,13 +1121,15 @@
 
 	if (client->irq) {
 		/*
-		 * Although we enable the transient interrupt source once and
-		 * for all here the transient event detection itself is not
-		 * enabled until userspace asks for it by
-		 * mma8452_write_event_config()
+		 * Although we enable the interrupt sources once and for
+		 * all here the event detection itself is not enabled until
+		 * userspace asks for it by mma8452_write_event_config()
 		 */
-		int supported_interrupts = MMA8452_INT_DRDY | MMA8452_INT_TRANS;
-		int enabled_interrupts = MMA8452_INT_TRANS;
+		int supported_interrupts = MMA8452_INT_DRDY |
+					   MMA8452_INT_TRANS |
+					   MMA8452_INT_FF_MT;
+		int enabled_interrupts = MMA8452_INT_TRANS |
+					 MMA8452_INT_FF_MT;
 
 		/* Assume wired to INT1 pin */
 		ret = i2c_smbus_write_byte_data(client,
@@ -987,17 +1218,14 @@
 #endif
 
 static const struct i2c_device_id mma8452_id[] = {
-	{ "mma8452", 0 },
+	{ "mma8452", mma8452 },
+	{ "mma8453", mma8453 },
+	{ "mma8652", mma8652 },
+	{ "mma8653", mma8653 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, mma8452_id);
 
-static const struct of_device_id mma8452_dt_ids[] = {
-	{ .compatible = "fsl,mma8452" },
-	{ }
-};
-MODULE_DEVICE_TABLE(of, mma8452_dt_ids);
-
 static struct i2c_driver mma8452_driver = {
 	.driver = {
 		.name	= "mma8452",
diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c
new file mode 100644
index 0000000..e72e218
--- /dev/null
+++ b/drivers/iio/accel/mxc4005.c
@@ -0,0 +1,567 @@
+/*
+ * 3-axis accelerometer driver for MXC4005XC Memsic sensor
+ *
+ * Copyright (c) 2014, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/acpi.h>
+#include <linux/gpio/consumer.h>
+#include <linux/regmap.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
+
+#define MXC4005_DRV_NAME		"mxc4005"
+#define MXC4005_IRQ_NAME		"mxc4005_event"
+#define MXC4005_REGMAP_NAME		"mxc4005_regmap"
+
+#define MXC4005_REG_XOUT_UPPER		0x03
+#define MXC4005_REG_XOUT_LOWER		0x04
+#define MXC4005_REG_YOUT_UPPER		0x05
+#define MXC4005_REG_YOUT_LOWER		0x06
+#define MXC4005_REG_ZOUT_UPPER		0x07
+#define MXC4005_REG_ZOUT_LOWER		0x08
+
+#define MXC4005_REG_INT_MASK1		0x0B
+#define MXC4005_REG_INT_MASK1_BIT_DRDYE	0x01
+
+#define MXC4005_REG_INT_CLR1		0x01
+#define MXC4005_REG_INT_CLR1_BIT_DRDYC	0x01
+
+#define MXC4005_REG_CONTROL		0x0D
+#define MXC4005_REG_CONTROL_MASK_FSR	GENMASK(6, 5)
+#define MXC4005_CONTROL_FSR_SHIFT	5
+
+#define MXC4005_REG_DEVICE_ID		0x0E
+
+enum mxc4005_axis {
+	AXIS_X,
+	AXIS_Y,
+	AXIS_Z,
+};
+
+enum mxc4005_range {
+	MXC4005_RANGE_2G,
+	MXC4005_RANGE_4G,
+	MXC4005_RANGE_8G,
+};
+
+struct mxc4005_data {
+	struct device *dev;
+	struct mutex mutex;
+	struct regmap *regmap;
+	struct iio_trigger *dready_trig;
+	__be16 buffer[8];
+	bool trigger_enabled;
+};
+
+/*
+ * MXC4005 can operate in the following ranges:
+ * +/- 2G, 4G, 8G (the default +/-2G)
+ *
+ * (2 + 2) * 9.81 / (2^12 - 1) = 0.009582
+ * (4 + 4) * 9.81 / (2^12 - 1) = 0.019164
+ * (8 + 8) * 9.81 / (2^12 - 1) = 0.038329
+ */
+static const struct {
+	u8 range;
+	int scale;
+} mxc4005_scale_table[] = {
+	{MXC4005_RANGE_2G, 9582},
+	{MXC4005_RANGE_4G, 19164},
+	{MXC4005_RANGE_8G, 38329},
+};
+
+
+static IIO_CONST_ATTR(in_accel_scale_available, "0.009582 0.019164 0.038329");
+
+static struct attribute *mxc4005_attributes[] = {
+	&iio_const_attr_in_accel_scale_available.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group mxc4005_attrs_group = {
+	.attrs = mxc4005_attributes,
+};
+
+static bool mxc4005_is_readable_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case MXC4005_REG_XOUT_UPPER:
+	case MXC4005_REG_XOUT_LOWER:
+	case MXC4005_REG_YOUT_UPPER:
+	case MXC4005_REG_YOUT_LOWER:
+	case MXC4005_REG_ZOUT_UPPER:
+	case MXC4005_REG_ZOUT_LOWER:
+	case MXC4005_REG_DEVICE_ID:
+	case MXC4005_REG_CONTROL:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool mxc4005_is_writeable_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case MXC4005_REG_INT_CLR1:
+	case MXC4005_REG_INT_MASK1:
+	case MXC4005_REG_CONTROL:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const struct regmap_config mxc4005_regmap_config = {
+	.name = MXC4005_REGMAP_NAME,
+
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = MXC4005_REG_DEVICE_ID,
+
+	.readable_reg = mxc4005_is_readable_reg,
+	.writeable_reg = mxc4005_is_writeable_reg,
+};
+
+static int mxc4005_read_xyz(struct mxc4005_data *data)
+{
+	int ret;
+
+	ret = regmap_bulk_read(data->regmap, MXC4005_REG_XOUT_UPPER,
+			       (u8 *) data->buffer, sizeof(data->buffer));
+	if (ret < 0) {
+		dev_err(data->dev, "failed to read axes\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int mxc4005_read_axis(struct mxc4005_data *data,
+			     unsigned int addr)
+{
+	__be16 reg;
+	int ret;
+
+	ret = regmap_bulk_read(data->regmap, addr, (u8 *) &reg, sizeof(reg));
+	if (ret < 0) {
+		dev_err(data->dev, "failed to read reg %02x\n", addr);
+		return ret;
+	}
+
+	return be16_to_cpu(reg);
+}
+
+static int mxc4005_read_scale(struct mxc4005_data *data)
+{
+	unsigned int reg;
+	int ret;
+	int i;
+
+	ret = regmap_read(data->regmap, MXC4005_REG_CONTROL, &reg);
+	if (ret < 0) {
+		dev_err(data->dev, "failed to read reg_control\n");
+		return ret;
+	}
+
+	i = reg >> MXC4005_CONTROL_FSR_SHIFT;
+
+	if (i < 0 || i >= ARRAY_SIZE(mxc4005_scale_table))
+		return -EINVAL;
+
+	return mxc4005_scale_table[i].scale;
+}
+
+static int mxc4005_set_scale(struct mxc4005_data *data, int val)
+{
+	unsigned int reg;
+	int i;
+	int ret;
+
+	for (i = 0; i < ARRAY_SIZE(mxc4005_scale_table); i++) {
+		if (mxc4005_scale_table[i].scale == val) {
+			reg = i << MXC4005_CONTROL_FSR_SHIFT;
+			ret = regmap_update_bits(data->regmap,
+						 MXC4005_REG_CONTROL,
+						 MXC4005_REG_CONTROL_MASK_FSR,
+						 reg);
+			if (ret < 0)
+				dev_err(data->dev,
+					"failed to write reg_control\n");
+			return ret;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int mxc4005_read_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int *val, int *val2, long mask)
+{
+	struct mxc4005_data *data = iio_priv(indio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		switch (chan->type) {
+		case IIO_ACCEL:
+			if (iio_buffer_enabled(indio_dev))
+				return -EBUSY;
+
+			ret = mxc4005_read_axis(data, chan->address);
+			if (ret < 0)
+				return ret;
+			*val = sign_extend32(ret >> chan->scan_type.shift,
+					     chan->scan_type.realbits - 1);
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
+	case IIO_CHAN_INFO_SCALE:
+		ret = mxc4005_read_scale(data);
+		if (ret < 0)
+			return ret;
+
+		*val = 0;
+		*val2 = ret;
+		return IIO_VAL_INT_PLUS_MICRO;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int mxc4005_write_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int val, int val2, long mask)
+{
+	struct mxc4005_data *data = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SCALE:
+		if (val != 0)
+			return -EINVAL;
+
+		return mxc4005_set_scale(data, val2);
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct iio_info mxc4005_info = {
+	.driver_module	= THIS_MODULE,
+	.read_raw	= mxc4005_read_raw,
+	.write_raw	= mxc4005_write_raw,
+	.attrs		= &mxc4005_attrs_group,
+};
+
+static const unsigned long mxc4005_scan_masks[] = {
+	BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z),
+	0
+};
+
+#define MXC4005_CHANNEL(_axis, _addr) {				\
+	.type = IIO_ACCEL,					\
+	.modified = 1,						\
+	.channel2 = IIO_MOD_##_axis,				\
+	.address = _addr,					\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+	.scan_index = AXIS_##_axis,				\
+	.scan_type = {						\
+		.sign = 's',					\
+		.realbits = 12,					\
+		.storagebits = 16,				\
+		.shift = 4,					\
+		.endianness = IIO_BE,				\
+	},							\
+}
+
+static const struct iio_chan_spec mxc4005_channels[] = {
+	MXC4005_CHANNEL(X, MXC4005_REG_XOUT_UPPER),
+	MXC4005_CHANNEL(Y, MXC4005_REG_YOUT_UPPER),
+	MXC4005_CHANNEL(Z, MXC4005_REG_ZOUT_UPPER),
+	IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+static irqreturn_t mxc4005_trigger_handler(int irq, void *private)
+{
+	struct iio_poll_func *pf = private;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct mxc4005_data *data = iio_priv(indio_dev);
+	int ret;
+
+	ret = mxc4005_read_xyz(data);
+	if (ret < 0)
+		goto err;
+
+	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+					   pf->timestamp);
+
+err:
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static int mxc4005_clr_intr(struct mxc4005_data *data)
+{
+	int ret;
+
+	/* clear interrupt */
+	ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1,
+			   MXC4005_REG_INT_CLR1_BIT_DRDYC);
+	if (ret < 0) {
+		dev_err(data->dev, "failed to write to reg_int_clr1\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int mxc4005_set_trigger_state(struct iio_trigger *trig,
+				     bool state)
+{
+	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+	struct mxc4005_data *data = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&data->mutex);
+	if (state) {
+		ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1,
+				   MXC4005_REG_INT_MASK1_BIT_DRDYE);
+	} else {
+		ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1,
+				   ~MXC4005_REG_INT_MASK1_BIT_DRDYE);
+	}
+
+	if (ret < 0) {
+		mutex_unlock(&data->mutex);
+		dev_err(data->dev, "failed to update reg_int_mask1");
+		return ret;
+	}
+
+	data->trigger_enabled = state;
+	mutex_unlock(&data->mutex);
+
+	return 0;
+}
+
+static int mxc4005_trigger_try_reen(struct iio_trigger *trig)
+{
+	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+	struct mxc4005_data *data = iio_priv(indio_dev);
+
+	if (!data->dready_trig)
+		return 0;
+
+	return mxc4005_clr_intr(data);
+}
+
+static const struct iio_trigger_ops mxc4005_trigger_ops = {
+	.set_trigger_state = mxc4005_set_trigger_state,
+	.try_reenable = mxc4005_trigger_try_reen,
+	.owner = THIS_MODULE,
+};
+
+static int mxc4005_gpio_probe(struct i2c_client *client,
+			      struct mxc4005_data *data)
+{
+	struct device *dev;
+	struct gpio_desc *gpio;
+	int ret;
+
+	if (!client)
+		return -EINVAL;
+
+	dev = &client->dev;
+
+	gpio = devm_gpiod_get_index(dev, "mxc4005_int", 0, GPIOD_IN);
+	if (IS_ERR(gpio)) {
+		dev_err(dev, "failed to get acpi gpio index\n");
+		return PTR_ERR(gpio);
+	}
+
+	ret = gpiod_to_irq(gpio);
+
+	dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
+
+	return ret;
+}
+
+static int mxc4005_chip_init(struct mxc4005_data *data)
+{
+	int ret;
+	unsigned int reg;
+
+	ret = regmap_read(data->regmap, MXC4005_REG_DEVICE_ID, &reg);
+	if (ret < 0) {
+		dev_err(data->dev, "failed to read chip id\n");
+		return ret;
+	}
+
+	dev_dbg(data->dev, "MXC4005 chip id %02x\n", reg);
+
+	return 0;
+}
+
+static int mxc4005_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct mxc4005_data *data;
+	struct iio_dev *indio_dev;
+	struct regmap *regmap;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	regmap = devm_regmap_init_i2c(client, &mxc4005_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(&client->dev, "failed to initialize regmap\n");
+		return PTR_ERR(regmap);
+	}
+
+	data = iio_priv(indio_dev);
+	i2c_set_clientdata(client, indio_dev);
+	data->dev = &client->dev;
+	data->regmap = regmap;
+
+	ret = mxc4005_chip_init(data);
+	if (ret < 0) {
+		dev_err(&client->dev, "failed to initialize chip\n");
+		return ret;
+	}
+
+	mutex_init(&data->mutex);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->channels = mxc4005_channels;
+	indio_dev->num_channels = ARRAY_SIZE(mxc4005_channels);
+	indio_dev->available_scan_masks = mxc4005_scan_masks;
+	indio_dev->name = MXC4005_DRV_NAME;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->info = &mxc4005_info;
+
+	ret = iio_triggered_buffer_setup(indio_dev,
+					 iio_pollfunc_store_time,
+					 mxc4005_trigger_handler,
+					 NULL);
+	if (ret < 0) {
+		dev_err(&client->dev,
+			"failed to setup iio triggered buffer\n");
+		return ret;
+	}
+
+	if (client->irq < 0)
+		client->irq = mxc4005_gpio_probe(client, data);
+
+	if (client->irq > 0) {
+		data->dready_trig = devm_iio_trigger_alloc(&client->dev,
+							   "%s-dev%d",
+							   indio_dev->name,
+							   indio_dev->id);
+		if (!data->dready_trig)
+			return -ENOMEM;
+
+		ret = devm_request_threaded_irq(&client->dev, client->irq,
+						iio_trigger_generic_data_rdy_poll,
+						NULL,
+						IRQF_TRIGGER_FALLING |
+						IRQF_ONESHOT,
+						MXC4005_IRQ_NAME,
+						data->dready_trig);
+		if (ret) {
+			dev_err(&client->dev,
+				"failed to init threaded irq\n");
+			goto err_buffer_cleanup;
+		}
+
+		data->dready_trig->dev.parent = &client->dev;
+		data->dready_trig->ops = &mxc4005_trigger_ops;
+		iio_trigger_set_drvdata(data->dready_trig, indio_dev);
+		indio_dev->trig = data->dready_trig;
+		iio_trigger_get(indio_dev->trig);
+		ret = iio_trigger_register(data->dready_trig);
+		if (ret) {
+			dev_err(&client->dev,
+				"failed to register trigger\n");
+			goto err_trigger_unregister;
+		}
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0) {
+		dev_err(&client->dev,
+			"unable to register iio device %d\n", ret);
+		goto err_buffer_cleanup;
+	}
+
+	return 0;
+
+err_trigger_unregister:
+	iio_trigger_unregister(data->dready_trig);
+err_buffer_cleanup:
+	iio_triggered_buffer_cleanup(indio_dev);
+
+	return ret;
+}
+
+static int mxc4005_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct mxc4005_data *data = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+
+	iio_triggered_buffer_cleanup(indio_dev);
+	if (data->dready_trig)
+		iio_trigger_unregister(data->dready_trig);
+
+	return 0;
+}
+
+static const struct acpi_device_id mxc4005_acpi_match[] = {
+	{"MXC4005",	0},
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, mxc4005_acpi_match);
+
+static const struct i2c_device_id mxc4005_id[] = {
+	{"mxc4005",	0},
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, mxc4005_id);
+
+static struct i2c_driver mxc4005_driver = {
+	.driver = {
+		.name = MXC4005_DRV_NAME,
+		.acpi_match_table = ACPI_PTR(mxc4005_acpi_match),
+	},
+	.probe		= mxc4005_probe,
+	.remove		= mxc4005_remove,
+	.id_table	= mxc4005_id,
+};
+
+module_i2c_driver(mxc4005_driver);
+
+MODULE_AUTHOR("Teodora Baluta <teodora.baluta@intel.com>");
+MODULE_LICENSE("GPL v2");
+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 ff30f88..dab8b76 100644
--- a/drivers/iio/accel/st_accel_core.c
+++ b/drivers/iio/accel/st_accel_core.c
@@ -618,6 +618,7 @@
 	.attrs = &st_accel_attribute_group,
 	.read_raw = &st_accel_read_raw,
 	.write_raw = &st_accel_write_raw,
+	.debugfs_reg_access = &st_sensors_debugfs_reg_access,
 };
 
 #ifdef CONFIG_IIO_TRIGGER
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 50c103d..7868c74 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -149,6 +149,17 @@
 	  Marvell Berlin2 ADC driver. This ADC has 8 channels, with one used for
 	  temperature measurement.
 
+config CC10001_ADC
+	tristate "Cosmic Circuits 10001 ADC driver"
+	depends on HAS_IOMEM && HAVE_CLK && REGULATOR
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	help
+	  Say yes here to build support for Cosmic Circuits 10001 ADC.
+
+	  This driver can also be built as a module. If so, the module will be
+	  called cc10001_adc.
+
 config DA9150_GPADC
 	tristate "Dialog DA9150 GPADC driver support"
 	depends on MFD_DA9150
@@ -161,17 +172,6 @@
 	  To compile this driver as a module, choose M here: the module will be
 	  called berlin2-adc.
 
-config CC10001_ADC
-	tristate "Cosmic Circuits 10001 ADC driver"
-	depends on HAS_IOMEM && HAVE_CLK && REGULATOR
-	select IIO_BUFFER
-	select IIO_TRIGGERED_BUFFER
-	help
-	  Say yes here to build support for Cosmic Circuits 10001 ADC.
-
-	  This driver can also be built as a module. If so, the module will be
-	  called cc10001_adc.
-
 config EXYNOS_ADC
 	tristate "Exynos ADC driver support"
 	depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST)
@@ -183,6 +183,17 @@
 	  To compile this driver as a module, choose M here: the module will be
 	  called exynos_adc.
 
+config HI8435
+	tristate "Holt Integrated Circuits HI-8435 threshold detector"
+	select IIO_TRIGGERED_EVENT
+	depends on SPI
+	help
+	  If you say yes here you get support for Holt Integrated Circuits
+	  HI-8435 chip.
+
+	  This driver can also be built as a module. If so, the module will be
+	  called hi8435.
+
 config LP8788_ADC
 	tristate "LP8788 ADC driver"
 	depends on MFD_LP8788
@@ -361,6 +372,8 @@
 config VF610_ADC
 	tristate "Freescale vf610 ADC driver"
 	depends on OF
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
 	help
 	  Say yes here to support for Vybrid board analog-to-digital converter.
 	  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 a096210..99b37a9 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -16,9 +16,10 @@
 obj-$(CONFIG_AT91_ADC) += at91_adc.o
 obj-$(CONFIG_AXP288_ADC) += axp288_adc.o
 obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o
-obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o
 obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o
+obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o
 obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
+obj-$(CONFIG_HI8435) += hi8435.o
 obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
 obj-$(CONFIG_MAX1027) += max1027.o
 obj-$(CONFIG_MAX1363) += max1363.o
diff --git a/drivers/iio/adc/berlin2-adc.c b/drivers/iio/adc/berlin2-adc.c
index 4946d9b..71c806e 100644
--- a/drivers/iio/adc/berlin2-adc.c
+++ b/drivers/iio/adc/berlin2-adc.c
@@ -27,13 +27,13 @@
 #define  BERLIN2_SM_CTRL_SM_SOC_INT		BIT(1)
 #define  BERLIN2_SM_CTRL_SOC_SM_INT		BIT(2)
 #define  BERLIN2_SM_CTRL_ADC_SEL(x)		((x) << 5)	/* 0-15 */
-#define  BERLIN2_SM_CTRL_ADC_SEL_MASK		(0xf << 5)
+#define  BERLIN2_SM_CTRL_ADC_SEL_MASK		GENMASK(8, 5)
 #define  BERLIN2_SM_CTRL_ADC_POWER		BIT(9)
 #define  BERLIN2_SM_CTRL_ADC_CLKSEL_DIV2	(0x0 << 10)
 #define  BERLIN2_SM_CTRL_ADC_CLKSEL_DIV3	(0x1 << 10)
 #define  BERLIN2_SM_CTRL_ADC_CLKSEL_DIV4	(0x2 << 10)
 #define  BERLIN2_SM_CTRL_ADC_CLKSEL_DIV8	(0x3 << 10)
-#define  BERLIN2_SM_CTRL_ADC_CLKSEL_MASK	(0x3 << 10)
+#define  BERLIN2_SM_CTRL_ADC_CLKSEL_MASK	GENMASK(11, 10)
 #define  BERLIN2_SM_CTRL_ADC_START		BIT(12)
 #define  BERLIN2_SM_CTRL_ADC_RESET		BIT(13)
 #define  BERLIN2_SM_CTRL_ADC_BANDGAP_RDY	BIT(14)
@@ -50,7 +50,7 @@
 #define  BERLIN2_SM_CTRL_TSEN_MODE_10_50	(0x1 << 22)	/* 10-50 C */
 #define  BERLIN2_SM_CTRL_TSEN_RESET		BIT(29)
 #define BERLIN2_SM_ADC_DATA			0x20
-#define  BERLIN2_SM_ADC_MASK			0x3ff
+#define  BERLIN2_SM_ADC_MASK			GENMASK(9, 0)
 #define BERLIN2_SM_ADC_STATUS			0x1c
 #define  BERLIN2_SM_ADC_STATUS_DATA_RDY(x)	BIT(x)		/* 0-15 */
 #define  BERLIN2_SM_ADC_STATUS_DATA_RDY_MASK	GENMASK(15, 0)
@@ -65,9 +65,9 @@
 #define  BERLIN2_SM_TSEN_CTRL_START		BIT(8)
 #define  BERLIN2_SM_TSEN_CTRL_SETTLING_4	(0x0 << 21)	/* 4 us */
 #define  BERLIN2_SM_TSEN_CTRL_SETTLING_12	(0x1 << 21)	/* 12 us */
-#define  BERLIN2_SM_TSEN_CTRL_SETTLING_MASK	(0x1 << 21)
+#define  BERLIN2_SM_TSEN_CTRL_SETTLING_MASK	BIT(21)
 #define  BERLIN2_SM_TSEN_CTRL_TRIM(x)		((x) << 22)
-#define  BERLIN2_SM_TSEN_CTRL_TRIM_MASK		(0xf << 22)
+#define  BERLIN2_SM_TSEN_CTRL_TRIM_MASK		GENMASK(25, 22)
 
 struct berlin2_adc_priv {
 	struct regmap		*regmap;
@@ -78,13 +78,13 @@
 };
 
 #define BERLIN2_ADC_CHANNEL(n, t)					\
-		{							\
-			.channel	= n,				\
-			.datasheet_name	= "channel"#n,			\
-			.type		= t,				\
-			.indexed	= 1,				\
-			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
-		}
+	{								\
+		.channel		= n,				\
+		.datasheet_name		= "channel"#n,			\
+		.type			= t,				\
+		.indexed		= 1,				\
+		.info_mask_separate	= BIT(IIO_CHAN_INFO_RAW),	\
+	}
 
 static const struct iio_chan_spec berlin2_adc_channels[] = {
 	BERLIN2_ADC_CHANNEL(0, IIO_VOLTAGE),	/* external input */
@@ -111,18 +111,24 @@
 
 	mutex_lock(&priv->lock);
 
+	/* Enable the interrupts */
+	regmap_write(priv->regmap, BERLIN2_SM_ADC_STATUS,
+		     BERLIN2_SM_ADC_STATUS_INT_EN(channel));
+
 	/* Configure the ADC */
 	regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL,
-			BERLIN2_SM_CTRL_ADC_RESET | BERLIN2_SM_CTRL_ADC_SEL_MASK
-			| BERLIN2_SM_CTRL_ADC_START,
-			BERLIN2_SM_CTRL_ADC_SEL(channel) | BERLIN2_SM_CTRL_ADC_START);
+			   BERLIN2_SM_CTRL_ADC_RESET |
+			   BERLIN2_SM_CTRL_ADC_SEL_MASK |
+			   BERLIN2_SM_CTRL_ADC_START,
+			   BERLIN2_SM_CTRL_ADC_SEL(channel) |
+			   BERLIN2_SM_CTRL_ADC_START);
 
 	ret = wait_event_interruptible_timeout(priv->wq, priv->data_available,
-			msecs_to_jiffies(1000));
+					       msecs_to_jiffies(1000));
 
 	/* Disable the interrupts */
 	regmap_update_bits(priv->regmap, BERLIN2_SM_ADC_STATUS,
-			BERLIN2_SM_ADC_STATUS_INT_EN(channel), 0);
+			   BERLIN2_SM_ADC_STATUS_INT_EN(channel), 0);
 
 	if (ret == 0)
 		ret = -ETIMEDOUT;
@@ -132,7 +138,7 @@
 	}
 
 	regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL,
-			BERLIN2_SM_CTRL_ADC_START, 0);
+			   BERLIN2_SM_CTRL_ADC_START, 0);
 
 	data = priv->data;
 	priv->data_available = false;
@@ -149,24 +155,31 @@
 
 	mutex_lock(&priv->lock);
 
+	/* Enable interrupts */
+	regmap_write(priv->regmap, BERLIN2_SM_TSEN_STATUS,
+		     BERLIN2_SM_TSEN_STATUS_INT_EN);
+
 	/* Configure the ADC */
 	regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL,
-			BERLIN2_SM_CTRL_TSEN_RESET | BERLIN2_SM_CTRL_ADC_ROTATE,
-			BERLIN2_SM_CTRL_ADC_ROTATE);
+			   BERLIN2_SM_CTRL_TSEN_RESET |
+			   BERLIN2_SM_CTRL_ADC_ROTATE,
+			   BERLIN2_SM_CTRL_ADC_ROTATE);
 
 	/* Configure the temperature sensor */
 	regmap_update_bits(priv->regmap, BERLIN2_SM_TSEN_CTRL,
-			BERLIN2_SM_TSEN_CTRL_TRIM_MASK | BERLIN2_SM_TSEN_CTRL_SETTLING_MASK
-			| BERLIN2_SM_TSEN_CTRL_START,
-			BERLIN2_SM_TSEN_CTRL_TRIM(3) | BERLIN2_SM_TSEN_CTRL_SETTLING_12
-			| BERLIN2_SM_TSEN_CTRL_START);
+			   BERLIN2_SM_TSEN_CTRL_TRIM_MASK |
+			   BERLIN2_SM_TSEN_CTRL_SETTLING_MASK |
+			   BERLIN2_SM_TSEN_CTRL_START,
+			   BERLIN2_SM_TSEN_CTRL_TRIM(3) |
+			   BERLIN2_SM_TSEN_CTRL_SETTLING_12 |
+			   BERLIN2_SM_TSEN_CTRL_START);
 
 	ret = wait_event_interruptible_timeout(priv->wq, priv->data_available,
-			msecs_to_jiffies(1000));
+					       msecs_to_jiffies(1000));
 
 	/* Disable interrupts */
 	regmap_update_bits(priv->regmap, BERLIN2_SM_TSEN_STATUS,
-			BERLIN2_SM_TSEN_STATUS_INT_EN, 0);
+			   BERLIN2_SM_TSEN_STATUS_INT_EN, 0);
 
 	if (ret == 0)
 		ret = -ETIMEDOUT;
@@ -176,7 +189,7 @@
 	}
 
 	regmap_update_bits(priv->regmap, BERLIN2_SM_TSEN_CTRL,
-			BERLIN2_SM_TSEN_CTRL_START, 0);
+			   BERLIN2_SM_TSEN_CTRL_START, 0);
 
 	data = priv->data;
 	priv->data_available = false;
@@ -187,10 +200,9 @@
 }
 
 static int berlin2_adc_read_raw(struct iio_dev *indio_dev,
-		struct iio_chan_spec const *chan, int *val, int *val2,
-		long mask)
+				struct iio_chan_spec const *chan, int *val,
+				int *val2, long mask)
 {
-	struct berlin2_adc_priv *priv = iio_priv(indio_dev);
 	int temp;
 
 	switch (mask) {
@@ -198,10 +210,6 @@
 		if (chan->type != IIO_VOLTAGE)
 			return -EINVAL;
 
-		/* Enable the interrupts */
-		regmap_write(priv->regmap, BERLIN2_SM_ADC_STATUS,
-				BERLIN2_SM_ADC_STATUS_INT_EN(chan->channel));
-
 		*val = berlin2_adc_read(indio_dev, chan->channel);
 		if (*val < 0)
 			return *val;
@@ -211,10 +219,6 @@
 		if (chan->type != IIO_TEMP)
 			return -EINVAL;
 
-		/* Enable interrupts */
-		regmap_write(priv->regmap, BERLIN2_SM_TSEN_STATUS,
-				BERLIN2_SM_TSEN_STATUS_INT_EN);
-
 		temp = berlin2_adc_tsen_read(indio_dev);
 		if (temp < 0)
 			return temp;
@@ -306,12 +310,12 @@
 		return tsen_irq;
 
 	ret = devm_request_irq(&pdev->dev, irq, berlin2_adc_irq, 0,
-			pdev->dev.driver->name, indio_dev);
+			       pdev->dev.driver->name, indio_dev);
 	if (ret)
 		return ret;
 
 	ret = devm_request_irq(&pdev->dev, tsen_irq, berlin2_adc_tsen_irq,
-			0, pdev->dev.driver->name, indio_dev);
+			       0, pdev->dev.driver->name, indio_dev);
 	if (ret)
 		return ret;
 
@@ -328,13 +332,14 @@
 
 	/* Power up the ADC */
 	regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL,
-			BERLIN2_SM_CTRL_ADC_POWER, BERLIN2_SM_CTRL_ADC_POWER);
+			   BERLIN2_SM_CTRL_ADC_POWER,
+			   BERLIN2_SM_CTRL_ADC_POWER);
 
 	ret = iio_device_register(indio_dev);
 	if (ret) {
 		/* Power down the ADC */
 		regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL,
-				BERLIN2_SM_CTRL_ADC_POWER, 0);
+				   BERLIN2_SM_CTRL_ADC_POWER, 0);
 		return ret;
 	}
 
@@ -350,7 +355,7 @@
 
 	/* Power down the ADC */
 	regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL,
-			BERLIN2_SM_CTRL_ADC_POWER, 0);
+			   BERLIN2_SM_CTRL_ADC_POWER, 0);
 
 	return 0;
 }
diff --git a/drivers/iio/adc/hi8435.c b/drivers/iio/adc/hi8435.c
new file mode 100644
index 0000000..c73c6c6
--- /dev/null
+++ b/drivers/iio/adc/hi8435.c
@@ -0,0 +1,534 @@
+/*
+ * Holt Integrated Circuits HI-8435 threshold detector driver
+ *
+ * Copyright (C) 2015 Zodiac Inflight Innovations
+ * Copyright (C) 2015 Cogent Embedded, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/delay.h>
+#include <linux/iio/events.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_event.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio/consumer.h>
+
+#define DRV_NAME "hi8435"
+
+/* Register offsets for HI-8435 */
+#define HI8435_CTRL_REG		0x02
+#define HI8435_PSEN_REG		0x04
+#define HI8435_TMDATA_REG	0x1E
+#define HI8435_GOCENHYS_REG	0x3A
+#define HI8435_SOCENHYS_REG	0x3C
+#define HI8435_SO7_0_REG	0x10
+#define HI8435_SO15_8_REG	0x12
+#define HI8435_SO23_16_REG	0x14
+#define HI8435_SO31_24_REG	0x16
+#define HI8435_SO31_0_REG	0x78
+
+#define HI8435_WRITE_OPCODE	0x00
+#define HI8435_READ_OPCODE	0x80
+
+/* CTRL register bits */
+#define HI8435_CTRL_TEST	0x01
+#define HI8435_CTRL_SRST	0x02
+
+struct hi8435_priv {
+	struct spi_device *spi;
+	struct mutex lock;
+
+	unsigned long event_scan_mask; /* soft mask/unmask channels events */
+	unsigned int event_prev_val;
+
+	unsigned threshold_lo[2]; /* GND-Open and Supply-Open thresholds */
+	unsigned threshold_hi[2]; /* GND-Open and Supply-Open thresholds */
+	u8 reg_buffer[3] ____cacheline_aligned;
+};
+
+static int hi8435_readb(struct hi8435_priv *priv, u8 reg, u8 *val)
+{
+	reg |= HI8435_READ_OPCODE;
+	return spi_write_then_read(priv->spi, &reg, 1, val, 1);
+}
+
+static int hi8435_readw(struct hi8435_priv *priv, u8 reg, u16 *val)
+{
+	int ret;
+	__be16 be_val;
+
+	reg |= HI8435_READ_OPCODE;
+	ret = spi_write_then_read(priv->spi, &reg, 1, &be_val, 2);
+	*val = be16_to_cpu(be_val);
+
+	return ret;
+}
+
+static int hi8435_readl(struct hi8435_priv *priv, u8 reg, u32 *val)
+{
+	int ret;
+	__be32 be_val;
+
+	reg |= HI8435_READ_OPCODE;
+	ret = spi_write_then_read(priv->spi, &reg, 1, &be_val, 4);
+	*val = be32_to_cpu(be_val);
+
+	return ret;
+}
+
+static int hi8435_writeb(struct hi8435_priv *priv, u8 reg, u8 val)
+{
+	priv->reg_buffer[0] = reg | HI8435_WRITE_OPCODE;
+	priv->reg_buffer[1] = val;
+
+	return spi_write(priv->spi, priv->reg_buffer, 2);
+}
+
+static int hi8435_writew(struct hi8435_priv *priv, u8 reg, u16 val)
+{
+	priv->reg_buffer[0] = reg | HI8435_WRITE_OPCODE;
+	priv->reg_buffer[1] = (val >> 8) & 0xff;
+	priv->reg_buffer[2] = val & 0xff;
+
+	return spi_write(priv->spi, priv->reg_buffer, 3);
+}
+
+static int hi8435_read_event_config(struct iio_dev *idev,
+				    const struct iio_chan_spec *chan,
+				    enum iio_event_type type,
+				    enum iio_event_direction dir)
+{
+	struct hi8435_priv *priv = iio_priv(idev);
+
+	return !!(priv->event_scan_mask & BIT(chan->channel));
+}
+
+static int hi8435_write_event_config(struct iio_dev *idev,
+				     const struct iio_chan_spec *chan,
+				     enum iio_event_type type,
+				     enum iio_event_direction dir, int state)
+{
+	struct hi8435_priv *priv = iio_priv(idev);
+
+	priv->event_scan_mask &= ~BIT(chan->channel);
+	if (state)
+		priv->event_scan_mask |= BIT(chan->channel);
+
+	return 0;
+}
+
+static int hi8435_read_event_value(struct iio_dev *idev,
+				   const struct iio_chan_spec *chan,
+				   enum iio_event_type type,
+				   enum iio_event_direction dir,
+				   enum iio_event_info info,
+				   int *val, int *val2)
+{
+	struct hi8435_priv *priv = iio_priv(idev);
+	int ret;
+	u8 mode, psen;
+	u16 reg;
+
+	ret = hi8435_readb(priv, HI8435_PSEN_REG, &psen);
+	if (ret < 0)
+		return ret;
+
+	/* Supply-Open or GND-Open sensing mode */
+	mode = !!(psen & BIT(chan->channel / 8));
+
+	ret = hi8435_readw(priv, mode ? HI8435_SOCENHYS_REG :
+				 HI8435_GOCENHYS_REG, &reg);
+	if (ret < 0)
+		return ret;
+
+	if (dir == IIO_EV_DIR_FALLING)
+		*val = ((reg & 0xff) - (reg >> 8)) / 2;
+	else if (dir == IIO_EV_DIR_RISING)
+		*val = ((reg & 0xff) + (reg >> 8)) / 2;
+
+	return IIO_VAL_INT;
+}
+
+static int hi8435_write_event_value(struct iio_dev *idev,
+				    const struct iio_chan_spec *chan,
+				    enum iio_event_type type,
+				    enum iio_event_direction dir,
+				    enum iio_event_info info,
+				    int val, int val2)
+{
+	struct hi8435_priv *priv = iio_priv(idev);
+	int ret;
+	u8 mode, psen;
+	u16 reg;
+
+	ret = hi8435_readb(priv, HI8435_PSEN_REG, &psen);
+	if (ret < 0)
+		return ret;
+
+	/* Supply-Open or GND-Open sensing mode */
+	mode = !!(psen & BIT(chan->channel / 8));
+
+	ret = hi8435_readw(priv, mode ? HI8435_SOCENHYS_REG :
+				 HI8435_GOCENHYS_REG, &reg);
+	if (ret < 0)
+		return ret;
+
+	if (dir == IIO_EV_DIR_FALLING) {
+		/* falling threshold range 2..21V, hysteresis minimum 2V */
+		if (val < 2 || val > 21 || (val + 2) > priv->threshold_hi[mode])
+			return -EINVAL;
+
+		if (val == priv->threshold_lo[mode])
+			return 0;
+
+		priv->threshold_lo[mode] = val;
+
+		/* hysteresis must not be odd */
+		if ((priv->threshold_hi[mode] - priv->threshold_lo[mode]) % 2)
+			priv->threshold_hi[mode]--;
+	} else if (dir == IIO_EV_DIR_RISING) {
+		/* rising threshold range 3..22V, hysteresis minimum 2V */
+		if (val < 3 || val > 22 || val < (priv->threshold_lo[mode] + 2))
+			return -EINVAL;
+
+		if (val == priv->threshold_hi[mode])
+			return 0;
+
+		priv->threshold_hi[mode] = val;
+
+		/* hysteresis must not be odd */
+		if ((priv->threshold_hi[mode] - priv->threshold_lo[mode]) % 2)
+			priv->threshold_lo[mode]++;
+	}
+
+	/* program thresholds */
+	mutex_lock(&priv->lock);
+
+	ret = hi8435_readw(priv, mode ? HI8435_SOCENHYS_REG :
+				 HI8435_GOCENHYS_REG, &reg);
+	if (ret < 0) {
+		mutex_unlock(&priv->lock);
+		return ret;
+	}
+
+	/* hysteresis */
+	reg = priv->threshold_hi[mode] - priv->threshold_lo[mode];
+	reg <<= 8;
+	/* threshold center */
+	reg |= (priv->threshold_hi[mode] + priv->threshold_lo[mode]);
+
+	ret = hi8435_writew(priv, mode ? HI8435_SOCENHYS_REG :
+				  HI8435_GOCENHYS_REG, reg);
+
+	mutex_unlock(&priv->lock);
+
+	return ret;
+}
+
+static int hi8435_debugfs_reg_access(struct iio_dev *idev,
+				     unsigned reg, unsigned writeval,
+				     unsigned *readval)
+{
+	struct hi8435_priv *priv = iio_priv(idev);
+	int ret;
+	u8 val;
+
+	if (readval != NULL) {
+		ret = hi8435_readb(priv, reg, &val);
+		*readval = val;
+	} else {
+		val = (u8)writeval;
+		ret = hi8435_writeb(priv, reg, val);
+	}
+
+	return ret;
+}
+
+static const struct iio_event_spec hi8435_events[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_EITHER,
+		.mask_separate = BIT(IIO_EV_INFO_ENABLE),
+	},
+};
+
+static int hi8435_get_sensing_mode(struct iio_dev *idev,
+				   const struct iio_chan_spec *chan)
+{
+	struct hi8435_priv *priv = iio_priv(idev);
+	int ret;
+	u8 reg;
+
+	ret = hi8435_readb(priv, HI8435_PSEN_REG, &reg);
+	if (ret < 0)
+		return ret;
+
+	return !!(reg & BIT(chan->channel / 8));
+}
+
+static int hi8435_set_sensing_mode(struct iio_dev *idev,
+				   const struct iio_chan_spec *chan,
+				   unsigned int mode)
+{
+	struct hi8435_priv *priv = iio_priv(idev);
+	int ret;
+	u8 reg;
+
+	mutex_lock(&priv->lock);
+
+	ret = hi8435_readb(priv, HI8435_PSEN_REG, &reg);
+	if (ret < 0) {
+		mutex_unlock(&priv->lock);
+		return ret;
+	}
+
+	reg &= ~BIT(chan->channel / 8);
+	if (mode)
+		reg |= BIT(chan->channel / 8);
+
+	ret = hi8435_writeb(priv, HI8435_PSEN_REG, reg);
+
+	mutex_unlock(&priv->lock);
+
+	return ret;
+}
+
+static const char * const hi8435_sensing_modes[] = { "GND-Open",
+						     "Supply-Open" };
+
+static const struct iio_enum hi8435_sensing_mode = {
+	.items = hi8435_sensing_modes,
+	.num_items = ARRAY_SIZE(hi8435_sensing_modes),
+	.get = hi8435_get_sensing_mode,
+	.set = hi8435_set_sensing_mode,
+};
+
+static const struct iio_chan_spec_ext_info hi8435_ext_info[] = {
+	IIO_ENUM("sensing_mode", IIO_SEPARATE, &hi8435_sensing_mode),
+	{},
+};
+
+#define HI8435_VOLTAGE_CHANNEL(num)			\
+{							\
+	.type = IIO_VOLTAGE,				\
+	.indexed = 1,					\
+	.channel = num,					\
+	.event_spec = hi8435_events,			\
+	.num_event_specs = ARRAY_SIZE(hi8435_events),	\
+	.ext_info = hi8435_ext_info,			\
+}
+
+static const struct iio_chan_spec hi8435_channels[] = {
+	HI8435_VOLTAGE_CHANNEL(0),
+	HI8435_VOLTAGE_CHANNEL(1),
+	HI8435_VOLTAGE_CHANNEL(2),
+	HI8435_VOLTAGE_CHANNEL(3),
+	HI8435_VOLTAGE_CHANNEL(4),
+	HI8435_VOLTAGE_CHANNEL(5),
+	HI8435_VOLTAGE_CHANNEL(6),
+	HI8435_VOLTAGE_CHANNEL(7),
+	HI8435_VOLTAGE_CHANNEL(8),
+	HI8435_VOLTAGE_CHANNEL(9),
+	HI8435_VOLTAGE_CHANNEL(10),
+	HI8435_VOLTAGE_CHANNEL(11),
+	HI8435_VOLTAGE_CHANNEL(12),
+	HI8435_VOLTAGE_CHANNEL(13),
+	HI8435_VOLTAGE_CHANNEL(14),
+	HI8435_VOLTAGE_CHANNEL(15),
+	HI8435_VOLTAGE_CHANNEL(16),
+	HI8435_VOLTAGE_CHANNEL(17),
+	HI8435_VOLTAGE_CHANNEL(18),
+	HI8435_VOLTAGE_CHANNEL(19),
+	HI8435_VOLTAGE_CHANNEL(20),
+	HI8435_VOLTAGE_CHANNEL(21),
+	HI8435_VOLTAGE_CHANNEL(22),
+	HI8435_VOLTAGE_CHANNEL(23),
+	HI8435_VOLTAGE_CHANNEL(24),
+	HI8435_VOLTAGE_CHANNEL(25),
+	HI8435_VOLTAGE_CHANNEL(26),
+	HI8435_VOLTAGE_CHANNEL(27),
+	HI8435_VOLTAGE_CHANNEL(28),
+	HI8435_VOLTAGE_CHANNEL(29),
+	HI8435_VOLTAGE_CHANNEL(30),
+	HI8435_VOLTAGE_CHANNEL(31),
+	IIO_CHAN_SOFT_TIMESTAMP(32),
+};
+
+static const struct iio_info hi8435_info = {
+	.driver_module = THIS_MODULE,
+	.read_event_config = &hi8435_read_event_config,
+	.write_event_config = hi8435_write_event_config,
+	.read_event_value = &hi8435_read_event_value,
+	.write_event_value = &hi8435_write_event_value,
+	.debugfs_reg_access = &hi8435_debugfs_reg_access,
+};
+
+static void hi8435_iio_push_event(struct iio_dev *idev, unsigned int val)
+{
+	struct hi8435_priv *priv = iio_priv(idev);
+	enum iio_event_direction dir;
+	unsigned int i;
+	unsigned int status = priv->event_prev_val ^ val;
+
+	if (!status)
+		return;
+
+	for_each_set_bit(i, &priv->event_scan_mask, 32) {
+		if (status & BIT(i)) {
+			dir = val & BIT(i) ? IIO_EV_DIR_RISING :
+					     IIO_EV_DIR_FALLING;
+			iio_push_event(idev,
+				       IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, i,
+						    IIO_EV_TYPE_THRESH, dir),
+				       iio_get_time_ns());
+		}
+	}
+
+	priv->event_prev_val = val;
+}
+
+static irqreturn_t hi8435_trigger_handler(int irq, void *private)
+{
+	struct iio_poll_func *pf = private;
+	struct iio_dev *idev = pf->indio_dev;
+	struct hi8435_priv *priv = iio_priv(idev);
+	u32 val;
+	int ret;
+
+	ret = hi8435_readl(priv, HI8435_SO31_0_REG, &val);
+	if (ret < 0)
+		goto err_read;
+
+	hi8435_iio_push_event(idev, val);
+
+err_read:
+	iio_trigger_notify_done(idev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static int hi8435_probe(struct spi_device *spi)
+{
+	struct iio_dev *idev;
+	struct hi8435_priv *priv;
+	struct gpio_desc *reset_gpio;
+	int ret;
+
+	idev = devm_iio_device_alloc(&spi->dev, sizeof(*priv));
+	if (!idev)
+		return -ENOMEM;
+
+	priv = iio_priv(idev);
+	priv->spi = spi;
+
+	reset_gpio = devm_gpiod_get(&spi->dev, NULL, GPIOD_OUT_LOW);
+	if (IS_ERR(reset_gpio)) {
+		/* chip s/w reset if h/w reset failed */
+		hi8435_writeb(priv, HI8435_CTRL_REG, HI8435_CTRL_SRST);
+		hi8435_writeb(priv, HI8435_CTRL_REG, 0);
+	} else {
+		udelay(5);
+		gpiod_set_value(reset_gpio, 1);
+	}
+
+	spi_set_drvdata(spi, idev);
+	mutex_init(&priv->lock);
+
+	idev->dev.parent	= &spi->dev;
+	idev->name		= spi_get_device_id(spi)->name;
+	idev->modes		= INDIO_DIRECT_MODE;
+	idev->info		= &hi8435_info;
+	idev->channels		= hi8435_channels;
+	idev->num_channels	= ARRAY_SIZE(hi8435_channels);
+
+	/* unmask all events */
+	priv->event_scan_mask = ~(0);
+	/*
+	 * There is a restriction in the chip - the hysteresis can not be odd.
+	 * If the hysteresis is set to odd value then chip gets into lock state
+	 * and not functional anymore.
+	 * After chip reset the thresholds are in undefined state, so we need to
+	 * initialize thresholds to some initial values and then prevent
+	 * userspace setting odd hysteresis.
+	 *
+	 * Set threshold low voltage to 2V, threshold high voltage to 4V
+	 * for both GND-Open and Supply-Open sensing modes.
+	 */
+	priv->threshold_lo[0] = priv->threshold_lo[1] = 2;
+	priv->threshold_hi[0] = priv->threshold_hi[1] = 4;
+	hi8435_writew(priv, HI8435_GOCENHYS_REG, 0x206);
+	hi8435_writew(priv, HI8435_SOCENHYS_REG, 0x206);
+
+	ret = iio_triggered_event_setup(idev, NULL, hi8435_trigger_handler);
+	if (ret)
+		return ret;
+
+	ret = iio_device_register(idev);
+	if (ret < 0) {
+		dev_err(&spi->dev, "unable to register device\n");
+		goto unregister_triggered_event;
+	}
+
+	return 0;
+
+unregister_triggered_event:
+	iio_triggered_event_cleanup(idev);
+	return ret;
+}
+
+static int hi8435_remove(struct spi_device *spi)
+{
+	struct iio_dev *idev = spi_get_drvdata(spi);
+
+	iio_device_unregister(idev);
+	iio_triggered_event_cleanup(idev);
+
+	return 0;
+}
+
+static const struct of_device_id hi8435_dt_ids[] = {
+	{ .compatible = "holt,hi8435" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, hi8435_dt_ids);
+
+static const struct spi_device_id hi8435_id[] = {
+	{ "hi8435", 0},
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, hi8435_id);
+
+static struct spi_driver hi8435_driver = {
+	.driver	= {
+		.name		= DRV_NAME,
+		.of_match_table	= of_match_ptr(hi8435_dt_ids),
+	},
+	.probe		= hi8435_probe,
+	.remove		= hi8435_remove,
+	.id_table	= hi8435_id,
+};
+module_spi_driver(hi8435_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Vladimir Barinov");
+MODULE_DESCRIPTION("HI-8435 threshold detector");
diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c
index 44bf815..54a8302 100644
--- a/drivers/iio/adc/max1027.c
+++ b/drivers/iio/adc/max1027.c
@@ -508,6 +508,7 @@
 static struct spi_driver max1027_driver = {
 	.driver = {
 		.name	= "max1027",
+		.of_match_table = of_match_ptr(max1027_adc_dt_ids),
 		.owner	= THIS_MODULE,
 	},
 	.probe		= max1027_probe,
diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c
index b19e4f9..41a21e9 100644
--- a/drivers/iio/adc/mcp320x.c
+++ b/drivers/iio/adc/mcp320x.c
@@ -404,6 +404,7 @@
 static struct spi_driver mcp320x_driver = {
 	.driver = {
 		.name = "mcp320x",
+		.of_match_table = of_match_ptr(mcp320x_dt_ids),
 		.owner = THIS_MODULE,
 	},
 	.probe = mcp320x_probe,
diff --git a/drivers/iio/adc/ti-adc128s052.c b/drivers/iio/adc/ti-adc128s052.c
index 915be6b..98c0d2b 100644
--- a/drivers/iio/adc/ti-adc128s052.c
+++ b/drivers/iio/adc/ti-adc128s052.c
@@ -174,6 +174,13 @@
 	return 0;
 }
 
+static const struct of_device_id adc128_of_match[] = {
+	{ .compatible = "ti,adc128s052", },
+	{ .compatible = "ti,adc122s021", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, adc128_of_match);
+
 static const struct spi_device_id adc128_id[] = {
 	{ "adc128s052", 0},	/* index into adc128_config */
 	{ "adc122s021",	1},
@@ -184,6 +191,7 @@
 static struct spi_driver adc128_driver = {
 	.driver = {
 		.name = "adc128s052",
+		.of_match_table = of_match_ptr(adc128_of_match),
 		.owner = THIS_MODULE,
 	},
 	.probe = adc128_probe,
diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c
index df12c57..becbb0a 100644
--- a/drivers/iio/adc/twl6030-gpadc.c
+++ b/drivers/iio/adc/twl6030-gpadc.c
@@ -875,6 +875,7 @@
 	},
 	{ /* end */ }
 };
+MODULE_DEVICE_TABLE(of, of_twl6030_match_tbl);
 
 static int twl6030_gpadc_probe(struct platform_device *pdev)
 {
diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
index 6bf4c20..599cde3 100644
--- a/drivers/iio/adc/vf610_adc.c
+++ b/drivers/iio/adc/vf610_adc.c
@@ -34,8 +34,11 @@
 #include <linux/err.h>
 
 #include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
 #include <linux/iio/sysfs.h>
-#include <linux/iio/driver.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
 
 /* This will be the driver name the kernel reports */
 #define DRIVER_NAME "vf610-adc"
@@ -170,6 +173,7 @@
 	u32 sample_freq_avail[5];
 
 	struct completion completion;
+	u16 buffer[8];
 };
 
 static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 };
@@ -505,12 +509,24 @@
 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |	\
 				BIT(IIO_CHAN_INFO_SAMP_FREQ),	\
 	.ext_info = vf610_ext_info,				\
+	.scan_index = (_idx),			\
+	.scan_type = {					\
+		.sign = 'u',				\
+		.realbits = 12,				\
+		.storagebits = 16,			\
+	},						\
 }
 
 #define VF610_ADC_TEMPERATURE_CHAN(_idx, _chan_type) {	\
 	.type = (_chan_type),	\
 	.channel = (_idx),		\
 	.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),	\
+	.scan_index = (_idx),					\
+	.scan_type = {						\
+		.sign = 'u',					\
+		.realbits = 12,					\
+		.storagebits = 16,				\
+	},							\
 }
 
 static const struct iio_chan_spec vf610_adc_iio_channels[] = {
@@ -531,6 +547,7 @@
 	VF610_ADC_CHAN(14, IIO_VOLTAGE),
 	VF610_ADC_CHAN(15, IIO_VOLTAGE),
 	VF610_ADC_TEMPERATURE_CHAN(26, IIO_TEMP),
+	IIO_CHAN_SOFT_TIMESTAMP(32),
 	/* sentinel */
 };
 
@@ -559,13 +576,20 @@
 
 static irqreturn_t vf610_adc_isr(int irq, void *dev_id)
 {
-	struct vf610_adc *info = (struct vf610_adc *)dev_id;
+	struct iio_dev *indio_dev = (struct iio_dev *)dev_id;
+	struct vf610_adc *info = iio_priv(indio_dev);
 	int coco;
 
 	coco = readl(info->regs + VF610_REG_ADC_HS);
 	if (coco & VF610_ADC_HS_COCO0) {
 		info->value = vf610_adc_read_data(info);
-		complete(&info->completion);
+		if (iio_buffer_enabled(indio_dev)) {
+			info->buffer[0] = info->value;
+			iio_push_to_buffers_with_timestamp(indio_dev,
+					info->buffer, iio_get_time_ns());
+			iio_trigger_notify_done(indio_dev->trig);
+		} else
+			complete(&info->completion);
 	}
 
 	return IRQ_HANDLED;
@@ -613,8 +637,12 @@
 	case IIO_CHAN_INFO_RAW:
 	case IIO_CHAN_INFO_PROCESSED:
 		mutex_lock(&indio_dev->mlock);
-		reinit_completion(&info->completion);
+		if (iio_buffer_enabled(indio_dev)) {
+			mutex_unlock(&indio_dev->mlock);
+			return -EBUSY;
+		}
 
+		reinit_completion(&info->completion);
 		hc_cfg = VF610_ADC_ADCHC(chan->channel);
 		hc_cfg |= VF610_ADC_AIEN;
 		writel(hc_cfg, info->regs + VF610_REG_ADC_HC0);
@@ -694,6 +722,56 @@
 	return -EINVAL;
 }
 
+static int vf610_adc_buffer_postenable(struct iio_dev *indio_dev)
+{
+	struct vf610_adc *info = iio_priv(indio_dev);
+	unsigned int channel;
+	int ret;
+	int val;
+
+	ret = iio_triggered_buffer_postenable(indio_dev);
+	if (ret)
+		return ret;
+
+	val = readl(info->regs + VF610_REG_ADC_GC);
+	val |= VF610_ADC_ADCON;
+	writel(val, info->regs + VF610_REG_ADC_GC);
+
+	channel = find_first_bit(indio_dev->active_scan_mask,
+						indio_dev->masklength);
+
+	val = VF610_ADC_ADCHC(channel);
+	val |= VF610_ADC_AIEN;
+
+	writel(val, info->regs + VF610_REG_ADC_HC0);
+
+	return 0;
+}
+
+static int vf610_adc_buffer_predisable(struct iio_dev *indio_dev)
+{
+	struct vf610_adc *info = iio_priv(indio_dev);
+	unsigned int hc_cfg = 0;
+	int val;
+
+	val = readl(info->regs + VF610_REG_ADC_GC);
+	val &= ~VF610_ADC_ADCON;
+	writel(val, info->regs + VF610_REG_ADC_GC);
+
+	hc_cfg |= VF610_ADC_CONV_DISABLE;
+	hc_cfg &= ~VF610_ADC_AIEN;
+
+	writel(hc_cfg, info->regs + VF610_REG_ADC_HC0);
+
+	return iio_triggered_buffer_predisable(indio_dev);
+}
+
+static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
+	.postenable = &vf610_adc_buffer_postenable,
+	.predisable = &vf610_adc_buffer_predisable,
+	.validate_scan_mask = &iio_validate_scan_mask_onehot,
+};
+
 static int vf610_adc_reg_access(struct iio_dev *indio_dev,
 			unsigned reg, unsigned writeval,
 			unsigned *readval)
@@ -753,7 +831,7 @@
 
 	ret = devm_request_irq(info->dev, irq,
 				vf610_adc_isr, 0,
-				dev_name(&pdev->dev), info);
+				dev_name(&pdev->dev), indio_dev);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed requesting irq, irq = %d\n", irq);
 		return ret;
@@ -806,15 +884,23 @@
 	vf610_adc_cfg_init(info);
 	vf610_adc_hw_init(info);
 
+	ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+					NULL, &iio_triggered_buffer_setup_ops);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Couldn't initialise the buffer\n");
+		goto error_iio_device_register;
+	}
+
 	ret = iio_device_register(indio_dev);
 	if (ret) {
 		dev_err(&pdev->dev, "Couldn't register the device.\n");
-		goto error_iio_device_register;
+		goto error_adc_buffer_init;
 	}
 
 	return 0;
 
-
+error_adc_buffer_init:
+	iio_triggered_buffer_cleanup(indio_dev);
 error_iio_device_register:
 	clk_disable_unprepare(info->clk);
 error_adc_clk_enable:
@@ -829,6 +915,7 @@
 	struct vf610_adc *info = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
 	regulator_disable(info->vref);
 	clk_disable_unprepare(info->clk);
 
diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c
index ce93bd8..0370624 100644
--- a/drivers/iio/adc/xilinx-xadc-core.c
+++ b/drivers/iio/adc/xilinx-xadc-core.c
@@ -273,33 +273,13 @@
 		schedule_delayed_work(&xadc->zynq_unmask_work,
 				msecs_to_jiffies(XADC_ZYNQ_UNMASK_TIMEOUT));
 	}
-}
 
-static irqreturn_t xadc_zynq_threaded_interrupt_handler(int irq, void *devid)
-{
-	struct iio_dev *indio_dev = devid;
-	struct xadc *xadc = iio_priv(indio_dev);
-	unsigned int alarm;
-
-	spin_lock_irq(&xadc->lock);
-	alarm = xadc->zynq_alarm;
-	xadc->zynq_alarm = 0;
-	spin_unlock_irq(&xadc->lock);
-
-	xadc_handle_events(indio_dev, xadc_zynq_transform_alarm(alarm));
-
-	/* unmask the required interrupts in timer. */
-	schedule_delayed_work(&xadc->zynq_unmask_work,
-			msecs_to_jiffies(XADC_ZYNQ_UNMASK_TIMEOUT));
-
-	return IRQ_HANDLED;
 }
 
 static irqreturn_t xadc_zynq_interrupt_handler(int irq, void *devid)
 {
 	struct iio_dev *indio_dev = devid;
 	struct xadc *xadc = iio_priv(indio_dev);
-	irqreturn_t ret = IRQ_HANDLED;
 	uint32_t status;
 
 	xadc_read_reg(xadc, XADC_ZYNQ_REG_INTSTS, &status);
@@ -321,18 +301,23 @@
 
 	status &= XADC_ZYNQ_INT_ALARM_MASK;
 	if (status) {
-		xadc->zynq_alarm |= status;
 		xadc->zynq_masked_alarm |= status;
 		/*
 		 * mask the current event interrupt,
 		 * unmask it when the interrupt is no more active.
 		 */
 		xadc_zynq_update_intmsk(xadc, 0, 0);
-		ret = IRQ_WAKE_THREAD;
+
+		xadc_handle_events(indio_dev,
+				xadc_zynq_transform_alarm(status));
+
+		/* unmask the required interrupts in timer. */
+		schedule_delayed_work(&xadc->zynq_unmask_work,
+				msecs_to_jiffies(XADC_ZYNQ_UNMASK_TIMEOUT));
 	}
 	spin_unlock(&xadc->lock);
 
-	return ret;
+	return IRQ_HANDLED;
 }
 
 #define XADC_ZYNQ_TCK_RATE_MAX 50000000
@@ -437,7 +422,6 @@
 	.setup = xadc_zynq_setup,
 	.get_dclk_rate = xadc_zynq_get_dclk_rate,
 	.interrupt_handler = xadc_zynq_interrupt_handler,
-	.threaded_interrupt_handler = xadc_zynq_threaded_interrupt_handler,
 	.update_alarm = xadc_zynq_update_alarm,
 };
 
@@ -1225,9 +1209,8 @@
 	if (ret)
 		goto err_free_samplerate_trigger;
 
-	ret = request_threaded_irq(irq, xadc->ops->interrupt_handler,
-				xadc->ops->threaded_interrupt_handler,
-				0, dev_name(&pdev->dev), indio_dev);
+	ret = request_irq(irq, xadc->ops->interrupt_handler, 0,
+			dev_name(&pdev->dev), indio_dev);
 	if (ret)
 		goto err_clk_disable_unprepare;
 
diff --git a/drivers/iio/adc/xilinx-xadc.h b/drivers/iio/adc/xilinx-xadc.h
index 54adc50..f6f0819 100644
--- a/drivers/iio/adc/xilinx-xadc.h
+++ b/drivers/iio/adc/xilinx-xadc.h
@@ -60,7 +60,6 @@
 
 	enum xadc_external_mux_mode external_mux_mode;
 
-	unsigned int zynq_alarm;
 	unsigned int zynq_masked_alarm;
 	unsigned int zynq_intmask;
 	struct delayed_work zynq_unmask_work;
@@ -79,7 +78,6 @@
 	void (*update_alarm)(struct xadc *, unsigned int);
 	unsigned long (*get_dclk_rate)(struct xadc *);
 	irqreturn_t (*interrupt_handler)(int, void *);
-	irqreturn_t (*threaded_interrupt_handler)(int, void *);
 
 	unsigned int flags;
 };
diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c
index c0d364e..32b82a2 100644
--- a/drivers/iio/amplifiers/ad8366.c
+++ b/drivers/iio/amplifiers/ad8366.c
@@ -195,6 +195,7 @@
 	{"ad8366", 0},
 	{}
 };
+MODULE_DEVICE_TABLE(spi, ad8366_id);
 
 static struct spi_driver ad8366_driver = {
 	.driver = {
diff --git a/drivers/iio/buffer/Kconfig b/drivers/iio/buffer/Kconfig
new file mode 100644
index 0000000..0a7b2fd
--- /dev/null
+++ b/drivers/iio/buffer/Kconfig
@@ -0,0 +1,24 @@
+#
+# Industrial I/O generic buffer implementations
+#
+# When adding new entries keep the list in alphabetical order
+
+config IIO_BUFFER_CB
+	tristate "IIO callback buffer used for push in-kernel interfaces"
+	help
+	  Should be selected by any drivers that do in-kernel push
+	  usage.  That is, those where the data is pushed to the consumer.
+
+config IIO_KFIFO_BUF
+	tristate "Industrial I/O buffering based on kfifo"
+	help
+	  A simple fifo based on kfifo.  Note that this currently provides
+	  no buffer events so it is up to userspace to work out how
+	  often to read from the buffer.
+
+config IIO_TRIGGERED_BUFFER
+	tristate
+	select IIO_TRIGGER
+	select IIO_KFIFO_BUF
+	help
+	  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 0000000..4d193b9
--- /dev/null
+++ b/drivers/iio/buffer/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the industrial I/O buffer implementations
+#
+
+# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_IIO_BUFFER_CB) += industrialio-buffer-cb.o
+obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o
+obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o
diff --git a/drivers/iio/buffer_cb.c b/drivers/iio/buffer/industrialio-buffer-cb.c
similarity index 88%
rename from drivers/iio/buffer_cb.c
rename to drivers/iio/buffer/industrialio-buffer-cb.c
index 1648e6e..323079c3 100644
--- a/drivers/iio/buffer_cb.c
+++ b/drivers/iio/buffer/industrialio-buffer-cb.c
@@ -1,4 +1,12 @@
+/* The industrial I/O callback buffer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/export.h>
@@ -124,3 +132,7 @@
 	return cb_buffer->channels;
 }
 EXPORT_SYMBOL_GPL(iio_channel_cb_get_channels);
+
+MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
+MODULE_DESCRIPTION("Industrial I/O callback buffer");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/industrialio-triggered-buffer.c b/drivers/iio/buffer/industrialio-triggered-buffer.c
similarity index 100%
rename from drivers/iio/industrialio-triggered-buffer.c
rename to drivers/iio/buffer/industrialio-triggered-buffer.c
diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/buffer/kfifo_buf.c
similarity index 100%
rename from drivers/iio/kfifo_buf.c
rename to drivers/iio/buffer/kfifo_buf.c
diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig
new file mode 100644
index 0000000..3061b72
--- /dev/null
+++ b/drivers/iio/chemical/Kconfig
@@ -0,0 +1,15 @@
+#
+# Chemical sensors
+#
+
+menu "Chemical Sensors"
+
+config VZ89X
+	tristate "SGX Sensortech MiCS VZ89X VOC sensor"
+	depends on I2C
+	help
+	  Say Y here to build I2C interface support for the SGX
+	  Sensortech MiCS VZ89X VOC (Volatile Organic Compounds)
+	  sensors
+
+endmenu
diff --git a/drivers/iio/chemical/Makefile b/drivers/iio/chemical/Makefile
new file mode 100644
index 0000000..7292f2d
--- /dev/null
+++ b/drivers/iio/chemical/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for IIO chemical sensors
+#
+
+# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_VZ89X)		+= vz89x.o
diff --git a/drivers/iio/chemical/vz89x.c b/drivers/iio/chemical/vz89x.c
new file mode 100644
index 0000000..b454200
--- /dev/null
+++ b/drivers/iio/chemical/vz89x.c
@@ -0,0 +1,237 @@
+/*
+ * vz89x.c - Support for SGX Sensortech MiCS VZ89X VOC sensors
+ *
+ * Copyright (C) 2015 Matt Ranostay <mranostay@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define VZ89X_REG_MEASUREMENT		0x09
+#define VZ89X_REG_MEASUREMENT_SIZE	6
+
+#define VZ89X_VOC_CO2_IDX		0
+#define VZ89X_VOC_SHORT_IDX		1
+#define VZ89X_VOC_TVOC_IDX		2
+#define VZ89X_VOC_RESISTANCE_IDX	3
+
+struct vz89x_data {
+	struct i2c_client *client;
+	struct mutex lock;
+	unsigned long last_update;
+
+	u8 buffer[VZ89X_REG_MEASUREMENT_SIZE];
+};
+
+static const struct iio_chan_spec vz89x_channels[] = {
+	{
+		.type = IIO_CONCENTRATION,
+		.channel2 = IIO_MOD_CO2,
+		.modified = 1,
+		.info_mask_separate =
+			BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_RAW),
+		.address = VZ89X_VOC_CO2_IDX,
+	},
+	{
+		.type = IIO_CONCENTRATION,
+		.channel2 = IIO_MOD_VOC,
+		.modified = 1,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.address = VZ89X_VOC_SHORT_IDX,
+		.extend_name = "short",
+	},
+	{
+		.type = IIO_CONCENTRATION,
+		.channel2 = IIO_MOD_VOC,
+		.modified = 1,
+		.info_mask_separate =
+			BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_RAW),
+		.address = VZ89X_VOC_TVOC_IDX,
+	},
+	{
+		.type = IIO_RESISTANCE,
+		.info_mask_separate =
+			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+		.address = VZ89X_VOC_RESISTANCE_IDX,
+	},
+};
+
+static IIO_CONST_ATTR(in_concentration_co2_scale, "0.00000698689");
+static IIO_CONST_ATTR(in_concentration_voc_scale, "0.00000000436681223");
+
+static struct attribute *vz89x_attributes[] = {
+	&iio_const_attr_in_concentration_co2_scale.dev_attr.attr,
+	&iio_const_attr_in_concentration_voc_scale.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group vz89x_attrs_group = {
+	.attrs = vz89x_attributes,
+};
+
+static int vz89x_get_measurement(struct vz89x_data *data)
+{
+	int ret;
+	int i;
+
+	/* sensor can only be polled once a second max per datasheet */
+	if (!time_after(jiffies, data->last_update + HZ))
+		return 0;
+
+	ret = i2c_smbus_write_word_data(data->client,
+					VZ89X_REG_MEASUREMENT, 0);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < VZ89X_REG_MEASUREMENT_SIZE; i++) {
+		ret = i2c_smbus_read_byte(data->client);
+		if (ret < 0)
+			return ret;
+		data->buffer[i] = ret;
+	}
+
+	data->last_update = jiffies;
+
+	return 0;
+}
+
+static int vz89x_get_resistance_reading(struct vz89x_data *data)
+{
+	u8 *buf = &data->buffer[VZ89X_VOC_TVOC_IDX];
+
+	return buf[0] | (buf[1] << 8) | (buf[2] << 16);
+}
+
+static int vz89x_read_raw(struct iio_dev *indio_dev,
+			  struct iio_chan_spec const *chan, int *val,
+			  int *val2, long mask)
+{
+	struct vz89x_data *data = iio_priv(indio_dev);
+	int ret = -EINVAL;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		mutex_lock(&data->lock);
+		ret = vz89x_get_measurement(data);
+		mutex_unlock(&data->lock);
+
+		if (ret)
+			return ret;
+
+		switch (chan->address) {
+		case VZ89X_VOC_CO2_IDX:
+		case VZ89X_VOC_SHORT_IDX:
+		case VZ89X_VOC_TVOC_IDX:
+			*val = data->buffer[chan->address];
+			return IIO_VAL_INT;
+		case VZ89X_VOC_RESISTANCE_IDX:
+			*val = vz89x_get_resistance_reading(data);
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		switch (chan->type) {
+		case IIO_RESISTANCE:
+			*val = 10;
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case IIO_CHAN_INFO_OFFSET:
+		switch (chan->address) {
+		case VZ89X_VOC_CO2_IDX:
+			*val = 44;
+			*val2 = 250000;
+			return IIO_VAL_INT_PLUS_MICRO;
+		case VZ89X_VOC_TVOC_IDX:
+			*val = -13;
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	return ret;
+}
+
+static const struct iio_info vz89x_info = {
+	.attrs		= &vz89x_attrs_group,
+	.read_raw	= vz89x_read_raw,
+	.driver_module	= THIS_MODULE,
+};
+
+static int vz89x_probe(struct i2c_client *client,
+		       const struct i2c_device_id *id)
+{
+	struct iio_dev *indio_dev;
+	struct vz89x_data *data;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA |
+				     I2C_FUNC_SMBUS_BYTE))
+		return -ENODEV;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	i2c_set_clientdata(client, indio_dev);
+	data->client = client;
+	data->last_update = jiffies - HZ;
+	mutex_init(&data->lock);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &vz89x_info,
+	indio_dev->name = dev_name(&client->dev);
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	indio_dev->channels = vz89x_channels;
+	indio_dev->num_channels = ARRAY_SIZE(vz89x_channels);
+
+	return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct i2c_device_id vz89x_id[] = {
+	{ "vz89x", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, vz89x_id);
+
+static const struct of_device_id vz89x_dt_ids[] = {
+	{ .compatible = "sgx,vz89x" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, vz89x_dt_ids);
+
+static struct i2c_driver vz89x_driver = {
+	.driver = {
+		.name	= "vz89x",
+		.of_match_table = of_match_ptr(vz89x_dt_ids),
+	},
+	.probe = vz89x_probe,
+	.id_table = vz89x_id,
+};
+module_i2c_driver(vz89x_driver);
+
+MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>");
+MODULE_DESCRIPTION("SGX Sensortech MiCS VZ89X VOC sensors");
+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 2e7fdb5..25258e2 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 @@
 	return err;
 }
 
+int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev,
+				  unsigned reg, unsigned writeval,
+				  unsigned *readval)
+{
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+	u8 readdata;
+	int err;
+
+	if (!readval)
+		return sdata->tf->write_byte(&sdata->tb, sdata->dev,
+					     (u8)reg, (u8)writeval);
+
+	err = sdata->tf->read_byte(&sdata->tb, sdata->dev, (u8)reg, &readdata);
+	if (err < 0)
+		return err;
+
+	*readval = (unsigned)readdata;
+
+	return 0;
+}
+EXPORT_SYMBOL(st_sensors_debugfs_reg_access);
+
 static int st_sensors_match_odr(struct st_sensor_settings *sensor_settings,
 			unsigned int odr, struct st_sensor_odr_avl *odr_out)
 {
diff --git a/drivers/iio/dac/ad7303.c b/drivers/iio/dac/ad7303.c
index fa28100..18a4ad5 100644
--- a/drivers/iio/dac/ad7303.c
+++ b/drivers/iio/dac/ad7303.c
@@ -281,6 +281,12 @@
 	return 0;
 }
 
+static const struct of_device_id ad7303_spi_of_match[] = {
+	{ .compatible = "adi,ad7303", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, ad7303_spi_of_match);
+
 static const struct spi_device_id ad7303_spi_ids[] = {
 	{ "ad7303", 0 },
 	{}
@@ -290,6 +296,7 @@
 static struct spi_driver ad7303_driver = {
 	.driver = {
 		.name = "ad7303",
+		.of_match_table = of_match_ptr(ad7303_spi_of_match),
 		.owner = THIS_MODULE,
 	},
 	.probe = ad7303_probe,
diff --git a/drivers/iio/dac/max5821.c b/drivers/iio/dac/max5821.c
index 28b8748..86e9e11 100644
--- a/drivers/iio/dac/max5821.c
+++ b/drivers/iio/dac/max5821.c
@@ -387,6 +387,7 @@
 	{ .compatible = "maxim,max5821" },
 	{ }
 };
+MODULE_DEVICE_TABLE(of, max5821_of_match);
 
 static struct i2c_driver max5821_driver = {
 	.driver = {
diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c
index 9890c81..73f27e0 100644
--- a/drivers/iio/frequency/adf4350.c
+++ b/drivers/iio/frequency/adf4350.c
@@ -616,15 +616,24 @@
 	return 0;
 }
 
+static const struct of_device_id adf4350_of_match[] = {
+	{ .compatible = "adi,adf4350", },
+	{ .compatible = "adi,adf4351", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, adf4350_of_match);
+
 static const struct spi_device_id adf4350_id[] = {
 	{"adf4350", 4350},
 	{"adf4351", 4351},
 	{}
 };
+MODULE_DEVICE_TABLE(spi, adf4350_id);
 
 static struct spi_driver adf4350_driver = {
 	.driver = {
 		.name	= "adf4350",
+		.of_match_table = of_match_ptr(adf4350_of_match),
 		.owner	= THIS_MODULE,
 	},
 	.probe		= adf4350_probe,
diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig
index 8d24393..e816d29 100644
--- a/drivers/iio/gyro/Kconfig
+++ b/drivers/iio/gyro/Kconfig
@@ -52,15 +52,26 @@
 
 config BMG160
 	tristate "BOSCH BMG160 Gyro Sensor"
-	depends on I2C
+	depends on (I2C || SPI_MASTER)
 	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
+	select BMG160_I2C if (I2C)
+	select BMG160_SPI if (SPI)
 	help
-	  Say yes here to build support for Bosch BMG160 Tri-axis Gyro Sensor
-	  driver. This driver also supports BMI055 gyroscope.
+	  Say yes here to build support for BOSCH BMG160 Tri-axis Gyro Sensor
+	  driver connected via I2C or SPI. This driver also supports BMI055
+	  gyroscope.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called bmg160.
+	  will be called bmg160_i2c or bmg160_spi.
+
+config BMG160_I2C
+	tristate
+	select REGMAP_I2C
+
+config BMG160_SPI
+	tristate
+	select REGMAP_SPI
 
 config HID_SENSOR_GYRO_3D
 	depends on HID_SENSOR_HUB
diff --git a/drivers/iio/gyro/Makefile b/drivers/iio/gyro/Makefile
index f46341b3..f866a4be 100644
--- a/drivers/iio/gyro/Makefile
+++ b/drivers/iio/gyro/Makefile
@@ -8,7 +8,9 @@
 obj-$(CONFIG_ADIS16136) += adis16136.o
 obj-$(CONFIG_ADIS16260) += adis16260.o
 obj-$(CONFIG_ADXRS450) += adxrs450.o
-obj-$(CONFIG_BMG160) += bmg160.o
+obj-$(CONFIG_BMG160) += bmg160_core.o
+obj-$(CONFIG_BMG160_I2C) += bmg160_i2c.o
+obj-$(CONFIG_BMG160_SPI) += bmg160_spi.o
 
 obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o
 
diff --git a/drivers/iio/gyro/bmg160.h b/drivers/iio/gyro/bmg160.h
new file mode 100644
index 0000000..72db723
--- /dev/null
+++ b/drivers/iio/gyro/bmg160.h
@@ -0,0 +1,10 @@
+#ifndef BMG160_H_
+#define BMG160_H_
+
+extern const struct dev_pm_ops bmg160_pm_ops;
+
+int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
+		      const char *name);
+void bmg160_core_remove(struct device *dev);
+
+#endif  /* BMG160_H_ */
diff --git a/drivers/iio/gyro/bmg160.c b/drivers/iio/gyro/bmg160_core.c
similarity index 75%
rename from drivers/iio/gyro/bmg160.c
rename to drivers/iio/gyro/bmg160_core.c
index 460bf71..02ff789 100644
--- a/drivers/iio/gyro/bmg160.c
+++ b/drivers/iio/gyro/bmg160_core.c
@@ -13,7 +13,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
@@ -28,8 +27,9 @@
 #include <linux/iio/events.h>
 #include <linux/iio/trigger_consumer.h>
 #include <linux/iio/triggered_buffer.h>
+#include <linux/regmap.h>
+#include "bmg160.h"
 
-#define BMG160_DRV_NAME		"bmg160"
 #define BMG160_IRQ_NAME		"bmg160_event"
 #define BMG160_GPIO_NAME		"gpio_int"
 
@@ -97,7 +97,8 @@
 #define BMG160_AUTO_SUSPEND_DELAY_MS	2000
 
 struct bmg160_data {
-	struct i2c_client *client;
+	struct device *dev;
+	struct regmap *regmap;
 	struct iio_trigger *dready_trig;
 	struct iio_trigger *motion_trig;
 	struct mutex mutex;
@@ -108,6 +109,7 @@
 	int slope_thres;
 	bool dready_trigger_on;
 	bool motion_trigger_on;
+	int irq;
 };
 
 enum bmg160_axis {
@@ -138,10 +140,9 @@
 {
 	int ret;
 
-	ret = i2c_smbus_write_byte_data(data->client,
-					BMG160_REG_PMU_LPW, mode);
+	ret = regmap_write(data->regmap, BMG160_REG_PMU_LPW, mode);
 	if (ret < 0) {
-		dev_err(&data->client->dev, "Error writing reg_pmu_lpw\n");
+		dev_err(data->dev, "Error writing reg_pmu_lpw\n");
 		return ret;
 	}
 
@@ -169,10 +170,9 @@
 	if (bw_bits < 0)
 		return bw_bits;
 
-	ret = i2c_smbus_write_byte_data(data->client, BMG160_REG_PMU_BW,
-					bw_bits);
+	ret = regmap_write(data->regmap, BMG160_REG_PMU_BW, bw_bits);
 	if (ret < 0) {
-		dev_err(&data->client->dev, "Error writing reg_pmu_bw\n");
+		dev_err(data->dev, "Error writing reg_pmu_bw\n");
 		return ret;
 	}
 
@@ -184,16 +184,17 @@
 static int bmg160_chip_init(struct bmg160_data *data)
 {
 	int ret;
+	unsigned int val;
 
-	ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_CHIP_ID);
+	ret = regmap_read(data->regmap, BMG160_REG_CHIP_ID, &val);
 	if (ret < 0) {
-		dev_err(&data->client->dev, "Error reading reg_chip_id\n");
+		dev_err(data->dev, "Error reading reg_chip_id\n");
 		return ret;
 	}
 
-	dev_dbg(&data->client->dev, "Chip Id %x\n", ret);
-	if (ret != BMG160_CHIP_ID_VAL) {
-		dev_err(&data->client->dev, "invalid chip %x\n", ret);
+	dev_dbg(data->dev, "Chip Id %x\n", val);
+	if (val != BMG160_CHIP_ID_VAL) {
+		dev_err(data->dev, "invalid chip %x\n", val);
 		return -ENODEV;
 	}
 
@@ -210,42 +211,33 @@
 		return ret;
 
 	/* Set Default Range */
-	ret = i2c_smbus_write_byte_data(data->client,
-					BMG160_REG_RANGE,
-					BMG160_RANGE_500DPS);
+	ret = regmap_write(data->regmap, BMG160_REG_RANGE, BMG160_RANGE_500DPS);
 	if (ret < 0) {
-		dev_err(&data->client->dev, "Error writing reg_range\n");
+		dev_err(data->dev, "Error writing reg_range\n");
 		return ret;
 	}
 	data->dps_range = BMG160_RANGE_500DPS;
 
-	ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_SLOPE_THRES);
+	ret = regmap_read(data->regmap, BMG160_REG_SLOPE_THRES, &val);
 	if (ret < 0) {
-		dev_err(&data->client->dev, "Error reading reg_slope_thres\n");
+		dev_err(data->dev, "Error reading reg_slope_thres\n");
 		return ret;
 	}
-	data->slope_thres = ret;
+	data->slope_thres = val;
 
 	/* Set default interrupt mode */
-	ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_INT_EN_1);
+	ret = regmap_update_bits(data->regmap, BMG160_REG_INT_EN_1,
+				 BMG160_INT1_BIT_OD, 0);
 	if (ret < 0) {
-		dev_err(&data->client->dev, "Error reading reg_int_en_1\n");
-		return ret;
-	}
-	ret &= ~BMG160_INT1_BIT_OD;
-	ret = i2c_smbus_write_byte_data(data->client,
-					BMG160_REG_INT_EN_1, ret);
-	if (ret < 0) {
-		dev_err(&data->client->dev, "Error writing reg_int_en_1\n");
+		dev_err(data->dev, "Error updating bits in reg_int_en_1\n");
 		return ret;
 	}
 
-	ret = i2c_smbus_write_byte_data(data->client,
-					BMG160_REG_INT_RST_LATCH,
-					BMG160_INT_MODE_LATCH_INT |
-					BMG160_INT_MODE_LATCH_RESET);
+	ret = regmap_write(data->regmap, BMG160_REG_INT_RST_LATCH,
+			   BMG160_INT_MODE_LATCH_INT |
+			   BMG160_INT_MODE_LATCH_RESET);
 	if (ret < 0) {
-		dev_err(&data->client->dev,
+		dev_err(data->dev,
 			"Error writing reg_motion_intr\n");
 		return ret;
 	}
@@ -259,17 +251,17 @@
 	int ret;
 
 	if (on)
-		ret = pm_runtime_get_sync(&data->client->dev);
+		ret = pm_runtime_get_sync(data->dev);
 	else {
-		pm_runtime_mark_last_busy(&data->client->dev);
-		ret = pm_runtime_put_autosuspend(&data->client->dev);
+		pm_runtime_mark_last_busy(data->dev);
+		ret = pm_runtime_put_autosuspend(data->dev);
 	}
 
 	if (ret < 0) {
-		dev_err(&data->client->dev,
+		dev_err(data->dev,
 			"Failed: bmg160_set_power_state for %d\n", on);
 		if (on)
-			pm_runtime_put_noidle(&data->client->dev);
+			pm_runtime_put_noidle(data->dev);
 
 		return ret;
 	}
@@ -284,43 +276,30 @@
 	int ret;
 
 	/* Enable/Disable INT_MAP0 mapping */
-	ret = i2c_smbus_read_byte_data(data->client,  BMG160_REG_INT_MAP_0);
+	ret = regmap_update_bits(data->regmap, BMG160_REG_INT_MAP_0,
+				 BMG160_INT_MAP_0_BIT_ANY,
+				 (status ? BMG160_INT_MAP_0_BIT_ANY : 0));
 	if (ret < 0) {
-		dev_err(&data->client->dev, "Error reading reg_int_map0\n");
-		return ret;
-	}
-	if (status)
-		ret |= BMG160_INT_MAP_0_BIT_ANY;
-	else
-		ret &= ~BMG160_INT_MAP_0_BIT_ANY;
-
-	ret = i2c_smbus_write_byte_data(data->client,
-					BMG160_REG_INT_MAP_0,
-					ret);
-	if (ret < 0) {
-		dev_err(&data->client->dev, "Error writing reg_int_map0\n");
+		dev_err(data->dev, "Error updating bits reg_int_map0\n");
 		return ret;
 	}
 
 	/* Enable/Disable slope interrupts */
 	if (status) {
 		/* Update slope thres */
-		ret = i2c_smbus_write_byte_data(data->client,
-						BMG160_REG_SLOPE_THRES,
-						data->slope_thres);
+		ret = regmap_write(data->regmap, BMG160_REG_SLOPE_THRES,
+				   data->slope_thres);
 		if (ret < 0) {
-			dev_err(&data->client->dev,
+			dev_err(data->dev,
 				"Error writing reg_slope_thres\n");
 			return ret;
 		}
 
-		ret = i2c_smbus_write_byte_data(data->client,
-						BMG160_REG_MOTION_INTR,
-						BMG160_INT_MOTION_X |
-						BMG160_INT_MOTION_Y |
-						BMG160_INT_MOTION_Z);
+		ret = regmap_write(data->regmap, BMG160_REG_MOTION_INTR,
+				   BMG160_INT_MOTION_X | BMG160_INT_MOTION_Y |
+				   BMG160_INT_MOTION_Z);
 		if (ret < 0) {
-			dev_err(&data->client->dev,
+			dev_err(data->dev,
 				"Error writing reg_motion_intr\n");
 			return ret;
 		}
@@ -331,28 +310,26 @@
 		 * to set latched mode, we will be flooded anyway with INTR
 		 */
 		if (!data->dready_trigger_on) {
-			ret = i2c_smbus_write_byte_data(data->client,
-						BMG160_REG_INT_RST_LATCH,
-						BMG160_INT_MODE_LATCH_INT |
-						BMG160_INT_MODE_LATCH_RESET);
+			ret = regmap_write(data->regmap,
+					   BMG160_REG_INT_RST_LATCH,
+					   BMG160_INT_MODE_LATCH_INT |
+					   BMG160_INT_MODE_LATCH_RESET);
 			if (ret < 0) {
-				dev_err(&data->client->dev,
+				dev_err(data->dev,
 					"Error writing reg_rst_latch\n");
 				return ret;
 			}
 		}
 
-		ret = i2c_smbus_write_byte_data(data->client,
-						BMG160_REG_INT_EN_0,
-						BMG160_DATA_ENABLE_INT);
+		ret = regmap_write(data->regmap, BMG160_REG_INT_EN_0,
+				   BMG160_DATA_ENABLE_INT);
 
-	} else
-		ret = i2c_smbus_write_byte_data(data->client,
-						BMG160_REG_INT_EN_0,
-						0);
+	} else {
+		ret = regmap_write(data->regmap, BMG160_REG_INT_EN_0, 0);
+	}
 
 	if (ret < 0) {
-		dev_err(&data->client->dev, "Error writing reg_int_en0\n");
+		dev_err(data->dev, "Error writing reg_int_en0\n");
 		return ret;
 	}
 
@@ -365,59 +342,43 @@
 	int ret;
 
 	/* Enable/Disable INT_MAP1 mapping */
-	ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_INT_MAP_1);
+	ret = regmap_update_bits(data->regmap, BMG160_REG_INT_MAP_1,
+				 BMG160_INT_MAP_1_BIT_NEW_DATA,
+				 (status ? BMG160_INT_MAP_1_BIT_NEW_DATA : 0));
 	if (ret < 0) {
-		dev_err(&data->client->dev, "Error reading reg_int_map1\n");
-		return ret;
-	}
-
-	if (status)
-		ret |= BMG160_INT_MAP_1_BIT_NEW_DATA;
-	else
-		ret &= ~BMG160_INT_MAP_1_BIT_NEW_DATA;
-
-	ret = i2c_smbus_write_byte_data(data->client,
-					BMG160_REG_INT_MAP_1,
-					ret);
-	if (ret < 0) {
-		dev_err(&data->client->dev, "Error writing reg_int_map1\n");
+		dev_err(data->dev, "Error updating bits in reg_int_map1\n");
 		return ret;
 	}
 
 	if (status) {
-		ret = i2c_smbus_write_byte_data(data->client,
-						BMG160_REG_INT_RST_LATCH,
-						BMG160_INT_MODE_NON_LATCH_INT |
-						BMG160_INT_MODE_LATCH_RESET);
+		ret = regmap_write(data->regmap, BMG160_REG_INT_RST_LATCH,
+				   BMG160_INT_MODE_NON_LATCH_INT |
+				   BMG160_INT_MODE_LATCH_RESET);
 		if (ret < 0) {
-			dev_err(&data->client->dev,
+			dev_err(data->dev,
 				"Error writing reg_rst_latch\n");
 				return ret;
 		}
 
-		ret = i2c_smbus_write_byte_data(data->client,
-						BMG160_REG_INT_EN_0,
-						BMG160_DATA_ENABLE_INT);
+		ret = regmap_write(data->regmap, BMG160_REG_INT_EN_0,
+				   BMG160_DATA_ENABLE_INT);
 
 	} else {
 		/* Restore interrupt mode */
-		ret = i2c_smbus_write_byte_data(data->client,
-						BMG160_REG_INT_RST_LATCH,
-						BMG160_INT_MODE_LATCH_INT |
-						BMG160_INT_MODE_LATCH_RESET);
+		ret = regmap_write(data->regmap, BMG160_REG_INT_RST_LATCH,
+				   BMG160_INT_MODE_LATCH_INT |
+				   BMG160_INT_MODE_LATCH_RESET);
 		if (ret < 0) {
-			dev_err(&data->client->dev,
+			dev_err(data->dev,
 				"Error writing reg_rst_latch\n");
 				return ret;
 		}
 
-		ret = i2c_smbus_write_byte_data(data->client,
-						BMG160_REG_INT_EN_0,
-						0);
+		ret = regmap_write(data->regmap, BMG160_REG_INT_EN_0, 0);
 	}
 
 	if (ret < 0) {
-		dev_err(&data->client->dev, "Error writing reg_int_en0\n");
+		dev_err(data->dev, "Error writing reg_int_en0\n");
 		return ret;
 	}
 
@@ -444,12 +405,10 @@
 
 	for (i = 0; i < ARRAY_SIZE(bmg160_scale_table); ++i) {
 		if (bmg160_scale_table[i].scale == val) {
-			ret = i2c_smbus_write_byte_data(
-					data->client,
-					BMG160_REG_RANGE,
-					bmg160_scale_table[i].dps_range);
+			ret = regmap_write(data->regmap, BMG160_REG_RANGE,
+					   bmg160_scale_table[i].dps_range);
 			if (ret < 0) {
-				dev_err(&data->client->dev,
+				dev_err(data->dev,
 					"Error writing reg_range\n");
 				return ret;
 			}
@@ -464,6 +423,7 @@
 static int bmg160_get_temp(struct bmg160_data *data, int *val)
 {
 	int ret;
+	unsigned int raw_val;
 
 	mutex_lock(&data->mutex);
 	ret = bmg160_set_power_state(data, true);
@@ -472,15 +432,15 @@
 		return ret;
 	}
 
-	ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_TEMP);
+	ret = regmap_read(data->regmap, BMG160_REG_TEMP, &raw_val);
 	if (ret < 0) {
-		dev_err(&data->client->dev, "Error reading reg_temp\n");
+		dev_err(data->dev, "Error reading reg_temp\n");
 		bmg160_set_power_state(data, false);
 		mutex_unlock(&data->mutex);
 		return ret;
 	}
 
-	*val = sign_extend32(ret, 7);
+	*val = sign_extend32(raw_val, 7);
 	ret = bmg160_set_power_state(data, false);
 	mutex_unlock(&data->mutex);
 	if (ret < 0)
@@ -492,6 +452,7 @@
 static int bmg160_get_axis(struct bmg160_data *data, int axis, int *val)
 {
 	int ret;
+	unsigned int raw_val;
 
 	mutex_lock(&data->mutex);
 	ret = bmg160_set_power_state(data, true);
@@ -500,15 +461,16 @@
 		return ret;
 	}
 
-	ret = i2c_smbus_read_word_data(data->client, BMG160_AXIS_TO_REG(axis));
+	ret = regmap_bulk_read(data->regmap, BMG160_AXIS_TO_REG(axis), &raw_val,
+			       2);
 	if (ret < 0) {
-		dev_err(&data->client->dev, "Error reading axis %d\n", axis);
+		dev_err(data->dev, "Error reading axis %d\n", axis);
 		bmg160_set_power_state(data, false);
 		mutex_unlock(&data->mutex);
 		return ret;
 	}
 
-	*val = sign_extend32(ret, 15);
+	*val = sign_extend32(raw_val, 15);
 	ret = bmg160_set_power_state(data, false);
 	mutex_unlock(&data->mutex);
 	if (ret < 0)
@@ -807,12 +769,13 @@
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct bmg160_data *data = iio_priv(indio_dev);
 	int bit, ret, i = 0;
+	unsigned int val;
 
 	mutex_lock(&data->mutex);
 	for_each_set_bit(bit, indio_dev->active_scan_mask,
 			 indio_dev->masklength) {
-		ret = i2c_smbus_read_word_data(data->client,
-					       BMG160_AXIS_TO_REG(bit));
+		ret = regmap_bulk_read(data->regmap, BMG160_AXIS_TO_REG(bit),
+				       &val, 2);
 		if (ret < 0) {
 			mutex_unlock(&data->mutex);
 			goto err;
@@ -840,12 +803,11 @@
 		return 0;
 
 	/* Set latched mode interrupt and clear any latched interrupt */
-	ret = i2c_smbus_write_byte_data(data->client,
-					BMG160_REG_INT_RST_LATCH,
-					BMG160_INT_MODE_LATCH_INT |
-					BMG160_INT_MODE_LATCH_RESET);
+	ret = regmap_write(data->regmap, BMG160_REG_INT_RST_LATCH,
+			   BMG160_INT_MODE_LATCH_INT |
+			   BMG160_INT_MODE_LATCH_RESET);
 	if (ret < 0) {
-		dev_err(&data->client->dev, "Error writing reg_rst_latch\n");
+		dev_err(data->dev, "Error writing reg_rst_latch\n");
 		return ret;
 	}
 
@@ -907,33 +869,34 @@
 	struct bmg160_data *data = iio_priv(indio_dev);
 	int ret;
 	int dir;
+	unsigned int val;
 
-	ret = i2c_smbus_read_byte_data(data->client, BMG160_REG_INT_STATUS_2);
+	ret = regmap_read(data->regmap, BMG160_REG_INT_STATUS_2, &val);
 	if (ret < 0) {
-		dev_err(&data->client->dev, "Error reading reg_int_status2\n");
+		dev_err(data->dev, "Error reading reg_int_status2\n");
 		goto ack_intr_status;
 	}
 
-	if (ret & 0x08)
+	if (val & 0x08)
 		dir = IIO_EV_DIR_RISING;
 	else
 		dir = IIO_EV_DIR_FALLING;
 
-	if (ret & BMG160_ANY_MOTION_BIT_X)
+	if (val & BMG160_ANY_MOTION_BIT_X)
 		iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL,
 							0,
 							IIO_MOD_X,
 							IIO_EV_TYPE_ROC,
 							dir),
 							iio_get_time_ns());
-	if (ret & BMG160_ANY_MOTION_BIT_Y)
+	if (val & BMG160_ANY_MOTION_BIT_Y)
 		iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL,
 							0,
 							IIO_MOD_Y,
 							IIO_EV_TYPE_ROC,
 							dir),
 							iio_get_time_ns());
-	if (ret & BMG160_ANY_MOTION_BIT_Z)
+	if (val & BMG160_ANY_MOTION_BIT_Z)
 		iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL,
 							0,
 							IIO_MOD_Z,
@@ -943,12 +906,11 @@
 
 ack_intr_status:
 	if (!data->dready_trigger_on) {
-		ret = i2c_smbus_write_byte_data(data->client,
-					BMG160_REG_INT_RST_LATCH,
-					BMG160_INT_MODE_LATCH_INT |
-					BMG160_INT_MODE_LATCH_RESET);
+		ret = regmap_write(data->regmap, BMG160_REG_INT_RST_LATCH,
+				   BMG160_INT_MODE_LATCH_INT |
+				   BMG160_INT_MODE_LATCH_RESET);
 		if (ret < 0)
-			dev_err(&data->client->dev,
+			dev_err(data->dev,
 				"Error writing reg_rst_latch\n");
 	}
 
@@ -993,18 +955,13 @@
 	.postdisable = bmg160_buffer_postdisable,
 };
 
-static int bmg160_gpio_probe(struct i2c_client *client,
-			     struct bmg160_data *data)
+static int bmg160_gpio_probe(struct bmg160_data *data)
 
 {
 	struct device *dev;
 	struct gpio_desc *gpio;
-	int ret;
 
-	if (!client)
-		return -EINVAL;
-
-	dev = &client->dev;
+	dev = data->dev;
 
 	/* data ready gpio interrupt pin */
 	gpio = devm_gpiod_get_index(dev, BMG160_GPIO_NAME, 0, GPIOD_IN);
@@ -1013,11 +970,12 @@
 		return PTR_ERR(gpio);
 	}
 
-	ret = gpiod_to_irq(gpio);
+	data->irq = gpiod_to_irq(gpio);
 
-	dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
+	dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio),
+		data->irq);
 
-	return ret;
+	return 0;
 }
 
 static const char *bmg160_match_acpi_device(struct device *dev)
@@ -1031,21 +989,22 @@
 	return dev_name(dev);
 }
 
-static int bmg160_probe(struct i2c_client *client,
-			const struct i2c_device_id *id)
+int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
+		      const char *name)
 {
 	struct bmg160_data *data;
 	struct iio_dev *indio_dev;
 	int ret;
-	const char *name = NULL;
 
-	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
 	if (!indio_dev)
 		return -ENOMEM;
 
 	data = iio_priv(indio_dev);
-	i2c_set_clientdata(client, indio_dev);
-	data->client = client;
+	dev_set_drvdata(dev, indio_dev);
+	data->dev = dev;
+	data->irq = irq;
+	data->regmap = regmap;
 
 	ret = bmg160_chip_init(data);
 	if (ret < 0)
@@ -1053,25 +1012,22 @@
 
 	mutex_init(&data->mutex);
 
-	if (id)
-		name = id->name;
+	if (ACPI_HANDLE(dev))
+		name = bmg160_match_acpi_device(dev);
 
-	if (ACPI_HANDLE(&client->dev))
-		name = bmg160_match_acpi_device(&client->dev);
-
-	indio_dev->dev.parent = &client->dev;
+	indio_dev->dev.parent = dev;
 	indio_dev->channels = bmg160_channels;
 	indio_dev->num_channels = ARRAY_SIZE(bmg160_channels);
 	indio_dev->name = name;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &bmg160_info;
 
-	if (client->irq <= 0)
-		client->irq = bmg160_gpio_probe(client, data);
+	if (data->irq <= 0)
+		bmg160_gpio_probe(data);
 
-	if (client->irq > 0) {
-		ret = devm_request_threaded_irq(&client->dev,
-						client->irq,
+	if (data->irq > 0) {
+		ret = devm_request_threaded_irq(dev,
+						data->irq,
 						bmg160_data_rdy_trig_poll,
 						bmg160_event_handler,
 						IRQF_TRIGGER_RISING,
@@ -1080,28 +1036,28 @@
 		if (ret)
 			return ret;
 
-		data->dready_trig = devm_iio_trigger_alloc(&client->dev,
+		data->dready_trig = devm_iio_trigger_alloc(dev,
 							   "%s-dev%d",
 							   indio_dev->name,
 							   indio_dev->id);
 		if (!data->dready_trig)
 			return -ENOMEM;
 
-		data->motion_trig = devm_iio_trigger_alloc(&client->dev,
+		data->motion_trig = devm_iio_trigger_alloc(dev,
 							  "%s-any-motion-dev%d",
 							  indio_dev->name,
 							  indio_dev->id);
 		if (!data->motion_trig)
 			return -ENOMEM;
 
-		data->dready_trig->dev.parent = &client->dev;
+		data->dready_trig->dev.parent = dev;
 		data->dready_trig->ops = &bmg160_trigger_ops;
 		iio_trigger_set_drvdata(data->dready_trig, indio_dev);
 		ret = iio_trigger_register(data->dready_trig);
 		if (ret)
 			return ret;
 
-		data->motion_trig->dev.parent = &client->dev;
+		data->motion_trig->dev.parent = dev;
 		data->motion_trig->ops = &bmg160_trigger_ops;
 		iio_trigger_set_drvdata(data->motion_trig, indio_dev);
 		ret = iio_trigger_register(data->motion_trig);
@@ -1116,25 +1072,25 @@
 					 bmg160_trigger_handler,
 					 &bmg160_buffer_setup_ops);
 	if (ret < 0) {
-		dev_err(&client->dev,
+		dev_err(dev,
 			"iio triggered buffer setup failed\n");
 		goto err_trigger_unregister;
 	}
 
 	ret = iio_device_register(indio_dev);
 	if (ret < 0) {
-		dev_err(&client->dev, "unable to register iio device\n");
+		dev_err(dev, "unable to register iio device\n");
 		goto err_buffer_cleanup;
 	}
 
-	ret = pm_runtime_set_active(&client->dev);
+	ret = pm_runtime_set_active(dev);
 	if (ret)
 		goto err_iio_unregister;
 
-	pm_runtime_enable(&client->dev);
-	pm_runtime_set_autosuspend_delay(&client->dev,
+	pm_runtime_enable(dev);
+	pm_runtime_set_autosuspend_delay(dev,
 					 BMG160_AUTO_SUSPEND_DELAY_MS);
-	pm_runtime_use_autosuspend(&client->dev);
+	pm_runtime_use_autosuspend(dev);
 
 	return 0;
 
@@ -1150,15 +1106,16 @@
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(bmg160_core_probe);
 
-static int bmg160_remove(struct i2c_client *client)
+void bmg160_core_remove(struct device *dev)
 {
-	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct bmg160_data *data = iio_priv(indio_dev);
 
-	pm_runtime_disable(&client->dev);
-	pm_runtime_set_suspended(&client->dev);
-	pm_runtime_put_noidle(&client->dev);
+	pm_runtime_disable(dev);
+	pm_runtime_set_suspended(dev);
+	pm_runtime_put_noidle(dev);
 
 	iio_device_unregister(indio_dev);
 	iio_triggered_buffer_cleanup(indio_dev);
@@ -1171,14 +1128,13 @@
 	mutex_lock(&data->mutex);
 	bmg160_set_mode(data, BMG160_MODE_DEEP_SUSPEND);
 	mutex_unlock(&data->mutex);
-
-	return 0;
 }
+EXPORT_SYMBOL_GPL(bmg160_core_remove);
 
 #ifdef CONFIG_PM_SLEEP
 static int bmg160_suspend(struct device *dev)
 {
-	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct bmg160_data *data = iio_priv(indio_dev);
 
 	mutex_lock(&data->mutex);
@@ -1190,7 +1146,7 @@
 
 static int bmg160_resume(struct device *dev)
 {
-	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct bmg160_data *data = iio_priv(indio_dev);
 
 	mutex_lock(&data->mutex);
@@ -1206,13 +1162,13 @@
 #ifdef CONFIG_PM
 static int bmg160_runtime_suspend(struct device *dev)
 {
-	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct bmg160_data *data = iio_priv(indio_dev);
 	int ret;
 
 	ret = bmg160_set_mode(data, BMG160_MODE_SUSPEND);
 	if (ret < 0) {
-		dev_err(&data->client->dev, "set mode failed\n");
+		dev_err(data->dev, "set mode failed\n");
 		return -EAGAIN;
 	}
 
@@ -1221,7 +1177,7 @@
 
 static int bmg160_runtime_resume(struct device *dev)
 {
-	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct bmg160_data *data = iio_priv(indio_dev);
 	int ret;
 
@@ -1235,39 +1191,12 @@
 }
 #endif
 
-static const struct dev_pm_ops bmg160_pm_ops = {
+const struct dev_pm_ops bmg160_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(bmg160_suspend, bmg160_resume)
 	SET_RUNTIME_PM_OPS(bmg160_runtime_suspend,
 			   bmg160_runtime_resume, NULL)
 };
-
-static const struct acpi_device_id bmg160_acpi_match[] = {
-	{"BMG0160", 0},
-	{"BMI055B", 0},
-	{},
-};
-
-MODULE_DEVICE_TABLE(acpi, bmg160_acpi_match);
-
-static const struct i2c_device_id bmg160_id[] = {
-	{"bmg160", 0},
-	{"bmi055_gyro", 0},
-	{}
-};
-
-MODULE_DEVICE_TABLE(i2c, bmg160_id);
-
-static struct i2c_driver bmg160_driver = {
-	.driver = {
-		.name	= BMG160_DRV_NAME,
-		.acpi_match_table = ACPI_PTR(bmg160_acpi_match),
-		.pm	= &bmg160_pm_ops,
-	},
-	.probe		= bmg160_probe,
-	.remove		= bmg160_remove,
-	.id_table	= bmg160_id,
-};
-module_i2c_driver(bmg160_driver);
+EXPORT_SYMBOL_GPL(bmg160_pm_ops);
 
 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
 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 0000000..90126a5
--- /dev/null
+++ b/drivers/iio/gyro/bmg160_i2c.c
@@ -0,0 +1,71 @@
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/acpi.h>
+
+#include "bmg160.h"
+
+static const struct regmap_config bmg160_regmap_i2c_conf = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = 0x3f
+};
+
+static int bmg160_i2c_probe(struct i2c_client *client,
+			    const struct i2c_device_id *id)
+{
+	struct regmap *regmap;
+	const char *name = NULL;
+
+	regmap = devm_regmap_init_i2c(client, &bmg160_regmap_i2c_conf);
+	if (IS_ERR(regmap)) {
+		dev_err(&client->dev, "Failed to register i2c regmap %d\n",
+			(int)PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+
+	if (id)
+		name = id->name;
+
+	return bmg160_core_probe(&client->dev, regmap, client->irq, name);
+}
+
+static int bmg160_i2c_remove(struct i2c_client *client)
+{
+	bmg160_core_remove(&client->dev);
+
+	return 0;
+}
+
+static const struct acpi_device_id bmg160_acpi_match[] = {
+	{"BMG0160", 0},
+	{"BMI055B", 0},
+	{},
+};
+
+MODULE_DEVICE_TABLE(acpi, bmg160_acpi_match);
+
+static const struct i2c_device_id bmg160_i2c_id[] = {
+	{"bmg160", 0},
+	{"bmi055_gyro", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, bmg160_i2c_id);
+
+static struct i2c_driver bmg160_i2c_driver = {
+	.driver = {
+		.name	= "bmg160_i2c",
+		.acpi_match_table = ACPI_PTR(bmg160_acpi_match),
+		.pm	= &bmg160_pm_ops,
+	},
+	.probe		= bmg160_i2c_probe,
+	.remove		= bmg160_i2c_remove,
+	.id_table	= bmg160_i2c_id,
+};
+module_i2c_driver(bmg160_i2c_driver);
+
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
+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 0000000..021ea5f
--- /dev/null
+++ b/drivers/iio/gyro/bmg160_spi.c
@@ -0,0 +1,57 @@
+#include <linux/spi/spi.h>
+#include <linux/regmap.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+
+#include "bmg160.h"
+
+static const struct regmap_config bmg160_regmap_spi_conf = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = 0x3f,
+};
+
+static int bmg160_spi_probe(struct spi_device *spi)
+{
+	struct regmap *regmap;
+	const struct spi_device_id *id = spi_get_device_id(spi);
+
+	regmap = devm_regmap_init_spi(spi, &bmg160_regmap_spi_conf);
+	if (IS_ERR(regmap)) {
+		dev_err(&spi->dev, "Failed to register spi regmap %d\n",
+			(int)PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+
+	return bmg160_core_probe(&spi->dev, regmap, spi->irq, id->name);
+}
+
+static int bmg160_spi_remove(struct spi_device *spi)
+{
+	bmg160_core_remove(&spi->dev);
+
+	return 0;
+}
+
+static const struct spi_device_id bmg160_spi_id[] = {
+	{"bmg160", 0},
+	{"bmi055_gyro", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(spi, bmg160_spi_id);
+
+static struct spi_driver bmg160_spi_driver = {
+	.driver = {
+		.name	= "bmg160_spi",
+		.pm	= &bmg160_pm_ops,
+	},
+	.probe		= bmg160_spi_probe,
+	.remove		= bmg160_spi_remove,
+	.id_table	= bmg160_spi_id,
+};
+module_spi_driver(bmg160_spi_driver);
+
+MODULE_AUTHOR("Markus Pargmann <mpa@pengutronix.de>");
+MODULE_LICENSE("GPL v2");
+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 4b993a5..02eddce 100644
--- a/drivers/iio/gyro/st_gyro_core.c
+++ b/drivers/iio/gyro/st_gyro_core.c
@@ -383,6 +383,7 @@
 	.attrs = &st_gyro_attribute_group,
 	.read_raw = &st_gyro_read_raw,
 	.write_raw = &st_gyro_write_raw,
+	.debugfs_reg_access = &st_sensors_debugfs_reg_access,
 };
 
 #ifdef CONFIG_IIO_TRIGGER
diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig
index 688c0d1..353ee9a 100644
--- a/drivers/iio/humidity/Kconfig
+++ b/drivers/iio/humidity/Kconfig
@@ -12,6 +12,16 @@
 	  Other sensors should work as well as long as they speak the
 	  same protocol.
 
+config HDC100X
+	tristate "TI HDC100x relative humidity and temperature sensor"
+	depends on I2C
+	help
+	 Say yes here to build support for the TI HDC100x series of
+	 relative humidity and temperature sensors.
+
+	 To compile this driver as a module, choose M here: the module
+	 will be called hdc100x.
+
 config SI7005
 	tristate "SI7005 relative humidity and temperature sensor"
 	depends on I2C
diff --git a/drivers/iio/humidity/Makefile b/drivers/iio/humidity/Makefile
index 86e2d26..3e62c0a 100644
--- a/drivers/iio/humidity/Makefile
+++ b/drivers/iio/humidity/Makefile
@@ -3,5 +3,6 @@
 #
 
 obj-$(CONFIG_DHT11) += dht11.o
+obj-$(CONFIG_HDC100X) += hdc100x.o
 obj-$(CONFIG_SI7005) += si7005.o
 obj-$(CONFIG_SI7020) += si7020.o
diff --git a/drivers/iio/humidity/hdc100x.c b/drivers/iio/humidity/hdc100x.c
new file mode 100644
index 0000000..2824578
--- /dev/null
+++ b/drivers/iio/humidity/hdc100x.c
@@ -0,0 +1,319 @@
+/*
+ * hdc100x.c - Support for the TI HDC100x temperature + humidity sensors
+ *
+ * Copyright (C) 2015 Matt Ranostay <mranostay@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define HDC100X_REG_TEMP			0x00
+#define HDC100X_REG_HUMIDITY			0x01
+
+#define HDC100X_REG_CONFIG			0x02
+#define HDC100X_REG_CONFIG_HEATER_EN		BIT(13)
+
+struct hdc100x_data {
+	struct i2c_client *client;
+	struct mutex lock;
+	u16 config;
+
+	/* integration time of the sensor */
+	int adc_int_us[2];
+};
+
+/* integration time in us */
+static const int hdc100x_int_time[][3] = {
+	{ 6350, 3650, 0 },	/* IIO_TEMP channel*/
+	{ 6500, 3850, 2500 },	/* IIO_HUMIDITYRELATIVE channel */
+};
+
+/* HDC100X_REG_CONFIG shift and mask values */
+static const struct {
+	int shift;
+	int mask;
+} hdc100x_resolution_shift[2] = {
+	{ /* IIO_TEMP channel */
+		.shift = 10,
+		.mask = 1
+	},
+	{ /* IIO_HUMIDITYRELATIVE channel */
+		.shift = 8,
+		.mask = 2,
+	},
+};
+
+static IIO_CONST_ATTR(temp_integration_time_available,
+		"0.00365 0.00635");
+
+static IIO_CONST_ATTR(humidityrelative_integration_time_available,
+		"0.0025 0.00385 0.0065");
+
+static IIO_CONST_ATTR(out_current_heater_raw_available,
+		"0 1");
+
+static struct attribute *hdc100x_attributes[] = {
+	&iio_const_attr_temp_integration_time_available.dev_attr.attr,
+	&iio_const_attr_humidityrelative_integration_time_available.dev_attr.attr,
+	&iio_const_attr_out_current_heater_raw_available.dev_attr.attr,
+	NULL
+};
+
+static struct attribute_group hdc100x_attribute_group = {
+	.attrs = hdc100x_attributes,
+};
+
+static const struct iio_chan_spec hdc100x_channels[] = {
+	{
+		.type = IIO_TEMP,
+		.address = HDC100X_REG_TEMP,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE) |
+			BIT(IIO_CHAN_INFO_INT_TIME) |
+			BIT(IIO_CHAN_INFO_OFFSET),
+	},
+	{
+		.type = IIO_HUMIDITYRELATIVE,
+		.address = HDC100X_REG_HUMIDITY,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE) |
+			BIT(IIO_CHAN_INFO_INT_TIME)
+	},
+	{
+		.type = IIO_CURRENT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.extend_name = "heater",
+		.output = 1,
+	},
+};
+
+static int hdc100x_update_config(struct hdc100x_data *data, int mask, int val)
+{
+	int tmp = (~mask & data->config) | val;
+	int ret;
+
+	ret = i2c_smbus_write_word_swapped(data->client,
+						HDC100X_REG_CONFIG, tmp);
+	if (!ret)
+		data->config = tmp;
+
+	return ret;
+}
+
+static int hdc100x_set_it_time(struct hdc100x_data *data, int chan, int val2)
+{
+	int shift = hdc100x_resolution_shift[chan].shift;
+	int ret = -EINVAL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(hdc100x_int_time[chan]); i++) {
+		if (val2 && val2 == hdc100x_int_time[chan][i]) {
+			ret = hdc100x_update_config(data,
+				hdc100x_resolution_shift[chan].mask << shift,
+				i << shift);
+			if (!ret)
+				data->adc_int_us[chan] = val2;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int hdc100x_get_measurement(struct hdc100x_data *data,
+				   struct iio_chan_spec const *chan)
+{
+	struct i2c_client *client = data->client;
+	int delay = data->adc_int_us[chan->address];
+	int ret;
+	int val;
+
+	/* start measurement */
+	ret = i2c_smbus_write_byte(client, chan->address);
+	if (ret < 0) {
+		dev_err(&client->dev, "cannot start measurement");
+		return ret;
+	}
+
+	/* wait for integration time to pass */
+	usleep_range(delay, delay + 1000);
+
+	/*
+	 * i2c_smbus_read_word_data cannot() be used here due to the command
+	 * value not being understood and causes NAKs preventing any reading
+	 * from being accessed.
+	 */
+	ret = i2c_smbus_read_byte(client);
+	if (ret < 0) {
+		dev_err(&client->dev, "cannot read high byte measurement");
+		return ret;
+	}
+	val = ret << 6;
+
+	ret = i2c_smbus_read_byte(client);
+	if (ret < 0) {
+		dev_err(&client->dev, "cannot read low byte measurement");
+		return ret;
+	}
+	val |= ret >> 2;
+
+	return val;
+}
+
+static int hdc100x_get_heater_status(struct hdc100x_data *data)
+{
+	return !!(data->config & HDC100X_REG_CONFIG_HEATER_EN);
+}
+
+static int hdc100x_read_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan, int *val,
+			    int *val2, long mask)
+{
+	struct hdc100x_data *data = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW: {
+		int ret;
+
+		mutex_lock(&data->lock);
+		if (chan->type == IIO_CURRENT) {
+			*val = hdc100x_get_heater_status(data);
+			ret = IIO_VAL_INT;
+		} else {
+			ret = hdc100x_get_measurement(data, chan);
+			if (ret >= 0) {
+				*val = ret;
+				ret = IIO_VAL_INT;
+			}
+		}
+		mutex_unlock(&data->lock);
+		return ret;
+	}
+	case IIO_CHAN_INFO_INT_TIME:
+		*val = 0;
+		*val2 = data->adc_int_us[chan->address];
+		return IIO_VAL_INT_PLUS_MICRO;
+	case IIO_CHAN_INFO_SCALE:
+		if (chan->type == IIO_TEMP) {
+			*val = 165;
+			*val2 = 65536 >> 2;
+			return IIO_VAL_FRACTIONAL;
+		} else {
+			*val = 0;
+			*val2 = 10000;
+			return IIO_VAL_INT_PLUS_MICRO;
+		}
+		break;
+	case IIO_CHAN_INFO_OFFSET:
+		*val = -40;
+		return IIO_VAL_INT;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int hdc100x_write_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int val, int val2, long mask)
+{
+	struct hdc100x_data *data = iio_priv(indio_dev);
+	int ret = -EINVAL;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_INT_TIME:
+		if (val != 0)
+			return -EINVAL;
+
+		mutex_lock(&data->lock);
+		ret = hdc100x_set_it_time(data, chan->address, val2);
+		mutex_unlock(&data->lock);
+		return ret;
+	case IIO_CHAN_INFO_RAW:
+		if (chan->type != IIO_CURRENT || val2 != 0)
+			return -EINVAL;
+
+		mutex_lock(&data->lock);
+		ret = hdc100x_update_config(data, HDC100X_REG_CONFIG_HEATER_EN,
+					val ? HDC100X_REG_CONFIG_HEATER_EN : 0);
+		mutex_unlock(&data->lock);
+		return ret;
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct iio_info hdc100x_info = {
+	.read_raw = hdc100x_read_raw,
+	.write_raw = hdc100x_write_raw,
+	.attrs = &hdc100x_attribute_group,
+	.driver_module = THIS_MODULE,
+};
+
+static int hdc100x_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct iio_dev *indio_dev;
+	struct hdc100x_data *data;
+
+	if (!i2c_check_functionality(client->adapter,
+				I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BYTE))
+		return -ENODEV;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	i2c_set_clientdata(client, indio_dev);
+	data->client = client;
+	mutex_init(&data->lock);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->name = dev_name(&client->dev);
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->info = &hdc100x_info;
+
+	indio_dev->channels = hdc100x_channels;
+	indio_dev->num_channels = ARRAY_SIZE(hdc100x_channels);
+
+	/* be sure we are in a known state */
+	hdc100x_set_it_time(data, 0, hdc100x_int_time[0][0]);
+	hdc100x_set_it_time(data, 1, hdc100x_int_time[1][0]);
+
+	return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct i2c_device_id hdc100x_id[] = {
+	{ "hdc100x", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, hdc100x_id);
+
+static struct i2c_driver hdc100x_driver = {
+	.driver = {
+		.name	= "hdc100x",
+	},
+	.probe = hdc100x_probe,
+	.id_table = hdc100x_id,
+};
+module_i2c_driver(hdc100x_driver);
+
+MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>");
+MODULE_DESCRIPTION("TI HDC100x humidity and temperature sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/humidity/si7020.c b/drivers/iio/humidity/si7020.c
index fa3b809..12128d1 100644
--- a/drivers/iio/humidity/si7020.c
+++ b/drivers/iio/humidity/si7020.c
@@ -57,8 +57,12 @@
 		if (ret < 0)
 			return ret;
 		*val = ret >> 2;
+		/*
+		 * Humidity values can slightly exceed the 0-100%RH
+		 * range and should be corrected by software
+		 */
 		if (chan->type == IIO_HUMIDITYRELATIVE)
-			*val &= GENMASK(11, 0);
+			*val = clamp_val(*val, 786, 13893);
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
 		if (chan->type == IIO_TEMP)
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index b3fcc2c..208358f 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -75,6 +75,8 @@
 	[IIO_ENERGY] = "energy",
 	[IIO_DISTANCE] = "distance",
 	[IIO_VELOCITY] = "velocity",
+	[IIO_CONCENTRATION] = "concentration",
+	[IIO_RESISTANCE] = "resistance",
 };
 
 static const char * const iio_modifier_names[] = {
@@ -111,6 +113,8 @@
 	[IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)",
 	[IIO_MOD_I] = "i",
 	[IIO_MOD_Q] = "q",
+	[IIO_MOD_CO2] = "co2",
+	[IIO_MOD_VOC] = "voc",
 };
 
 /* relies on pairs of these shared then separate */
@@ -962,7 +966,7 @@
 static void iio_dev_release(struct device *device)
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(device);
-	if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
+	if (indio_dev->modes & (INDIO_BUFFER_TRIGGERED | INDIO_EVENT_TRIGGERED))
 		iio_device_unregister_trigger_consumer(indio_dev);
 	iio_device_unregister_eventset(indio_dev);
 	iio_device_unregister_sysfs(indio_dev);
@@ -1153,6 +1157,8 @@
 
 	if (cmd == IIO_GET_EVENT_FD_IOCTL) {
 		fd = iio_event_getfd(indio_dev);
+		if (fd < 0)
+			return fd;
 		if (copy_to_user(ip, &fd, sizeof(fd)))
 			return -EFAULT;
 		return 0;
@@ -1241,7 +1247,7 @@
 			"Failed to register event set\n");
 		goto error_free_sysfs;
 	}
-	if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
+	if (indio_dev->modes & (INDIO_BUFFER_TRIGGERED | INDIO_EVENT_TRIGGERED))
 		iio_device_register_trigger_consumer(indio_dev);
 
 	if ((indio_dev->modes & INDIO_ALL_BUFFER_MODES) &&
diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c
index 570606c..ae2806a 100644
--- a/drivers/iio/industrialio-trigger.c
+++ b/drivers/iio/industrialio-trigger.c
@@ -366,10 +366,18 @@
 
 	indio_dev->trig = trig;
 
-	if (oldtrig)
+	if (oldtrig) {
+		if (indio_dev->modes & INDIO_EVENT_TRIGGERED)
+			iio_trigger_detach_poll_func(oldtrig,
+						     indio_dev->pollfunc_event);
 		iio_trigger_put(oldtrig);
-	if (indio_dev->trig)
+	}
+	if (indio_dev->trig) {
 		iio_trigger_get(indio_dev->trig);
+		if (indio_dev->modes & INDIO_EVENT_TRIGGERED)
+			iio_trigger_attach_poll_func(indio_dev->trig,
+						     indio_dev->pollfunc_event);
+	}
 
 	return len;
 }
diff --git a/drivers/iio/industrialio-triggered-event.c b/drivers/iio/industrialio-triggered-event.c
new file mode 100644
index 0000000..8cc254f
--- /dev/null
+++ b/drivers/iio/industrialio-triggered-event.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 Cogent Embedded, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/triggered_event.h>
+#include <linux/iio/trigger_consumer.h>
+
+/**
+ * iio_triggered_event_setup() - Setup pollfunc_event for triggered event
+ * @indio_dev:	IIO device structure
+ * @h:		Function which will be used as pollfunc_event top half
+ * @thread:	Function which will be used as pollfunc_event bottom half
+ *
+ * This function combines some common tasks which will normally be performed
+ * when setting up a triggered event. It will allocate the pollfunc_event and
+ * set mode to use it for triggered event.
+ *
+ * Before calling this function the indio_dev structure should already be
+ * completely initialized, but not yet registered. In practice this means that
+ * this function should be called right before iio_device_register().
+ *
+ * To free the resources allocated by this function call
+ * iio_triggered_event_cleanup().
+ */
+int iio_triggered_event_setup(struct iio_dev *indio_dev,
+			      irqreturn_t (*h)(int irq, void *p),
+			      irqreturn_t (*thread)(int irq, void *p))
+{
+	indio_dev->pollfunc_event = iio_alloc_pollfunc(h,
+						       thread,
+						       IRQF_ONESHOT,
+						       indio_dev,
+						       "%s_consumer%d",
+						       indio_dev->name,
+						       indio_dev->id);
+	if (indio_dev->pollfunc_event == NULL)
+		return -ENOMEM;
+
+	/* Flag that events polling is possible */
+	indio_dev->modes |= INDIO_EVENT_TRIGGERED;
+
+	return 0;
+}
+EXPORT_SYMBOL(iio_triggered_event_setup);
+
+/**
+ * iio_triggered_event_cleanup() - Free resources allocated by iio_triggered_event_setup()
+ * @indio_dev: IIO device structure
+ */
+void iio_triggered_event_cleanup(struct iio_dev *indio_dev)
+{
+	indio_dev->modes &= ~INDIO_EVENT_TRIGGERED;
+	iio_dealloc_pollfunc(indio_dev->pollfunc_event);
+}
+EXPORT_SYMBOL(iio_triggered_event_cleanup);
+
+MODULE_AUTHOR("Vladimir Barinov");
+MODULE_DESCRIPTION("IIO helper functions for setting up triggered events");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index 7ed859a..cfd3df8 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -50,6 +50,19 @@
 	 To compile this driver as a module, choose M here: the
 	 module will be called apds9300.
 
+config APDS9960
+	tristate "Avago APDS9960 gesture/RGB/ALS/proximity sensor"
+	select REGMAP_I2C
+	select IIO_BUFFER
+	select IIO_KFIFO_BUF
+	depends on I2C
+	help
+	  Say Y here to build I2C interface support for the Avago
+	  APDS9960 gesture/RGB/ALS/proximity sensor.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called apds9960
+
 config BH1750
 	tristate "ROHM BH1750 ambient light sensor"
 	depends on I2C
@@ -287,6 +300,16 @@
 	 To compile this driver as a module, choose M here: the
 	 module will be called tsl4531.
 
+config US5182D
+	tristate "UPISEMI light and proximity sensor"
+	depends on I2C
+	help
+	 If you say yes here you get support for the UPISEMI US5182D
+	 ambient light and proximity sensor.
+
+	 This driver can also be built as a module.  If so, the module
+	 will be called us5182d.
+
 config VCNL4000
 	tristate "VCNL4000 combined ALS and proximity sensor"
 	depends on I2C
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
index 91c74c0..b2c3105 100644
--- a/drivers/iio/light/Makefile
+++ b/drivers/iio/light/Makefile
@@ -7,6 +7,7 @@
 obj-$(CONFIG_ADJD_S311)		+= adjd_s311.o
 obj-$(CONFIG_AL3320A)		+= al3320a.o
 obj-$(CONFIG_APDS9300)		+= apds9300.o
+obj-$(CONFIG_APDS9960)		+= apds9960.o
 obj-$(CONFIG_BH1750)		+= bh1750.o
 obj-$(CONFIG_CM32181)		+= cm32181.o
 obj-$(CONFIG_CM3232)		+= cm3232.o
@@ -27,4 +28,5 @@
 obj-$(CONFIG_TCS3414)		+= tcs3414.o
 obj-$(CONFIG_TCS3472)		+= tcs3472.o
 obj-$(CONFIG_TSL4531)		+= tsl4531.o
+obj-$(CONFIG_US5182D)		+= us5182d.o
 obj-$(CONFIG_VCNL4000)		+= vcnl4000.o
diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c
new file mode 100644
index 0000000..bf80ce4
--- /dev/null
+++ b/drivers/iio/light/apds9960.c
@@ -0,0 +1,1130 @@
+/*
+ * apds9960.c - Support for Avago APDS9960 gesture/RGB/ALS/proximity sensor
+ *
+ * Copyright (C) 2015 Matt Ranostay <mranostay@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * TODO: gesture + proximity calib offsets
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/err.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/events.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/sysfs.h>
+#include <linux/of_gpio.h>
+
+#define APDS9960_REGMAP_NAME	"apds9960_regmap"
+#define APDS9960_DRV_NAME	"apds9960"
+
+#define APDS9960_REG_RAM_START	0x00
+#define APDS9960_REG_RAM_END	0x7f
+
+#define APDS9960_REG_ENABLE	0x80
+#define APDS9960_REG_ATIME	0x81
+#define APDS9960_REG_WTIME	0x83
+
+#define APDS9960_REG_AILTL	0x84
+#define APDS9960_REG_AILTH	0x85
+#define APDS9960_REG_AIHTL	0x86
+#define APDS9960_REG_AIHTH	0x87
+
+#define APDS9960_REG_PILT	0x89
+#define APDS9960_REG_PIHT	0x8b
+#define APDS9960_REG_PERS	0x8c
+
+#define APDS9960_REG_CONFIG_1	0x8d
+#define APDS9960_REG_PPULSE	0x8e
+
+#define APDS9960_REG_CONTROL	0x8f
+#define APDS9960_REG_CONTROL_AGAIN_MASK		0x03
+#define APDS9960_REG_CONTROL_PGAIN_MASK		0x0c
+#define APDS9960_REG_CONTROL_AGAIN_MASK_SHIFT	0
+#define APDS9960_REG_CONTROL_PGAIN_MASK_SHIFT	2
+
+#define APDS9960_REG_CONFIG_2	0x90
+#define APDS9960_REG_CONFIG_2_GGAIN_MASK	0x60
+#define APDS9960_REG_CONFIG_2_GGAIN_MASK_SHIFT	5
+
+#define APDS9960_REG_ID		0x92
+
+#define APDS9960_REG_STATUS	0x93
+#define APDS9960_REG_STATUS_PS_INT	BIT(5)
+#define APDS9960_REG_STATUS_ALS_INT	BIT(4)
+#define APDS9960_REG_STATUS_GINT	BIT(2)
+
+#define APDS9960_REG_PDATA	0x9c
+#define APDS9960_REG_POFFSET_UR	0x9d
+#define APDS9960_REG_POFFSET_DL 0x9e
+#define APDS9960_REG_CONFIG_3	0x9f
+
+#define APDS9960_REG_GPENTH	0xa0
+#define APDS9960_REG_GEXTH	0xa1
+
+#define APDS9960_REG_GCONF_1	0xa2
+#define APDS9960_REG_GCONF_1_GFIFO_THRES_MASK		0xc0
+#define APDS9960_REG_GCONF_1_GFIFO_THRES_MASK_SHIFT	6
+
+#define APDS9960_REG_GCONF_2	0xa3
+#define APDS9960_REG_GOFFSET_U	0xa4
+#define APDS9960_REG_GOFFSET_D	0xa5
+#define APDS9960_REG_GPULSE	0xa6
+#define APDS9960_REG_GOFFSET_L	0xa7
+#define APDS9960_REG_GOFFSET_R	0xa9
+#define APDS9960_REG_GCONF_3	0xaa
+
+#define APDS9960_REG_GCONF_4	0xab
+#define APDS9960_REG_GFLVL	0xae
+#define APDS9960_REG_GSTATUS	0xaf
+
+#define APDS9960_REG_IFORCE	0xe4
+#define APDS9960_REG_PICLEAR	0xe5
+#define APDS9960_REG_CICLEAR	0xe6
+#define APDS9960_REG_AICLEAR	0xe7
+
+#define APDS9960_DEFAULT_PERS	0x33
+#define APDS9960_DEFAULT_GPENTH	0x50
+#define APDS9960_DEFAULT_GEXTH	0x40
+
+#define APDS9960_MAX_PXS_THRES_VAL	255
+#define APDS9960_MAX_ALS_THRES_VAL	0xffff
+#define APDS9960_MAX_INT_TIME_IN_US	1000000
+
+enum apds9960_als_channel_idx {
+	IDX_ALS_CLEAR, IDX_ALS_RED, IDX_ALS_GREEN, IDX_ALS_BLUE,
+};
+
+#define APDS9960_REG_ALS_BASE	0x94
+#define APDS9960_REG_ALS_CHANNEL(_colour) \
+	(APDS9960_REG_ALS_BASE + (IDX_ALS_##_colour * 2))
+
+enum apds9960_gesture_channel_idx {
+	IDX_DIR_UP, IDX_DIR_DOWN, IDX_DIR_LEFT, IDX_DIR_RIGHT,
+};
+
+#define APDS9960_REG_GFIFO_BASE	0xfc
+#define APDS9960_REG_GFIFO_DIR(_dir) \
+	(APDS9960_REG_GFIFO_BASE + IDX_DIR_##_dir)
+
+struct apds9960_data {
+	struct i2c_client *client;
+	struct iio_dev *indio_dev;
+	struct mutex lock;
+
+	/* regmap fields */
+	struct regmap *regmap;
+	struct regmap_field *reg_int_als;
+	struct regmap_field *reg_int_ges;
+	struct regmap_field *reg_int_pxs;
+
+	struct regmap_field *reg_enable_als;
+	struct regmap_field *reg_enable_ges;
+	struct regmap_field *reg_enable_pxs;
+
+	/* state */
+	int als_int;
+	int pxs_int;
+	int gesture_mode_running;
+
+	/* gain values */
+	int als_gain;
+	int pxs_gain;
+
+	/* integration time value in us */
+	int als_adc_int_us;
+
+	/* gesture buffer */
+	u8 buffer[4]; /* 4 8-bit channels */
+};
+
+static const struct reg_default apds9960_reg_defaults[] = {
+	/* Default ALS integration time = 2.48ms */
+	{ APDS9960_REG_ATIME, 0xff },
+};
+
+static const struct regmap_range apds9960_volatile_ranges[] = {
+	regmap_reg_range(APDS9960_REG_STATUS,
+				APDS9960_REG_PDATA),
+	regmap_reg_range(APDS9960_REG_GFLVL,
+				APDS9960_REG_GSTATUS),
+	regmap_reg_range(APDS9960_REG_GFIFO_DIR(UP),
+				APDS9960_REG_GFIFO_DIR(RIGHT)),
+	regmap_reg_range(APDS9960_REG_IFORCE,
+				APDS9960_REG_AICLEAR),
+};
+
+static const struct regmap_access_table apds9960_volatile_table = {
+	.yes_ranges	= apds9960_volatile_ranges,
+	.n_yes_ranges	= ARRAY_SIZE(apds9960_volatile_ranges),
+};
+
+static const struct regmap_range apds9960_precious_ranges[] = {
+	regmap_reg_range(APDS9960_REG_RAM_START, APDS9960_REG_RAM_END),
+};
+
+static const struct regmap_access_table apds9960_precious_table = {
+	.yes_ranges	= apds9960_precious_ranges,
+	.n_yes_ranges	= ARRAY_SIZE(apds9960_precious_ranges),
+};
+
+static const struct regmap_range apds9960_readable_ranges[] = {
+	regmap_reg_range(APDS9960_REG_ENABLE,
+				APDS9960_REG_GSTATUS),
+	regmap_reg_range(APDS9960_REG_GFIFO_DIR(UP),
+				APDS9960_REG_GFIFO_DIR(RIGHT)),
+};
+
+static const struct regmap_access_table apds9960_readable_table = {
+	.yes_ranges	= apds9960_readable_ranges,
+	.n_yes_ranges	= ARRAY_SIZE(apds9960_readable_ranges),
+};
+
+static const struct regmap_range apds9960_writeable_ranges[] = {
+	regmap_reg_range(APDS9960_REG_ENABLE, APDS9960_REG_CONFIG_2),
+	regmap_reg_range(APDS9960_REG_POFFSET_UR, APDS9960_REG_GCONF_4),
+	regmap_reg_range(APDS9960_REG_IFORCE, APDS9960_REG_AICLEAR),
+};
+
+static const struct regmap_access_table apds9960_writeable_table = {
+	.yes_ranges	= apds9960_writeable_ranges,
+	.n_yes_ranges	= ARRAY_SIZE(apds9960_writeable_ranges),
+};
+
+static const struct regmap_config apds9960_regmap_config = {
+	.name = APDS9960_REGMAP_NAME,
+	.reg_bits = 8,
+	.val_bits = 8,
+	.use_single_rw = 1,
+
+	.volatile_table = &apds9960_volatile_table,
+	.precious_table = &apds9960_precious_table,
+	.rd_table = &apds9960_readable_table,
+	.wr_table = &apds9960_writeable_table,
+
+	.reg_defaults = apds9960_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(apds9960_reg_defaults),
+	.max_register = APDS9960_REG_GFIFO_DIR(RIGHT),
+	.cache_type = REGCACHE_RBTREE,
+};
+
+static const struct iio_event_spec apds9960_pxs_event_spec[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	},
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	},
+};
+
+static const struct iio_event_spec apds9960_als_event_spec[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	},
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	},
+};
+
+#define APDS9960_GESTURE_CHANNEL(_dir, _si) { \
+	.type = IIO_PROXIMITY, \
+	.channel = _si + 1, \
+	.scan_index = _si, \
+	.indexed = 1, \
+	.scan_type = { \
+		.sign = 'u', \
+		.realbits = 8, \
+		.storagebits = 8, \
+	}, \
+}
+
+#define APDS9960_INTENSITY_CHANNEL(_colour) { \
+	.type = IIO_INTENSITY, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+			BIT(IIO_CHAN_INFO_INT_TIME), \
+	.channel2 = IIO_MOD_LIGHT_##_colour, \
+	.address = APDS9960_REG_ALS_CHANNEL(_colour), \
+	.modified = 1, \
+	.scan_index = -1, \
+}
+
+static const unsigned long apds9960_scan_masks[] = {0xf, 0};
+
+static const struct iio_chan_spec apds9960_channels[] = {
+	{
+		.type = IIO_PROXIMITY,
+		.address = APDS9960_REG_PDATA,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+		.channel = 0,
+		.indexed = 0,
+		.scan_index = -1,
+
+		.event_spec = apds9960_pxs_event_spec,
+		.num_event_specs = ARRAY_SIZE(apds9960_pxs_event_spec),
+	},
+	/* Gesture Sensor */
+	APDS9960_GESTURE_CHANNEL(UP, 0),
+	APDS9960_GESTURE_CHANNEL(DOWN, 1),
+	APDS9960_GESTURE_CHANNEL(LEFT, 2),
+	APDS9960_GESTURE_CHANNEL(RIGHT, 3),
+	/* ALS */
+	{
+		.type = IIO_INTENSITY,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
+			BIT(IIO_CHAN_INFO_INT_TIME),
+		.channel2 = IIO_MOD_LIGHT_CLEAR,
+		.address = APDS9960_REG_ALS_CHANNEL(CLEAR),
+		.modified = 1,
+		.scan_index = -1,
+
+		.event_spec = apds9960_als_event_spec,
+		.num_event_specs = ARRAY_SIZE(apds9960_als_event_spec),
+	},
+	/* RGB Sensor */
+	APDS9960_INTENSITY_CHANNEL(RED),
+	APDS9960_INTENSITY_CHANNEL(GREEN),
+	APDS9960_INTENSITY_CHANNEL(BLUE),
+};
+
+/* integration time in us */
+static const int apds9960_int_time[][2] =
+	{ {28000, 246}, {100000, 219}, {200000, 182}, {700000, 0} };
+
+/* gain mapping */
+static const int apds9960_pxs_gain_map[] = {1, 2, 4, 8};
+static const int apds9960_als_gain_map[] = {1, 4, 16, 64};
+
+static IIO_CONST_ATTR(proximity_scale_available, "1 2 4 8");
+static IIO_CONST_ATTR(intensity_scale_available, "1 4 16 64");
+static IIO_CONST_ATTR_INT_TIME_AVAIL("0.028 0.1 0.2 0.7");
+
+static struct attribute *apds9960_attributes[] = {
+	&iio_const_attr_proximity_scale_available.dev_attr.attr,
+	&iio_const_attr_intensity_scale_available.dev_attr.attr,
+	&iio_const_attr_integration_time_available.dev_attr.attr,
+	NULL,
+};
+
+static struct attribute_group apds9960_attribute_group = {
+	.attrs = apds9960_attributes,
+};
+
+static const struct reg_field apds9960_reg_field_int_als =
+				REG_FIELD(APDS9960_REG_ENABLE, 4, 4);
+
+static const struct reg_field apds9960_reg_field_int_ges =
+				REG_FIELD(APDS9960_REG_GCONF_4, 1, 1);
+
+static const struct reg_field apds9960_reg_field_int_pxs =
+				REG_FIELD(APDS9960_REG_ENABLE, 5, 5);
+
+static const struct reg_field apds9960_reg_field_enable_als =
+				REG_FIELD(APDS9960_REG_ENABLE, 1, 1);
+
+static const struct reg_field apds9960_reg_field_enable_ges =
+				REG_FIELD(APDS9960_REG_ENABLE, 6, 6);
+
+static const struct reg_field apds9960_reg_field_enable_pxs =
+				REG_FIELD(APDS9960_REG_ENABLE, 2, 2);
+
+static int apds9960_set_it_time(struct apds9960_data *data, int val2)
+{
+	int ret = -EINVAL;
+	int idx;
+
+	for (idx = 0; idx < ARRAY_SIZE(apds9960_int_time); idx++) {
+		if (apds9960_int_time[idx][0] == val2) {
+			mutex_lock(&data->lock);
+			ret = regmap_write(data->regmap, APDS9960_REG_ATIME,
+						 apds9960_int_time[idx][1]);
+			if (!ret)
+				data->als_adc_int_us = val2;
+			mutex_unlock(&data->lock);
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int apds9960_set_pxs_gain(struct apds9960_data *data, int val)
+{
+	int ret = -EINVAL;
+	int idx;
+
+	for (idx = 0; idx < ARRAY_SIZE(apds9960_pxs_gain_map); idx++) {
+		if (apds9960_pxs_gain_map[idx] == val) {
+			/* pxs + gesture gains are mirrored */
+			mutex_lock(&data->lock);
+			ret = regmap_update_bits(data->regmap,
+				APDS9960_REG_CONTROL,
+				APDS9960_REG_CONTROL_PGAIN_MASK,
+				idx << APDS9960_REG_CONTROL_PGAIN_MASK_SHIFT);
+			if (ret) {
+				mutex_unlock(&data->lock);
+				break;
+			}
+
+			ret = regmap_update_bits(data->regmap,
+				APDS9960_REG_CONFIG_2,
+				APDS9960_REG_CONFIG_2_GGAIN_MASK,
+				idx << APDS9960_REG_CONFIG_2_GGAIN_MASK_SHIFT);
+			if (!ret)
+				data->pxs_gain = idx;
+			mutex_unlock(&data->lock);
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int apds9960_set_als_gain(struct apds9960_data *data, int val)
+{
+	int ret = -EINVAL;
+	int idx;
+
+	for (idx = 0; idx < ARRAY_SIZE(apds9960_als_gain_map); idx++) {
+		if (apds9960_als_gain_map[idx] == val) {
+			mutex_lock(&data->lock);
+			ret = regmap_update_bits(data->regmap,
+					APDS9960_REG_CONTROL,
+					APDS9960_REG_CONTROL_AGAIN_MASK, idx);
+			if (!ret)
+				data->als_gain = idx;
+			mutex_unlock(&data->lock);
+			break;
+		}
+	}
+
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int apds9960_set_power_state(struct apds9960_data *data, bool on)
+{
+	struct device *dev = &data->client->dev;
+	int ret = 0;
+
+	mutex_lock(&data->lock);
+
+	if (on) {
+		int suspended;
+
+		suspended = pm_runtime_suspended(dev);
+		ret = pm_runtime_get_sync(dev);
+
+		/* Allow one integration cycle before allowing a reading */
+		if (suspended)
+			usleep_range(data->als_adc_int_us,
+				     APDS9960_MAX_INT_TIME_IN_US);
+	} else {
+		ret = pm_runtime_put_autosuspend(dev);
+	}
+
+	mutex_unlock(&data->lock);
+
+	return ret;
+}
+#else
+static int apds9960_set_power_state(struct apds9960_data *data, bool on)
+{
+	return 0;
+}
+#endif
+
+static int apds9960_read_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int *val, int *val2, long mask)
+{
+	struct apds9960_data *data = iio_priv(indio_dev);
+	u16 buf;
+	int ret = -EINVAL;
+
+	if (data->gesture_mode_running)
+		return -EBUSY;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		apds9960_set_power_state(data, true);
+		switch (chan->type) {
+		case IIO_PROXIMITY:
+			ret = regmap_read(data->regmap, chan->address, val);
+			if (!ret)
+				ret = IIO_VAL_INT;
+			break;
+		case IIO_INTENSITY:
+			ret = regmap_bulk_read(data->regmap, chan->address,
+					       &buf, 2);
+			if (!ret)
+				ret = IIO_VAL_INT;
+			*val = le16_to_cpu(buf);
+			break;
+		default:
+			ret = -EINVAL;
+		}
+		apds9960_set_power_state(data, false);
+		break;
+	case IIO_CHAN_INFO_INT_TIME:
+		/* RGB + ALS sensors only have integration time */
+		mutex_lock(&data->lock);
+		switch (chan->type) {
+		case IIO_INTENSITY:
+			*val = 0;
+			*val2 = data->als_adc_int_us;
+			ret = IIO_VAL_INT_PLUS_MICRO;
+			break;
+		default:
+			ret = -EINVAL;
+		}
+		mutex_unlock(&data->lock);
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		mutex_lock(&data->lock);
+		switch (chan->type) {
+		case IIO_PROXIMITY:
+			*val = apds9960_pxs_gain_map[data->pxs_gain];
+			ret = IIO_VAL_INT;
+			break;
+		case IIO_INTENSITY:
+			*val = apds9960_als_gain_map[data->als_gain];
+			ret = IIO_VAL_INT;
+			break;
+		default:
+			ret = -EINVAL;
+		}
+		mutex_unlock(&data->lock);
+		break;
+	}
+
+	return ret;
+};
+
+static int apds9960_write_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int val, int val2, long mask)
+{
+	struct apds9960_data *data = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_INT_TIME:
+		/* RGB + ALS sensors only have int time */
+		switch (chan->type) {
+		case IIO_INTENSITY:
+			if (val != 0)
+				return -EINVAL;
+			return apds9960_set_it_time(data, val2);
+		default:
+			return -EINVAL;
+		}
+	case IIO_CHAN_INFO_SCALE:
+		if (val2 != 0)
+			return -EINVAL;
+		switch (chan->type) {
+		case IIO_PROXIMITY:
+			return apds9960_set_pxs_gain(data, val);
+		case IIO_INTENSITY:
+			return apds9960_set_als_gain(data, val);
+		default:
+			return -EINVAL;
+		}
+	default:
+		return -EINVAL;
+	};
+
+	return 0;
+}
+
+static inline int apds9960_get_thres_reg(const struct iio_chan_spec *chan,
+					 enum iio_event_direction dir,
+					 u8 *reg)
+{
+	switch (dir) {
+	case IIO_EV_DIR_RISING:
+		switch (chan->type) {
+		case IIO_PROXIMITY:
+			*reg = APDS9960_REG_PIHT;
+			break;
+		case IIO_INTENSITY:
+			*reg = APDS9960_REG_AIHTL;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case IIO_EV_DIR_FALLING:
+		switch (chan->type) {
+		case IIO_PROXIMITY:
+			*reg = APDS9960_REG_PILT;
+			break;
+		case IIO_INTENSITY:
+			*reg = APDS9960_REG_AILTL;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int apds9960_read_event(struct iio_dev *indio_dev,
+			       const struct iio_chan_spec *chan,
+			       enum iio_event_type type,
+			       enum iio_event_direction dir,
+			       enum iio_event_info info,
+			       int *val, int *val2)
+{
+	u8 reg;
+	u16 buf;
+	int ret = 0;
+	struct apds9960_data *data = iio_priv(indio_dev);
+
+	if (info != IIO_EV_INFO_VALUE)
+		return -EINVAL;
+
+	ret = apds9960_get_thres_reg(chan, dir, &reg);
+	if (ret < 0)
+		return ret;
+
+	if (chan->type == IIO_PROXIMITY) {
+		ret = regmap_read(data->regmap, reg, val);
+		if (ret < 0)
+			return ret;
+	} else if (chan->type == IIO_INTENSITY) {
+		ret = regmap_bulk_read(data->regmap, reg, &buf, 2);
+		if (ret < 0)
+			return ret;
+		*val = le16_to_cpu(buf);
+	} else
+		return -EINVAL;
+
+	*val2 = 0;
+
+	return IIO_VAL_INT;
+}
+
+static int apds9960_write_event(struct iio_dev *indio_dev,
+				const struct iio_chan_spec *chan,
+				enum iio_event_type type,
+				enum iio_event_direction dir,
+				enum iio_event_info info,
+				int val, int val2)
+{
+	u8 reg;
+	u16 buf;
+	int ret = 0;
+	struct apds9960_data *data = iio_priv(indio_dev);
+
+	if (info != IIO_EV_INFO_VALUE)
+		return -EINVAL;
+
+	ret = apds9960_get_thres_reg(chan, dir, &reg);
+	if (ret < 0)
+		return ret;
+
+	if (chan->type == IIO_PROXIMITY) {
+		if (val < 0 || val > APDS9960_MAX_PXS_THRES_VAL)
+			return -EINVAL;
+		ret = regmap_write(data->regmap, reg, val);
+		if (ret < 0)
+			return ret;
+	} else if (chan->type == IIO_INTENSITY) {
+		if (val < 0 || val > APDS9960_MAX_ALS_THRES_VAL)
+			return -EINVAL;
+		buf = cpu_to_le16(val);
+		ret = regmap_bulk_write(data->regmap, reg, &buf, 2);
+		if (ret < 0)
+			return ret;
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int apds9960_read_event_config(struct iio_dev *indio_dev,
+				      const struct iio_chan_spec *chan,
+				      enum iio_event_type type,
+				      enum iio_event_direction dir)
+{
+	struct apds9960_data *data = iio_priv(indio_dev);
+
+	switch (chan->type) {
+	case IIO_PROXIMITY:
+		return data->pxs_int;
+	case IIO_INTENSITY:
+		return data->als_int;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int apds9960_write_event_config(struct iio_dev *indio_dev,
+				       const struct iio_chan_spec *chan,
+				       enum iio_event_type type,
+				       enum iio_event_direction dir,
+				       int state)
+{
+	struct apds9960_data *data = iio_priv(indio_dev);
+	int ret;
+
+	state = !!state;
+
+	switch (chan->type) {
+	case IIO_PROXIMITY:
+		if (data->pxs_int == state)
+			return -EINVAL;
+
+		ret = regmap_field_write(data->reg_int_pxs, state);
+		if (ret)
+			return ret;
+		data->pxs_int = state;
+		apds9960_set_power_state(data, state);
+		break;
+	case IIO_INTENSITY:
+		if (data->als_int == state)
+			return -EINVAL;
+
+		ret = regmap_field_write(data->reg_int_als, state);
+		if (ret)
+			return ret;
+		data->als_int = state;
+		apds9960_set_power_state(data, state);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct iio_info apds9960_info = {
+	.driver_module = THIS_MODULE,
+	.attrs = &apds9960_attribute_group,
+	.read_raw = apds9960_read_raw,
+	.write_raw = apds9960_write_raw,
+	.read_event_value = apds9960_read_event,
+	.write_event_value = apds9960_write_event,
+	.read_event_config = apds9960_read_event_config,
+	.write_event_config = apds9960_write_event_config,
+
+};
+
+static inline int apds9660_fifo_is_empty(struct apds9960_data *data)
+{
+	int cnt;
+	int ret;
+
+	ret = regmap_read(data->regmap, APDS9960_REG_GFLVL, &cnt);
+	if (ret)
+		return ret;
+
+	return cnt;
+}
+
+static void apds9960_read_gesture_fifo(struct apds9960_data *data)
+{
+	int ret, cnt = 0;
+
+	mutex_lock(&data->lock);
+	data->gesture_mode_running = 1;
+
+	while (cnt-- || (cnt = apds9660_fifo_is_empty(data) > 0)) {
+		ret = regmap_bulk_read(data->regmap, APDS9960_REG_GFIFO_BASE,
+				      &data->buffer, 4);
+
+		if (ret)
+			goto err_read;
+
+		iio_push_to_buffers(data->indio_dev, data->buffer);
+	}
+
+err_read:
+	data->gesture_mode_running = 0;
+	mutex_unlock(&data->lock);
+}
+
+static irqreturn_t apds9960_interrupt_handler(int irq, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	struct apds9960_data *data = iio_priv(indio_dev);
+	int ret, status;
+
+	ret = regmap_read(data->regmap, APDS9960_REG_STATUS, &status);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "irq status reg read failed\n");
+		return IRQ_HANDLED;
+	}
+
+	if ((status & APDS9960_REG_STATUS_ALS_INT) && data->als_int) {
+		iio_push_event(indio_dev,
+			       IIO_UNMOD_EVENT_CODE(IIO_INTENSITY, 0,
+						    IIO_EV_TYPE_THRESH,
+						    IIO_EV_DIR_EITHER),
+			       iio_get_time_ns());
+		regmap_write(data->regmap, APDS9960_REG_CICLEAR, 1);
+	}
+
+	if ((status & APDS9960_REG_STATUS_PS_INT) && data->pxs_int) {
+		iio_push_event(indio_dev,
+			       IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0,
+						    IIO_EV_TYPE_THRESH,
+						    IIO_EV_DIR_EITHER),
+			       iio_get_time_ns());
+		regmap_write(data->regmap, APDS9960_REG_PICLEAR, 1);
+	}
+
+	if (status & APDS9960_REG_STATUS_GINT)
+		apds9960_read_gesture_fifo(data);
+
+	return IRQ_HANDLED;
+}
+
+static int apds9960_set_powermode(struct apds9960_data *data, bool state)
+{
+	return regmap_update_bits(data->regmap, APDS9960_REG_ENABLE, 1, state);
+}
+
+static int apds9960_buffer_postenable(struct iio_dev *indio_dev)
+{
+	struct apds9960_data *data = iio_priv(indio_dev);
+	int ret;
+
+	ret = regmap_field_write(data->reg_int_ges, 1);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(data->reg_enable_ges, 1);
+	if (ret)
+		return ret;
+
+	pm_runtime_get_sync(&data->client->dev);
+
+	return 0;
+}
+
+static int apds9960_buffer_predisable(struct iio_dev *indio_dev)
+{
+	struct apds9960_data *data = iio_priv(indio_dev);
+	int ret;
+
+	ret = regmap_field_write(data->reg_enable_ges, 0);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(data->reg_int_ges, 0);
+	if (ret)
+		return ret;
+
+	pm_runtime_put_autosuspend(&data->client->dev);
+
+	return 0;
+}
+
+static const struct iio_buffer_setup_ops apds9960_buffer_setup_ops = {
+	.postenable = apds9960_buffer_postenable,
+	.predisable = apds9960_buffer_predisable,
+};
+
+static int apds9960_regfield_init(struct apds9960_data *data)
+{
+	struct device *dev = &data->client->dev;
+	struct regmap *regmap = data->regmap;
+
+	data->reg_int_als = devm_regmap_field_alloc(dev, regmap,
+						apds9960_reg_field_int_als);
+	if (IS_ERR(data->reg_int_als)) {
+		dev_err(dev, "INT ALS reg field init failed\n");
+		return PTR_ERR(data->reg_int_als);
+	}
+
+	data->reg_int_ges = devm_regmap_field_alloc(dev, regmap,
+						apds9960_reg_field_int_ges);
+	if (IS_ERR(data->reg_int_ges)) {
+		dev_err(dev, "INT gesture reg field init failed\n");
+		return PTR_ERR(data->reg_int_ges);
+	}
+
+	data->reg_int_pxs = devm_regmap_field_alloc(dev, regmap,
+						apds9960_reg_field_int_pxs);
+	if (IS_ERR(data->reg_int_pxs)) {
+		dev_err(dev, "INT pxs reg field init failed\n");
+		return PTR_ERR(data->reg_int_pxs);
+	}
+
+	data->reg_enable_als = devm_regmap_field_alloc(dev, regmap,
+						apds9960_reg_field_enable_als);
+	if (IS_ERR(data->reg_enable_als)) {
+		dev_err(dev, "Enable ALS reg field init failed\n");
+		return PTR_ERR(data->reg_enable_als);
+	}
+
+	data->reg_enable_ges = devm_regmap_field_alloc(dev, regmap,
+						apds9960_reg_field_enable_ges);
+	if (IS_ERR(data->reg_enable_ges)) {
+		dev_err(dev, "Enable gesture reg field init failed\n");
+		return PTR_ERR(data->reg_enable_ges);
+	}
+
+	data->reg_enable_pxs = devm_regmap_field_alloc(dev, regmap,
+						apds9960_reg_field_enable_pxs);
+	if (IS_ERR(data->reg_enable_pxs)) {
+		dev_err(dev, "Enable PXS reg field init failed\n");
+		return PTR_ERR(data->reg_enable_pxs);
+	}
+
+	return 0;
+}
+
+static int apds9960_chip_init(struct apds9960_data *data)
+{
+	int ret;
+
+	/* Default IT for ALS of 28 ms */
+	ret = apds9960_set_it_time(data, 28000);
+	if (ret)
+		return ret;
+
+	/* Ensure gesture interrupt is OFF */
+	ret = regmap_field_write(data->reg_int_ges, 0);
+	if (ret)
+		return ret;
+
+	/* Disable gesture sensor, since polling is useless from user-space */
+	ret = regmap_field_write(data->reg_enable_ges, 0);
+	if (ret)
+		return ret;
+
+	/* Ensure proximity interrupt is OFF */
+	ret = regmap_field_write(data->reg_int_pxs, 0);
+	if (ret)
+		return ret;
+
+	/* Enable proximity sensor for polling */
+	ret = regmap_field_write(data->reg_enable_pxs, 1);
+	if (ret)
+		return ret;
+
+	/* Ensure ALS interrupt is OFF */
+	ret = regmap_field_write(data->reg_int_als, 0);
+	if (ret)
+		return ret;
+
+	/* Enable ALS sensor for polling */
+	ret = regmap_field_write(data->reg_enable_als, 1);
+	if (ret)
+		return ret;
+	/*
+	 * When enabled trigger an interrupt after 3 readings
+	 * outside threshold for ALS + PXS
+	 */
+	ret = regmap_write(data->regmap, APDS9960_REG_PERS,
+			   APDS9960_DEFAULT_PERS);
+	if (ret)
+		return ret;
+
+	/*
+	 * Wait for 4 event outside gesture threshold to prevent interrupt
+	 * flooding.
+	 */
+	ret = regmap_update_bits(data->regmap, APDS9960_REG_GCONF_1,
+			APDS9960_REG_GCONF_1_GFIFO_THRES_MASK,
+			BIT(0) << APDS9960_REG_GCONF_1_GFIFO_THRES_MASK_SHIFT);
+	if (ret)
+		return ret;
+
+	/* Default ENTER and EXIT thresholds for the GESTURE engine. */
+	ret = regmap_write(data->regmap, APDS9960_REG_GPENTH,
+			   APDS9960_DEFAULT_GPENTH);
+	if (ret)
+		return ret;
+
+	ret = regmap_write(data->regmap, APDS9960_REG_GEXTH,
+			   APDS9960_DEFAULT_GEXTH);
+	if (ret)
+		return ret;
+
+	return apds9960_set_powermode(data, 1);
+}
+
+static int apds9960_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	struct apds9960_data *data;
+	struct iio_buffer *buffer;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	buffer = devm_iio_kfifo_allocate(&client->dev);
+	if (!buffer)
+		return -ENOMEM;
+
+	iio_device_attach_buffer(indio_dev, buffer);
+
+	indio_dev->info = &apds9960_info;
+	indio_dev->name = APDS9960_DRV_NAME;
+	indio_dev->channels = apds9960_channels;
+	indio_dev->num_channels = ARRAY_SIZE(apds9960_channels);
+	indio_dev->available_scan_masks = apds9960_scan_masks;
+	indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
+	indio_dev->setup_ops = &apds9960_buffer_setup_ops;
+
+	data = iio_priv(indio_dev);
+	i2c_set_clientdata(client, indio_dev);
+
+	data->regmap = devm_regmap_init_i2c(client, &apds9960_regmap_config);
+	if (IS_ERR(data->regmap)) {
+		dev_err(&client->dev, "regmap initialization failed.\n");
+		return PTR_ERR(data->regmap);
+	}
+
+	data->client = client;
+	data->indio_dev = indio_dev;
+	mutex_init(&data->lock);
+
+	ret = pm_runtime_set_active(&client->dev);
+	if (ret)
+		goto error_power_down;
+
+	pm_runtime_enable(&client->dev);
+	pm_runtime_set_autosuspend_delay(&client->dev, 5000);
+	pm_runtime_use_autosuspend(&client->dev);
+
+	apds9960_set_power_state(data, true);
+
+	ret = apds9960_regfield_init(data);
+	if (ret)
+		goto error_power_down;
+
+	ret = apds9960_chip_init(data);
+	if (ret)
+		goto error_power_down;
+
+	if (client->irq <= 0) {
+		dev_err(&client->dev, "no valid irq defined\n");
+		ret = -EINVAL;
+		goto error_power_down;
+	}
+	ret = devm_request_threaded_irq(&client->dev, client->irq,
+					NULL, apds9960_interrupt_handler,
+					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+					"apds9960_event",
+					indio_dev);
+	if (ret) {
+		dev_err(&client->dev, "request irq (%d) failed\n", client->irq);
+		goto error_power_down;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto error_power_down;
+
+	apds9960_set_power_state(data, false);
+
+	return 0;
+
+error_power_down:
+	apds9960_set_power_state(data, false);
+
+	return ret;
+}
+
+static int apds9960_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct apds9960_data *data = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	pm_runtime_disable(&client->dev);
+	pm_runtime_set_suspended(&client->dev);
+	apds9960_set_powermode(data, 0);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int apds9960_runtime_suspend(struct device *dev)
+{
+	struct apds9960_data *data =
+			iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
+
+	return apds9960_set_powermode(data, 0);
+}
+
+static int apds9960_runtime_resume(struct device *dev)
+{
+	struct apds9960_data *data =
+			iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
+
+	return apds9960_set_powermode(data, 1);
+}
+#endif
+
+static const struct dev_pm_ops apds9960_pm_ops = {
+	SET_RUNTIME_PM_OPS(apds9960_runtime_suspend,
+			   apds9960_runtime_resume, NULL)
+};
+
+static const struct i2c_device_id apds9960_id[] = {
+	{ "apds9960", 0 },
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, apds9960_id);
+
+static struct i2c_driver apds9960_driver = {
+	.driver = {
+		.name	= APDS9960_DRV_NAME,
+		.pm	= &apds9960_pm_ops,
+	},
+	.probe		= apds9960_probe,
+	.remove		= apds9960_remove,
+	.id_table	= apds9960_id,
+};
+module_i2c_driver(apds9960_driver);
+
+MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>");
+MODULE_DESCRIPTION("ADPS9960 Gesture/RGB/ALS/Proximity sensor");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c
index 923aa6a..01e111e7 100644
--- a/drivers/iio/light/opt3001.c
+++ b/drivers/iio/light/opt3001.c
@@ -793,7 +793,6 @@
 	.driver = {
 		.name = "opt3001",
 		.of_match_table = of_match_ptr(opt3001_of_match),
-		.owner = THIS_MODULE,
 	},
 };
 
diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c
index 993eb20..013b217 100644
--- a/drivers/iio/light/stk3310.c
+++ b/drivers/iio/light/stk3310.c
@@ -35,8 +35,8 @@
 #define STK3310_REG_ID				0x3E
 #define STK3310_MAX_REG				0x80
 
-#define STK3310_STATE_EN_PS			0x01
-#define STK3310_STATE_EN_ALS			0x02
+#define STK3310_STATE_EN_PS			BIT(0)
+#define STK3310_STATE_EN_ALS			BIT(1)
 #define STK3310_STATE_STANDBY			0x00
 
 #define STK3310_CHIP_ID_VAL			0x13
@@ -241,8 +241,11 @@
 	struct stk3310_data *data = iio_priv(indio_dev);
 	struct i2c_client *client = data->client;
 
-	regmap_field_read(data->reg_ps_gain, &index);
-	if (val > stk3310_ps_max[index])
+	ret = regmap_field_read(data->reg_ps_gain, &index);
+	if (ret < 0)
+		return ret;
+
+	if (val < 0 || val > stk3310_ps_max[index])
 		return -EINVAL;
 
 	if (dir == IIO_EV_DIR_RISING)
@@ -266,9 +269,12 @@
 				     enum iio_event_direction dir)
 {
 	unsigned int event_val;
+	int ret;
 	struct stk3310_data *data = iio_priv(indio_dev);
 
-	regmap_field_read(data->reg_int_ps, &event_val);
+	ret = regmap_field_read(data->reg_int_ps, &event_val);
+	if (ret < 0)
+		return ret;
 
 	return event_val;
 }
@@ -307,14 +313,16 @@
 	struct stk3310_data *data = iio_priv(indio_dev);
 	struct i2c_client *client = data->client;
 
+	if (chan->type != IIO_LIGHT && chan->type != IIO_PROXIMITY)
+		return -EINVAL;
+
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
 		if (chan->type == IIO_LIGHT)
 			reg = STK3310_REG_ALS_DATA_MSB;
-		else if (chan->type == IIO_PROXIMITY)
-			reg = STK3310_REG_PS_DATA_MSB;
 		else
-			return -EINVAL;
+			reg = STK3310_REG_PS_DATA_MSB;
+
 		mutex_lock(&data->lock);
 		ret = regmap_bulk_read(data->regmap, reg, &buf, 2);
 		if (ret < 0) {
@@ -327,17 +335,23 @@
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_INT_TIME:
 		if (chan->type == IIO_LIGHT)
-			regmap_field_read(data->reg_als_it, &index);
+			ret = regmap_field_read(data->reg_als_it, &index);
 		else
-			regmap_field_read(data->reg_ps_it, &index);
+			ret = regmap_field_read(data->reg_ps_it, &index);
+		if (ret < 0)
+			return ret;
+
 		*val = stk3310_it_table[index][0];
 		*val2 = stk3310_it_table[index][1];
 		return IIO_VAL_INT_PLUS_MICRO;
 	case IIO_CHAN_INFO_SCALE:
 		if (chan->type == IIO_LIGHT)
-			regmap_field_read(data->reg_als_gain, &index);
+			ret = regmap_field_read(data->reg_als_gain, &index);
 		else
-			regmap_field_read(data->reg_ps_gain, &index);
+			ret = regmap_field_read(data->reg_ps_gain, &index);
+		if (ret < 0)
+			return ret;
+
 		*val = stk3310_scale_table[index][0];
 		*val2 = stk3310_scale_table[index][1];
 		return IIO_VAL_INT_PLUS_MICRO;
@@ -354,6 +368,9 @@
 	int index;
 	struct stk3310_data *data = iio_priv(indio_dev);
 
+	if (chan->type != IIO_LIGHT && chan->type != IIO_PROXIMITY)
+		return -EINVAL;
+
 	switch (mask) {
 	case IIO_CHAN_INFO_INT_TIME:
 		index = stk3310_get_index(stk3310_it_table,
@@ -368,7 +385,7 @@
 			ret = regmap_field_write(data->reg_ps_it, index);
 		if (ret < 0)
 			dev_err(&data->client->dev,
-					"sensor configuration failed\n");
+				"sensor configuration failed\n");
 		mutex_unlock(&data->lock);
 		return ret;
 
@@ -385,7 +402,7 @@
 			ret = regmap_field_write(data->reg_ps_gain, index);
 		if (ret < 0)
 			dev_err(&data->client->dev,
-					"sensor configuration failed\n");
+				"sensor configuration failed\n");
 		mutex_unlock(&data->lock);
 		return ret;
 	}
@@ -419,8 +436,8 @@
 		dev_err(&client->dev, "failed to change sensor state\n");
 	} else if (state != STK3310_STATE_STANDBY) {
 		/* Don't reset the 'enabled' flags if we're going in standby */
-		data->ps_enabled  = !!(state & 0x01);
-		data->als_enabled = !!(state & 0x02);
+		data->ps_enabled  = !!(state & STK3310_STATE_EN_PS);
+		data->als_enabled = !!(state & STK3310_STATE_EN_ALS);
 	}
 	mutex_unlock(&data->lock);
 
@@ -435,7 +452,10 @@
 	struct stk3310_data *data = iio_priv(indio_dev);
 	struct i2c_client *client = data->client;
 
-	regmap_read(data->regmap, STK3310_REG_ID, &chipid);
+	ret = regmap_read(data->regmap, STK3310_REG_ID, &chipid);
+	if (ret < 0)
+		return ret;
+
 	if (chipid != STK3310_CHIP_ID_VAL &&
 	    chipid != STK3311_CHIP_ID_VAL) {
 		dev_err(&client->dev, "invalid chip id: 0x%x\n", chipid);
@@ -604,8 +624,13 @@
 	if (ret < 0)
 		return ret;
 
-	if (client->irq < 0)
+	if (client->irq < 0) {
 		client->irq = stk3310_gpio_probe(client);
+		if (client->irq < 0) {
+			ret = client->irq;
+			goto err_standby;
+		}
+	}
 
 	if (client->irq >= 0) {
 		ret = devm_request_threaded_irq(&client->dev, client->irq,
@@ -614,17 +639,23 @@
 						IRQF_TRIGGER_FALLING |
 						IRQF_ONESHOT,
 						STK3310_EVENT, indio_dev);
-		if (ret < 0)
+		if (ret < 0) {
 			dev_err(&client->dev, "request irq %d failed\n",
-					client->irq);
+				client->irq);
+			goto err_standby;
+		}
 	}
 
 	ret = iio_device_register(indio_dev);
 	if (ret < 0) {
 		dev_err(&client->dev, "device_register failed\n");
-		stk3310_set_state(data, STK3310_STATE_STANDBY);
+		goto err_standby;
 	}
 
+	return 0;
+
+err_standby:
+	stk3310_set_state(data, STK3310_STATE_STANDBY);
 	return ret;
 }
 
@@ -648,7 +679,7 @@
 
 static int stk3310_resume(struct device *dev)
 {
-	int state = 0;
+	u8 state = 0;
 	struct stk3310_data *data;
 
 	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 2697918..cf94ec7 100644
--- a/drivers/iio/light/tsl4531.c
+++ b/drivers/iio/light/tsl4531.c
@@ -158,9 +158,9 @@
 	case TSL45313_ID:
 	case TSL45315_ID:
 	case TSL45317_ID:
-		return 1;
-	default:
 		return 0;
+	default:
+		return -ENODEV;
 	}
 }
 
@@ -180,9 +180,10 @@
 	data->client = client;
 	mutex_init(&data->lock);
 
-	if (!tsl4531_check_id(client)) {
+	ret = tsl4531_check_id(client);
+	if (ret) {
 		dev_err(&client->dev, "no TSL4531 sensor\n");
-		return -ENODEV;
+		return ret;
 	}
 
 	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 0000000..49dab3c
--- /dev/null
+++ b/drivers/iio/light/us5182d.c
@@ -0,0 +1,507 @@
+/*
+ * Copyright (c) 2015 Intel Corporation
+ *
+ * Driver for UPISEMI us5182d Proximity and Ambient Light Sensor.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * To do: Interrupt support.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/mutex.h>
+
+#define US5182D_REG_CFG0				0x00
+#define US5182D_CFG0_ONESHOT_EN				BIT(6)
+#define US5182D_CFG0_SHUTDOWN_EN			BIT(7)
+#define US5182D_CFG0_WORD_ENABLE			BIT(0)
+
+#define US5182D_REG_CFG1				0x01
+#define US5182D_CFG1_ALS_RES16				BIT(4)
+#define US5182D_CFG1_AGAIN_DEFAULT			0x00
+
+#define US5182D_REG_CFG2				0x02
+#define US5182D_CFG2_PX_RES16				BIT(4)
+#define US5182D_CFG2_PXGAIN_DEFAULT			BIT(2)
+
+#define US5182D_REG_CFG3				0x03
+#define US5182D_CFG3_LED_CURRENT100			(BIT(4) | BIT(5))
+
+#define US5182D_REG_CFG4				0x10
+
+/*
+ * Registers for tuning the auto dark current cancelling feature.
+ * DARK_TH(reg 0x27,0x28) - threshold (counts) for auto dark cancelling.
+ * when ALS  > DARK_TH --> ALS_Code = ALS - Upper(0x2A) * Dark
+ * when ALS < DARK_TH --> ALS_Code = ALS - Lower(0x29) * Dark
+ */
+#define US5182D_REG_UDARK_TH			0x27
+#define US5182D_REG_DARK_AUTO_EN		0x2b
+#define US5182D_REG_AUTO_LDARK_GAIN		0x29
+#define US5182D_REG_AUTO_HDARK_GAIN		0x2a
+
+#define US5182D_OPMODE_ALS			0x01
+#define US5182D_OPMODE_PX			0x02
+#define US5182D_OPMODE_SHIFT			4
+
+#define US5182D_REG_DARK_AUTO_EN_DEFAULT	0x80
+#define US5182D_REG_AUTO_LDARK_GAIN_DEFAULT	0x16
+#define US5182D_REG_AUTO_HDARK_GAIN_DEFAULT	0x00
+
+#define US5182D_REG_ADL				0x0c
+#define US5182D_REG_PDL				0x0e
+
+#define US5182D_REG_MODE_STORE			0x21
+#define US5182D_STORE_MODE			0x01
+
+#define US5182D_REG_CHIPID			0xb2
+
+#define US5182D_OPMODE_MASK			GENMASK(5, 4)
+#define US5182D_AGAIN_MASK			0x07
+#define US5182D_RESET_CHIP			0x01
+
+#define US5182D_CHIPID				0x26
+#define US5182D_DRV_NAME			"us5182d"
+
+#define US5182D_GA_RESOLUTION			1000
+
+#define US5182D_READ_BYTE			1
+#define US5182D_READ_WORD			2
+#define US5182D_OPSTORE_SLEEP_TIME		20 /* ms */
+
+/* Available ranges: [12354, 7065, 3998, 2202, 1285, 498, 256, 138] lux */
+static const int us5182d_scales[] = {188500, 107800, 61000, 33600, 19600, 7600,
+				     3900, 2100};
+
+/*
+ * Experimental thresholds that work with US5182D sensor on evaluation board
+ * roughly between 12-32 lux
+ */
+static u16 us5182d_dark_ths_vals[] = {170, 200, 512, 512, 800, 2000, 4000,
+				      8000};
+
+enum mode {
+	US5182D_ALS_PX,
+	US5182D_ALS_ONLY,
+	US5182D_PX_ONLY
+};
+
+struct us5182d_data {
+	struct i2c_client *client;
+	struct mutex lock;
+
+	/* Glass attenuation factor */
+	u32 ga;
+
+	/* Dark gain tuning */
+	u8 lower_dark_gain;
+	u8 upper_dark_gain;
+	u16 *us5182d_dark_ths;
+
+	u8 opmode;
+};
+
+static IIO_CONST_ATTR(in_illuminance_scale_available,
+		      "0.0021 0.0039 0.0076 0.0196 0.0336 0.061 0.1078 0.1885");
+
+static struct attribute *us5182d_attrs[] = {
+	&iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group us5182d_attr_group = {
+	.attrs = us5182d_attrs,
+};
+
+static const struct {
+	u8 reg;
+	u8 val;
+} us5182d_regvals[] = {
+	{US5182D_REG_CFG0, (US5182D_CFG0_SHUTDOWN_EN |
+			    US5182D_CFG0_WORD_ENABLE)},
+	{US5182D_REG_CFG1, US5182D_CFG1_ALS_RES16},
+	{US5182D_REG_CFG2, (US5182D_CFG2_PX_RES16 |
+			    US5182D_CFG2_PXGAIN_DEFAULT)},
+	{US5182D_REG_CFG3, US5182D_CFG3_LED_CURRENT100},
+	{US5182D_REG_MODE_STORE, US5182D_STORE_MODE},
+	{US5182D_REG_CFG4, 0x00},
+};
+
+static const struct iio_chan_spec us5182d_channels[] = {
+	{
+		.type = IIO_LIGHT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_SCALE),
+	},
+	{
+		.type = IIO_PROXIMITY,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+	}
+};
+
+static int us5182d_get_als(struct us5182d_data *data)
+{
+	int ret;
+	unsigned long result;
+
+	ret = i2c_smbus_read_word_data(data->client,
+				       US5182D_REG_ADL);
+	if (ret < 0)
+		return ret;
+
+	result = ret * data->ga / US5182D_GA_RESOLUTION;
+	if (result > 0xffff)
+		result = 0xffff;
+
+	return result;
+}
+
+static int us5182d_set_opmode(struct us5182d_data *data, u8 mode)
+{
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * In oneshot mode the chip will power itself down after taking the
+	 * required measurement.
+	 */
+	ret = ret | US5182D_CFG0_ONESHOT_EN;
+
+	/* update mode */
+	ret = ret & ~US5182D_OPMODE_MASK;
+	ret = ret | (mode << US5182D_OPMODE_SHIFT);
+
+	/*
+	 * After updating the operating mode, the chip requires that
+	 * the operation is stored, by writing 1 in the STORE_MODE
+	 * register (auto-clearing).
+	 */
+	ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret);
+	if (ret < 0)
+		return ret;
+
+	if (mode == data->opmode)
+		return 0;
+
+	ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_MODE_STORE,
+					US5182D_STORE_MODE);
+	if (ret < 0)
+		return ret;
+
+	data->opmode = mode;
+	msleep(US5182D_OPSTORE_SLEEP_TIME);
+
+	return 0;
+}
+
+static int us5182d_read_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan, int *val,
+			    int *val2, long mask)
+{
+	struct us5182d_data *data = iio_priv(indio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		switch (chan->type) {
+		case IIO_LIGHT:
+			mutex_lock(&data->lock);
+			ret = us5182d_set_opmode(data, US5182D_OPMODE_ALS);
+			if (ret < 0)
+				goto out_err;
+
+			ret = us5182d_get_als(data);
+			if (ret < 0)
+				goto out_err;
+			mutex_unlock(&data->lock);
+			*val = ret;
+			return IIO_VAL_INT;
+		case IIO_PROXIMITY:
+			mutex_lock(&data->lock);
+			ret = us5182d_set_opmode(data, US5182D_OPMODE_PX);
+			if (ret < 0)
+				goto out_err;
+
+			ret = i2c_smbus_read_word_data(data->client,
+						       US5182D_REG_PDL);
+			if (ret < 0)
+				goto out_err;
+			mutex_unlock(&data->lock);
+			*val = ret;
+			return  IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
+
+	case IIO_CHAN_INFO_SCALE:
+		ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1);
+		if (ret < 0)
+			return ret;
+
+		*val = 0;
+		*val2 = us5182d_scales[ret & US5182D_AGAIN_MASK];
+
+		return IIO_VAL_INT_PLUS_MICRO;
+	default:
+		return -EINVAL;
+	}
+
+	return -EINVAL;
+out_err:
+	mutex_unlock(&data->lock);
+	return ret;
+}
+
+/**
+ * us5182d_update_dark_th - update Darh_Th registers
+ * @data	us5182d_data structure
+ * @index	index in us5182d_dark_ths array to use for the updated value
+ *
+ * Function needs to be called with a lock held because it needs two i2c write
+ * byte operations as these registers (0x27 0x28) don't work in word mode
+ * accessing.
+ */
+static int us5182d_update_dark_th(struct us5182d_data *data, int index)
+{
+	__be16 dark_th = cpu_to_be16(data->us5182d_dark_ths[index]);
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_UDARK_TH,
+					((u8 *)&dark_th)[0]);
+	if (ret < 0)
+		return ret;
+
+	return i2c_smbus_write_byte_data(data->client, US5182D_REG_UDARK_TH + 1,
+					((u8 *)&dark_th)[1]);
+}
+
+/**
+ * us5182d_apply_scale - update the ALS scale
+ * @data	us5182d_data structure
+ * @index	index in us5182d_scales array to use for the updated value
+ *
+ * Function needs to be called with a lock held as we're having more than one
+ * i2c operation.
+ */
+static int us5182d_apply_scale(struct us5182d_data *data, int index)
+{
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1);
+	if (ret < 0)
+		return ret;
+
+	ret = ret & (~US5182D_AGAIN_MASK);
+	ret |= index;
+
+	ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG1, ret);
+	if (ret < 0)
+		return ret;
+
+	return us5182d_update_dark_th(data, index);
+}
+
+static int us5182d_write_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan, int val,
+			     int val2, long mask)
+{
+	struct us5182d_data *data = iio_priv(indio_dev);
+	int ret, i;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SCALE:
+		if (val != 0)
+			return -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(us5182d_scales); i++)
+			if (val2 == us5182d_scales[i]) {
+				mutex_lock(&data->lock);
+				ret = us5182d_apply_scale(data, i);
+				mutex_unlock(&data->lock);
+				return ret;
+			}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return -EINVAL;
+}
+
+static const struct iio_info us5182d_info = {
+	.driver_module	= THIS_MODULE,
+	.read_raw = us5182d_read_raw,
+	.write_raw = us5182d_write_raw,
+	.attrs = &us5182d_attr_group,
+};
+
+static int us5182d_reset(struct iio_dev *indio_dev)
+{
+	struct us5182d_data *data = iio_priv(indio_dev);
+
+	return i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG3,
+					 US5182D_RESET_CHIP);
+}
+
+static int us5182d_init(struct iio_dev *indio_dev)
+{
+	struct us5182d_data *data = iio_priv(indio_dev);
+	int i, ret;
+
+	ret = us5182d_reset(indio_dev);
+	if (ret < 0)
+		return ret;
+
+	data->opmode = 0;
+	for (i = 0; i < ARRAY_SIZE(us5182d_regvals); i++) {
+		ret = i2c_smbus_write_byte_data(data->client,
+						us5182d_regvals[i].reg,
+						us5182d_regvals[i].val);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void us5182d_get_platform_data(struct iio_dev *indio_dev)
+{
+	struct us5182d_data *data = iio_priv(indio_dev);
+
+	if (device_property_read_u32(&data->client->dev, "upisemi,glass-coef",
+				     &data->ga))
+		data->ga = US5182D_GA_RESOLUTION;
+	if (device_property_read_u16_array(&data->client->dev,
+					   "upisemi,dark-ths",
+					   data->us5182d_dark_ths,
+					   ARRAY_SIZE(us5182d_dark_ths_vals)))
+		data->us5182d_dark_ths = us5182d_dark_ths_vals;
+	if (device_property_read_u8(&data->client->dev,
+				    "upisemi,upper-dark-gain",
+				    &data->upper_dark_gain))
+		data->upper_dark_gain = US5182D_REG_AUTO_HDARK_GAIN_DEFAULT;
+	if (device_property_read_u8(&data->client->dev,
+				    "upisemi,lower-dark-gain",
+				    &data->lower_dark_gain))
+		data->lower_dark_gain = US5182D_REG_AUTO_LDARK_GAIN_DEFAULT;
+}
+
+static int  us5182d_dark_gain_config(struct iio_dev *indio_dev)
+{
+	struct us5182d_data *data = iio_priv(indio_dev);
+	int ret;
+
+	ret = us5182d_update_dark_th(data, US5182D_CFG1_AGAIN_DEFAULT);
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_smbus_write_byte_data(data->client,
+					US5182D_REG_AUTO_LDARK_GAIN,
+					data->lower_dark_gain);
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_smbus_write_byte_data(data->client,
+					US5182D_REG_AUTO_HDARK_GAIN,
+					data->upper_dark_gain);
+	if (ret < 0)
+		return ret;
+
+	return i2c_smbus_write_byte_data(data->client, US5182D_REG_DARK_AUTO_EN,
+					 US5182D_REG_DARK_AUTO_EN_DEFAULT);
+}
+
+static int us5182d_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct us5182d_data *data;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	i2c_set_clientdata(client, indio_dev);
+	data->client = client;
+
+	mutex_init(&data->lock);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &us5182d_info;
+	indio_dev->name = US5182D_DRV_NAME;
+	indio_dev->channels = us5182d_channels;
+	indio_dev->num_channels = ARRAY_SIZE(us5182d_channels);
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CHIPID);
+	if (ret != US5182D_CHIPID) {
+		dev_err(&data->client->dev,
+			"Failed to detect US5182 light chip\n");
+		return (ret < 0) ? ret : -ENODEV;
+	}
+
+	us5182d_get_platform_data(indio_dev);
+	ret = us5182d_init(indio_dev);
+	if (ret < 0)
+		return ret;
+
+	ret = us5182d_dark_gain_config(indio_dev);
+	if (ret < 0)
+		return ret;
+
+	return iio_device_register(indio_dev);
+}
+
+static int us5182d_remove(struct i2c_client *client)
+{
+	iio_device_unregister(i2c_get_clientdata(client));
+	return i2c_smbus_write_byte_data(client, US5182D_REG_CFG0,
+					 US5182D_CFG0_SHUTDOWN_EN);
+}
+
+static const struct acpi_device_id us5182d_acpi_match[] = {
+	{ "USD5182", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(acpi, us5182d_acpi_match);
+
+static const struct i2c_device_id us5182d_id[] = {
+		{"usd5182", 0},
+		{}
+};
+
+MODULE_DEVICE_TABLE(i2c, us5182d_id);
+
+static struct i2c_driver us5182d_driver = {
+	.driver = {
+		.name = US5182D_DRV_NAME,
+		.acpi_match_table = ACPI_PTR(us5182d_acpi_match),
+	},
+	.probe = us5182d_probe,
+	.remove = us5182d_remove,
+	.id_table = us5182d_id,
+
+};
+module_i2c_driver(us5182d_driver);
+
+MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>");
+MODULE_DESCRIPTION("Driver for us5182d Proximity and Light Sensor");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig
index efb9350..868abad 100644
--- a/drivers/iio/magnetometer/Kconfig
+++ b/drivers/iio/magnetometer/Kconfig
@@ -24,6 +24,24 @@
 	help
 	  Deprecated: AK09911 is now supported by AK8975 driver.
 
+config BMC150_MAGN
+	tristate "Bosch BMC150 Magnetometer Driver"
+	depends on I2C
+	select REGMAP_I2C
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	help
+	  Say yes here to build support for the BMC150 magnetometer.
+
+	  Currently this only supports the device via an i2c interface.
+
+	  This is a combo module with both accelerometer and magnetometer.
+	  This driver is only implementing magnetometer part, which has
+	  its own address and register map.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called bmc150_magn.
+
 config MAG3110
 	tristate "Freescale MAG3110 3-Axis Magnetometer"
 	depends on I2C
@@ -87,19 +105,4 @@
 	depends on IIO_ST_MAGN_3AXIS
 	depends on IIO_ST_SENSORS_SPI
 
-config BMC150_MAGN
-	tristate "Bosch BMC150 Magnetometer Driver"
-	depends on I2C
-	select REGMAP_I2C
-	select IIO_BUFFER
-	select IIO_TRIGGERED_BUFFER
-	help
-	  Say yes here to build support for the BMC150 magnetometer.
-
-	  Currently this only supports the device via an i2c interface.
-
-	  This is a combo module with both accelerometer and magnetometer.
-	  This driver is only implementing magnetometer part, which has
-	  its own address and register map.
-
 endmenu
diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile
index 33b1d4d..2c72df4 100644
--- a/drivers/iio/magnetometer/Makefile
+++ b/drivers/iio/magnetometer/Makefile
@@ -4,6 +4,7 @@
 
 # When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AK8975)	+= ak8975.o
+obj-$(CONFIG_BMC150_MAGN) += bmc150_magn.o
 obj-$(CONFIG_MAG3110)	+= mag3110.o
 obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o
 obj-$(CONFIG_MMC35240)	+= mmc35240.o
@@ -14,5 +15,3 @@
 
 obj-$(CONFIG_IIO_ST_MAGN_I2C_3AXIS) += st_magn_i2c.o
 obj-$(CONFIG_IIO_ST_MAGN_SPI_3AXIS) += st_magn_spi.o
-
-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 f8dc4b8..b27f014 100644
--- a/drivers/iio/magnetometer/st_magn_core.c
+++ b/drivers/iio/magnetometer/st_magn_core.c
@@ -560,6 +560,7 @@
 	.attrs = &st_magn_attribute_group,
 	.read_raw = &st_magn_read_raw,
 	.write_raw = &st_magn_write_raw,
+	.debugfs_reg_access = &st_sensors_debugfs_reg_access,
 };
 
 #ifdef CONFIG_IIO_TRIGGER
diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c
index eb41d2b..b39a2fb 100644
--- a/drivers/iio/pressure/st_pressure_core.c
+++ b/drivers/iio/pressure/st_pressure_core.c
@@ -400,6 +400,7 @@
 	.attrs = &st_press_attribute_group,
 	.read_raw = &st_press_read_raw,
 	.write_raw = &st_press_write_raw,
+	.debugfs_reg_access = &st_sensors_debugfs_reg_access,
 };
 
 #ifdef CONFIG_IIO_TRIGGER
diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig
index 41a8d8f..ef4c73d 100644
--- a/drivers/iio/proximity/Kconfig
+++ b/drivers/iio/proximity/Kconfig
@@ -20,6 +20,18 @@
 
 menu "Proximity sensors"
 
+config LIDAR_LITE_V2
+	tristate "PulsedLight LIDAR sensor"
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	depends on I2C
+	help
+	  Say Y to build a driver for PulsedLight LIDAR range finding
+	  sensor.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pulsedlight-lite-v2
+
 config SX9500
 	tristate "SX9500 Semtech proximity sensor"
 	select IIO_BUFFER
diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile
index 9818dc5..9aadd9a 100644
--- a/drivers/iio/proximity/Makefile
+++ b/drivers/iio/proximity/Makefile
@@ -4,4 +4,5 @@
 
 # When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AS3935)		+= as3935.o
+obj-$(CONFIG_LIDAR_LITE_V2)	+= pulsedlight-lidar-lite-v2.o
 obj-$(CONFIG_SX9500)		+= sx9500.o
diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c
index bc0d68e..e950351 100644
--- a/drivers/iio/proximity/as3935.c
+++ b/drivers/iio/proximity/as3935.c
@@ -434,6 +434,12 @@
 	return 0;
 }
 
+static const struct of_device_id as3935_of_match[] = {
+	{ .compatible = "ams,as3935", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, as3935_of_match);
+
 static const struct spi_device_id as3935_id[] = {
 	{"as3935", 0},
 	{},
@@ -443,6 +449,7 @@
 static struct spi_driver as3935_driver = {
 	.driver = {
 		.name	= "as3935",
+		.of_match_table = of_match_ptr(as3935_of_match),
 		.owner	= THIS_MODULE,
 		.pm	= AS3935_PM_OPS,
 	},
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 0000000..185a7ab
--- /dev/null
+++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
@@ -0,0 +1,288 @@
+/*
+ * pulsedlight-lidar-lite-v2.c - Support for PulsedLight LIDAR sensor
+ *
+ * Copyright (C) 2015 Matt Ranostay <mranostay@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * TODO: runtime pm, interrupt mode, and signal strength reporting
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
+
+#define LIDAR_REG_CONTROL		0x00
+#define LIDAR_REG_CONTROL_ACQUIRE	BIT(2)
+
+#define LIDAR_REG_STATUS		0x01
+#define LIDAR_REG_STATUS_INVALID	BIT(3)
+#define LIDAR_REG_STATUS_READY		BIT(0)
+
+#define LIDAR_REG_DATA_HBYTE	0x0f
+#define LIDAR_REG_DATA_LBYTE	0x10
+
+#define LIDAR_DRV_NAME "lidar"
+
+struct lidar_data {
+	struct iio_dev *indio_dev;
+	struct i2c_client *client;
+
+	u16 buffer[8]; /* 2 byte distance + 8 byte timestamp */
+};
+
+static const struct iio_chan_spec lidar_channels[] = {
+	{
+		.type = IIO_DISTANCE,
+		.info_mask_separate =
+			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+		.scan_index = 0,
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 16,
+			.storagebits = 16,
+		},
+	},
+	IIO_CHAN_SOFT_TIMESTAMP(1),
+};
+
+static int lidar_read_byte(struct lidar_data *data, int reg)
+{
+	struct i2c_client *client = data->client;
+	int ret;
+
+	/*
+	 * Device needs a STOP condition between address write, and data read
+	 * so in turn i2c_smbus_read_byte_data cannot be used
+	 */
+
+	ret = i2c_smbus_write_byte(client, reg);
+	if (ret < 0) {
+		dev_err(&client->dev, "cannot write addr value");
+		return ret;
+	}
+
+	ret = i2c_smbus_read_byte(client);
+	if (ret < 0)
+		dev_err(&client->dev, "cannot read data value");
+
+	return ret;
+}
+
+static inline int lidar_write_control(struct lidar_data *data, int val)
+{
+	return i2c_smbus_write_byte_data(data->client, LIDAR_REG_CONTROL, val);
+}
+
+static int lidar_read_measurement(struct lidar_data *data, u16 *reg)
+{
+	int ret;
+	int val;
+
+	ret = lidar_read_byte(data, LIDAR_REG_DATA_HBYTE);
+	if (ret < 0)
+		return ret;
+	val = ret << 8;
+
+	ret = lidar_read_byte(data, LIDAR_REG_DATA_LBYTE);
+	if (ret < 0)
+		return ret;
+
+	val |= ret;
+	*reg = val;
+
+	return 0;
+}
+
+static int lidar_get_measurement(struct lidar_data *data, u16 *reg)
+{
+	struct i2c_client *client = data->client;
+	int tries = 10;
+	int ret;
+
+	/* start sample */
+	ret = lidar_write_control(data, LIDAR_REG_CONTROL_ACQUIRE);
+	if (ret < 0) {
+		dev_err(&client->dev, "cannot send start measurement command");
+		return ret;
+	}
+
+	while (tries--) {
+		usleep_range(1000, 2000);
+
+		ret = lidar_read_byte(data, LIDAR_REG_STATUS);
+		if (ret < 0)
+			break;
+
+		/* return 0 since laser is likely pointed out of range */
+		if (ret & LIDAR_REG_STATUS_INVALID) {
+			*reg = 0;
+			ret = 0;
+			break;
+		}
+
+		/* sample ready to read */
+		if (!(ret & LIDAR_REG_STATUS_READY)) {
+			ret = lidar_read_measurement(data, reg);
+			break;
+		}
+		ret = -EIO;
+	}
+
+	return ret;
+}
+
+static int lidar_read_raw(struct iio_dev *indio_dev,
+			  struct iio_chan_spec const *chan,
+			  int *val, int *val2, long mask)
+{
+	struct lidar_data *data = iio_priv(indio_dev);
+	int ret = -EINVAL;
+
+	mutex_lock(&indio_dev->mlock);
+
+	if (iio_buffer_enabled(indio_dev) && mask == IIO_CHAN_INFO_RAW) {
+		ret = -EBUSY;
+		goto error_busy;
+	}
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW: {
+		u16 reg;
+
+		ret = lidar_get_measurement(data, &reg);
+		if (!ret) {
+			*val = reg;
+			ret = IIO_VAL_INT;
+		}
+		break;
+	}
+	case IIO_CHAN_INFO_SCALE:
+		*val = 0;
+		*val2 = 10000;
+		ret = IIO_VAL_INT_PLUS_MICRO;
+		break;
+	}
+
+error_busy:
+	mutex_unlock(&indio_dev->mlock);
+
+	return ret;
+}
+
+static irqreturn_t lidar_trigger_handler(int irq, void *private)
+{
+	struct iio_poll_func *pf = private;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct lidar_data *data = iio_priv(indio_dev);
+	int ret;
+
+	ret = lidar_get_measurement(data, data->buffer);
+	if (!ret) {
+		iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+						   iio_get_time_ns());
+	} else {
+		dev_err(&data->client->dev, "cannot read LIDAR measurement");
+	}
+
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static const struct iio_info lidar_info = {
+	.driver_module = THIS_MODULE,
+	.read_raw = lidar_read_raw,
+};
+
+static int lidar_probe(struct i2c_client *client,
+		       const struct i2c_device_id *id)
+{
+	struct lidar_data *data;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	indio_dev->info = &lidar_info;
+	indio_dev->name = LIDAR_DRV_NAME;
+	indio_dev->channels = lidar_channels;
+	indio_dev->num_channels = ARRAY_SIZE(lidar_channels);
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	data = iio_priv(indio_dev);
+	i2c_set_clientdata(client, indio_dev);
+
+	data->client = client;
+	data->indio_dev = indio_dev;
+
+	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+					 lidar_trigger_handler, NULL);
+	if (ret)
+		return ret;
+
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto error_unreg_buffer;
+
+	return 0;
+
+error_unreg_buffer:
+	iio_triggered_buffer_cleanup(indio_dev);
+
+	return ret;
+}
+
+static int lidar_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+	iio_device_unregister(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+
+	return 0;
+}
+
+static const struct i2c_device_id lidar_id[] = {
+	{"lidar-lite-v2", 0},
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, lidar_id);
+
+static const struct of_device_id lidar_dt_ids[] = {
+	{ .compatible = "pulsedlight,lidar-lite-v2" },
+	{ }
+};
+
+static struct i2c_driver lidar_driver = {
+	.driver = {
+		.name	= LIDAR_DRV_NAME,
+		.of_match_table	= of_match_ptr(lidar_dt_ids),
+	},
+	.probe		= lidar_probe,
+	.remove		= lidar_remove,
+	.id_table	= lidar_id,
+};
+module_i2c_driver(lidar_driver);
+
+MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>");
+MODULE_DESCRIPTION("PulsedLight LIDAR sensor");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c
index 5d033a5..3fd3ba4 100644
--- a/drivers/iio/temperature/mlx90614.c
+++ b/drivers/iio/temperature/mlx90614.c
@@ -3,6 +3,7 @@
  *
  * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
  * Copyright (c) 2015 Essensium NV
+ * Copyright (c) 2015 Melexis
  *
  * This file is subject to the terms and conditions of version 2 of
  * the GNU General Public License.  See the file COPYING in the main
@@ -20,7 +21,6 @@
  * always has a pull-up so we do not need an extra GPIO to drive it high.  If
  * the "wakeup" GPIO is not given, power management will be disabled.
  *
- * TODO: filter configuration
  */
 
 #include <linux/err.h>
@@ -32,6 +32,7 @@
 #include <linux/pm_runtime.h>
 
 #include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
 
 #define MLX90614_OP_RAM		0x00
 #define MLX90614_OP_EEPROM	0x20
@@ -79,6 +80,20 @@
 	unsigned long ready_timestamp; /* in jiffies */
 };
 
+/* Bandwidth values for IIR filtering */
+static const int mlx90614_iir_values[] = {77, 31, 20, 15, 723, 153, 110, 86};
+static IIO_CONST_ATTR(in_temp_object_filter_low_pass_3db_frequency_available,
+		      "0.15 0.20 0.31 0.77 0.86 1.10 1.53 7.23");
+
+static struct attribute *mlx90614_attributes[] = {
+	&iio_const_attr_in_temp_object_filter_low_pass_3db_frequency_available.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group mlx90614_attr_group = {
+	.attrs = mlx90614_attributes,
+};
+
 /*
  * Erase an address and write word.
  * The mutex must be locked before calling.
@@ -117,6 +132,42 @@
 	return ret;
 }
 
+/*
+ * Find the IIR value inside mlx90614_iir_values array and return its position
+ * which is equivalent to the bit value in sensor register
+ */
+static inline s32 mlx90614_iir_search(const struct i2c_client *client,
+				      int value)
+{
+	int i;
+	s32 ret;
+
+	for (i = 0; i < ARRAY_SIZE(mlx90614_iir_values); ++i) {
+		if (value == mlx90614_iir_values[i])
+			break;
+	}
+
+	if (i == ARRAY_SIZE(mlx90614_iir_values))
+		return -EINVAL;
+
+	/*
+	 * CONFIG register values must not be changed so
+	 * we must read them before we actually write
+	 * changes
+	 */
+	ret = i2c_smbus_read_word_data(client, MLX90614_CONFIG);
+	if (ret > 0)
+		return ret;
+
+	/* Write changed values */
+	ret = mlx90614_write_word(client, MLX90614_CONFIG,
+			(i << MLX90614_CONFIG_IIR_SHIFT) |
+			(((u16) ((0x7 << MLX90614_CONFIG_FIR_SHIFT) |
+			((u16) ret & (~((u16) MLX90614_CONFIG_FIR_MASK))))) &
+			(~(u16) MLX90614_CONFIG_IIR_MASK)));
+	return ret;
+}
+
 #ifdef CONFIG_PM
 /*
  * If @startup is true, make sure MLX90614_TIMING_STARTUP ms have elapsed since
@@ -236,6 +287,21 @@
 			*val2 = ret * MLX90614_CONST_EMISSIVITY_RESOLUTION;
 		}
 		return IIO_VAL_INT_PLUS_NANO;
+	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: /* IIR setting with
+							     FIR = 1024 */
+		mlx90614_power_get(data, false);
+		mutex_lock(&data->lock);
+		ret = i2c_smbus_read_word_data(data->client, MLX90614_CONFIG);
+		mutex_unlock(&data->lock);
+		mlx90614_power_put(data);
+
+		if (ret < 0)
+			return ret;
+
+		*val = mlx90614_iir_values[ret & MLX90614_CONFIG_IIR_MASK] / 100;
+		*val2 = (mlx90614_iir_values[ret & MLX90614_CONFIG_IIR_MASK] % 100) *
+			10000;
+		return IIO_VAL_INT_PLUS_MICRO;
 	default:
 		return -EINVAL;
 	}
@@ -263,6 +329,18 @@
 		mlx90614_power_put(data);
 
 		return ret;
+	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: /* IIR Filter setting */
+		if (val < 0 || val2 < 0)
+			return -EINVAL;
+
+		mlx90614_power_get(data, false);
+		mutex_lock(&data->lock);
+		ret = mlx90614_iir_search(data->client,
+					  val * 100 + val2 / 10000);
+		mutex_unlock(&data->lock);
+		mlx90614_power_put(data);
+
+		return ret;
 	default:
 		return -EINVAL;
 	}
@@ -275,6 +353,8 @@
 	switch (mask) {
 	case IIO_CHAN_INFO_CALIBEMISSIVITY:
 		return IIO_VAL_INT_PLUS_NANO;
+	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+		return IIO_VAL_INT_PLUS_MICRO;
 	default:
 		return -EINVAL;
 	}
@@ -294,7 +374,8 @@
 		.modified = 1,
 		.channel2 = IIO_MOD_TEMP_OBJECT,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-		    BIT(IIO_CHAN_INFO_CALIBEMISSIVITY),
+		    BIT(IIO_CHAN_INFO_CALIBEMISSIVITY) |
+			BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),
 		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
 		    BIT(IIO_CHAN_INFO_SCALE),
 	},
@@ -305,7 +386,8 @@
 		.channel = 1,
 		.channel2 = IIO_MOD_TEMP_OBJECT,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-		    BIT(IIO_CHAN_INFO_CALIBEMISSIVITY),
+		    BIT(IIO_CHAN_INFO_CALIBEMISSIVITY) |
+			BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),
 		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
 		    BIT(IIO_CHAN_INFO_SCALE),
 	},
@@ -315,6 +397,7 @@
 	.read_raw = mlx90614_read_raw,
 	.write_raw = mlx90614_write_raw,
 	.write_raw_get_fmt = mlx90614_write_raw_get_fmt,
+	.attrs = &mlx90614_attr_group,
 	.driver_module = THIS_MODULE,
 };
 
@@ -569,5 +652,6 @@
 
 MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
 MODULE_AUTHOR("Vianney le Clément de Saint-Marcq <vianney.leclement@essensium.com>");
+MODULE_AUTHOR("Crt Mori <cmo@melexis.com>");
 MODULE_DESCRIPTION("Melexis MLX90614 contactless IR temperature sensor driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/iio/adc/lpc32xx_adc.c b/drivers/staging/iio/adc/lpc32xx_adc.c
index 5331c44..bcf4ebb 100644
--- a/drivers/staging/iio/adc/lpc32xx_adc.c
+++ b/drivers/staging/iio/adc/lpc32xx_adc.c
@@ -137,7 +137,7 @@
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(&pdev->dev, "failed to get platform I/O memory\n");
-		return -EBUSY;
+		return -ENXIO;
 	}
 
 	iodev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
@@ -162,7 +162,7 @@
 	irq = platform_get_irq(pdev, 0);
 	if (irq <= 0) {
 		dev_err(&pdev->dev, "failed getting interrupt resource\n");
-		return -EINVAL;
+		return -ENXIO;
 	}
 
 	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 6d38854..86d8447 100644
--- a/drivers/staging/iio/iio_dummy_evgen.c
+++ b/drivers/staging/iio/iio_dummy_evgen.c
@@ -24,9 +24,21 @@
 #include "iio_dummy_evgen.h"
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
+#include <linux/irq_work.h>
 
 /* Fiddly bit of faking and irq without hardware */
 #define IIO_EVENTGEN_NO 10
+
+/**
+ * struct iio_dummy_handle_irq - helper struct to simulate interrupt generation
+ * @work: irq_work used to run handlers from hardirq context
+ * @irq: fake irq line number to trigger an interrupt
+ */
+struct iio_dummy_handle_irq {
+	struct irq_work work;
+	int irq;
+};
+
 /**
  * struct iio_dummy_evgen - evgen state
  * @chip: irq chip we are faking
@@ -35,6 +47,7 @@
  * @inuse: mask of which irqs are connected
  * @regs: irq regs we are faking
  * @lock: protect the evgen state
+ * @handler: helper for a 'hardware-like' interrupt simulation
  */
 struct iio_dummy_eventgen {
 	struct irq_chip chip;
@@ -43,6 +56,7 @@
 	bool inuse[IIO_EVENTGEN_NO];
 	struct iio_dummy_regs regs[IIO_EVENTGEN_NO];
 	struct mutex lock;
+	struct iio_dummy_handle_irq handler;
 };
 
 /* We can only ever have one instance of this 'device' */
@@ -67,6 +81,14 @@
 	evgen->enabled[d->irq - evgen->base] = true;
 }
 
+static void iio_dummy_work_handler(struct irq_work *work)
+{
+	struct iio_dummy_handle_irq *irq_handler;
+
+	irq_handler = container_of(work, struct iio_dummy_handle_irq, work);
+	handle_simple_irq(irq_handler->irq, irq_to_desc(irq_handler->irq));
+}
+
 static int iio_dummy_evgen_create(void)
 {
 	int ret, i;
@@ -91,6 +113,7 @@
 				  IRQ_NOREQUEST | IRQ_NOAUTOEN,
 				  IRQ_NOPROBE);
 	}
+	init_irq_work(&iio_evgen->handler.work, iio_dummy_work_handler);
 	mutex_init(&iio_evgen->lock);
 	return 0;
 }
@@ -169,8 +192,9 @@
 	iio_evgen->regs[this_attr->address].reg_id   = this_attr->address;
 	iio_evgen->regs[this_attr->address].reg_data = event;
 
+	iio_evgen->handler.irq = iio_evgen->base + this_attr->address;
 	if (iio_evgen->enabled[this_attr->address])
-		handle_nested_irq(iio_evgen->base + this_attr->address);
+		irq_work_queue(&iio_evgen->handler.work);
 
 	return len;
 }
diff --git a/drivers/staging/iio/iio_simple_dummy.h b/drivers/staging/iio/iio_simple_dummy.h
index 8d00224..5c2f4d0 100644
--- a/drivers/staging/iio/iio_simple_dummy.h
+++ b/drivers/staging/iio/iio_simple_dummy.h
@@ -46,6 +46,7 @@
 	int event_irq;
 	int event_val;
 	bool event_en;
+	s64 event_timestamp;
 #endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */
 };
 
diff --git a/drivers/staging/iio/iio_simple_dummy_events.c b/drivers/staging/iio/iio_simple_dummy_events.c
index 73108ba..bfbf1c5 100644
--- a/drivers/staging/iio/iio_simple_dummy_events.c
+++ b/drivers/staging/iio/iio_simple_dummy_events.c
@@ -153,6 +153,15 @@
 	return 0;
 }
 
+static irqreturn_t iio_simple_dummy_get_timestamp(int irq, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	struct iio_dummy_state *st = iio_priv(indio_dev);
+
+	st->event_timestamp = iio_get_time_ns();
+	return IRQ_HANDLED;
+}
+
 /**
  * iio_simple_dummy_event_handler() - identify and pass on event
  * @irq: irq of event line
@@ -177,7 +186,7 @@
 			       IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0,
 					      IIO_EV_DIR_RISING,
 					      IIO_EV_TYPE_THRESH, 0, 0, 0),
-			       iio_get_time_ns());
+			       st->event_timestamp);
 		break;
 	case 1:
 		if (st->activity_running > st->event_val)
@@ -187,7 +196,7 @@
 						      IIO_EV_DIR_RISING,
 						      IIO_EV_TYPE_THRESH,
 						      0, 0, 0),
-				       iio_get_time_ns());
+				       st->event_timestamp);
 		break;
 	case 2:
 		if (st->activity_walking < st->event_val)
@@ -197,14 +206,14 @@
 						      IIO_EV_DIR_FALLING,
 						      IIO_EV_TYPE_THRESH,
 						      0, 0, 0),
-				       iio_get_time_ns());
+				       st->event_timestamp);
 		break;
 	case 3:
 		iio_push_event(indio_dev,
 			       IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD,
 					      IIO_EV_DIR_NONE,
 					      IIO_EV_TYPE_CHANGE, 0, 0, 0),
-			       iio_get_time_ns());
+			       st->event_timestamp);
 		break;
 	default:
 		break;
@@ -238,7 +247,7 @@
 	st->regs = iio_dummy_evgen_get_regs(st->event_irq);
 
 	ret = request_threaded_irq(st->event_irq,
-				   NULL,
+				   &iio_simple_dummy_get_timestamp,
 				   &iio_simple_dummy_event_handler,
 				   IRQF_ONESHOT,
 				   "iio_simple_event",
diff --git a/drivers/staging/iio/magnetometer/hmc5843.h b/drivers/staging/iio/magnetometer/hmc5843.h
index f3d0da2..06f35d3 100644
--- a/drivers/staging/iio/magnetometer/hmc5843.h
+++ b/drivers/staging/iio/magnetometer/hmc5843.h
@@ -48,7 +48,7 @@
 };
 
 int hmc5843_common_probe(struct device *dev, struct regmap *regmap,
-			 enum hmc5843_ids id);
+			 enum hmc5843_ids id, const char *name);
 int hmc5843_common_remove(struct device *dev);
 
 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 fffca3a..4aab022 100644
--- a/drivers/staging/iio/magnetometer/hmc5843_core.c
+++ b/drivers/staging/iio/magnetometer/hmc5843_core.c
@@ -577,7 +577,7 @@
 EXPORT_SYMBOL(hmc5843_common_resume);
 
 int hmc5843_common_probe(struct device *dev, struct regmap *regmap,
-			 enum hmc5843_ids id)
+			 enum hmc5843_ids id, const char *name)
 {
 	struct hmc5843_data *data;
 	struct iio_dev *indio_dev;
@@ -597,7 +597,7 @@
 	mutex_init(&data->lock);
 
 	indio_dev->dev.parent = dev;
-	indio_dev->name = dev->driver->name;
+	indio_dev->name = name;
 	indio_dev->info = &hmc5843_info;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	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 ff08667..3e06ceb 100644
--- a/drivers/staging/iio/magnetometer/hmc5843_i2c.c
+++ b/drivers/staging/iio/magnetometer/hmc5843_i2c.c
@@ -61,7 +61,7 @@
 {
 	return hmc5843_common_probe(&cli->dev,
 			devm_regmap_init_i2c(cli, &hmc5843_i2c_regmap_config),
-			id->driver_data);
+			id->driver_data, id->name);
 }
 
 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 8e658f7..1549192 100644
--- a/drivers/staging/iio/magnetometer/hmc5843_spi.c
+++ b/drivers/staging/iio/magnetometer/hmc5843_spi.c
@@ -59,6 +59,7 @@
 static int hmc5843_spi_probe(struct spi_device *spi)
 {
 	int ret;
+	const struct spi_device_id *id = spi_get_device_id(spi);
 
 	spi->mode = SPI_MODE_3;
 	spi->max_speed_hz = 8000000;
@@ -69,7 +70,7 @@
 
 	return hmc5843_common_probe(&spi->dev,
 			devm_regmap_init_spi(spi, &hmc5843_spi_regmap_config),
-			HMC5983_ID);
+			id->driver_data, id->name);
 }
 
 static int hmc5843_spi_remove(struct spi_device *spi)
@@ -81,6 +82,7 @@
 	{ "hmc5983", HMC5983_ID },
 	{ }
 };
+MODULE_DEVICE_TABLE(spi, hmc5843_id);
 
 static struct spi_driver hmc5843_driver = {
 		.driver = {
diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h
index 3c17cd7..2fe939c 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_disable(struct iio_dev *indio_dev);
 
+int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev,
+				  unsigned reg, unsigned writeval,
+				  unsigned *readval);
+
 int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr);
 
 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 7bb7f67..19c94c9 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -294,6 +294,7 @@
 #define INDIO_BUFFER_TRIGGERED		0x02
 #define INDIO_BUFFER_SOFTWARE		0x04
 #define INDIO_BUFFER_HARDWARE		0x08
+#define INDIO_EVENT_TRIGGERED		0x10
 
 #define INDIO_ALL_BUFFER_MODES					\
 	(INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE | INDIO_BUFFER_SOFTWARE)
@@ -457,6 +458,7 @@
  * @scan_index_timestamp:[INTERN] cache of the index to the timestamp
  * @trig:		[INTERN] current device trigger (buffer modes)
  * @pollfunc:		[DRIVER] function run on trigger being received
+ * @pollfunc_event:	[DRIVER] function run on events trigger being received
  * @channels:		[DRIVER] channel specification structure table
  * @num_channels:	[DRIVER] number of channels specified in @channels.
  * @channel_attr_list:	[INTERN] keep track of automatically created channel
@@ -495,6 +497,7 @@
 	unsigned			scan_index_timestamp;
 	struct iio_trigger		*trig;
 	struct iio_poll_func		*pollfunc;
+	struct iio_poll_func		*pollfunc_event;
 
 	struct iio_chan_spec const	*channels;
 	int				num_channels;
diff --git a/include/linux/iio/triggered_event.h b/include/linux/iio/triggered_event.h
new file mode 100644
index 0000000..8fe8537
--- /dev/null
+++ b/include/linux/iio/triggered_event.h
@@ -0,0 +1,11 @@
+#ifndef _LINUX_IIO_TRIGGERED_EVENT_H_
+#define _LINUX_IIO_TRIGGERED_EVENT_H_
+
+#include <linux/interrupt.h>
+
+int iio_triggered_event_setup(struct iio_dev *indio_dev,
+	irqreturn_t (*h)(int irq, void *p),
+	irqreturn_t (*thread)(int irq, void *p));
+void iio_triggered_event_cleanup(struct iio_dev *indio_dev);
+
+#endif
diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h
index 2f8b117..7c63bd6 100644
--- a/include/uapi/linux/iio/types.h
+++ b/include/uapi/linux/iio/types.h
@@ -35,6 +35,8 @@
 	IIO_ENERGY,
 	IIO_DISTANCE,
 	IIO_VELOCITY,
+	IIO_CONCENTRATION,
+	IIO_RESISTANCE,
 };
 
 enum iio_modifier {
@@ -72,6 +74,8 @@
 	IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z,
 	IIO_MOD_I,
 	IIO_MOD_Q,
+	IIO_MOD_CO2,
+	IIO_MOD_VOC,
 };
 
 enum iio_event_type {
diff --git a/tools/iio/generic_buffer.c b/tools/iio/generic_buffer.c
index 9f7b85b..01c4f67 100644
--- a/tools/iio/generic_buffer.c
+++ b/tools/iio/generic_buffer.c
@@ -328,6 +328,15 @@
 			"diag %s\n", dev_dir_name);
 		goto error_free_triggername;
 	}
+	if (!num_channels) {
+		fprintf(stderr,
+			"No channels are enabled, we have nothing to scan.\n");
+		fprintf(stderr, "Enable channels manually in "
+			FORMAT_SCAN_ELEMENTS_DIR
+			"/*_en and try again.\n", dev_dir_name);
+		ret = -ENOENT;
+		goto error_free_triggername;
+	}
 
 	/*
 	 * 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 cd3fd41..d51eb04 100644
--- a/tools/iio/iio_event_monitor.c
+++ b/tools/iio/iio_event_monitor.c
@@ -284,7 +284,11 @@
 	ret = ioctl(fd, IIO_GET_EVENT_FD_IOCTL, &event_fd);
 	if (ret == -1 || event_fd == -1) {
 		ret = -errno;
-		fprintf(stderr, "Failed to retrieve event fd\n");
+		if (ret == -ENODEV)
+			fprintf(stderr,
+				"This device does not support events\n");
+		else
+			fprintf(stderr, "Failed to retrieve event fd\n");
 		if (close(fd) == -1)
 			perror("Failed to close character device file");